From 99f1e62fca722ad8628ddeee6a1edc4b8e45b9b5 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 18 Jul 2011 20:04:31 -0500 Subject: [PATCH] --- yaml --- r: 267722 b: refs/heads/master c: 0157d2e55c04a6fc7b69e4f9f0daed48c3597415 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/char/scc.h | 613 ++ trunk/drivers/staging/Kconfig | 4 +- trunk/drivers/staging/Makefile | 2 +- trunk/drivers/staging/altera-stapl/altera.c | 2 +- trunk/drivers/staging/ath6kl/Kconfig | 158 + trunk/drivers/staging/ath6kl/Makefile | 122 + trunk/drivers/staging/ath6kl/TODO | 25 + .../staging/ath6kl/bmi/include/bmi_internal.h | 54 + trunk/drivers/staging/ath6kl/bmi/src/bmi.c | 1010 +++ .../ath6kl/hif/common/hif_sdio_common.h | 87 + .../sdio/linux_sdio/include/hif_internal.h | 131 + .../ath6kl/hif/sdio/linux_sdio/src/hif.c | 1273 ++++ .../hif/sdio/linux_sdio/src/hif_scatter.c | 393 + .../drivers/staging/ath6kl/htc2/AR6000/ar6k.c | 1479 ++++ .../drivers/staging/ath6kl/htc2/AR6000/ar6k.h | 401 + .../staging/ath6kl/htc2/AR6000/ar6k_events.c | 783 ++ .../staging/ath6kl/htc2/AR6000/ar6k_gmbox.c | 755 ++ .../ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c | 1284 ++++ trunk/drivers/staging/ath6kl/htc2/htc.c | 575 ++ trunk/drivers/staging/ath6kl/htc2/htc_debug.h | 38 + .../staging/ath6kl/htc2/htc_internal.h | 211 + trunk/drivers/staging/ath6kl/htc2/htc_recv.c | 1572 ++++ trunk/drivers/staging/ath6kl/htc2/htc_send.c | 1018 +++ .../staging/ath6kl/htc2/htc_services.c | 450 ++ .../drivers/staging/ath6kl/include/a_config.h | 31 + .../drivers/staging/ath6kl/include/a_debug.h | 195 + trunk/drivers/staging/ath6kl/include/a_drv.h | 32 + .../staging/ath6kl/include/a_drv_api.h | 204 + .../drivers/staging/ath6kl/include/a_osapi.h | 32 + .../staging/ath6kl/include/aggr_recv_api.h | 140 + .../staging/ath6kl/include/ar3kconfig.h | 65 + .../staging/ath6kl/include/ar6000_api.h | 32 + .../staging/ath6kl/include/ar6000_diag.h | 48 + .../staging/ath6kl/include/ar6kap_common.h | 44 + .../staging/ath6kl/include/athbtfilter.h | 135 + trunk/drivers/staging/ath6kl/include/bmi.h | 134 + .../include/common/AR6002/AR6K_version.h | 52 + .../ath6kl/include/common/AR6002/addrs.h | 90 + .../AR6002/hw4.0/hw/apb_athr_wlan_map.h | 40 + .../include/common/AR6002/hw4.0/hw/apb_map.h | 40 + .../common/AR6002/hw4.0/hw/mbox_host_reg.h | 24 + .../include/common/AR6002/hw4.0/hw/mbox_reg.h | 552 ++ .../AR6002/hw4.0/hw/mbox_wlan_host_reg.h | 471 ++ .../common/AR6002/hw4.0/hw/mbox_wlan_reg.h | 589 ++ .../include/common/AR6002/hw4.0/hw/rtc_reg.h | 187 + .../common/AR6002/hw4.0/hw/rtc_wlan_reg.h | 162 + .../include/common/AR6002/hw4.0/hw/uart_reg.h | 40 + .../staging/ath6kl/include/common/athdefs.h | 75 + .../staging/ath6kl/include/common/bmi_msg.h | 233 + .../staging/ath6kl/include/common/cnxmgmt.h | 36 + .../staging/ath6kl/include/common/dbglog.h | 126 + .../staging/ath6kl/include/common/dbglog_id.h | 558 ++ .../staging/ath6kl/include/common/discovery.h | 75 + .../ath6kl/include/common/epping_test.h | 111 + .../staging/ath6kl/include/common/gmboxif.h | 70 + .../staging/ath6kl/include/common/gpio_reg.h | 9 + .../staging/ath6kl/include/common/htc.h | 227 + .../ath6kl/include/common/htc_services.h | 52 + .../staging/ath6kl/include/common/pkt_log.h | 45 + .../staging/ath6kl/include/common/roaming.h | 41 + .../staging/ath6kl/include/common/targaddrs.h | 395 + .../staging/ath6kl/include/common/testcmd.h | 185 + .../staging/ath6kl/include/common/tlpm.h | 38 + .../staging/ath6kl/include/common/wlan_defs.h | 79 + .../staging/ath6kl/include/common/wmi.h | 3220 ++++++++ .../staging/ath6kl/include/common/wmix.h | 271 + .../staging/ath6kl/include/common_drv.h | 104 + .../staging/ath6kl/include/dbglog_api.h | 52 + .../drivers/staging/ath6kl/include/dl_list.h | 153 + .../drivers/staging/ath6kl/include/dset_api.h | 65 + .../ath6kl/include/hci_transport_api.h | 259 + trunk/drivers/staging/ath6kl/include/hif.h | 456 ++ .../staging/ath6kl/include/host_version.h | 52 + .../drivers/staging/ath6kl/include/htc_api.h | 575 ++ .../staging/ath6kl/include/htc_packet.h | 227 + .../drivers/staging/ath6kl/include/wlan_api.h | 128 + .../drivers/staging/ath6kl/include/wmi_api.h | 441 ++ .../staging/ath6kl/miscdrv/ar3kconfig.c | 565 ++ .../ath6kl/miscdrv/ar3kps/ar3kpsconfig.c | 572 ++ .../ath6kl/miscdrv/ar3kps/ar3kpsconfig.h | 75 + .../ath6kl/miscdrv/ar3kps/ar3kpsparser.c | 969 +++ .../ath6kl/miscdrv/ar3kps/ar3kpsparser.h | 113 + .../staging/ath6kl/miscdrv/common_drv.c | 910 +++ .../staging/ath6kl/miscdrv/credit_dist.c | 417 ++ .../drivers/staging/ath6kl/miscdrv/miscdrv.h | 42 + .../staging/ath6kl/os/linux/ar6000_drv.c | 6267 ++++++++++++++++ .../staging/ath6kl/os/linux/ar6000_pm.c | 626 ++ .../staging/ath6kl/os/linux/ar6000_raw_if.c | 455 ++ .../staging/ath6kl/os/linux/cfg80211.c | 1892 +++++ .../ath6kl/os/linux/export_hci_transport.c | 124 + .../staging/ath6kl/os/linux/hci_bridge.c | 1141 +++ .../ath6kl/os/linux/include/ar6000_drv.h | 776 ++ .../ath6kl/os/linux/include/ar6k_pal.h | 36 + .../ath6kl/os/linux/include/ar6xapi_linux.h | 190 + .../ath6kl/os/linux/include/athdrv_linux.h | 1217 ++++ .../ath6kl/os/linux/include/cfg80211.h | 61 + .../ath6kl/os/linux/include/config_linux.h | 51 + .../ath6kl/os/linux/include/debug_linux.h | 50 + .../os/linux/include/export_hci_transport.h | 76 + .../ath6kl/os/linux/include/ieee80211_ioctl.h | 177 + .../ath6kl/os/linux/include/osapi_linux.h | 339 + .../ath6kl/os/linux/include/wlan_config.h | 108 + .../os/linux/include/wmi_filter_linux.h | 300 + .../drivers/staging/ath6kl/os/linux/netbuf.c | 231 + .../staging/ath6kl/reorder/aggr_rx_internal.h | 117 + .../drivers/staging/ath6kl/reorder/rcv_aggr.c | 661 ++ .../staging/ath6kl/wlan/include/ieee80211.h | 397 + .../ath6kl/wlan/include/ieee80211_node.h | 93 + .../staging/ath6kl/wlan/src/wlan_node.c | 636 ++ .../ath6kl/wlan/src/wlan_recv_beacon.c | 199 + .../staging/ath6kl/wlan/src/wlan_utils.c | 58 + trunk/drivers/staging/ath6kl/wmi/wmi.c | 6444 +++++++++++++++++ trunk/drivers/staging/ath6kl/wmi/wmi_host.h | 102 + trunk/drivers/staging/bcm/Bcmchar.c | 3172 ++++---- trunk/drivers/staging/bcm/Macros.h | 337 +- trunk/drivers/staging/bcm/headers.h | 2 - trunk/drivers/staging/bcm/nvm.c | 13 +- trunk/drivers/staging/brcm80211/Kconfig | 7 +- trunk/drivers/staging/brcm80211/TODO | 4 + .../staging/brcm80211/brcmfmac/bcmsdh.c | 539 +- .../staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 965 ++- .../drivers/staging/brcm80211/brcmfmac/dhd.h | 228 +- .../staging/brcm80211/brcmfmac/dhd_common.c | 128 +- .../staging/brcm80211/brcmfmac/dhd_linux.c | 235 +- .../staging/brcm80211/brcmfmac/dhd_sdio.c | 1635 +++-- .../staging/brcm80211/brcmfmac/sdio_host.h | 278 +- .../staging/brcm80211/brcmfmac/wl_cfg80211.c | 244 +- .../staging/brcm80211/brcmfmac/wl_cfg80211.h | 14 +- .../staging/brcm80211/brcmsmac/Makefile | 1 + .../staging/brcm80211/brcmsmac/aiutils.c | 773 +- .../staging/brcm80211/brcmsmac/aiutils.h | 58 +- .../staging/brcm80211/brcmsmac/alloc.c | 9 +- .../staging/brcm80211/brcmsmac/ampdu.c | 230 +- .../staging/brcm80211/brcmsmac/antsel.c | 25 +- .../drivers/staging/brcm80211/brcmsmac/bmac.c | 3593 +++++++++ .../drivers/staging/brcm80211/brcmsmac/bmac.h | 174 + .../staging/brcm80211/brcmsmac/channel.c | 388 +- .../staging/brcm80211/brcmsmac/channel.h | 25 +- .../drivers/staging/brcm80211/brcmsmac/d11.h | 641 +- .../drivers/staging/brcm80211/brcmsmac/dma.c | 961 ++- .../drivers/staging/brcm80211/brcmsmac/dma.h | 186 +- .../staging/brcm80211/brcmsmac/mac80211_if.c | 171 +- .../staging/brcm80211/brcmsmac/mac80211_if.h | 17 +- .../drivers/staging/brcm80211/brcmsmac/main.c | 4865 ++----------- .../drivers/staging/brcm80211/brcmsmac/main.h | 852 +-- .../staging/brcm80211/brcmsmac/nicpci.c | 75 +- .../staging/brcm80211/brcmsmac/nicpci.h | 30 +- .../drivers/staging/brcm80211/brcmsmac/otp.c | 155 +- .../drivers/staging/brcm80211/brcmsmac/otp.h | 15 +- .../staging/brcm80211/brcmsmac/phy/phy_cmn.c | 589 +- .../staging/brcm80211/brcmsmac/phy/phy_hal.h | 85 +- .../staging/brcm80211/brcmsmac/phy/phy_int.h | 188 +- .../staging/brcm80211/brcmsmac/phy/phy_lcn.c | 582 +- .../staging/brcm80211/brcmsmac/phy/phy_n.c | 5114 ++++++------- .../brcm80211/brcmsmac/phy/phy_qmath.c | 172 +- .../brcm80211/brcmsmac/phy/phytbl_lcn.c | 1168 ++- .../staging/brcm80211/brcmsmac/phy/phytbl_n.c | 3 +- .../staging/brcm80211/brcmsmac/phy/phytbl_n.h | 24 +- .../staging/brcm80211/brcmsmac/phy_shim.c | 24 +- .../staging/brcm80211/brcmsmac/phy_shim.h | 69 +- .../drivers/staging/brcm80211/brcmsmac/pmu.c | 54 +- .../drivers/staging/brcm80211/brcmsmac/pub.h | 272 +- .../drivers/staging/brcm80211/brcmsmac/rate.c | 163 +- .../drivers/staging/brcm80211/brcmsmac/rate.h | 186 +- .../drivers/staging/brcm80211/brcmsmac/scb.h | 36 +- .../drivers/staging/brcm80211/brcmsmac/srom.c | 114 +- .../drivers/staging/brcm80211/brcmsmac/srom.h | 4 +- .../drivers/staging/brcm80211/brcmsmac/stf.c | 100 +- .../drivers/staging/brcm80211/brcmsmac/stf.h | 6 +- .../staging/brcm80211/brcmsmac/types.h | 280 +- .../staging/brcm80211/brcmutil/utils.c | 110 +- .../drivers/staging/brcm80211/brcmutil/wifi.c | 37 +- .../staging/brcm80211/include/brcmu_utils.h | 19 +- .../staging/brcm80211/include/brcmu_wifi.h | 135 +- .../staging/brcm80211/include/chipcommon.h | 13 +- .../drivers/staging/brcm80211/include/defs.h | 18 +- trunk/drivers/staging/brcm80211/include/soc.h | 5 +- trunk/drivers/staging/comedi/Kconfig | 18 +- trunk/drivers/staging/comedi/comedi_fops.c | 2 +- trunk/drivers/staging/comedi/drivers/Makefile | 1 - .../staging/comedi/drivers/adv_pci_dio.c | 2 +- .../drivers/staging/comedi/drivers/ni_labpc.c | 20 +- .../staging/comedi/drivers/ni_pcidio.c | 2 +- .../staging/comedi/drivers/usbduxsigma.c | 2880 -------- trunk/drivers/staging/cxd2099/Makefile | 6 +- trunk/drivers/staging/easycap/easycap_ioctl.c | 30 +- trunk/drivers/staging/et131x/et1310_eeprom.c | 32 +- trunk/drivers/staging/et131x/et1310_mac.c | 379 +- trunk/drivers/staging/et131x/et1310_phy.c | 556 +- trunk/drivers/staging/et131x/et1310_pm.c | 48 +- trunk/drivers/staging/et131x/et1310_rx.c | 625 +- trunk/drivers/staging/et131x/et1310_rx.h | 62 +- trunk/drivers/staging/et131x/et1310_tx.c | 464 +- trunk/drivers/staging/et131x/et131x.h | 74 +- trunk/drivers/staging/et131x/et131x_adapter.h | 95 +- trunk/drivers/staging/et131x/et131x_initpci.c | 165 +- trunk/drivers/staging/et131x/et131x_isr.c | 57 +- trunk/drivers/staging/et131x/et131x_netdev.c | 137 +- .../staging/ft1000/ft1000-pcmcia/ft1000.h | 10 - .../staging/ft1000/ft1000-pcmcia/ft1000_cs.c | 8 +- .../ft1000/ft1000-pcmcia/ft1000_dnld.c | 3 +- .../staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 24 +- .../ft1000/ft1000-pcmcia/ft1000_proc.c | 4 +- .../staging/ft1000/ft1000-usb/ft1000_hw.c | 2 +- trunk/drivers/staging/go7007/Makefile | 8 +- trunk/drivers/staging/go7007/wis-tw2804.c | 6 +- trunk/drivers/staging/hv/hv.c | 4 +- trunk/drivers/staging/hv/hv_mouse.c | 40 +- .../drivers/staging/hv/tools/hv_kvp_daemon.c | 19 +- trunk/drivers/staging/hv/vmbus_drv.c | 19 +- .../staging/iio/Documentation/sysfs-bus-iio | 23 +- .../Documentation/sysfs-bus-iio-adc-ad7280a | 21 - .../sysfs-bus-iio-impedance-analyzer-ad5933 | 30 - trunk/drivers/staging/iio/Kconfig | 1 - trunk/drivers/staging/iio/Makefile | 1 - trunk/drivers/staging/iio/accel/accel.h | 87 + .../staging/iio/accel/adis16201_core.c | 4 + .../staging/iio/accel/adis16201_ring.c | 19 +- .../staging/iio/accel/adis16201_trigger.c | 13 +- .../staging/iio/accel/adis16203_core.c | 3 + .../staging/iio/accel/adis16203_ring.c | 12 +- .../staging/iio/accel/adis16203_trigger.c | 14 +- .../staging/iio/accel/adis16204_core.c | 47 +- .../staging/iio/accel/adis16204_ring.c | 12 +- .../staging/iio/accel/adis16204_trigger.c | 14 +- .../staging/iio/accel/adis16209_core.c | 3 + .../staging/iio/accel/adis16209_ring.c | 12 +- .../staging/iio/accel/adis16209_trigger.c | 14 +- .../staging/iio/accel/adis16220_core.c | 343 +- .../staging/iio/accel/adis16240_core.c | 2 + .../staging/iio/accel/adis16240_ring.c | 12 +- .../staging/iio/accel/adis16240_trigger.c | 14 +- .../drivers/staging/iio/accel/inclinometer.h | 25 + trunk/drivers/staging/iio/accel/kxsd9.c | 268 +- .../staging/iio/accel/lis3l02dq_core.c | 26 +- .../staging/iio/accel/lis3l02dq_ring.c | 18 +- .../drivers/staging/iio/accel/sca3000_core.c | 19 +- .../drivers/staging/iio/accel/sca3000_ring.c | 71 + trunk/drivers/staging/iio/adc/Kconfig | 24 - trunk/drivers/staging/iio/adc/Makefile | 2 - trunk/drivers/staging/iio/adc/ad7150.c | 10 +- trunk/drivers/staging/iio/adc/ad7192.c | 1184 --- trunk/drivers/staging/iio/adc/ad7192.h | 47 - trunk/drivers/staging/iio/adc/ad7280a.c | 992 --- trunk/drivers/staging/iio/adc/ad7280a.h | 38 - trunk/drivers/staging/iio/adc/ad7298_core.c | 1 + trunk/drivers/staging/iio/adc/ad7298_ring.c | 12 +- trunk/drivers/staging/iio/adc/ad7476_core.c | 1 + trunk/drivers/staging/iio/adc/ad7476_ring.c | 12 +- trunk/drivers/staging/iio/adc/ad7606_core.c | 1 + trunk/drivers/staging/iio/adc/ad7606_ring.c | 12 +- trunk/drivers/staging/iio/adc/ad7780.c | 1 + trunk/drivers/staging/iio/adc/ad7793.c | 10 +- trunk/drivers/staging/iio/adc/ad7816.c | 2 +- trunk/drivers/staging/iio/adc/ad7887_core.c | 2 +- trunk/drivers/staging/iio/adc/ad7887_ring.c | 13 +- trunk/drivers/staging/iio/adc/ad799x_core.c | 13 +- trunk/drivers/staging/iio/adc/ad799x_ring.c | 13 +- trunk/drivers/staging/iio/adc/adc.h | 42 + trunk/drivers/staging/iio/adc/adt75.c | 2 +- trunk/drivers/staging/iio/adc/max1363_core.c | 19 +- trunk/drivers/staging/iio/adc/max1363_ring.c | 13 +- trunk/drivers/staging/iio/addac/adt7316.c | 2 +- trunk/drivers/staging/iio/dac/ad5504.c | 4 +- trunk/drivers/staging/iio/dac/ad5791.c | 1 + trunk/drivers/staging/iio/dds/ad9852.c | 1 + trunk/drivers/staging/iio/dds/ad9910.c | 1 + trunk/drivers/staging/iio/dds/ad9951.c | 1 + .../drivers/staging/iio/gyro/adis16060_core.c | 115 +- .../drivers/staging/iio/gyro/adis16080_core.c | 92 +- .../drivers/staging/iio/gyro/adis16130_core.c | 144 +- .../drivers/staging/iio/gyro/adis16260_core.c | 2 + .../drivers/staging/iio/gyro/adis16260_ring.c | 12 +- .../staging/iio/gyro/adis16260_trigger.c | 14 +- .../drivers/staging/iio/gyro/adxrs450_core.c | 252 +- trunk/drivers/staging/iio/gyro/gyro.h | 85 + trunk/drivers/staging/iio/iio.h | 91 +- trunk/drivers/staging/iio/iio_core.h | 48 - trunk/drivers/staging/iio/iio_core_trigger.h | 46 - .../staging/iio/impedance-analyzer/Kconfig | 16 - .../staging/iio/impedance-analyzer/Makefile | 5 - .../staging/iio/impedance-analyzer/ad5933.c | 818 --- .../staging/iio/impedance-analyzer/ad5933.h | 28 - .../drivers/staging/iio/imu/adis16400_core.c | 72 +- .../drivers/staging/iio/imu/adis16400_ring.c | 12 +- .../staging/iio/imu/adis16400_trigger.c | 14 +- trunk/drivers/staging/iio/industrialio-core.c | 211 +- trunk/drivers/staging/iio/industrialio-ring.c | 1 - .../staging/iio/industrialio-trigger.c | 82 +- trunk/drivers/staging/iio/light/isl29018.c | 46 - trunk/drivers/staging/iio/light/tsl2563.c | 4 +- trunk/drivers/staging/iio/light/tsl2583.c | 220 +- .../drivers/staging/iio/magnetometer/ak8975.c | 214 +- .../staging/iio/magnetometer/hmc5843.c | 96 +- .../drivers/staging/iio/magnetometer/magnet.h | 31 + .../drivers/staging/iio/meter/ade7758_ring.c | 19 +- .../staging/iio/meter/ade7758_trigger.c | 16 +- trunk/drivers/staging/iio/meter/ade7854.c | 2 +- trunk/drivers/staging/iio/resolver/ad2s1210.c | 1 + trunk/drivers/staging/iio/resolver/ad2s90.c | 1 + trunk/drivers/staging/iio/sysfs.h | 79 +- trunk/drivers/staging/iio/trigger.h | 115 +- .../staging/iio/trigger/iio-trig-bfin-timer.c | 6 +- .../staging/iio/trigger/iio-trig-gpio.c | 6 +- .../iio/trigger/iio-trig-periodic-rtc.c | 7 +- .../staging/iio/trigger/iio-trig-sysfs.c | 13 +- trunk/drivers/staging/iio/trigger_consumer.h | 71 +- trunk/drivers/staging/keucr/scsiglue.c | 5 +- trunk/drivers/staging/keucr/smil.h | 6 +- trunk/drivers/staging/keucr/smilsub.c | 1574 +++- trunk/drivers/staging/keucr/smscsi.c | 117 +- trunk/drivers/staging/mei/interrupt.c | 6 - trunk/drivers/staging/mei/main.c | 30 +- trunk/drivers/staging/nvec/nvec.c | 168 +- trunk/drivers/staging/nvec/nvec.h | 13 +- trunk/drivers/staging/nvec/nvec_kbd.c | 41 +- trunk/drivers/staging/nvec/nvec_ps2.c | 19 +- trunk/drivers/staging/olpc_dcon/olpc_dcon.c | 43 +- trunk/drivers/staging/pohmelfs/trans.c | 6 +- trunk/drivers/staging/rtl8187se/Makefile | 6 +- .../staging/rtl8187se/ieee80211/ieee80211.h | 4 +- .../rtl8187se/ieee80211/ieee80211_softmac.c | 14 +- .../staging/rtl8187se/r8180_rtl8225z2.c | 4 +- trunk/drivers/staging/rtl8192e/rtl819x_Qos.h | 4 +- .../staging/rtl8192u/ieee80211/compress.c | 4 +- .../staging/rtl8192u/ieee80211/ieee80211.h | 4 +- .../rtl8192u/ieee80211/ieee80211_softmac.c | 14 +- trunk/drivers/staging/rtl8712/big_endian.h | 25 - trunk/drivers/staging/rtl8712/drv_types.h | 5 - trunk/drivers/staging/rtl8712/ethernet.h | 25 - trunk/drivers/staging/rtl8712/generic.h | 25 - trunk/drivers/staging/rtl8712/if_ether.h | 25 - trunk/drivers/staging/rtl8712/little_endian.h | 25 - trunk/drivers/staging/rtl8712/mlme_osdep.h | 25 - trunk/drivers/staging/rtl8712/mp_custom_oid.h | 25 - trunk/drivers/staging/rtl8712/os_intfs.c | 14 - trunk/drivers/staging/rtl8712/osdep_service.h | 1 + trunk/drivers/staging/rtl8712/recv_osdep.h | 25 - .../drivers/staging/rtl8712/rtl8712_bitdef.h | 21 - .../staging/rtl8712/rtl8712_cmdctrl_bitdef.h | 19 - .../staging/rtl8712/rtl8712_cmdctrl_regdef.h | 19 - .../rtl8712/rtl8712_debugctrl_bitdef.h | 19 - .../rtl8712/rtl8712_debugctrl_regdef.h | 19 - .../rtl8712/rtl8712_edcasetting_bitdef.h | 25 - .../rtl8712/rtl8712_edcasetting_regdef.h | 19 - .../staging/rtl8712/rtl8712_fifoctrl_bitdef.h | 19 - .../staging/rtl8712/rtl8712_fifoctrl_regdef.h | 19 - .../staging/rtl8712/rtl8712_gp_bitdef.h | 25 - .../staging/rtl8712/rtl8712_gp_regdef.h | 25 - trunk/drivers/staging/rtl8712/rtl8712_hal.h | 25 - .../rtl8712/rtl8712_interrupt_bitdef.h | 19 - .../rtl8712/rtl8712_macsetting_bitdef.h | 19 - .../rtl8712/rtl8712_macsetting_regdef.h | 19 - .../rtl8712/rtl8712_powersave_bitdef.h | 19 - .../rtl8712/rtl8712_powersave_regdef.h | 19 - .../staging/rtl8712/rtl8712_ratectrl_bitdef.h | 19 - .../staging/rtl8712/rtl8712_ratectrl_regdef.h | 25 - .../drivers/staging/rtl8712/rtl8712_regdef.h | 25 - .../staging/rtl8712/rtl8712_security_bitdef.h | 19 - trunk/drivers/staging/rtl8712/rtl8712_spec.h | 25 - .../staging/rtl8712/rtl8712_syscfg_bitdef.h | 25 - .../staging/rtl8712/rtl8712_syscfg_regdef.h | 25 - .../staging/rtl8712/rtl8712_timectrl_bitdef.h | 19 - .../staging/rtl8712/rtl8712_timectrl_regdef.h | 19 - .../staging/rtl8712/rtl8712_wmac_bitdef.h | 25 - .../staging/rtl8712/rtl8712_wmac_regdef.h | 25 - .../staging/rtl8712/rtl871x_byteorder.h | 19 - .../drivers/staging/rtl8712/rtl871x_eeprom.h | 19 - trunk/drivers/staging/rtl8712/rtl871x_event.h | 25 - trunk/drivers/staging/rtl8712/rtl871x_ht.h | 25 - .../staging/rtl8712/rtl871x_ioctl_linux.c | 28 +- .../staging/rtl8712/rtl871x_ioctl_set.h | 25 - trunk/drivers/staging/rtl8712/rtl871x_mp.h | 25 - .../drivers/staging/rtl8712/rtl871x_pwrctrl.h | 25 - trunk/drivers/staging/rtl8712/rtl871x_rf.h | 25 - .../staging/rtl8712/rtl871x_security.h | 25 - .../staging/rtl8712/rtl871x_wlan_sme.h | 25 - trunk/drivers/staging/rtl8712/swab.h | 25 - trunk/drivers/staging/rtl8712/usb_ops.h | 25 - trunk/drivers/staging/rtl8712/usb_osintf.h | 25 - .../drivers/staging/rtl8712/usb_vendor_req.h | 25 - trunk/drivers/staging/rts5139/Kconfig | 16 - trunk/drivers/staging/rts5139/Makefile | 37 - trunk/drivers/staging/rts5139/TODO | 5 - trunk/drivers/staging/rts5139/debug.h | 46 - trunk/drivers/staging/rts5139/ms.c | 4191 ----------- trunk/drivers/staging/rts5139/ms.h | 263 - trunk/drivers/staging/rts5139/ms_mg.c | 642 -- trunk/drivers/staging/rts5139/ms_mg.h | 41 - trunk/drivers/staging/rts5139/rts51x.c | 967 --- trunk/drivers/staging/rts5139/rts51x.h | 205 - trunk/drivers/staging/rts5139/rts51x_card.c | 986 --- trunk/drivers/staging/rts5139/rts51x_card.h | 881 --- trunk/drivers/staging/rts5139/rts51x_chip.c | 1167 --- trunk/drivers/staging/rts5139/rts51x_chip.h | 904 --- trunk/drivers/staging/rts5139/rts51x_fop.c | 298 - trunk/drivers/staging/rts5139/rts51x_fop.h | 62 - trunk/drivers/staging/rts5139/rts51x_scsi.c | 2234 ------ trunk/drivers/staging/rts5139/rts51x_scsi.h | 162 - trunk/drivers/staging/rts5139/rts51x_sys.h | 54 - .../staging/rts5139/rts51x_transport.c | 1000 --- .../staging/rts5139/rts51x_transport.h | 80 - trunk/drivers/staging/rts5139/sd.c | 3400 --------- trunk/drivers/staging/rts5139/sd.h | 304 - trunk/drivers/staging/rts5139/sd_cprm.c | 1215 ---- trunk/drivers/staging/rts5139/sd_cprm.h | 54 - trunk/drivers/staging/rts5139/trace.h | 137 - trunk/drivers/staging/rts5139/xd.c | 2255 ------ trunk/drivers/staging/rts5139/xd.h | 193 - trunk/drivers/staging/rts_pstor/Makefile | 2 +- trunk/drivers/staging/rts_pstor/rtsx_scsi.c | 2 +- trunk/drivers/staging/rts_pstor/sd.c | 4 +- trunk/drivers/staging/rts_pstor/spi.c | 2 +- trunk/drivers/staging/serqt_usb2/serqt_usb2.c | 34 +- trunk/drivers/staging/spectra/ffsport.c | 15 +- trunk/drivers/staging/tidspbridge/gen/gh.c | 2 +- trunk/drivers/staging/usbip/stub.h | 5 - trunk/drivers/staging/usbip/stub_dev.c | 6 +- trunk/drivers/staging/usbip/stub_rx.c | 5 +- .../drivers/staging/usbip/usbip_protocol.txt | 358 - .../usbip/userspace/libsrc/vhci_driver.c | 2 +- .../usbip/userspace/src/usbip_attach.c | 4 +- trunk/drivers/staging/usbip/vhci.h | 5 - .../staging/vme/bridges/vme_ca91cx42.c | 24 - .../drivers/staging/vme/bridges/vme_tsi148.c | 24 - trunk/drivers/staging/vme/devices/vme_user.c | 4 +- trunk/drivers/staging/vme/vme.c | 74 +- trunk/drivers/staging/vme/vme_bridge.h | 11 +- trunk/drivers/staging/vt6655/IEEE11h.c | 406 +- trunk/drivers/staging/vt6655/device_main.c | 10 +- trunk/drivers/staging/vt6655/dpc.c | 30 +- trunk/drivers/staging/vt6655/wmgr.c | 49 +- trunk/drivers/staging/vt6656/dpc.c | 30 +- trunk/drivers/staging/vt6656/main_usb.c | 11 +- trunk/drivers/staging/vt6656/wmgr.c | 49 +- .../drivers/staging/winbond/phy_calibration.c | 12 +- trunk/drivers/staging/xgifb/XGI_main.h | 128 +- trunk/drivers/staging/xgifb/XGI_main_26.c | 544 +- trunk/drivers/staging/xgifb/XGIfb.h | 12 + trunk/drivers/staging/xgifb/vb_def.h | 590 +- trunk/drivers/staging/xgifb/vb_ext.h | 20 + trunk/drivers/staging/xgifb/vb_setmode.c | 3 + trunk/drivers/staging/xgifb/vb_struct.h | 71 + trunk/drivers/staging/xgifb/vb_table.h | 729 ++ trunk/drivers/staging/xgifb/vgatypes.h | 5 + trunk/drivers/staging/zcache/zcache-main.c | 6 +- trunk/drivers/staging/zram/zram_drv.c | 36 +- trunk/drivers/staging/zram/zram_drv.h | 4 +- trunk/drivers/staging/zram/zram_sysfs.c | 4 +- 450 files changed, 74422 insertions(+), 47731 deletions(-) create mode 100644 trunk/drivers/char/scc.h create mode 100644 trunk/drivers/staging/ath6kl/Kconfig create mode 100644 trunk/drivers/staging/ath6kl/Makefile create mode 100644 trunk/drivers/staging/ath6kl/TODO create mode 100644 trunk/drivers/staging/ath6kl/bmi/include/bmi_internal.h create mode 100644 trunk/drivers/staging/ath6kl/bmi/src/bmi.c create mode 100644 trunk/drivers/staging/ath6kl/hif/common/hif_sdio_common.h create mode 100644 trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h create mode 100644 trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c create mode 100644 trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.h create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_debug.h create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_internal.h create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_recv.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_send.c create mode 100644 trunk/drivers/staging/ath6kl/htc2/htc_services.c create mode 100644 trunk/drivers/staging/ath6kl/include/a_config.h create mode 100644 trunk/drivers/staging/ath6kl/include/a_debug.h create mode 100644 trunk/drivers/staging/ath6kl/include/a_drv.h create mode 100644 trunk/drivers/staging/ath6kl/include/a_drv_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/a_osapi.h create mode 100644 trunk/drivers/staging/ath6kl/include/aggr_recv_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/ar3kconfig.h create mode 100644 trunk/drivers/staging/ath6kl/include/ar6000_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/ar6000_diag.h create mode 100644 trunk/drivers/staging/ath6kl/include/ar6kap_common.h create mode 100644 trunk/drivers/staging/ath6kl/include/athbtfilter.h create mode 100644 trunk/drivers/staging/ath6kl/include/bmi.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/addrs.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/athdefs.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/bmi_msg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/cnxmgmt.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/dbglog.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/dbglog_id.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/discovery.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/epping_test.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/gmboxif.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/gpio_reg.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/htc.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/htc_services.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/pkt_log.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/roaming.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/targaddrs.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/testcmd.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/tlpm.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/wlan_defs.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/wmi.h create mode 100644 trunk/drivers/staging/ath6kl/include/common/wmix.h create mode 100644 trunk/drivers/staging/ath6kl/include/common_drv.h create mode 100644 trunk/drivers/staging/ath6kl/include/dbglog_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/dl_list.h create mode 100644 trunk/drivers/staging/ath6kl/include/dset_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/hci_transport_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/hif.h create mode 100644 trunk/drivers/staging/ath6kl/include/host_version.h create mode 100644 trunk/drivers/staging/ath6kl/include/htc_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/htc_packet.h create mode 100644 trunk/drivers/staging/ath6kl/include/wlan_api.h create mode 100644 trunk/drivers/staging/ath6kl/include/wmi_api.h create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kconfig.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/common_drv.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/credit_dist.c create mode 100644 trunk/drivers/staging/ath6kl/miscdrv/miscdrv.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/ar6000_drv.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/ar6000_pm.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/cfg80211.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/export_hci_transport.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/hci_bridge.c create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/cfg80211.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/config_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/debug_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/osapi_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/wlan_config.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h create mode 100644 trunk/drivers/staging/ath6kl/os/linux/netbuf.c create mode 100644 trunk/drivers/staging/ath6kl/reorder/aggr_rx_internal.h create mode 100644 trunk/drivers/staging/ath6kl/reorder/rcv_aggr.c create mode 100644 trunk/drivers/staging/ath6kl/wlan/include/ieee80211.h create mode 100644 trunk/drivers/staging/ath6kl/wlan/include/ieee80211_node.h create mode 100644 trunk/drivers/staging/ath6kl/wlan/src/wlan_node.c create mode 100644 trunk/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c create mode 100644 trunk/drivers/staging/ath6kl/wlan/src/wlan_utils.c create mode 100644 trunk/drivers/staging/ath6kl/wmi/wmi.c create mode 100644 trunk/drivers/staging/ath6kl/wmi/wmi_host.h create mode 100644 trunk/drivers/staging/brcm80211/brcmsmac/bmac.c create mode 100644 trunk/drivers/staging/brcm80211/brcmsmac/bmac.h delete mode 100644 trunk/drivers/staging/comedi/drivers/usbduxsigma.c delete mode 100644 trunk/drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a delete mode 100644 trunk/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933 create mode 100644 trunk/drivers/staging/iio/accel/accel.h create mode 100644 trunk/drivers/staging/iio/accel/inclinometer.h delete mode 100644 trunk/drivers/staging/iio/adc/ad7192.c delete mode 100644 trunk/drivers/staging/iio/adc/ad7192.h delete mode 100644 trunk/drivers/staging/iio/adc/ad7280a.c delete mode 100644 trunk/drivers/staging/iio/adc/ad7280a.h create mode 100644 trunk/drivers/staging/iio/adc/adc.h create mode 100644 trunk/drivers/staging/iio/gyro/gyro.h delete mode 100644 trunk/drivers/staging/iio/iio_core.h delete mode 100644 trunk/drivers/staging/iio/iio_core_trigger.h delete mode 100644 trunk/drivers/staging/iio/impedance-analyzer/Kconfig delete mode 100644 trunk/drivers/staging/iio/impedance-analyzer/Makefile delete mode 100644 trunk/drivers/staging/iio/impedance-analyzer/ad5933.c delete mode 100644 trunk/drivers/staging/iio/impedance-analyzer/ad5933.h create mode 100644 trunk/drivers/staging/iio/magnetometer/magnet.h delete mode 100644 trunk/drivers/staging/rts5139/Kconfig delete mode 100644 trunk/drivers/staging/rts5139/Makefile delete mode 100644 trunk/drivers/staging/rts5139/TODO delete mode 100644 trunk/drivers/staging/rts5139/debug.h delete mode 100644 trunk/drivers/staging/rts5139/ms.c delete mode 100644 trunk/drivers/staging/rts5139/ms.h delete mode 100644 trunk/drivers/staging/rts5139/ms_mg.c delete mode 100644 trunk/drivers/staging/rts5139/ms_mg.h delete mode 100644 trunk/drivers/staging/rts5139/rts51x.c delete mode 100644 trunk/drivers/staging/rts5139/rts51x.h delete mode 100644 trunk/drivers/staging/rts5139/rts51x_card.c delete mode 100644 trunk/drivers/staging/rts5139/rts51x_card.h delete mode 100644 trunk/drivers/staging/rts5139/rts51x_chip.c delete mode 100644 trunk/drivers/staging/rts5139/rts51x_chip.h delete mode 100644 trunk/drivers/staging/rts5139/rts51x_fop.c delete mode 100644 trunk/drivers/staging/rts5139/rts51x_fop.h delete mode 100644 trunk/drivers/staging/rts5139/rts51x_scsi.c delete mode 100644 trunk/drivers/staging/rts5139/rts51x_scsi.h delete mode 100644 trunk/drivers/staging/rts5139/rts51x_sys.h delete mode 100644 trunk/drivers/staging/rts5139/rts51x_transport.c delete mode 100644 trunk/drivers/staging/rts5139/rts51x_transport.h delete mode 100644 trunk/drivers/staging/rts5139/sd.c delete mode 100644 trunk/drivers/staging/rts5139/sd.h delete mode 100644 trunk/drivers/staging/rts5139/sd_cprm.c delete mode 100644 trunk/drivers/staging/rts5139/sd_cprm.h delete mode 100644 trunk/drivers/staging/rts5139/trace.h delete mode 100644 trunk/drivers/staging/rts5139/xd.c delete mode 100644 trunk/drivers/staging/rts5139/xd.h delete mode 100644 trunk/drivers/staging/usbip/usbip_protocol.txt diff --git a/[refs] b/[refs] index b432fec494e9..ac1397c52b10 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 1ec3ba93c5fad9dca0dab272491c625fe6a2f67d +refs/heads/master: 0157d2e55c04a6fc7b69e4f9f0daed48c3597415 diff --git a/trunk/drivers/char/scc.h b/trunk/drivers/char/scc.h new file mode 100644 index 000000000000..341b1142bea8 --- /dev/null +++ b/trunk/drivers/char/scc.h @@ -0,0 +1,613 @@ +/* + * atari_SCC.h: Definitions for the Am8530 Serial Communications Controller + * + * Copyright 1994 Roman Hodek + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + */ + + +#ifndef _SCC_H +#define _SCC_H + +#include + +/* Special configuration ioctls for the Atari SCC5380 Serial + * Communications Controller + */ + +/* ioctl command codes */ + +#define TIOCGATSCC 0x54c0 /* get SCC configuration */ +#define TIOCSATSCC 0x54c1 /* set SCC configuration */ +#define TIOCDATSCC 0x54c2 /* reset configuration to defaults */ + +/* Clock sources */ + +#define CLK_RTxC 0 +#define CLK_TRxC 1 +#define CLK_PCLK 2 + +/* baud_bases for the common clocks in the Atari. These are the real + * frequencies divided by 16. + */ + +#define SCC_BAUD_BASE_TIMC 19200 /* 0.3072 MHz from TT-MFP, Timer C */ +#define SCC_BAUD_BASE_BCLK 153600 /* 2.4576 MHz */ +#define SCC_BAUD_BASE_PCLK4 229500 /* 3.6720 MHz */ +#define SCC_BAUD_BASE_PCLK 503374 /* 8.0539763 MHz */ +#define SCC_BAUD_BASE_NONE 0 /* for not connected or unused + * clock sources */ + +/* The SCC clock configuration structure */ + +struct scc_clock_config { + unsigned RTxC_base; /* base_baud of RTxC */ + unsigned TRxC_base; /* base_baud of TRxC */ + unsigned PCLK_base; /* base_baud of PCLK, both channels! */ + struct { + unsigned clksrc; /* CLK_RTxC, CLK_TRxC or CLK_PCLK */ + unsigned divisor; /* divisor for base baud, valid values: + * see below */ + } baud_table[17]; /* For 50, 75, 110, 135, 150, 200, 300, + * 600, 1200, 1800, 2400, 4800, 9600, + * 19200, 38400, 57600 and 115200 bps. + * The last two could be replaced by + * other rates > 38400 if they're not + * possible. + */ +}; + +/* The following divisors are valid: + * + * - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use + * the BRG) + * + * - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible) + * + * - CLK_PCLK: >= 4 and even (no direct modes, only BRG) + * + */ + +struct scc_port { + struct gs_port gs; + volatile unsigned char *ctrlp; + volatile unsigned char *datap; + int x_char; /* xon/xoff character */ + int c_dcd; + int channel; + struct scc_port *port_a; /* Reference to port A and B */ + struct scc_port *port_b; /* structs for reg access */ +}; + +#define SCC_MAGIC 0x52696368 + +/***********************************************************************/ +/* */ +/* Register Names */ +/* */ +/***********************************************************************/ + +/* The SCC documentation gives no explicit names to the registers, + * they're just called WR0..15 and RR0..15. To make the source code + * better readable and make the transparent write reg read access (see + * below) possible, I christen them here with self-invented names. + * Note that (real) read registers are assigned numbers 16..31. WR7' + * has number 33. + */ + +#define COMMAND_REG 0 /* wo */ +#define INT_AND_DMA_REG 1 /* wo */ +#define INT_VECTOR_REG 2 /* rw, common to both channels */ +#define RX_CTRL_REG 3 /* rw */ +#define AUX1_CTRL_REG 4 /* rw */ +#define TX_CTRL_REG 5 /* rw */ +#define SYNC_ADR_REG 6 /* wo */ +#define SYNC_CHAR_REG 7 /* wo */ +#define SDLC_OPTION_REG 33 /* wo */ +#define TX_DATA_REG 8 /* wo */ +#define MASTER_INT_CTRL 9 /* wo, common to both channels */ +#define AUX2_CTRL_REG 10 /* rw */ +#define CLK_CTRL_REG 11 /* wo */ +#define TIMER_LOW_REG 12 /* rw */ +#define TIMER_HIGH_REG 13 /* rw */ +#define DPLL_CTRL_REG 14 /* wo */ +#define INT_CTRL_REG 15 /* rw */ + +#define STATUS_REG 16 /* ro */ +#define SPCOND_STATUS_REG 17 /* wo */ +/* RR2 is WR2 for Channel A, Channel B gives vector + current status: */ +#define CURR_VECTOR_REG 18 /* Ch. B only, Ch. A for rw */ +#define INT_PENDING_REG 19 /* Channel A only! */ +/* RR4 is WR4, if b6(MR7') == 1 */ +/* RR5 is WR5, if b6(MR7') == 1 */ +#define FS_FIFO_LOW_REG 22 /* ro */ +#define FS_FIFO_HIGH_REG 23 /* ro */ +#define RX_DATA_REG 24 /* ro */ +/* RR9 is WR3, if b6(MR7') == 1 */ +#define DPLL_STATUS_REG 26 /* ro */ +/* RR11 is WR10, if b6(MR7') == 1 */ +/* RR12 is WR12 */ +/* RR13 is WR13 */ +/* RR14 not present */ +/* RR15 is WR15 */ + + +/***********************************************************************/ +/* */ +/* Register Values */ +/* */ +/***********************************************************************/ + + +/* WR0: COMMAND_REG "CR" */ + +#define CR_RX_CRC_RESET 0x40 +#define CR_TX_CRC_RESET 0x80 +#define CR_TX_UNDERRUN_RESET 0xc0 + +#define CR_EXTSTAT_RESET 0x10 +#define CR_SEND_ABORT 0x18 +#define CR_ENAB_INT_NEXT_RX 0x20 +#define CR_TX_PENDING_RESET 0x28 +#define CR_ERROR_RESET 0x30 +#define CR_HIGHEST_IUS_RESET 0x38 + + +/* WR1: INT_AND_DMA_REG "IDR" */ + +#define IDR_EXTSTAT_INT_ENAB 0x01 +#define IDR_TX_INT_ENAB 0x02 +#define IDR_PARERR_AS_SPCOND 0x04 + +#define IDR_RX_INT_DISAB 0x00 +#define IDR_RX_INT_FIRST 0x08 +#define IDR_RX_INT_ALL 0x10 +#define IDR_RX_INT_SPCOND 0x18 +#define IDR_RX_INT_MASK 0x18 + +#define IDR_WAITREQ_RX 0x20 +#define IDR_WAITREQ_IS_REQ 0x40 +#define IDR_WAITREQ_ENAB 0x80 + + +/* WR3: RX_CTRL_REG "RCR" */ + +#define RCR_RX_ENAB 0x01 +#define RCR_DISCARD_SYNC_CHARS 0x02 +#define RCR_ADDR_SEARCH 0x04 +#define RCR_CRC_ENAB 0x08 +#define RCR_SEARCH_MODE 0x10 +#define RCR_AUTO_ENAB_MODE 0x20 + +#define RCR_CHSIZE_MASK 0xc0 +#define RCR_CHSIZE_5 0x00 +#define RCR_CHSIZE_6 0x40 +#define RCR_CHSIZE_7 0x80 +#define RCR_CHSIZE_8 0xc0 + + +/* WR4: AUX1_CTRL_REG "A1CR" */ + +#define A1CR_PARITY_MASK 0x03 +#define A1CR_PARITY_NONE 0x00 +#define A1CR_PARITY_ODD 0x01 +#define A1CR_PARITY_EVEN 0x03 + +#define A1CR_MODE_MASK 0x0c +#define A1CR_MODE_SYNCR 0x00 +#define A1CR_MODE_ASYNC_1 0x04 +#define A1CR_MODE_ASYNC_15 0x08 +#define A1CR_MODE_ASYNC_2 0x0c + +#define A1CR_SYNCR_MODE_MASK 0x30 +#define A1CR_SYNCR_MONOSYNC 0x00 +#define A1CR_SYNCR_BISYNC 0x10 +#define A1CR_SYNCR_SDLC 0x20 +#define A1CR_SYNCR_EXTCSYNC 0x30 + +#define A1CR_CLKMODE_MASK 0xc0 +#define A1CR_CLKMODE_x1 0x00 +#define A1CR_CLKMODE_x16 0x40 +#define A1CR_CLKMODE_x32 0x80 +#define A1CR_CLKMODE_x64 0xc0 + + +/* WR5: TX_CTRL_REG "TCR" */ + +#define TCR_TX_CRC_ENAB 0x01 +#define TCR_RTS 0x02 +#define TCR_USE_CRC_CCITT 0x00 +#define TCR_USE_CRC_16 0x04 +#define TCR_TX_ENAB 0x08 +#define TCR_SEND_BREAK 0x10 + +#define TCR_CHSIZE_MASK 0x60 +#define TCR_CHSIZE_5 0x00 +#define TCR_CHSIZE_6 0x20 +#define TCR_CHSIZE_7 0x40 +#define TCR_CHSIZE_8 0x60 + +#define TCR_DTR 0x80 + + +/* WR7': SLDC_OPTION_REG "SOR" */ + +#define SOR_AUTO_TX_ENAB 0x01 +#define SOR_AUTO_EOM_RESET 0x02 +#define SOR_AUTO_RTS_MODE 0x04 +#define SOR_NRZI_DISAB_HIGH 0x08 +#define SOR_ALT_DTRREQ_TIMING 0x10 +#define SOR_READ_CRC_CHARS 0x20 +#define SOR_EXTENDED_REG_ACCESS 0x40 + + +/* WR9: MASTER_INT_CTRL "MIC" */ + +#define MIC_VEC_INCL_STAT 0x01 +#define MIC_NO_VECTOR 0x02 +#define MIC_DISAB_LOWER_CHAIN 0x04 +#define MIC_MASTER_INT_ENAB 0x08 +#define MIC_STATUS_HIGH 0x10 +#define MIC_IGN_INTACK 0x20 + +#define MIC_NO_RESET 0x00 +#define MIC_CH_A_RESET 0x40 +#define MIC_CH_B_RESET 0x80 +#define MIC_HARD_RESET 0xc0 + + +/* WR10: AUX2_CTRL_REG "A2CR" */ + +#define A2CR_SYNC_6 0x01 +#define A2CR_LOOP_MODE 0x02 +#define A2CR_ABORT_ON_UNDERRUN 0x04 +#define A2CR_MARK_IDLE 0x08 +#define A2CR_GO_ACTIVE_ON_POLL 0x10 + +#define A2CR_CODING_MASK 0x60 +#define A2CR_CODING_NRZ 0x00 +#define A2CR_CODING_NRZI 0x20 +#define A2CR_CODING_FM1 0x40 +#define A2CR_CODING_FM0 0x60 + +#define A2CR_PRESET_CRC_1 0x80 + + +/* WR11: CLK_CTRL_REG "CCR" */ + +#define CCR_TRxCOUT_MASK 0x03 +#define CCR_TRxCOUT_XTAL 0x00 +#define CCR_TRxCOUT_TXCLK 0x01 +#define CCR_TRxCOUT_BRG 0x02 +#define CCR_TRxCOUT_DPLL 0x03 + +#define CCR_TRxC_OUTPUT 0x04 + +#define CCR_TXCLK_MASK 0x18 +#define CCR_TXCLK_RTxC 0x00 +#define CCR_TXCLK_TRxC 0x08 +#define CCR_TXCLK_BRG 0x10 +#define CCR_TXCLK_DPLL 0x18 + +#define CCR_RXCLK_MASK 0x60 +#define CCR_RXCLK_RTxC 0x00 +#define CCR_RXCLK_TRxC 0x20 +#define CCR_RXCLK_BRG 0x40 +#define CCR_RXCLK_DPLL 0x60 + +#define CCR_RTxC_XTAL 0x80 + + +/* WR14: DPLL_CTRL_REG "DCR" */ + +#define DCR_BRG_ENAB 0x01 +#define DCR_BRG_USE_PCLK 0x02 +#define DCR_DTRREQ_IS_REQ 0x04 +#define DCR_AUTO_ECHO 0x08 +#define DCR_LOCAL_LOOPBACK 0x10 + +#define DCR_DPLL_EDGE_SEARCH 0x20 +#define DCR_DPLL_ERR_RESET 0x40 +#define DCR_DPLL_DISAB 0x60 +#define DCR_DPLL_CLK_BRG 0x80 +#define DCR_DPLL_CLK_RTxC 0xa0 +#define DCR_DPLL_FM 0xc0 +#define DCR_DPLL_NRZI 0xe0 + + +/* WR15: INT_CTRL_REG "ICR" */ + +#define ICR_OPTIONREG_SELECT 0x01 +#define ICR_ENAB_BRG_ZERO_INT 0x02 +#define ICR_USE_FS_FIFO 0x04 +#define ICR_ENAB_DCD_INT 0x08 +#define ICR_ENAB_SYNC_INT 0x10 +#define ICR_ENAB_CTS_INT 0x20 +#define ICR_ENAB_UNDERRUN_INT 0x40 +#define ICR_ENAB_BREAK_INT 0x80 + + +/* RR0: STATUS_REG "SR" */ + +#define SR_CHAR_AVAIL 0x01 +#define SR_BRG_ZERO 0x02 +#define SR_TX_BUF_EMPTY 0x04 +#define SR_DCD 0x08 +#define SR_SYNC_ABORT 0x10 +#define SR_CTS 0x20 +#define SR_TX_UNDERRUN 0x40 +#define SR_BREAK 0x80 + + +/* RR1: SPCOND_STATUS_REG "SCSR" */ + +#define SCSR_ALL_SENT 0x01 +#define SCSR_RESIDUAL_MASK 0x0e +#define SCSR_PARITY_ERR 0x10 +#define SCSR_RX_OVERRUN 0x20 +#define SCSR_CRC_FRAME_ERR 0x40 +#define SCSR_END_OF_FRAME 0x80 + + +/* RR3: INT_PENDING_REG "IPR" */ + +#define IPR_B_EXTSTAT 0x01 +#define IPR_B_TX 0x02 +#define IPR_B_RX 0x04 +#define IPR_A_EXTSTAT 0x08 +#define IPR_A_TX 0x10 +#define IPR_A_RX 0x20 + + +/* RR7: FS_FIFO_HIGH_REG "FFHR" */ + +#define FFHR_CNT_MASK 0x3f +#define FFHR_IS_FROM_FIFO 0x40 +#define FFHR_FIFO_OVERRUN 0x80 + + +/* RR10: DPLL_STATUS_REG "DSR" */ + +#define DSR_ON_LOOP 0x02 +#define DSR_ON_LOOP_SENDING 0x10 +#define DSR_TWO_CLK_MISSING 0x40 +#define DSR_ONE_CLK_MISSING 0x80 + +/***********************************************************************/ +/* */ +/* Register Access */ +/* */ +/***********************************************************************/ + + +/* The SCC needs 3.5 PCLK cycles recovery time between to register + * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 * + * 125 ns = 437.5 ns. This is too short for udelay(). + * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be + * quite right + */ + +#define scc_reg_delay() \ + do { \ + if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) \ + __asm__ __volatile__ ( " nop; nop"); \ + else if (MACH_IS_ATARI) \ + __asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\ + } while (0) + +static unsigned char scc_shadow[2][16]; + +/* The following functions should relax the somehow complicated + * register access of the SCC. _SCCwrite() stores all written values + * (except for WR0 and WR8) in shadow registers for later recall. This + * removes the burden of remembering written values as needed. The + * extra work of storing the value doesn't count, since a delay is + * needed after a SCC access anyway. Additionally, _SCCwrite() manages + * writes to WR0 and WR8 differently, because these can be accessed + * directly with less overhead. Another special case are WR7 and WR7'. + * _SCCwrite automatically checks what of this registers is selected + * and changes b0 of WR15 if needed. + * + * _SCCread() for standard read registers is straightforward, except + * for RR2 (split into two "virtual" registers: one for the value + * written to WR2 (from the shadow) and one for the vector including + * status from RR2, Ch. B) and RR3. The latter must be read from + * Channel A, because it reads as all zeros on Ch. B. RR0 and RR8 can + * be accessed directly as before. + * + * The two inline function contain complicated switch statements. But + * I rely on regno and final_delay being constants, so gcc can reduce + * the whole stuff to just some assembler statements. + * + * _SCCwrite and _SCCread aren't intended to be used directly under + * normal circumstances. The macros SCCread[_ND] and SCCwrite[_ND] are + * for that purpose. They assume that a local variable 'port' is + * declared and pointing to the port's scc_struct entry. The + * variants with "_NB" appended should be used if no other SCC + * accesses follow immediately (within 0.5 usecs). They just skip the + * final delay nops. + * + * Please note that accesses to SCC registers should only take place + * when interrupts are turned off (at least if SCC interrupts are + * enabled). Otherwise, an interrupt could interfere with the + * two-stage accessing process. + * + */ + + +static __inline__ void _SCCwrite( + struct scc_port *port, + unsigned char *shadow, + volatile unsigned char *_scc_del, + int regno, + unsigned char val, int final_delay ) +{ + switch( regno ) { + + case COMMAND_REG: + /* WR0 can be written directly without pointing */ + *port->ctrlp = val; + break; + + case SYNC_CHAR_REG: + /* For WR7, first set b0 of WR15 to 0, if needed */ + if (shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT) { + *port->ctrlp = 15; + shadow[INT_CTRL_REG] &= ~ICR_OPTIONREG_SELECT; + scc_reg_delay(); + *port->ctrlp = shadow[INT_CTRL_REG]; + scc_reg_delay(); + } + goto normal_case; + + case SDLC_OPTION_REG: + /* For WR7', first set b0 of WR15 to 1, if needed */ + if (!(shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT)) { + *port->ctrlp = 15; + shadow[INT_CTRL_REG] |= ICR_OPTIONREG_SELECT; + scc_reg_delay(); + *port->ctrlp = shadow[INT_CTRL_REG]; + scc_reg_delay(); + } + *port->ctrlp = 7; + shadow[8] = val; /* WR7' shadowed at WR8 */ + scc_reg_delay(); + *port->ctrlp = val; + break; + + case TX_DATA_REG: /* WR8 */ + /* TX_DATA_REG can be accessed directly on some h/w */ + if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) + { + *port->ctrlp = regno; + scc_reg_delay(); + *port->ctrlp = val; + } + else + *port->datap = val; + break; + + case MASTER_INT_CTRL: + *port->ctrlp = regno; + val &= 0x3f; /* bits 6..7 are the reset commands */ + scc_shadow[0][regno] = val; + scc_reg_delay(); + *port->ctrlp = val; + break; + + case DPLL_CTRL_REG: + *port->ctrlp = regno; + val &= 0x1f; /* bits 5..7 are the DPLL commands */ + shadow[regno] = val; + scc_reg_delay(); + *port->ctrlp = val; + break; + + case 1 ... 6: + case 10 ... 13: + case 15: + normal_case: + *port->ctrlp = regno; + shadow[regno] = val; + scc_reg_delay(); + *port->ctrlp = val; + break; + + default: + printk( "Bad SCC write access to WR%d\n", regno ); + break; + + } + + if (final_delay) + scc_reg_delay(); +} + + +static __inline__ unsigned char _SCCread( + struct scc_port *port, + unsigned char *shadow, + volatile unsigned char *_scc_del, + int regno, int final_delay ) +{ + unsigned char rv; + + switch( regno ) { + + /* --- real read registers --- */ + case STATUS_REG: + rv = *port->ctrlp; + break; + + case INT_PENDING_REG: + /* RR3: read only from Channel A! */ + port = port->port_a; + goto normal_case; + + case RX_DATA_REG: + /* RR8 can be accessed directly on some h/w */ + if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) + { + *port->ctrlp = 8; + scc_reg_delay(); + rv = *port->ctrlp; + } + else + rv = *port->datap; + break; + + case CURR_VECTOR_REG: + /* RR2 (vector including status) from Ch. B */ + port = port->port_b; + goto normal_case; + + /* --- reading write registers: access the shadow --- */ + case 1 ... 7: + case 10 ... 15: + return shadow[regno]; /* no final delay! */ + + /* WR7' is special, because it is shadowed at the place of WR8 */ + case SDLC_OPTION_REG: + return shadow[8]; /* no final delay! */ + + /* WR9 is special too, because it is common for both channels */ + case MASTER_INT_CTRL: + return scc_shadow[0][9]; /* no final delay! */ + + default: + printk( "Bad SCC read access to %cR%d\n", (regno & 16) ? 'R' : 'W', + regno & ~16 ); + break; + + case SPCOND_STATUS_REG: + case FS_FIFO_LOW_REG: + case FS_FIFO_HIGH_REG: + case DPLL_STATUS_REG: + normal_case: + *port->ctrlp = regno & 0x0f; + scc_reg_delay(); + rv = *port->ctrlp; + break; + + } + + if (final_delay) + scc_reg_delay(); + return rv; +} + +#define SCC_ACCESS_INIT(port) \ + unsigned char *_scc_shadow = &scc_shadow[port->channel][0] + +#define SCCwrite(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),1) +#define SCCwrite_NB(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),0) +#define SCCread(reg) _SCCread(port,_scc_shadow,scc_del,(reg),1) +#define SCCread_NB(reg) _SCCread(port,_scc_shadow,scc_del,(reg),0) + +#define SCCmod(reg,and,or) SCCwrite((reg),(SCCread(reg)&(and))|(or)) + +#endif /* _SCC_H */ diff --git a/trunk/drivers/staging/Kconfig b/trunk/drivers/staging/Kconfig index eac0a7fd8ef6..06c9081d596d 100644 --- a/trunk/drivers/staging/Kconfig +++ b/trunk/drivers/staging/Kconfig @@ -64,8 +64,6 @@ source "drivers/staging/rtl8712/Kconfig" source "drivers/staging/rts_pstor/Kconfig" -source "drivers/staging/rts5139/Kconfig" - source "drivers/staging/frontier/Kconfig" source "drivers/staging/pohmelfs/Kconfig" @@ -128,6 +126,8 @@ source "drivers/staging/quickstart/Kconfig" source "drivers/staging/sbe-2t3e3/Kconfig" +source "drivers/staging/ath6kl/Kconfig" + source "drivers/staging/keucr/Kconfig" source "drivers/staging/bcm/Kconfig" diff --git a/trunk/drivers/staging/Makefile b/trunk/drivers/staging/Makefile index 20be11294242..f3c5e33bb263 100644 --- a/trunk/drivers/staging/Makefile +++ b/trunk/drivers/staging/Makefile @@ -25,7 +25,6 @@ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ obj-$(CONFIG_RTS_PSTOR) += rts_pstor/ -obj-$(CONFIG_RTS5139) += rts5139/ obj-$(CONFIG_SPECTRA) += spectra/ obj-$(CONFIG_TRANZPORT) += frontier/ obj-$(CONFIG_POHMELFS) += pohmelfs/ @@ -55,6 +54,7 @@ obj-$(CONFIG_SOLO6X10) += solo6x10/ obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/ obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/ obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/ +obj-$(CONFIG_ATH6K_LEGACY) += ath6kl/ obj-$(CONFIG_USB_ENESTORAGE) += keucr/ obj-$(CONFIG_BCM_WIMAX) += bcm/ obj-$(CONFIG_FT1000) += ft1000/ diff --git a/trunk/drivers/staging/altera-stapl/altera.c b/trunk/drivers/staging/altera-stapl/altera.c index be777a4945ca..8d73a8642736 100644 --- a/trunk/drivers/staging/altera-stapl/altera.c +++ b/trunk/drivers/staging/altera-stapl/altera.c @@ -2384,7 +2384,7 @@ static int altera_get_act_info(u8 *p, act_proc_attribute = (p[proc_table + (13 * act_proc_id) + 8] & 0x03); - procptr = + procptr = (struct altera_procinfo *) kzalloc(sizeof(struct altera_procinfo), GFP_KERNEL); diff --git a/trunk/drivers/staging/ath6kl/Kconfig b/trunk/drivers/staging/ath6kl/Kconfig new file mode 100644 index 000000000000..afd6cc16a2b8 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/Kconfig @@ -0,0 +1,158 @@ +config ATH6K_LEGACY + tristate "Atheros AR6003 support (non mac80211)" + depends on MMC && WLAN + depends on CFG80211 + select WIRELESS_EXT + select WEXT_PRIV + help + This module adds support for wireless adapters based on Atheros AR6003 chipset running over SDIO. If you choose to build it as a module, it will be called ath6kl. Pls note that AR6002 and AR6001 are not supported by this driver. + +choice + prompt "AR6003 Board Data Configuration" + depends on ATH6K_LEGACY + default AR600x_SD31_XXX + help + Select the appropriate board data template from the list below that matches your AR6003 based reference design. + +config AR600x_SD31_XXX + bool "SD31-xxx" + help + Board Data file for a standard SD31 reference design (File: bdata.SD31.bin) + +config AR600x_WB31_XXX + bool "WB31-xxx" + help + Board Data file for a standard WB31 (BT/WiFi) reference design (File: bdata.WB31.bin) + +config AR600x_SD32_XXX + bool "SD32-xxx" + help + Board Data file for a standard SD32 (5GHz) reference design (File: bdata.SD32.bin) + +config AR600x_CUSTOM_XXX + bool "CUSTOM-xxx" + help + Board Data file for a custom reference design (File: should be named as bdata.CUSTOM.bin) +endchoice + +config ATH6KL_ENABLE_COEXISTENCE + bool "BT Coexistence support" + depends on ATH6K_LEGACY + help + Enables WLAN/BT coexistence support. Select the apprpriate configuration from below. + +choice + prompt "Front-End Antenna Configuration" + depends on ATH6KL_ENABLE_COEXISTENCE + default AR600x_DUAL_ANTENNA + help + Indicates the number of antennas being used by BT and WLAN. Select the appropriate configuration from the list below that matches your AR6003 based reference design. + +config AR600x_DUAL_ANTENNA + bool "Dual Antenna" + help + Dual Antenna Design + +config AR600x_SINGLE_ANTENNA + bool "Single Antenna" + help + Single Antenna Design +endchoice + +choice + prompt "Collocated Bluetooth Type" + depends on ATH6KL_ENABLE_COEXISTENCE + default AR600x_BT_AR3001 + help + Select the appropriate configuration from the list below that matches your AR6003 based reference design. + +config AR600x_BT_QCOM + bool "Qualcomm BTS4020X" + help + Qualcomm BT (3 Wire PTA) + +config AR600x_BT_CSR + bool "CSR BC06" + help + CSR BT (3 Wire PTA) + +config AR600x_BT_AR3001 + bool "Atheros AR3001" + help + Atheros BT (3 Wire PTA) +endchoice + +config ATH6KL_HCI_BRIDGE + bool "HCI over SDIO support" + depends on ATH6K_LEGACY + help + Enables BT over SDIO. Applicable only for combo designs (eg: WB31) + +config ATH6KL_CONFIG_GPIO_BT_RESET + bool "Configure BT Reset GPIO" + depends on ATH6KL_HCI_BRIDGE + help + Configure a WLAN GPIO for use with BT. + +config AR600x_BT_RESET_PIN + int "GPIO" + depends on ATH6KL_CONFIG_GPIO_BT_RESET + default 22 + help + WLAN GPIO to be used for resetting BT + +config ATH6KL_HTC_RAW_INTERFACE + bool "RAW HTC support" + depends on ATH6K_LEGACY + help + Enables raw HTC interface. Allows application to directly talk to the HTC interface via the ioctl interface + +config ATH6KL_VIRTUAL_SCATTER_GATHER + bool "Virtual Scatter-Gather support" + depends on ATH6K_LEGACY + help + Enables virtual scatter gather support for the hardware that does not support it natively. + +config ATH6KL_SKIP_ABI_VERSION_CHECK + bool "Skip ABI version check support" + depends on ATH6K_LEGACY + help + Forces the driver to disable ABI version check. Caution: Incompatilbity between the host driver and target firmware may lead to unknown side effects. + +config ATH6KL_BT_UART_FC_POLARITY + int "UART Flow Control Polarity" + depends on ATH6KL_LEGACY + default 0 + help + Configures the polarity of UART Flow Control. A value of 0 implies active low and is the default setting. Set it to 1 for active high. + +config ATH6KL_DEBUG + bool "Debug support" + depends on ATH6K_LEGACY + help + Enables debug support + +config ATH6KL_ENABLE_HOST_DEBUG + bool "Host Debug support" + depends on ATH6KL_DEBUG + help + Enables debug support in the driver + +config ATH6KL_ENABLE_TARGET_DEBUG_PRINTS + bool "Target Debug support - Enable UART prints" + depends on ATH6KL_DEBUG + help + Enables uart prints + +config AR600x_DEBUG_UART_TX_PIN + int "GPIO" + depends on ATH6KL_ENABLE_TARGET_DEBUG_PRINTS + default 8 + help + WLAN GPIO to be used for Debug UART (Tx) + +config ATH6KL_DISABLE_TARGET_DBGLOGS + bool "Target Debug support - Disable Debug logs" + depends on ATH6KL_DEBUG + help + Enables debug logs diff --git a/trunk/drivers/staging/ath6kl/Makefile b/trunk/drivers/staging/ath6kl/Makefile new file mode 100644 index 000000000000..1d3f2390a172 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/Makefile @@ -0,0 +1,122 @@ +#------------------------------------------------------------------------------ +# Copyright (c) 2004-2010 Atheros Communications Inc. +# All rights reserved. +# +# +# +# Permission to use, copy, modify, and/or 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. +# +# +# +# Author(s): ="Atheros" +#------------------------------------------------------------------------------ + +ccflags-y += -I$(obj)/include +ccflags-y += -I$(obj)/include/common +ccflags-y += -I$(obj)/wlan/include +ccflags-y += -I$(obj)/os/linux/include +ccflags-y += -I$(obj)/os +ccflags-y += -I$(obj)/bmi/include +ccflags-y += -I$(obj)/include/common/AR6002/hw4.0 + +ifeq ($(CONFIG_AR600x_DUAL_ANTENNA),y) +ccflags-y += -DAR600x_DUAL_ANTENNA +endif + +ifeq ($(CONFIG_AR600x_SINGLE_ANTENNA),y) +ccflags-y += -DAR600x_SINGLE_ANTENNA +endif + +ifeq ($(CONFIG_AR600x_BT_QCOM),y) +ccflags-y += -DAR600x_BT_QCOM +endif + +ifeq ($(CONFIG_AR600x_BT_CSR),y) +ccflags-y += -DAR600x_BT_CSR +endif + +ifeq ($(CONFIG_AR600x_BT_AR3001),y) +ccflags-y += -DAR600x_BT_AR3001 +endif + +ifeq ($(CONFIG_ATH6KL_HCI_BRIDGE),y) +ccflags-y += -DATH_AR6K_ENABLE_GMBOX +ccflags-y += -DHCI_TRANSPORT_SDIO +ccflags-y += -DSETUPHCI_ENABLED +ccflags-y += -DSETUPBTDEV_ENABLED +ath6kl-y += htc2/AR6000/ar6k_gmbox.o +ath6kl-y += htc2/AR6000/ar6k_gmbox_hciuart.o +ath6kl-y += miscdrv/ar3kconfig.o +ath6kl-y += miscdrv/ar3kps/ar3kpsconfig.o +ath6kl-y += miscdrv/ar3kps/ar3kpsparser.o +endif + +ifeq ($(CONFIG_ATH6KL_CONFIG_GPIO_BT_RESET),y) +ccflags-y += -DATH6KL_CONFIG_GPIO_BT_RESET +endif + +ifeq ($(CONFIG_ATH6KL_HTC_RAW_INTERFACE),y) +ccflags-y += -DHTC_RAW_INTERFACE +endif + +ifeq ($(CONFIG_ATH6KL_ENABLE_HOST_DEBUG),y) +ccflags-y += -DDEBUG +ccflags-y += -DATH_DEBUG_MODULE +endif + +ifeq ($(CONFIG_ATH6KL_ENABLE_TARGET_DEBUG_PRINTS),y) +ccflags-y += -DENABLEUARTPRINT_SET +endif + +ifeq ($(CONFIG_ATH6KL_DISABLE_TARGET_DBGLOGS),y) +ccflags-y += -DATH6KL_DISABLE_TARGET_DBGLOGS +endif + +ifeq ($(CONFIG_ATH6KL_VIRTUAL_SCATTER_GATHER),y) +ccflags-y += -DATH6KL_CONFIG_HIF_VIRTUAL_SCATTER +endif + +ifeq ($(CONFIG_ATH6KL_SKIP_ABI_VERSION_CHECK),y) +ccflags-y += -DATH6KL_SKIP_ABI_VERSION_CHECK +endif + +ccflags-y += -DWAPI_ENABLE +ccflags-y += -DCHECKSUM_OFFLOAD + +obj-$(CONFIG_ATH6K_LEGACY) := ath6kl.o +ath6kl-y += htc2/AR6000/ar6k.o +ath6kl-y += htc2/AR6000/ar6k_events.o +ath6kl-y += htc2/htc_send.o +ath6kl-y += htc2/htc_recv.o +ath6kl-y += htc2/htc_services.o +ath6kl-y += htc2/htc.o +ath6kl-y += bmi/src/bmi.o +ath6kl-y += os/linux/cfg80211.o +ath6kl-y += os/linux/ar6000_drv.o +ath6kl-y += os/linux/ar6000_raw_if.o +ath6kl-y += os/linux/ar6000_pm.o +ath6kl-y += os/linux/netbuf.o +ath6kl-y += os/linux/hci_bridge.o +ath6kl-y += miscdrv/common_drv.o +ath6kl-y += miscdrv/credit_dist.o +ath6kl-y += wmi/wmi.o +ath6kl-y += reorder/rcv_aggr.o +ath6kl-y += wlan/src/wlan_node.o +ath6kl-y += wlan/src/wlan_recv_beacon.o +ath6kl-y += wlan/src/wlan_utils.o + +# ATH_HIF_TYPE := sdio +ccflags-y += -I$(obj)/hif/sdio/linux_sdio/include +ccflags-y += -DSDIO +ath6kl-y += hif/sdio/linux_sdio/src/hif.o +ath6kl-y += hif/sdio/linux_sdio/src/hif_scatter.o diff --git a/trunk/drivers/staging/ath6kl/TODO b/trunk/drivers/staging/ath6kl/TODO new file mode 100644 index 000000000000..7be4b46ebb59 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/TODO @@ -0,0 +1,25 @@ +TODO: + +We are working hard on cleaning up the driver. There's sooooooooo much todo +so instead of editing this file please use the wiki: + +http://wireless.kernel.org/en/users/Drivers/ath6kl + +There's a respective TODO page there. Please also subscribe to the wiki page +to get e-mail updates on changes. + +IRC: + +We *really* need to coordinate development for ath6kl as the cleanup +patches will break pretty much any other patches. Please use IRC to +help coordinate better: + +irc.freenode.net +#ath6kl + +Send patches to: + + - Greg Kroah-Hartman + - Luis R. Rodriguez + - Joe Perches + - Naveen Singh diff --git a/trunk/drivers/staging/ath6kl/bmi/include/bmi_internal.h b/trunk/drivers/staging/ath6kl/bmi/include/bmi_internal.h new file mode 100644 index 000000000000..8e2577074d65 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/bmi/include/bmi_internal.h @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef BMI_INTERNAL_H +#define BMI_INTERNAL_H + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME bmi +#include "a_debug.h" +#include "hw/mbox_host_reg.h" +#include "bmi_msg.h" + +#define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0) + + +#define BMI_COMMUNICATION_TIMEOUT 100000 + +/* ------ Global Variable Declarations ------- */ +static bool bmiDone; + +int +bmiBufferSend(struct hif_device *device, + u8 *buffer, + u32 length); + +int +bmiBufferReceive(struct hif_device *device, + u8 *buffer, + u32 length, + bool want_timeout); + +#endif diff --git a/trunk/drivers/staging/ath6kl/bmi/src/bmi.c b/trunk/drivers/staging/ath6kl/bmi/src/bmi.c new file mode 100644 index 000000000000..f1f085eba9c8 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/bmi/src/bmi.c @@ -0,0 +1,1010 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// +// Author(s): ="Atheros" +//============================================================================== + + +#ifdef THREAD_X +#include +#endif + +#include "hif.h" +#include "bmi.h" +#include "htc_api.h" +#include "bmi_internal.h" + +#ifdef ATH_DEBUG_MODULE +static struct ath_debug_mask_description bmi_debug_desc[] = { + { ATH_DEBUG_BMI , "BMI Tracing"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi, + "bmi", + "Boot Manager Interface", + ATH_DEBUG_MASK_DEFAULTS, + ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc), + bmi_debug_desc); + +#endif + +/* +Although we had envisioned BMI to run on top of HTC, this is not how the +final implementation ended up. On the Target side, BMI is a part of the BSP +and does not use the HTC protocol nor even DMA -- it is intentionally kept +very simple. +*/ + +static bool pendingEventsFuncCheck = false; +static u32 *pBMICmdCredits; +static u8 *pBMICmdBuf; +#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \ + sizeof(u32) /* cmd */ + \ + sizeof(u32) /* addr */ + \ + sizeof(u32))/* length */ +#define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ) + +/* APIs visible to the driver */ +void +BMIInit(void) +{ + bmiDone = false; + pendingEventsFuncCheck = false; + + /* + * On some platforms, it's not possible to DMA to a static variable + * in a device driver (e.g. Linux loadable driver module). + * So we need to A_MALLOC space for "command credits" and for commands. + * + * Note: implicitly relies on A_MALLOC to provide a buffer that is + * suitable for DMA (or PIO). This buffer will be passed down the + * bus stack. + */ + if (!pBMICmdCredits) { + pBMICmdCredits = (u32 *)A_MALLOC_NOWAIT(4); + A_ASSERT(pBMICmdCredits); + } + + if (!pBMICmdBuf) { + pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ); + A_ASSERT(pBMICmdBuf); + } + + A_REGISTER_MODULE_DEBUG_INFO(bmi); +} + +void +BMICleanup(void) +{ + if (pBMICmdCredits) { + kfree(pBMICmdCredits); + pBMICmdCredits = NULL; + } + + if (pBMICmdBuf) { + kfree(pBMICmdBuf); + pBMICmdBuf = NULL; + } +} + +int +BMIDone(struct hif_device *device) +{ + int status; + u32 cid; + + if (bmiDone) { + AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n")); + return 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device)); + bmiDone = true; + cid = BMI_DONE; + + status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid)); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + if (pBMICmdCredits) { + kfree(pBMICmdCredits); + pBMICmdCredits = NULL; + } + + if (pBMICmdBuf) { + kfree(pBMICmdBuf); + pBMICmdBuf = NULL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n")); + + return 0; +} + +int +BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info) +{ + int status; + u32 cid; + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device)); + cid = BMI_GET_TARGET_INFO; + + status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid)); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver, + sizeof(targ_info->target_ver), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n")); + return A_ERROR; + } + + if (targ_info->target_ver == TARGET_VERSION_SENTINAL) { + /* Determine how many bytes are in the Target's targ_info */ + status = bmiBufferReceive(device, (u8 *)&targ_info->target_info_byte_count, + sizeof(targ_info->target_info_byte_count), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n")); + return A_ERROR; + } + + /* + * The Target's targ_info doesn't match the Host's targ_info. + * We need to do some backwards compatibility work to make this OK. + */ + A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info)); + + /* Read the remainder of the targ_info */ + status = bmiBufferReceive(device, + ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count), + sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n", + targ_info->target_info_byte_count)); + return A_ERROR; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n", + targ_info->target_ver, targ_info->target_type)); + + return 0; +} + +int +BMIReadMemory(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length) +{ + u32 cid; + int status; + u32 offset; + u32 remaining, rxlen; + + A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length))); + memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", + device, address, length)); + + cid = BMI_READ_MEMORY; + + remaining = length; + + while (remaining) + { + rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX; + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen)); + offset += sizeof(length); + + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + status = bmiBufferReceive(device, pBMICmdBuf, rxlen, true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + memcpy(&buffer[length - remaining], pBMICmdBuf, rxlen); + remaining -= rxlen; address += rxlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n")); + return 0; +} + +int +BMIWriteMemory(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length) +{ + u32 cid; + int status; + u32 offset; + u32 remaining, txlen; + const u32 header = sizeof(cid) + sizeof(address) + sizeof(length); + u8 alignedBuffer[BMI_DATASZ_MAX]; + u8 *src; + + A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); + memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", + device, address, length)); + + cid = BMI_WRITE_MEMORY; + + remaining = length; + while (remaining) + { + src = &buffer[length - remaining]; + if (remaining < (BMI_DATASZ_MAX - header)) { + if (remaining & 3) { + /* align it with 4 bytes */ + remaining = remaining + (4 - (remaining & 3)); + memcpy(alignedBuffer, src, remaining); + src = alignedBuffer; + } + txlen = remaining; + } else { + txlen = (BMI_DATASZ_MAX - header); + } + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + memcpy(&(pBMICmdBuf[offset]), src, txlen); + offset += txlen; + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + remaining -= txlen; address += txlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n")); + + return 0; +} + +int +BMIExecute(struct hif_device *device, + u32 address, + u32 *param) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n", + device, address, *param)); + + cid = BMI_EXECUTE; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param)); + offset += sizeof(*param); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), false); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + + memcpy(param, pBMICmdBuf, sizeof(*param)); + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param)); + return 0; +} + +int +BMISetAppStart(struct hif_device *device, + u32 address) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n", + device, address)); + + cid = BMI_SET_APP_START; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n")); + return 0; +} + +int +BMIReadSOCRegister(struct hif_device *device, + u32 address, + u32 *param) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n", + device, address)); + + cid = BMI_READ_SOC_REGISTER; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + memcpy(param, pBMICmdBuf, sizeof(*param)); + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param)); + return 0; +} + +int +BMIWriteSOCRegister(struct hif_device *device, + u32 address, + u32 param) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n", + device, address, param)); + + cid = BMI_WRITE_SOC_REGISTER; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + memcpy(&(pBMICmdBuf[offset]), ¶m, sizeof(param)); + offset += sizeof(param); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n")); + return 0; +} + +int +BMIrompatchInstall(struct hif_device *device, + u32 ROM_addr, + u32 RAM_addr, + u32 nbytes, + u32 do_activate, + u32 *rompatch_id) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) + + sizeof(nbytes) + sizeof(do_activate))); + memset(pBMICmdBuf, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) + + sizeof(nbytes) + sizeof(do_activate)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n", + device, ROM_addr, RAM_addr, nbytes, do_activate)); + + cid = BMI_ROMPATCH_INSTALL; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr)); + offset += sizeof(ROM_addr); + memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr)); + offset += sizeof(RAM_addr); + memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes)); + offset += sizeof(nbytes); + memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate)); + offset += sizeof(do_activate); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); + return A_ERROR; + } + memcpy(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id)); + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id)); + return 0; +} + +int +BMIrompatchUninstall(struct hif_device *device, + u32 rompatch_id) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n", + device, rompatch_id)); + + cid = BMI_ROMPATCH_UNINSTALL; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id)); + offset += sizeof(rompatch_id); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id)); + return 0; +} + +static int +_BMIrompatchChangeActivation(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list, + u32 do_activate) +{ + u32 cid; + int status; + u32 offset; + u32 length; + + A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count))); + memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n", + device, rompatch_count)); + + cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE; + + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count)); + offset += sizeof(rompatch_count); + length = rompatch_count * sizeof(*rompatch_list); + memcpy(&(pBMICmdBuf[offset]), rompatch_list, length); + offset += length; + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n")); + + return 0; +} + +int +BMIrompatchActivate(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list) +{ + return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1); +} + +int +BMIrompatchDeactivate(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list) +{ + return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0); +} + +int +BMILZData(struct hif_device *device, + u8 *buffer, + u32 length) +{ + u32 cid; + int status; + u32 offset; + u32 remaining, txlen; + const u32 header = sizeof(cid) + sizeof(length); + + A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header)); + memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n", + device, length)); + + cid = BMI_LZ_DATA; + + remaining = length; + while (remaining) + { + txlen = (remaining < (BMI_DATASZ_MAX - header)) ? + remaining : (BMI_DATASZ_MAX - header); + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen); + offset += txlen; + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); + return A_ERROR; + } + remaining -= txlen; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n")); + + return 0; +} + +int +BMILZStreamStart(struct hif_device *device, + u32 address) +{ + u32 cid; + int status; + u32 offset; + + A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); + + if (bmiDone) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, + ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n", + device, address)); + + cid = BMI_LZ_STREAM_START; + offset = 0; + memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); + offset += sizeof(address); + status = bmiBufferSend(device, pBMICmdBuf, offset); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n")); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n")); + + return 0; +} + +/* BMI Access routines */ +int +bmiBufferSend(struct hif_device *device, + u8 *buffer, + u32 length) +{ + int status; + u32 timeout; + u32 address; + u32 mboxAddress[HTC_MAILBOX_NUM_MAX]; + + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, + &mboxAddress[0], sizeof(mboxAddress)); + + *pBMICmdCredits = 0; + timeout = BMI_COMMUNICATION_TIMEOUT; + + while(timeout-- && !(*pBMICmdCredits)) { + /* Read the counter register to get the command credits */ + address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; + /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause + * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to + * make all HIF accesses 4-byte aligned */ + status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, 4, + HIF_RD_SYNC_BYTE_INC, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n")); + return A_ERROR; + } + /* the counter is only 8=bits, ignore anything in the upper 3 bytes */ + (*pBMICmdCredits) &= 0xFF; + } + + if (*pBMICmdCredits) { + address = mboxAddress[ENDPOINT1]; + status = HIFReadWrite(device, address, buffer, length, + HIF_WR_SYNC_BYTE_INC, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n")); + return A_ERROR; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n")); + return A_ERROR; + } + + return status; +} + +int +bmiBufferReceive(struct hif_device *device, + u8 *buffer, + u32 length, + bool want_timeout) +{ + int status; + u32 address; + u32 mboxAddress[HTC_MAILBOX_NUM_MAX]; + struct hif_pending_events_info hifPendingEvents; + static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL; + + if (!pendingEventsFuncCheck) { + /* see if the HIF layer implements an alternative function to get pending events + * do this only once! */ + HIFConfigureDevice(device, + HIF_DEVICE_GET_PENDING_EVENTS_FUNC, + &getPendingEventsFunc, + sizeof(getPendingEventsFunc)); + pendingEventsFuncCheck = true; + } + + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, + &mboxAddress[0], sizeof(mboxAddress)); + + /* + * During normal bootup, small reads may be required. + * Rather than issue an HIF Read and then wait as the Target + * adds successive bytes to the FIFO, we wait here until + * we know that response data is available. + * + * This allows us to cleanly timeout on an unexpected + * Target failure rather than risk problems at the HIF level. In + * particular, this avoids SDIO timeouts and possibly garbage + * data on some host controllers. And on an interconnect + * such as Compact Flash (as well as some SDIO masters) which + * does not provide any indication on data timeout, it avoids + * a potential hang or garbage response. + * + * Synchronization is more difficult for reads larger than the + * size of the MBOX FIFO (128B), because the Target is unable + * to push the 129th byte of data until AFTER the Host posts an + * HIF Read and removes some FIFO data. So for large reads the + * Host proceeds to post an HIF Read BEFORE all the data is + * actually available to read. Fortunately, large BMI reads do + * not occur in practice -- they're supported for debug/development. + * + * So Host/Target BMI synchronization is divided into these cases: + * CASE 1: length < 4 + * Should not happen + * + * CASE 2: 4 <= length <= 128 + * Wait for first 4 bytes to be in FIFO + * If CONSERVATIVE_BMI_READ is enabled, also wait for + * a BMI command credit, which indicates that the ENTIRE + * response is available in the the FIFO + * + * CASE 3: length > 128 + * Wait for the first 4 bytes to be in FIFO + * + * For most uses, a small timeout should be sufficient and we will + * usually see a response quickly; but there may be some unusual + * (debug) cases of BMI_EXECUTE where we want an larger timeout. + * For now, we use an unbounded busy loop while waiting for + * BMI_EXECUTE. + * + * If BMI_EXECUTE ever needs to support longer-latency execution, + * especially in production, this code needs to be enhanced to sleep + * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently + * a function of Host processor speed. + */ + if (length >= 4) { /* NB: Currently, always true */ + /* + * NB: word_available is declared static for esoteric reasons + * having to do with protection on some OSes. + */ + static u32 word_available; + u32 timeout; + + word_available = 0; + timeout = BMI_COMMUNICATION_TIMEOUT; + while((!want_timeout || timeout--) && !word_available) { + + if (getPendingEventsFunc != NULL) { + status = getPendingEventsFunc(device, + &hifPendingEvents, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n")); + break; + } + + if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) { + word_available = 1; + } + continue; + } + + status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available, + sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n")); + return A_ERROR; + } + /* We did a 4-byte read to the same register; all we really want is one bit */ + word_available &= (1 << ENDPOINT1); + } + + if (!word_available) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n")); + return A_ERROR; + } + } + +#define CONSERVATIVE_BMI_READ 0 +#if CONSERVATIVE_BMI_READ + /* + * This is an extra-conservative CREDIT check. It guarantees + * that ALL data is available in the FIFO before we start to + * read from the interconnect. + * + * This credit check is useless when firmware chooses to + * allow multiple outstanding BMI Command Credits, since the next + * credit will already be present. To restrict the Target to one + * BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT. + * + * And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set) + * we cannot wait for the next credit because the Target's FIFO + * will not hold the entire response. So we need the Host to + * start to empty the FIFO sooner. (And again, large reads are + * not used in practice; they are for debug/development only.) + * + * For a more conservative Host implementation (which would be + * safer for a Compact Flash interconnect): + * Set CONSERVATIVE_BMI_READ (above) to 1 + * Set HI_OPTION_BMI_CRED_LIMIT and + * reduce BMI_DATASZ_MAX to 32 or 64 + */ + if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */ + u32 timeout; + + *pBMICmdCredits = 0; + timeout = BMI_COMMUNICATION_TIMEOUT; + while((!want_timeout || timeout--) && !(*pBMICmdCredits) { + /* Read the counter register to get the command credits */ + address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1; + /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing, + * we can read this counter multiple times using a non-incrementing address mode. + * The rationale here is to make all HIF accesses a multiple of 4 bytes */ + status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits), + HIF_RD_SYNC_BYTE_FIX, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n")); + return A_ERROR; + } + /* we did a 4-byte read to the same count register so mask off upper bytes */ + (*pBMICmdCredits) &= 0xFF; + } + + if (!(*pBMICmdCredits)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n")); + return A_ERROR; + } + } +#endif + + address = mboxAddress[ENDPOINT1]; + status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n")); + return A_ERROR; + } + + return 0; +} + +int +BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length) +{ + int status = A_ERROR; + u32 lastWord = 0; + u32 lastWordOffset = length & ~0x3; + u32 unalignedBytes = length & 0x3; + + status = BMILZStreamStart (device, address); + if (status) { + return A_ERROR; + } + + if (unalignedBytes) { + /* copy the last word into a zero padded buffer */ + memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes); + } + + status = BMILZData(device, buffer, lastWordOffset); + + if (status) { + return A_ERROR; + } + + if (unalignedBytes) { + status = BMILZData(device, (u8 *)&lastWord, 4); + } + + if (!status) { + // + // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches. + // + status = BMILZStreamStart (device, 0x00); + if (status) { + return A_ERROR; + } + } + return status; +} + +int +BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length) +{ + return bmiBufferSend(device, buffer, length); +} + +int +BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout) +{ + return bmiBufferReceive(device, buffer, length, want_timeout); +} diff --git a/trunk/drivers/staging/ath6kl/hif/common/hif_sdio_common.h b/trunk/drivers/staging/ath6kl/hif/common/hif_sdio_common.h new file mode 100644 index 000000000000..93a2adceca33 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/hif/common/hif_sdio_common.h @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// common header file for HIF modules designed for SDIO +// +// Author(s): ="Atheros" +//============================================================================== + +#ifndef HIF_SDIO_COMMON_H_ +#define HIF_SDIO_COMMON_H_ + + /* SDIO manufacturer ID and Codes */ +#define MANUFACTURER_ID_AR6002_BASE 0x200 +#define MANUFACTURER_ID_AR6003_BASE 0x300 +#define MANUFACTURER_ID_AR6K_BASE_MASK 0xFF00 +#define FUNCTION_CLASS 0x0 +#define MANUFACTURER_CODE 0x271 /* Atheros */ + + /* Mailbox address in SDIO address space */ +#define HIF_MBOX_BASE_ADDR 0x800 +#define HIF_MBOX_WIDTH 0x800 +#define HIF_MBOX_START_ADDR(mbox) \ + ( HIF_MBOX_BASE_ADDR + mbox * HIF_MBOX_WIDTH) + +#define HIF_MBOX_END_ADDR(mbox) \ + (HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1) + + /* extended MBOX address for larger MBOX writes to MBOX 0*/ +#define HIF_MBOX0_EXTENDED_BASE_ADDR 0x2800 +#define HIF_MBOX0_EXTENDED_WIDTH_AR6002 (6*1024) +#define HIF_MBOX0_EXTENDED_WIDTH_AR6003 (18*1024) + + /* version 1 of the chip has only a 12K extended mbox range */ +#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1 0x4000 +#define HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1 (12*1024) + + /* GMBOX addresses */ +#define HIF_GMBOX_BASE_ADDR 0x7000 +#define HIF_GMBOX_WIDTH 0x4000 + + /* for SDIO we recommend a 128-byte block size */ +#define HIF_DEFAULT_IO_BLOCK_SIZE 128 + + /* set extended MBOX window information for SDIO interconnects */ +static INLINE void SetExtendedMboxWindowInfo(u16 Manfid, struct hif_device_mbox_info *pInfo) +{ + switch (Manfid & MANUFACTURER_ID_AR6K_BASE_MASK) { + case MANUFACTURER_ID_AR6002_BASE : + /* MBOX 0 has an extended range */ + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6002; + break; + case MANUFACTURER_ID_AR6003_BASE : + /* MBOX 0 has an extended range */ + pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1; + pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1; + pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR; + pInfo->GMboxSize = HIF_GMBOX_WIDTH; + break; + default: + A_ASSERT(false); + break; + } +} + +/* special CCCR (func 0) registers */ + +#define CCCR_SDIO_IRQ_MODE_REG 0xF0 /* interrupt mode register */ +#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0) /* mode to enable special 4-bit interrupt assertion without clock*/ + +#endif /*HIF_SDIO_COMMON_H_*/ diff --git a/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h new file mode 100644 index 000000000000..ed7ad4786f5a --- /dev/null +++ b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h @@ -0,0 +1,131 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// internal header file for hif layer +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HIF_INTERNAL_H_ +#define _HIF_INTERNAL_H_ + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "hif.h" +#include "../../../common/hif_sdio_common.h" +#include +#define HIF_LINUX_MMC_SCATTER_SUPPORT + +#define BUS_REQUEST_MAX_NUM 64 + +#define SDIO_CLOCK_FREQUENCY_DEFAULT 25000000 +#define SDWLAN_ENABLE_DISABLE_TIMEOUT 20 +#define FLAGS_CARD_ENAB 0x02 +#define FLAGS_CARD_IRQ_UNMSK 0x04 + +#define HIF_MBOX_BLOCK_SIZE HIF_DEFAULT_IO_BLOCK_SIZE +#define HIF_MBOX0_BLOCK_SIZE 1 +#define HIF_MBOX1_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE +#define HIF_MBOX2_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE +#define HIF_MBOX3_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE + +typedef struct bus_request { + struct bus_request *next; /* link list of available requests */ + struct bus_request *inusenext; /* link list of in use requests */ + struct semaphore sem_req; + u32 address; /* request data */ + u8 *buffer; + u32 length; + u32 request; + void *context; + int status; + struct hif_scatter_req_priv *pScatterReq; /* this request is a scatter request */ +} BUS_REQUEST; + +struct hif_device { + struct sdio_func *func; + spinlock_t asynclock; + struct task_struct* async_task; /* task to handle async commands */ + struct semaphore sem_async; /* wake up for async task */ + int async_shutdown; /* stop the async task */ + struct completion async_completion; /* thread completion */ + BUS_REQUEST *asyncreq; /* request for async tasklet */ + BUS_REQUEST *taskreq; /* async tasklet data */ + spinlock_t lock; + BUS_REQUEST *s_busRequestFreeQueue; /* free list */ + BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; /* available bus requests */ + void *claimedContext; + HTC_CALLBACKS htcCallbacks; + u8 *dma_buffer; + struct dl_list ScatterReqHead; /* scatter request list head */ + bool scatter_enabled; /* scatter enabled flag */ + bool is_suspend; + bool is_disabled; + atomic_t irqHandling; + HIF_DEVICE_POWER_CHANGE_TYPE powerConfig; + const struct sdio_device_id *id; +}; + +#define HIF_DMA_BUFFER_SIZE (32 * 1024) +#define CMD53_FIXED_ADDRESS 1 +#define CMD53_INCR_ADDRESS 2 + +BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device); +void hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest); +void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest); + +#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT + +#define MAX_SCATTER_REQUESTS 4 +#define MAX_SCATTER_ENTRIES_PER_REQ 16 +#define MAX_SCATTER_REQ_TRANSFER_SIZE 32*1024 + +struct hif_scatter_req_priv { + struct hif_scatter_req *pHifScatterReq; /* HIF scatter request with allocated entries */ + struct hif_device *device; /* this device */ + BUS_REQUEST *busrequest; /* request associated with request */ + /* scatter list for linux */ + struct scatterlist sgentries[MAX_SCATTER_ENTRIES_PER_REQ]; +}; + +#define ATH_DEBUG_SCATTER ATH_DEBUG_MAKE_MODULE_MASK(0) + +int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo); +void CleanupHIFScatterResources(struct hif_device *device); +int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest); + +#else // HIF_LINUX_MMC_SCATTER_SUPPORT + +static inline int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo) +{ + return A_ENOTSUP; +} + +static inline int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest) +{ + return A_ENOTSUP; +} + +#define CleanupHIFScatterResources(d) { } + +#endif // HIF_LINUX_MMC_SCATTER_SUPPORT + +#endif // _HIF_INTERNAL_H_ + diff --git a/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c new file mode 100644 index 000000000000..5f5d67720fa4 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c @@ -0,0 +1,1273 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HIF layer reference implementation for Linux Native MMC stack +// +// Author(s): ="Atheros" +//============================================================================== +#include +#include +#include +#include +#include +#include +#include +#include + +/* by default setup a bounce buffer for the data packets, if the underlying host controller driver + does not use DMA you may be able to skip this step and save the memory allocation and transfer time */ +#define HIF_USE_DMA_BOUNCE_BUFFER 1 +#include "hif_internal.h" +#define ATH_MODULE_NAME hif +#include "a_debug.h" +#include "hw/mbox_host_reg.h" + +#if HIF_USE_DMA_BOUNCE_BUFFER +/* macro to check if DMA buffer is WORD-aligned and DMA-able. Most host controllers assume the + * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack). + * virt_addr_valid check fails on stack memory. + */ +#define BUFFER_NEEDS_BOUNCE(buffer) (((unsigned long)(buffer) & 0x3) || !virt_addr_valid((buffer))) +#else +#define BUFFER_NEEDS_BOUNCE(buffer) (false) +#endif + +/* ATHENV */ +#if defined(CONFIG_PM) +#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) +#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) +#endif /* CONFIG_PM */ +static void delHifDevice(struct hif_device * device); +static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte); +static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte); + +static int hifEnableFunc(struct hif_device *device, struct sdio_func *func); +static int hifDisableFunc(struct hif_device *device, struct sdio_func *func); +OSDRV_CALLBACKS osdrvCallbacks; + +int reset_sdio_on_unload = 0; +module_param(reset_sdio_on_unload, int, 0644); + +extern u32 nohifscattersupport; + +static struct hif_device *ath6kl_alloc_hifdev(struct sdio_func *func) +{ + struct hif_device *hifdevice; + + hifdevice = kzalloc(sizeof(struct hif_device), GFP_KERNEL); + +#if HIF_USE_DMA_BOUNCE_BUFFER + hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL); +#endif + hifdevice->func = func; + hifdevice->powerConfig = HIF_DEVICE_POWER_UP; + sdio_set_drvdata(func, hifdevice); + + return hifdevice; +} + +static struct hif_device *ath6kl_get_hifdev(struct sdio_func *func) +{ + return (struct hif_device *) sdio_get_drvdata(func); +} + +static const struct sdio_device_id ath6kl_hifdev_ids[] = { + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x1)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0)) }, + { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1)) }, + { /* null */ }, +}; + +MODULE_DEVICE_TABLE(sdio, ath6kl_hifdev_ids); + +static int ath6kl_hifdev_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int ret; + struct hif_device *device; + int count; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("ath6kl: Function: 0x%X, Vendor ID: 0x%X, " + "Device ID: 0x%X, block size: 0x%X/0x%X\n", + func->num, func->vendor, func->device, + func->max_blksize, func->cur_blksize)); + + ath6kl_alloc_hifdev(func); + device = ath6kl_get_hifdev(func); + + device->id = id; + device->is_disabled = true; + + spin_lock_init(&device->lock); + spin_lock_init(&device->asynclock); + + DL_LIST_INIT(&device->ScatterReqHead); + + /* Try to allow scatter unless globally overridden */ + if (!nohifscattersupport) + device->scatter_enabled = true; + + A_MEMZERO(device->busRequest, sizeof(device->busRequest)); + + for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) { + sema_init(&device->busRequest[count].sem_req, 0); + hifFreeBusRequest(device, &device->busRequest[count]); + } + + sema_init(&device->sem_async, 0); + + ret = hifEnableFunc(device, func); + + return ret; +} + +static void ath6kl_hifdev_remove(struct sdio_func *func) +{ + int status = 0; + struct hif_device *device; + + device = ath6kl_get_hifdev(func); + if (device->claimedContext != NULL) + status = osdrvCallbacks. + deviceRemovedHandler(device->claimedContext, device); + + if (device->is_disabled) + device->is_disabled = false; + else + status = hifDisableFunc(device, func); + + CleanupHIFScatterResources(device); + + delHifDevice(device); +} + +#if defined(CONFIG_PM) +static int ath6kl_hifdev_suspend(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + int status = 0; + struct hif_device *device; + + device = ath6kl_get_hifdev(func); + + if (device && device->claimedContext && + osdrvCallbacks.deviceSuspendHandler) { + /* set true first for PowerStateChangeNotify(..) */ + device->is_suspend = true; + status = osdrvCallbacks. + deviceSuspendHandler(device->claimedContext); + if (status) + device->is_suspend = false; + } + + CleanupHIFScatterResources(device); + + switch (status) { + case 0: + return 0; + case A_EBUSY: + /* Hack for kernel in order to support deep sleep and wow */ + return -EBUSY; + default: + return -1; + } +} + +static int ath6kl_hifdev_resume(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + int status = 0; + struct hif_device *device; + + device = ath6kl_get_hifdev(func); + if (device && device->claimedContext && + osdrvCallbacks.deviceSuspendHandler) { + status = osdrvCallbacks. + deviceResumeHandler(device->claimedContext); + if (status == 0) + device->is_suspend = false; + } + + return status; +} + +static const struct dev_pm_ops ath6kl_hifdev_pmops = { + .suspend = ath6kl_hifdev_suspend, + .resume = ath6kl_hifdev_resume, +}; +#endif /* CONFIG_PM */ + +static struct sdio_driver ath6kl_hifdev_driver = { + .name = "ath6kl_hifdev", + .id_table = ath6kl_hifdev_ids, + .probe = ath6kl_hifdev_probe, + .remove = ath6kl_hifdev_remove, +#if defined(CONFIG_PM) + .drv = { + .pm = &ath6kl_hifdev_pmops, + }, +#endif +}; + +/* make sure we only unregister when registered. */ +static int registered = 0; + +extern u32 onebitmode; +extern u32 busspeedlow; +extern u32 debughif; + +static void ResetAllCards(void); + +#ifdef DEBUG + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, + "hif", + "(Linux MMC) Host Interconnect Framework", + ATH_DEBUG_MASK_DEFAULTS, + 0, + NULL); + +#endif + + +/* ------ Functions ------ */ +int HIFInit(OSDRV_CALLBACKS *callbacks) +{ + int r; + AR_DEBUG_ASSERT(callbacks != NULL); + + A_REGISTER_MODULE_DEBUG_INFO(hif); + + /* store the callback handlers */ + osdrvCallbacks = *callbacks; + + /* Register with bus driver core */ + registered = 1; + + r = sdio_register_driver(&ath6kl_hifdev_driver); + if (r < 0) + return r; + + return 0; +} + +static int +__HIFReadWrite(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length, + u32 request, + void *context) +{ + u8 opcode; + int status = 0; + int ret; + u8 *tbuffer; + bool bounced = false; + + AR_DEBUG_ASSERT(device != NULL); + AR_DEBUG_ASSERT(device->func != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: 0x%p, buffer:0x%p (addr:0x%X)\n", + device, buffer, address)); + + do { + if (request & HIF_EXTENDED_IO) { + //AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Command type: CMD53\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid command type: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + + if (request & HIF_BLOCK_BASIS) { + /* round to whole block length size */ + length = (length / HIF_MBOX_BLOCK_SIZE) * HIF_MBOX_BLOCK_SIZE; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Block mode (BlockLen: %d)\n", + length)); + } else if (request & HIF_BYTE_BASIS) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Byte mode (BlockLen: %d)\n", + length)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid data mode: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + +#if 0 + /* useful for checking register accesses */ + if (length & 0x3) { + A_PRINTF(KERN_ALERT"AR6000: HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n", + request & HIF_WRITE ? "write":"read", address, length); + } +#endif + + if (request & HIF_WRITE) { + if ((address >= HIF_MBOX_START_ADDR(0)) && + (address <= HIF_MBOX_END_ADDR(3))) + { + + AR_DEBUG_ASSERT(length <= HIF_MBOX_WIDTH); + + /* + * Mailbox write. Adjust the address so that the last byte + * falls on the EOM address. + */ + address += (HIF_MBOX_WIDTH - length); + } + } + + if (request & HIF_FIXED_ADDRESS) { + opcode = CMD53_FIXED_ADDRESS; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Fixed 0x%X\n", address)); + } else if (request & HIF_INCREMENTAL_ADDRESS) { + opcode = CMD53_INCR_ADDRESS; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Incremental 0x%X\n", address)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid address mode: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + + if (request & HIF_WRITE) { +#if HIF_USE_DMA_BOUNCE_BUFFER + if (BUFFER_NEEDS_BOUNCE(buffer)) { + AR_DEBUG_ASSERT(device->dma_buffer != NULL); + tbuffer = device->dma_buffer; + /* copy the write data to the dma buffer */ + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); + memcpy(tbuffer, buffer, length); + bounced = true; + } else { + tbuffer = buffer; + } +#else + tbuffer = buffer; +#endif + if (opcode == CMD53_FIXED_ADDRESS) { + ret = sdio_writesb(device->func, address, tbuffer, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } else { + ret = sdio_memcpy_toio(device->func, address, tbuffer, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } + } else if (request & HIF_READ) { +#if HIF_USE_DMA_BOUNCE_BUFFER + if (BUFFER_NEEDS_BOUNCE(buffer)) { + AR_DEBUG_ASSERT(device->dma_buffer != NULL); + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); + tbuffer = device->dma_buffer; + bounced = true; + } else { + tbuffer = buffer; + } +#else + tbuffer = buffer; +#endif + if (opcode == CMD53_FIXED_ADDRESS) { + ret = sdio_readsb(device->func, tbuffer, address, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readsb ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } else { + ret = sdio_memcpy_fromio(device->func, tbuffer, address, length); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readio ret=%d address: 0x%X, len: %d, 0x%X\n", + ret, address, length, *(int *)tbuffer)); + } +#if HIF_USE_DMA_BOUNCE_BUFFER + if (bounced) { + /* copy the read data from the dma buffer */ + memcpy(buffer, tbuffer, length); + } +#endif + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid direction: 0x%08x\n", request)); + status = A_EINVAL; + break; + } + + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret)); + status = A_ERROR; + } + } while (false); + + return status; +} + +void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest) +{ + unsigned long flags; + BUS_REQUEST *async; + BUS_REQUEST *active; + + spin_lock_irqsave(&device->asynclock, flags); + active = device->asyncreq; + if (active == NULL) { + device->asyncreq = busrequest; + device->asyncreq->inusenext = NULL; + } else { + for (async = device->asyncreq; + async != NULL; + async = async->inusenext) { + active = async; + } + active->inusenext = busrequest; + busrequest->inusenext = NULL; + } + spin_unlock_irqrestore(&device->asynclock, flags); +} + + +/* queue a read/write request */ +int +HIFReadWrite(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length, + u32 request, + void *context) +{ + int status = 0; + BUS_REQUEST *busrequest; + + + AR_DEBUG_ASSERT(device != NULL); + AR_DEBUG_ASSERT(device->func != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: %p addr:0x%X\n", device,address)); + + do { + if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)){ + /* serialize all requests through the async thread */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Execution mode: %s\n", + (request & HIF_ASYNCHRONOUS)?"Async":"Synch")); + busrequest = hifAllocateBusRequest(device); + if (busrequest == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: no async bus requests available (%s, addr:0x%X, len:%d) \n", + request & HIF_READ ? "READ":"WRITE", address, length)); + return A_ERROR; + } + busrequest->address = address; + busrequest->buffer = buffer; + busrequest->length = length; + busrequest->request = request; + busrequest->context = context; + + AddToAsyncList(device, busrequest); + + if (request & HIF_SYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%lX\n", (unsigned long)busrequest)); + + /* wait for completion */ + up(&device->sem_async); + if (down_interruptible(&busrequest->sem_req) != 0) { + /* interrupted, exit */ + return A_ERROR; + } else { + int status = busrequest->status; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%lX: 0x%X\n", + (unsigned long)busrequest, busrequest->status)); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request)); + hifFreeBusRequest(device, busrequest); + return status; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%lX\n", (unsigned long)busrequest)); + up(&device->sem_async); + return A_PENDING; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: Invalid execution mode: 0x%08x\n", (unsigned int)request)); + status = A_EINVAL; + break; + } + } while(0); + + return status; +} +/* thread to serialize all requests, both sync and async */ +static int async_task(void *param) + { + struct hif_device *device; + BUS_REQUEST *request; + int status; + unsigned long flags; + + device = (struct hif_device *)param; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task\n")); + set_current_state(TASK_INTERRUPTIBLE); + while(!device->async_shutdown) { + /* wait for work */ + if (down_interruptible(&device->sem_async) != 0) { + /* interrupted, exit */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task interrupted\n")); + break; + } + if (device->async_shutdown) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task stopping\n")); + break; + } + /* we want to hold the host over multiple cmds if possible, but holding the host blocks card interrupts */ + sdio_claim_host(device->func); + spin_lock_irqsave(&device->asynclock, flags); + /* pull the request to work on */ + while (device->asyncreq != NULL) { + request = device->asyncreq; + if (request->inusenext != NULL) { + device->asyncreq = request->inusenext; + } else { + device->asyncreq = NULL; + } + spin_unlock_irqrestore(&device->asynclock, flags); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task processing req: 0x%lX\n", (unsigned long)request)); + + if (request->pScatterReq != NULL) { + A_ASSERT(device->scatter_enabled); + /* this is a queued scatter request, pass the request to scatter routine which + * executes it synchronously, note, no need to free the request since scatter requests + * are maintained on a separate list */ + status = DoHifReadWriteScatter(device,request); + } else { + /* call HIFReadWrite in sync mode to do the work */ + status = __HIFReadWrite(device, request->address, request->buffer, + request->length, request->request & ~HIF_SYNCHRONOUS, NULL); + if (request->request & HIF_ASYNCHRONOUS) { + void *context = request->context; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task freeing req: 0x%lX\n", (unsigned long)request)); + hifFreeBusRequest(device, request); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task completion routine req: 0x%lX\n", (unsigned long)request)); + device->htcCallbacks.rwCompletionHandler(context, status); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task upping req: 0x%lX\n", (unsigned long)request)); + request->status = status; + up(&request->sem_req); + } + } + spin_lock_irqsave(&device->asynclock, flags); + } + spin_unlock_irqrestore(&device->asynclock, flags); + sdio_release_host(device->func); + } + + complete_and_exit(&device->async_completion, 0); + return 0; +} + +static s32 IssueSDCommand(struct hif_device *device, u32 opcode, u32 arg, u32 flags, u32 *resp) +{ + struct mmc_command cmd; + s32 err; + struct mmc_host *host; + struct sdio_func *func; + + func = device->func; + host = func->card->host; + + memset(&cmd, 0, sizeof(struct mmc_command)); + cmd.opcode = opcode; + cmd.arg = arg; + cmd.flags = flags; + err = mmc_wait_for_cmd(host, &cmd, 3); + + if ((!err) && (resp)) { + *resp = cmd.resp[0]; + } + + return err; +} + +int ReinitSDIO(struct hif_device *device) +{ + s32 err; + struct mmc_host *host; + struct mmc_card *card; + struct sdio_func *func; + u8 cmd52_resp; + u32 clock; + + func = device->func; + card = func->card; + host = card->host; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +ReinitSDIO \n")); + sdio_claim_host(func); + + do { + if (!device->is_suspend) { + u32 resp; + u16 rca; + u32 i; + int bit = fls(host->ocr_avail) - 1; + /* emulate the mmc_power_up(...) */ + host->ios.vdd = bit; + host->ios.chip_select = MMC_CS_DONTCARE; + host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; + host->ios.power_mode = MMC_POWER_UP; + host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; + host->ops->set_ios(host, &host->ios); + /* + * This delay should be sufficient to allow the power supply + * to reach the minimum voltage. + */ + msleep(2); + + host->ios.clock = host->f_min; + host->ios.power_mode = MMC_POWER_ON; + host->ops->set_ios(host, &host->ios); + + /* + * This delay must be at least 74 clock sizes, or 1 ms, or the + * time required to reach a stable voltage. + */ + msleep(2); + + /* Issue CMD0. Goto idle state */ + host->ios.chip_select = MMC_CS_HIGH; + host->ops->set_ios(host, &host->ios); + msleep(1); + err = IssueSDCommand(device, MMC_GO_IDLE_STATE, 0, (MMC_RSP_NONE | MMC_CMD_BC), NULL); + host->ios.chip_select = MMC_CS_DONTCARE; + host->ops->set_ios(host, &host->ios); + msleep(1); + host->use_spi_crc = 0; + + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD0 failed : %d \n",err)); + break; + } + + if (!host->ocr) { + /* Issue CMD5, arg = 0 */ + err = IssueSDCommand(device, SD_IO_SEND_OP_COND, 0, (MMC_RSP_R4 | MMC_CMD_BCR), &resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err)); + break; + } + host->ocr = resp; + } + + /* Issue CMD5, arg = ocr. Wait till card is ready */ + for (i=0;i<100;i++) { + err = IssueSDCommand(device, SD_IO_SEND_OP_COND, host->ocr, (MMC_RSP_R4 | MMC_CMD_BCR), &resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err)); + break; + } + if (resp & MMC_CARD_BUSY) { + break; + } + msleep(10); + } + + if ((i == 100) || (err)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: card in not ready : %d %d \n",i,err)); + break; + } + + /* Issue CMD3, get RCA */ + err = IssueSDCommand(device, SD_SEND_RELATIVE_ADDR, 0, MMC_RSP_R6 | MMC_CMD_BCR, &resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD3 failed : %d \n",err)); + break; + } + rca = resp >> 16; + host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; + host->ops->set_ios(host, &host->ios); + + /* Issue CMD7, select card */ + err = IssueSDCommand(device, MMC_SELECT_CARD, (rca << 16), MMC_RSP_R1 | MMC_CMD_AC, NULL); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD7 failed : %d \n",err)); + break; + } + } + + /* Enable high speed */ + if (card->host->caps & MMC_CAP_SD_HIGHSPEED) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("ReinitSDIO: Set high speed mode\n")); + err = Func0_CMD52ReadByte(card, SDIO_CCCR_SPEED, &cmd52_resp); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 read to CCCR speed register failed : %d \n",err)); + card->state &= ~MMC_STATE_HIGHSPEED; + /* no need to break */ + } else { + err = Func0_CMD52WriteByte(card, SDIO_CCCR_SPEED, (cmd52_resp | SDIO_SPEED_EHS)); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 write to CCCR speed register failed : %d \n",err)); + break; + } + mmc_card_set_highspeed(card); + host->ios.timing = MMC_TIMING_SD_HS; + host->ops->set_ios(host, &host->ios); + } + } + + /* Set clock */ + if (mmc_card_highspeed(card)) { + clock = 50000000; + } else { + clock = card->cis.max_dtr; + } + + if (clock > host->f_max) { + clock = host->f_max; + } + host->ios.clock = clock; + host->ops->set_ios(host, &host->ios); + + + if (card->host->caps & MMC_CAP_4_BIT_DATA) { + /* CMD52: Set bus width & disable card detect resistor */ + err = Func0_CMD52WriteByte(card, SDIO_CCCR_IF, SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_4BIT); + if (err) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 to set bus mode failed : %d \n",err)); + break; + } + host->ios.bus_width = MMC_BUS_WIDTH_4; + host->ops->set_ios(host, &host->ios); + } + } while (0); + + sdio_release_host(func); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -ReinitSDIO \n")); + + return (err) ? A_ERROR : 0; +} + +int +PowerStateChangeNotify(struct hif_device *device, HIF_DEVICE_POWER_CHANGE_TYPE config) +{ + int status = 0; +#if defined(CONFIG_PM) + struct sdio_func *func = device->func; + int old_reset_val; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +PowerStateChangeNotify %d\n", config)); + switch (config) { + case HIF_DEVICE_POWER_DOWN: + case HIF_DEVICE_POWER_CUT: + old_reset_val = reset_sdio_on_unload; + reset_sdio_on_unload = 1; + status = hifDisableFunc(device, func); + reset_sdio_on_unload = old_reset_val; + if (!device->is_suspend) { + struct mmc_host *host = func->card->host; + host->ios.clock = 0; + host->ios.vdd = 0; + host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; + host->ios.chip_select = MMC_CS_DONTCARE; + host->ios.power_mode = MMC_POWER_OFF; + host->ios.bus_width = MMC_BUS_WIDTH_1; + host->ios.timing = MMC_TIMING_LEGACY; + host->ops->set_ios(host, &host->ios); + } + break; + case HIF_DEVICE_POWER_UP: + if (device->powerConfig == HIF_DEVICE_POWER_CUT) { + status = ReinitSDIO(device); + } + if (status == 0) { + status = hifEnableFunc(device, func); + } + break; + } + device->powerConfig = config; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -PowerStateChangeNotify\n")); +#endif + return status; +} + +int +HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode, + void *config, u32 configLen) +{ + u32 count; + int status = 0; + + switch(opcode) { + case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: + ((u32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; + ((u32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; + ((u32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; + ((u32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; + break; + + case HIF_DEVICE_GET_MBOX_ADDR: + for (count = 0; count < 4; count ++) { + ((u32 *)config)[count] = HIF_MBOX_START_ADDR(count); + } + + if (configLen >= sizeof(struct hif_device_mbox_info)) { + SetExtendedMboxWindowInfo((u16)device->func->device, + (struct hif_device_mbox_info *)config); + } + + break; + case HIF_DEVICE_GET_IRQ_PROC_MODE: + *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY; + break; + case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT: + if (!device->scatter_enabled) { + return A_ENOTSUP; + } + status = SetupHIFScatterSupport(device, (struct hif_device_scatter_support_info *)config); + if (status) { + device->scatter_enabled = false; + } + break; + case HIF_DEVICE_GET_OS_DEVICE: + /* pass back a pointer to the SDIO function's "dev" struct */ + ((struct hif_device_os_device_info *)config)->pOSDevice = &device->func->dev; + break; + case HIF_DEVICE_POWER_STATE_CHANGE: + status = PowerStateChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TYPE *)config); + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6000: Unsupported configuration opcode: %d\n", opcode)); + status = A_ERROR; + } + + return status; +} + +void +HIFShutDownDevice(struct hif_device *device) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n")); + if (device != NULL) { + AR_DEBUG_ASSERT(device->func != NULL); + } else { + /* since we are unloading the driver anyways, reset all cards in case the SDIO card + * is externally powered and we are unloading the SDIO stack. This avoids the problem when + * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already + * enumerated */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFShutDownDevice, resetting\n")); + ResetAllCards(); + + /* Unregister with bus driver core */ + if (registered) { + registered = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Unregistering with the bus driver\n")); + sdio_unregister_driver(&ath6kl_hifdev_driver); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("AR6000: Unregistered\n")); + } + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -HIFShutDownDevice\n")); +} + +static void +hifIRQHandler(struct sdio_func *func) +{ + int status; + struct hif_device *device; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n")); + + device = ath6kl_get_hifdev(func); + atomic_set(&device->irqHandling, 1); + /* release the host during ints so we can pick it back up when we process cmds */ + sdio_release_host(device->func); + status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context); + sdio_claim_host(device->func); + atomic_set(&device->irqHandling, 0); + AR_DEBUG_ASSERT(status == 0 || status == A_ECANCELED); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n")); +} + +/* handle HTC startup via thread*/ +static int startup_task(void *param) +{ + struct hif_device *device; + + device = (struct hif_device *)param; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n")); + /* start up inform DRV layer */ + if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); + } + return 0; +} + +#if defined(CONFIG_PM) +static int enable_task(void *param) +{ + struct hif_device *device; + device = (struct hif_device *)param; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call from resume_task\n")); + + /* start up inform DRV layer */ + if (device && + device->claimedContext && + osdrvCallbacks.devicePowerChangeHandler && + osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n")); + } + + return 0; +} +#endif + +void +HIFAckInterrupt(struct hif_device *device) +{ + AR_DEBUG_ASSERT(device != NULL); + + /* Acknowledge our function IRQ */ +} + +void +HIFUnMaskInterrupt(struct hif_device *device) +{ + int ret; + + AR_DEBUG_ASSERT(device != NULL); + AR_DEBUG_ASSERT(device->func != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFUnMaskInterrupt\n")); + + /* Register the IRQ Handler */ + sdio_claim_host(device->func); + ret = sdio_claim_irq(device->func, hifIRQHandler); + sdio_release_host(device->func); + AR_DEBUG_ASSERT(ret == 0); +} + +void HIFMaskInterrupt(struct hif_device *device) +{ + int ret; + AR_DEBUG_ASSERT(device != NULL); + AR_DEBUG_ASSERT(device->func != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFMaskInterrupt\n")); + + /* Mask our function IRQ */ + sdio_claim_host(device->func); + while (atomic_read(&device->irqHandling)) { + sdio_release_host(device->func); + schedule_timeout(HZ/10); + sdio_claim_host(device->func); + } + ret = sdio_release_irq(device->func); + sdio_release_host(device->func); + AR_DEBUG_ASSERT(ret == 0); +} + +BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device) +{ + BUS_REQUEST *busrequest; + unsigned long flag; + + /* Acquire lock */ + spin_lock_irqsave(&device->lock, flag); + + /* Remove first in list */ + if((busrequest = device->s_busRequestFreeQueue) != NULL) + { + device->s_busRequestFreeQueue = busrequest->next; + } + /* Release lock */ + spin_unlock_irqrestore(&device->lock, flag); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifAllocateBusRequest: 0x%p\n", busrequest)); + return busrequest; +} + +void +hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest) +{ + unsigned long flag; + + AR_DEBUG_ASSERT(busrequest != NULL); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifFreeBusRequest: 0x%p\n", busrequest)); + /* Acquire lock */ + spin_lock_irqsave(&device->lock, flag); + + + /* Insert first in list */ + busrequest->next = device->s_busRequestFreeQueue; + busrequest->inusenext = NULL; + device->s_busRequestFreeQueue = busrequest; + + /* Release lock */ + spin_unlock_irqrestore(&device->lock, flag); +} + +static int hifDisableFunc(struct hif_device *device, struct sdio_func *func) +{ + int ret; + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDisableFunc\n")); + device = ath6kl_get_hifdev(func); + if (!IS_ERR(device->async_task)) { + init_completion(&device->async_completion); + device->async_shutdown = 1; + up(&device->sem_async); + wait_for_completion(&device->async_completion); + device->async_task = NULL; + } + /* Disable the card */ + sdio_claim_host(device->func); + ret = sdio_disable_func(device->func); + if (ret) { + status = A_ERROR; + } + + if (reset_sdio_on_unload) { + /* reset the SDIO interface. This is useful in automated testing where the card + * does not need to be removed at the end of the test. It is expected that the user will + * also unload/reload the host controller driver to force the bus driver to re-enumerate the slot */ + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uninitialized state \n")); + + /* NOTE : sdio_f0_writeb() cannot be used here, that API only allows access + * to undefined registers in the range of: 0xF0-0xFF */ + + ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3)); + if (ret) { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret)); + } + } + + sdio_release_host(device->func); + + if (status == 0) { + device->is_disabled = true; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDisableFunc\n")); + + return status; +} + +static int hifEnableFunc(struct hif_device *device, struct sdio_func *func) +{ + struct task_struct* pTask; + const char *taskName = NULL; + int (*taskFunc)(void *) = NULL; + int ret = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n")); + device = ath6kl_get_hifdev(func); + + if (device->is_disabled) { + /* enable the SDIO function */ + sdio_claim_host(func); + + if ((device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK) >= MANUFACTURER_ID_AR6003_BASE) { + /* enable 4-bit ASYNC interrupt on AR6003 or later devices */ + ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG, SDIO_IRQ_MODE_ASYNC_4BIT_IRQ); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to enable 4-bit ASYNC IRQ mode %d \n",ret)); + sdio_release_host(func); + return ret; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: 4-bit ASYNC IRQ mode enabled\n")); + } + /* give us some time to enable, in ms */ + func->enable_timeout = 100; + ret = sdio_enable_func(func); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n", + __FUNCTION__, ret)); + sdio_release_host(func); + return ret; + } + ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); + sdio_release_host(func); + if (ret) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x AR6K: 0x%X\n", + __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret)); + return ret; + } + device->is_disabled = false; + /* create async I/O thread */ + if (!device->async_task) { + device->async_shutdown = 0; + device->async_task = kthread_create(async_task, + (void *)device, + "AR6K Async"); + if (IS_ERR(device->async_task)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__)); + return -ENOMEM; + } + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n")); + wake_up_process(device->async_task ); + } + } + + if (!device->claimedContext) { + taskFunc = startup_task; + taskName = "AR6K startup"; + ret = 0; +#if defined(CONFIG_PM) + } else { + taskFunc = enable_task; + taskName = "AR6K enable"; + ret = -ENOMEM; +#endif /* CONFIG_PM */ + } + /* create resume thread */ + pTask = kthread_create(taskFunc, (void *)device, taskName); + if (IS_ERR(pTask)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create enabel task\n", __FUNCTION__)); + return -ENOMEM; + } + wake_up_process(pTask); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifEnableFunc\n")); + + /* task will call the enable func, indicate pending */ + return ret; +} + +/* + * This should be moved to AR6K HTC layer. + */ +int hifWaitForPendingRecv(struct hif_device *device) +{ + s32 cnt = 10; + u8 host_int_status; + int status = 0; + + do { + while (atomic_read(&device->irqHandling)) { + /* wait until irq handler finished all the jobs */ + schedule_timeout(HZ/10); + } + /* check if there is any pending irq due to force done */ + host_int_status = 0; + status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS, + (u8 *)&host_int_status, sizeof(host_int_status), + HIF_RD_SYNC_BYTE_INC, NULL); + host_int_status = !status ? (host_int_status & (1 << 0)) : 0; + if (host_int_status) { + schedule(); /* schedule for next dsrHandler */ + } + } while (host_int_status && --cnt > 0); + + if (host_int_status && cnt == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("AR6000: %s(), Unable clear up pending IRQ before the system suspended\n", __FUNCTION__)); + } + + return 0; +} + +static void +delHifDevice(struct hif_device * device) +{ + AR_DEBUG_ASSERT(device!= NULL); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device)); + kfree(device->dma_buffer); + kfree(device); +} + +static void ResetAllCards(void) +{ +} + +void HIFClaimDevice(struct hif_device *device, void *context) +{ + device->claimedContext = context; +} + +void HIFReleaseDevice(struct hif_device *device) +{ + device->claimedContext = NULL; +} + +int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks) +{ + if (device->htcCallbacks.context != NULL) { + /* already in use! */ + return A_ERROR; + } + device->htcCallbacks = *callbacks; + return 0; +} + +void HIFDetachHTC(struct hif_device *device) +{ + A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks)); +} + +#define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \ + (arg) = (((rw) & 1) << 31) | \ + (((func) & 0x7) << 28) | \ + (((raw) & 1) << 27) | \ + (1 << 26) | \ + (((address) & 0x1FFFF) << 9) | \ + (1 << 8) | \ + ((writedata) & 0xFF) + +#define SDIO_SET_CMD52_READ_ARG(arg,func,address) \ + SDIO_SET_CMD52_ARG(arg,0,(func),0,address,0x00) +#define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \ + SDIO_SET_CMD52_ARG(arg,1,(func),0,address,value) + +static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte) +{ + struct mmc_command ioCmd; + unsigned long arg; + + memset(&ioCmd,0,sizeof(ioCmd)); + SDIO_SET_CMD52_WRITE_ARG(arg,0,address,byte); + ioCmd.opcode = SD_IO_RW_DIRECT; + ioCmd.arg = arg; + ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC; + + return mmc_wait_for_cmd(card->host, &ioCmd, 0); +} + +static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte) +{ + struct mmc_command ioCmd; + unsigned long arg; + s32 err; + + memset(&ioCmd,0,sizeof(ioCmd)); + SDIO_SET_CMD52_READ_ARG(arg,0,address); + ioCmd.opcode = SD_IO_RW_DIRECT; + ioCmd.arg = arg; + ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC; + + err = mmc_wait_for_cmd(card->host, &ioCmd, 0); + + if ((!err) && (byte)) { + *byte = ioCmd.resp[0] & 0xFF; + } + + return err; +} diff --git a/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c new file mode 100644 index 000000000000..7516d913dab3 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c @@ -0,0 +1,393 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HIF scatter implementation +// +// Author(s): ="Atheros" +//============================================================================== + +#include +#include +#include +#include +#include +#include +#include "hif_internal.h" +#define ATH_MODULE_NAME hif +#include "a_debug.h" + +#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT + +#define _CMD53_ARG_READ 0 +#define _CMD53_ARG_WRITE 1 +#define _CMD53_ARG_BLOCK_BASIS 1 +#define _CMD53_ARG_FIXED_ADDRESS 0 +#define _CMD53_ARG_INCR_ADDRESS 1 + +#define SDIO_SET_CMD53_ARG(arg,rw,func,mode,opcode,address,bytes_blocks) \ + (arg) = (((rw) & 1) << 31) | \ + (((func) & 0x7) << 28) | \ + (((mode) & 1) << 27) | \ + (((opcode) & 1) << 26) | \ + (((address) & 0x1FFFF) << 9) | \ + ((bytes_blocks) & 0x1FF) + +static void FreeScatterReq(struct hif_device *device, struct hif_scatter_req *pReq) +{ + unsigned long flag; + + spin_lock_irqsave(&device->lock, flag); + + DL_ListInsertTail(&device->ScatterReqHead, &pReq->ListLink); + + spin_unlock_irqrestore(&device->lock, flag); + +} + +static struct hif_scatter_req *AllocScatterReq(struct hif_device *device) +{ + struct dl_list *pItem; + unsigned long flag; + + spin_lock_irqsave(&device->lock, flag); + + pItem = DL_ListRemoveItemFromHead(&device->ScatterReqHead); + + spin_unlock_irqrestore(&device->lock, flag); + + if (pItem != NULL) { + return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink); + } + + return NULL; +} + + /* called by async task to perform the operation synchronously using direct MMC APIs */ +int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest) +{ + int i; + u8 rw; + u8 opcode; + struct mmc_request mmcreq; + struct mmc_command cmd; + struct mmc_data data; + struct hif_scatter_req_priv *pReqPriv; + struct hif_scatter_req *pReq; + int status = 0; + struct scatterlist *pSg; + + pReqPriv = busrequest->pScatterReq; + + A_ASSERT(pReqPriv != NULL); + + pReq = pReqPriv->pHifScatterReq; + + memset(&mmcreq, 0, sizeof(struct mmc_request)); + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + + data.blksz = HIF_MBOX_BLOCK_SIZE; + data.blocks = pReq->TotalLength / HIF_MBOX_BLOCK_SIZE; + + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: (%s) Address: 0x%X, (BlockLen: %d, BlockCount: %d) , (tot:%d,sg:%d)\n", + (pReq->Request & HIF_WRITE) ? "WRITE":"READ", pReq->Address, data.blksz, data.blocks, + pReq->TotalLength,pReq->ValidScatterEntries)); + + if (pReq->Request & HIF_WRITE) { + rw = _CMD53_ARG_WRITE; + data.flags = MMC_DATA_WRITE; + } else { + rw = _CMD53_ARG_READ; + data.flags = MMC_DATA_READ; + } + + if (pReq->Request & HIF_FIXED_ADDRESS) { + opcode = _CMD53_ARG_FIXED_ADDRESS; + } else { + opcode = _CMD53_ARG_INCR_ADDRESS; + } + + /* fill SG entries */ + pSg = pReqPriv->sgentries; + sg_init_table(pSg, pReq->ValidScatterEntries); + + /* assemble SG list */ + for (i = 0 ; i < pReq->ValidScatterEntries ; i++, pSg++) { + /* setup each sg entry */ + if ((unsigned long)pReq->ScatterList[i].pBuffer & 0x3) { + /* note some scatter engines can handle unaligned buffers, print this + * as informational only */ + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, + ("HIF: (%s) Scatter Buffer is unaligned 0x%lx\n", + pReq->Request & HIF_WRITE ? "WRITE":"READ", + (unsigned long)pReq->ScatterList[i].pBuffer)); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, (" %d: Addr:0x%lX, Len:%d \n", + i,(unsigned long)pReq->ScatterList[i].pBuffer,pReq->ScatterList[i].Length)); + + sg_set_buf(pSg, pReq->ScatterList[i].pBuffer, pReq->ScatterList[i].Length); + } + /* set scatter-gather table for request */ + data.sg = pReqPriv->sgentries; + data.sg_len = pReq->ValidScatterEntries; + /* set command argument */ + SDIO_SET_CMD53_ARG(cmd.arg, + rw, + device->func->num, + _CMD53_ARG_BLOCK_BASIS, + opcode, + pReq->Address, + data.blocks); + + cmd.opcode = SD_IO_RW_EXTENDED; + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + mmcreq.cmd = &cmd; + mmcreq.data = &data; + + mmc_set_data_timeout(&data, device->func->card); + /* synchronous call to process request */ + mmc_wait_for_req(device->func->card->host, &mmcreq); + + if (cmd.error) { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: cmd error: %d \n",cmd.error)); + } + + if (data.error) { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: data error: %d \n",data.error)); + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: FAILED!!! (%s) Address: 0x%X, Block mode (BlockLen: %d, BlockCount: %d)\n", + (pReq->Request & HIF_WRITE) ? "WRITE":"READ",pReq->Address, data.blksz, data.blocks)); + } + + /* set completion status, fail or success */ + pReq->CompletionStatus = status; + + if (pReq->Request & HIF_ASYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: async_task completion routine req: 0x%lX (%d)\n",(unsigned long)busrequest, status)); + /* complete the request */ + A_ASSERT(pReq->CompletionRoutine != NULL); + pReq->CompletionRoutine(pReq); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER async_task upping busrequest : 0x%lX (%d)\n", (unsigned long)busrequest,status)); + /* signal wait */ + up(&busrequest->sem_req); + } + + return status; +} + + /* callback to issue a read-write scatter request */ +static int HifReadWriteScatter(struct hif_device *device, struct hif_scatter_req *pReq) +{ + int status = A_EINVAL; + u32 request = pReq->Request; + struct hif_scatter_req_priv *pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0]; + + do { + + A_ASSERT(pReqPriv != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: total len: %d Scatter Entries: %d\n", + pReq->TotalLength, pReq->ValidScatterEntries)); + + if (!(request & HIF_EXTENDED_IO)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid command type: 0x%08x\n", request)); + break; + } + + if (!(request & (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS))) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid execution mode: 0x%08x\n", request)); + break; + } + + if (!(request & HIF_BLOCK_BASIS)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid data mode: 0x%08x\n", request)); + break; + } + + if (pReq->TotalLength > MAX_SCATTER_REQ_TRANSFER_SIZE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("HIF-SCATTER: Invalid length: %d \n", pReq->TotalLength)); + break; + } + + if (pReq->TotalLength == 0) { + A_ASSERT(false); + break; + } + + /* add bus request to the async list for the async I/O thread to process */ + AddToAsyncList(device, pReqPriv->busrequest); + + if (request & HIF_SYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued sync req: 0x%lX\n", (unsigned long)pReqPriv->busrequest)); + /* signal thread and wait */ + up(&device->sem_async); + if (down_interruptible(&pReqPriv->busrequest->sem_req) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,("HIF-SCATTER: interrupted! \n")); + /* interrupted, exit */ + status = A_ERROR; + break; + } else { + status = pReq->CompletionStatus; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued async req: 0x%lX\n", (unsigned long)pReqPriv->busrequest)); + /* wake thread, it will process and then take care of the async callback */ + up(&device->sem_async); + status = 0; + } + + } while (false); + + if (status && (request & HIF_ASYNCHRONOUS)) { + pReq->CompletionStatus = status; + pReq->CompletionRoutine(pReq); + status = 0; + } + + return status; +} + + /* setup of HIF scatter resources */ +int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo) +{ + int status = A_ERROR; + int i; + struct hif_scatter_req_priv *pReqPriv; + BUS_REQUEST *busrequest; + + do { + + /* check if host supports scatter requests and it meets our requirements */ + if (device->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : host only supports scatter of : %d entries, need: %d \n", + device->func->card->host->max_segs, MAX_SCATTER_ENTRIES_PER_REQ)); + status = A_ENOTSUP; + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HIF-SCATTER Enabled: max scatter req : %d entries: %d \n", + MAX_SCATTER_REQUESTS, MAX_SCATTER_ENTRIES_PER_REQ)); + + for (i = 0; i < MAX_SCATTER_REQUESTS; i++) { + /* allocate the private request blob */ + pReqPriv = (struct hif_scatter_req_priv *)A_MALLOC(sizeof(struct hif_scatter_req_priv)); + if (NULL == pReqPriv) { + break; + } + A_MEMZERO(pReqPriv, sizeof(struct hif_scatter_req_priv)); + /* save the device instance*/ + pReqPriv->device = device; + /* allocate the scatter request */ + pReqPriv->pHifScatterReq = (struct hif_scatter_req *)A_MALLOC(sizeof(struct hif_scatter_req) + + (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item))); + + if (NULL == pReqPriv->pHifScatterReq) { + kfree(pReqPriv); + break; + } + /* just zero the main part of the scatter request */ + A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(struct hif_scatter_req)); + /* back pointer to the private struct */ + pReqPriv->pHifScatterReq->HIFPrivate[0] = pReqPriv; + /* allocate a bus request for this scatter request */ + busrequest = hifAllocateBusRequest(device); + if (NULL == busrequest) { + kfree(pReqPriv->pHifScatterReq); + kfree(pReqPriv); + break; + } + /* assign the scatter request to this bus request */ + busrequest->pScatterReq = pReqPriv; + /* point back to the request */ + pReqPriv->busrequest = busrequest; + /* add it to the scatter pool */ + FreeScatterReq(device,pReqPriv->pHifScatterReq); + } + + if (i != MAX_SCATTER_REQUESTS) { + status = A_NO_MEMORY; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : failed to alloc scatter resources !\n")); + break; + } + + /* set scatter function pointers */ + pInfo->pAllocateReqFunc = AllocScatterReq; + pInfo->pFreeReqFunc = FreeScatterReq; + pInfo->pReadWriteScatterFunc = HifReadWriteScatter; + pInfo->MaxScatterEntries = MAX_SCATTER_ENTRIES_PER_REQ; + pInfo->MaxTransferSizePerScatterReq = MAX_SCATTER_REQ_TRANSFER_SIZE; + + status = 0; + + } while (false); + + if (status) { + CleanupHIFScatterResources(device); + } + + return status; +} + + /* clean up scatter support */ +void CleanupHIFScatterResources(struct hif_device *device) +{ + struct hif_scatter_req_priv *pReqPriv; + struct hif_scatter_req *pReq; + + /* empty the free list */ + + while (1) { + + pReq = AllocScatterReq(device); + + if (NULL == pReq) { + break; + } + + pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0]; + A_ASSERT(pReqPriv != NULL); + + if (pReqPriv->busrequest != NULL) { + pReqPriv->busrequest->pScatterReq = NULL; + /* free bus request */ + hifFreeBusRequest(device, pReqPriv->busrequest); + pReqPriv->busrequest = NULL; + } + + if (pReqPriv->pHifScatterReq != NULL) { + kfree(pReqPriv->pHifScatterReq); + pReqPriv->pHifScatterReq = NULL; + } + + kfree(pReqPriv); + } +} + +#endif // HIF_LINUX_MMC_SCATTER_SUPPORT diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.c b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.c new file mode 100644 index 000000000000..f8607bc08929 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.c @@ -0,0 +1,1479 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// AR6K device layer that handles register level I/O +// +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "hw/mbox_host_reg.h" +#include "a_osapi.h" +#include "../htc_debug.h" +#include "hif.h" +#include "htc_packet.h" +#include "ar6k.h" + +#define MAILBOX_FOR_BLOCK_SIZE 1 + +int DevEnableInterrupts(struct ar6k_device *pDev); +int DevDisableInterrupts(struct ar6k_device *pDev); + +static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev); + +void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket) +{ + LOCK_AR6K(pDev); + HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket); + UNLOCK_AR6K(pDev); +} + +struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev) +{ + struct htc_packet *pPacket; + + LOCK_AR6K(pDev); + pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList); + UNLOCK_AR6K(pDev); + + return pPacket; +} + +void DevCleanup(struct ar6k_device *pDev) +{ + DevCleanupGMbox(pDev); + + if (pDev->HifAttached) { + HIFDetachHTC(pDev->HIFDevice); + pDev->HifAttached = false; + } + + DevCleanupVirtualScatterSupport(pDev); + + if (A_IS_MUTEX_VALID(&pDev->Lock)) { + A_MUTEX_DELETE(&pDev->Lock); + } +} + +int DevSetup(struct ar6k_device *pDev) +{ + u32 blocksizes[AR6K_MAILBOXES]; + int status = 0; + int i; + HTC_CALLBACKS htcCallbacks; + + do { + + DL_LIST_INIT(&pDev->ScatterReqHead); + /* initialize our free list of IO packets */ + INIT_HTC_PACKET_QUEUE(&pDev->RegisterIOList); + A_MUTEX_INIT(&pDev->Lock); + + A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS)); + /* the device layer handles these */ + htcCallbacks.rwCompletionHandler = DevRWCompletionHandler; + htcCallbacks.dsrHandler = DevDsrHandler; + htcCallbacks.context = pDev; + + status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks); + + if (status) { + break; + } + + pDev->HifAttached = true; + + /* get the addresses for all 4 mailboxes */ + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR, + &pDev->MailBoxInfo, sizeof(pDev->MailBoxInfo)); + + if (status) { + A_ASSERT(false); + break; + } + + /* carve up register I/O packets (these are for ASYNC register I/O ) */ + for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) { + struct htc_packet *pIOPacket; + pIOPacket = &pDev->RegIOBuffers[i].HtcPacket; + SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket, + pDev, + pDev->RegIOBuffers[i].Buffer, + AR6K_REG_IO_BUFFER_SIZE, + 0); /* don't care */ + AR6KFreeIOPacket(pDev,pIOPacket); + } + + /* get the block sizes */ + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + blocksizes, sizeof(blocksizes)); + + if (status) { + A_ASSERT(false); + break; + } + + /* note: we actually get the block size of a mailbox other than 0, for SDIO the block + * size on mailbox 0 is artificially set to 1. So we use the block size that is set + * for the other 3 mailboxes */ + pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE]; + /* must be a power of 2 */ + A_ASSERT((pDev->BlockSize & (pDev->BlockSize - 1)) == 0); + + /* assemble mask, used for padding to a block */ + pDev->BlockMask = pDev->BlockSize - 1; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("BlockSize: %d, MailboxAddress:0x%X \n", + pDev->BlockSize, pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX])); + + pDev->GetPendingEventsFunc = NULL; + /* see if the HIF layer implements the get pending events function */ + HIFConfigureDevice(pDev->HIFDevice, + HIF_DEVICE_GET_PENDING_EVENTS_FUNC, + &pDev->GetPendingEventsFunc, + sizeof(pDev->GetPendingEventsFunc)); + + /* assume we can process HIF interrupt events asynchronously */ + pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC; + + /* see if the HIF layer overrides this assumption */ + HIFConfigureDevice(pDev->HIFDevice, + HIF_DEVICE_GET_IRQ_PROC_MODE, + &pDev->HifIRQProcessingMode, + sizeof(pDev->HifIRQProcessingMode)); + + switch (pDev->HifIRQProcessingMode) { + case HIF_DEVICE_IRQ_SYNC_ONLY: + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HIF Interrupt processing is SYNC ONLY\n")); + /* see if HIF layer wants HTC to yield */ + HIFConfigureDevice(pDev->HIFDevice, + HIF_DEVICE_GET_IRQ_YIELD_PARAMS, + &pDev->HifIRQYieldParams, + sizeof(pDev->HifIRQYieldParams)); + + if (pDev->HifIRQYieldParams.RecvPacketYieldCount > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("HIF requests that DSR yield per %d RECV packets \n", + pDev->HifIRQYieldParams.RecvPacketYieldCount)); + pDev->DSRCanYield = true; + } + break; + case HIF_DEVICE_IRQ_ASYNC_SYNC: + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n")); + break; + default: + A_ASSERT(false); + } + + pDev->HifMaskUmaskRecvEvent = NULL; + + /* see if the HIF layer implements the mask/unmask recv events function */ + HIFConfigureDevice(pDev->HIFDevice, + HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, + &pDev->HifMaskUmaskRecvEvent, + sizeof(pDev->HifMaskUmaskRecvEvent)); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%lX , 0x%lX\n", + (unsigned long)pDev->GetPendingEventsFunc, (unsigned long)pDev->HifMaskUmaskRecvEvent)); + + status = DevDisableInterrupts(pDev); + + if (status) { + break; + } + + status = DevSetupGMbox(pDev); + + } while (false); + + if (status) { + if (pDev->HifAttached) { + HIFDetachHTC(pDev->HIFDevice); + pDev->HifAttached = false; + } + } + + return status; + +} + +int DevEnableInterrupts(struct ar6k_device *pDev) +{ + int status; + struct ar6k_irq_enable_registers regs; + + LOCK_AR6K(pDev); + + /* Enable all the interrupts except for the internal AR6000 CPU interrupt */ + pDev->IrqEnableRegisters.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) | + INT_STATUS_ENABLE_CPU_SET(0x01) | + INT_STATUS_ENABLE_COUNTER_SET(0x01); + + if (NULL == pDev->GetPendingEventsFunc) { + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); + } else { + /* The HIF layer provided us with a pending events function which means that + * the detection of pending mbox messages is handled in the HIF layer. + * This is the case for the SPI2 interface. + * In the normal case we enable MBOX interrupts, for the case + * with HIFs that offer this mechanism, we keep these interrupts + * masked */ + pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); + } + + + /* Set up the CPU Interrupt Status Register */ + pDev->IrqEnableRegisters.cpu_int_status_enable = CPU_INT_STATUS_ENABLE_BIT_SET(0x00); + + /* Set up the Error Interrupt Status Register */ + pDev->IrqEnableRegisters.error_status_enable = + ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) | + ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01); + + /* Set up the Counter Interrupt Status Register (only for debug interrupt to catch fatal errors) */ + pDev->IrqEnableRegisters.counter_int_status_enable = + COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK); + + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + + UNLOCK_AR6K(pDev); + + /* always synchronous */ + status = HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_enable, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + /* Can't write it for some reason */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Failed to update interrupt control registers err: %d\n", status)); + + } + + return status; +} + +int DevDisableInterrupts(struct ar6k_device *pDev) +{ + struct ar6k_irq_enable_registers regs; + + LOCK_AR6K(pDev); + /* Disable all interrupts */ + pDev->IrqEnableRegisters.int_status_enable = 0; + pDev->IrqEnableRegisters.cpu_int_status_enable = 0; + pDev->IrqEnableRegisters.error_status_enable = 0; + pDev->IrqEnableRegisters.counter_int_status_enable = 0; + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + + UNLOCK_AR6K(pDev); + + /* always synchronous */ + return HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_enable, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_SYNC_BYTE_INC, + NULL); +} + +/* enable device interrupts */ +int DevUnmaskInterrupts(struct ar6k_device *pDev) +{ + /* for good measure, make sure interrupt are disabled before unmasking at the HIF + * layer. + * The rationale here is that between device insertion (where we clear the interrupts the first time) + * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets. + * The AR6K interrupt enables reset back to an "enabled" state when this happens. + * */ + int IntStatus = 0; + DevDisableInterrupts(pDev); + +#ifdef THREAD_X + // Tobe verified... + IntStatus = DevEnableInterrupts(pDev); + /* Unmask the host controller interrupts */ + HIFUnMaskInterrupt(pDev->HIFDevice); +#else + /* Unmask the host controller interrupts */ + HIFUnMaskInterrupt(pDev->HIFDevice); + IntStatus = DevEnableInterrupts(pDev); +#endif + + return IntStatus; +} + +/* disable all device interrupts */ +int DevMaskInterrupts(struct ar6k_device *pDev) +{ + /* mask the interrupt at the HIF layer, we don't want a stray interrupt taken while + * we zero out our shadow registers in DevDisableInterrupts()*/ + HIFMaskInterrupt(pDev->HIFDevice); + + return DevDisableInterrupts(pDev); +} + +/* callback when our fetch to enable/disable completes */ +static void DevDoEnableDisableRecvAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" Failed to disable receiver, status:%d \n", pPacket->Status)); + } + /* free this IO packet */ + AR6KFreeIOPacket(pDev,pPacket); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDoEnableDisableRecvAsyncHandler \n")); +} + +/* disable packet reception (used in case the host runs out of buffers) + * this is the "override" method when the HIF reports another methods to + * disable recv events */ +static int DevDoEnableDisableRecvOverride(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode) +{ + int status = 0; + struct htc_packet *pIOPacket = NULL; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n", + EnableRecv,AsyncMode)); + + do { + + if (AsyncMode) { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler; + pIOPacket->pContext = pDev; + + /* call the HIF layer override and do this asynchronously */ + status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice, + EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV, + pIOPacket); + break; + } + + /* if we get here we are doing it synchronously */ + status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice, + EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV, + NULL); + + } while (false); + + if (status && (pIOPacket != NULL)) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + + return status; +} + +/* disable packet reception (used in case the host runs out of buffers) + * this is the "normal" method using the interrupt enable registers through + * the host I/F */ +static int DevDoEnableDisableRecvNormal(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode) +{ + int status = 0; + struct htc_packet *pIOPacket = NULL; + struct ar6k_irq_enable_registers regs; + + /* take the lock to protect interrupt enable shadows */ + LOCK_AR6K(pDev); + + if (EnableRecv) { + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); + } else { + pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); + } + + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + UNLOCK_AR6K(pDev); + + do { + + if (AsyncMode) { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* copy values to write to our async I/O buffer */ + memcpy(pIOPacket->pBuffer,®s,AR6K_IRQ_ENABLE_REGS_SIZE); + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler; + pIOPacket->pContext = pDev; + + /* write it out asynchronously */ + HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + pIOPacket->pBuffer, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_ASYNC_BYTE_INC, + pIOPacket); + break; + } + + /* if we get here we are doing it synchronously */ + + status = HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_enable, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_SYNC_BYTE_INC, + NULL); + + } while (false); + + if (status && (pIOPacket != NULL)) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + + return status; +} + + +int DevStopRecv(struct ar6k_device *pDev, bool AsyncMode) +{ + if (NULL == pDev->HifMaskUmaskRecvEvent) { + return DevDoEnableDisableRecvNormal(pDev,false,AsyncMode); + } else { + return DevDoEnableDisableRecvOverride(pDev,false,AsyncMode); + } +} + +int DevEnableRecv(struct ar6k_device *pDev, bool AsyncMode) +{ + if (NULL == pDev->HifMaskUmaskRecvEvent) { + return DevDoEnableDisableRecvNormal(pDev,true,AsyncMode); + } else { + return DevDoEnableDisableRecvOverride(pDev,true,AsyncMode); + } +} + +int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending) +{ + int status = 0; + u8 host_int_status = 0x0; + u32 counter = 0x0; + + if(TimeoutInMs < 100) + { + TimeoutInMs = 100; + } + + counter = TimeoutInMs / 100; + + do + { + //Read the Host Interrupt Status Register + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + &host_int_status, + sizeof(u8), + HIF_RD_SYNC_BYTE_INC, + NULL); + if (status) + { + AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status)); + break; + } + + host_int_status = !status ? (host_int_status & (1 << 0)):0; + if(!host_int_status) + { + status = 0; + *pbIsRecvPending = false; + break; + } + else + { + *pbIsRecvPending = true; + } + + A_MDELAY(100); + + counter--; + + }while(counter); + return status; +} + +void DevDumpRegisters(struct ar6k_device *pDev, + struct ar6k_irq_proc_registers *pIrqProcRegs, + struct ar6k_irq_enable_registers *pIrqEnableRegs) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\n<------- Register Table -------->\n")); + + if (pIrqProcRegs != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Host Int Status: 0x%x\n",pIrqProcRegs->host_int_status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("CPU Int Status: 0x%x\n",pIrqProcRegs->cpu_int_status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Error Int Status: 0x%x\n",pIrqProcRegs->error_int_status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Counter Int Status: 0x%x\n",pIrqProcRegs->counter_int_status)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Mbox Frame: 0x%x\n",pIrqProcRegs->mbox_frame)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Rx Lookahead Valid: 0x%x\n",pIrqProcRegs->rx_lookahead_valid)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Rx Lookahead 0: 0x%x\n",pIrqProcRegs->rx_lookahead[0])); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Rx Lookahead 1: 0x%x\n",pIrqProcRegs->rx_lookahead[1])); + + if (pDev->MailBoxInfo.GMboxAddress != 0) { + /* if the target supports GMBOX hardware, dump some additional state */ + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("GMBOX Host Int Status 2: 0x%x\n",pIrqProcRegs->host_int_status2)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("GMBOX RX Avail: 0x%x\n",pIrqProcRegs->gmbox_rx_avail)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("GMBOX lookahead alias 0: 0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[0])); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("GMBOX lookahead alias 1: 0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[1])); + } + + } + + if (pIrqEnableRegs != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Int Status Enable: 0x%x\n",pIrqEnableRegs->int_status_enable)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("Counter Int Status Enable: 0x%x\n",pIrqEnableRegs->counter_int_status_enable)); + } + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<------------------------------->\n")); +} + + +#define DEV_GET_VIRT_DMA_INFO(p) ((struct dev_scatter_dma_virtual_info *)((p)->HIFPrivate[0])) + +static struct hif_scatter_req *DevAllocScatterReq(struct hif_device *Context) +{ + struct dl_list *pItem; + struct ar6k_device *pDev = (struct ar6k_device *)Context; + LOCK_AR6K(pDev); + pItem = DL_ListRemoveItemFromHead(&pDev->ScatterReqHead); + UNLOCK_AR6K(pDev); + if (pItem != NULL) { + return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink); + } + return NULL; +} + +static void DevFreeScatterReq(struct hif_device *Context, struct hif_scatter_req *pReq) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + LOCK_AR6K(pDev); + DL_ListInsertTail(&pDev->ScatterReqHead, &pReq->ListLink); + UNLOCK_AR6K(pDev); +} + +int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA) +{ + u8 *pDMABuffer = NULL; + int i, remaining; + u32 length; + + pDMABuffer = pReq->pScatterBounceBuffer; + + if (pDMABuffer == NULL) { + A_ASSERT(false); + return A_EINVAL; + } + + remaining = (int)pReq->TotalLength; + + for (i = 0; i < pReq->ValidScatterEntries; i++) { + + length = min((int)pReq->ScatterList[i].Length, remaining); + + if (length != (int)pReq->ScatterList[i].Length) { + A_ASSERT(false); + /* there is a problem with the scatter list */ + return A_EINVAL; + } + + if (FromDMA) { + /* from DMA buffer */ + memcpy(pReq->ScatterList[i].pBuffer, pDMABuffer , length); + } else { + /* to DMA buffer */ + memcpy(pDMABuffer, pReq->ScatterList[i].pBuffer, length); + } + + pDMABuffer += length; + remaining -= length; + } + + return 0; +} + +static void DevReadWriteScatterAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + struct hif_scatter_req *pReq = (struct hif_scatter_req *)pPacket->pPktContext; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevReadWriteScatterAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + pReq->CompletionStatus = pPacket->Status; + + AR6KFreeIOPacket(pDev,pPacket); + + pReq->CompletionRoutine(pReq); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevReadWriteScatterAsyncHandler \n")); +} + +static int DevReadWriteScatter(struct hif_device *Context, struct hif_scatter_req *pReq) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + int status = 0; + struct htc_packet *pIOPacket = NULL; + u32 request = pReq->Request; + + do { + + if (pReq->TotalLength > AR6K_MAX_TRANSFER_SIZE_PER_SCATTER) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Invalid length: %d \n", pReq->TotalLength)); + break; + } + + if (pReq->TotalLength == 0) { + A_ASSERT(false); + break; + } + + if (request & HIF_ASYNCHRONOUS) { + /* use an I/O packet to carry this request */ + pIOPacket = AR6KAllocIOPacket(pDev); + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + break; + } + + /* save the request */ + pIOPacket->pPktContext = pReq; + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevReadWriteScatterAsyncHandler; + pIOPacket->pContext = pDev; + } + + if (request & HIF_WRITE) { + /* in virtual DMA, we are issuing the requests through the legacy HIFReadWrite API + * this API will adjust the address automatically for the last byte to fall on the mailbox + * EOM. */ + + /* if the address is an extended address, we can adjust the address here since the extended + * address will bypass the normal checks in legacy HIF layers */ + if (pReq->Address == pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress) { + pReq->Address += pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize - pReq->TotalLength; + } + } + + /* use legacy readwrite */ + status = HIFReadWrite(pDev->HIFDevice, + pReq->Address, + DEV_GET_VIRT_DMA_INFO(pReq)->pVirtDmaBuffer, + pReq->TotalLength, + request, + (request & HIF_ASYNCHRONOUS) ? pIOPacket : NULL); + + } while (false); + + if ((status != A_PENDING) && status && (request & HIF_ASYNCHRONOUS)) { + if (pIOPacket != NULL) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + pReq->CompletionStatus = status; + pReq->CompletionRoutine(pReq); + status = 0; + } + + return status; +} + + +static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev) +{ + struct hif_scatter_req *pReq; + + while (1) { + pReq = DevAllocScatterReq((struct hif_device *)pDev); + if (NULL == pReq) { + break; + } + kfree(pReq); + } + +} + + /* function to set up virtual scatter support if HIF layer has not implemented the interface */ +static int DevSetupVirtualScatterSupport(struct ar6k_device *pDev) +{ + int status = 0; + int bufferSize, sgreqSize; + int i; + struct dev_scatter_dma_virtual_info *pVirtualInfo; + struct hif_scatter_req *pReq; + + bufferSize = sizeof(struct dev_scatter_dma_virtual_info) + + 2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER; + + sgreqSize = sizeof(struct hif_scatter_req) + + (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item)); + + for (i = 0; i < AR6K_SCATTER_REQS; i++) { + /* allocate the scatter request, buffer info and the actual virtual buffer itself */ + pReq = (struct hif_scatter_req *)A_MALLOC(sgreqSize + bufferSize); + + if (NULL == pReq) { + status = A_NO_MEMORY; + break; + } + + A_MEMZERO(pReq, sgreqSize); + + /* the virtual DMA starts after the scatter request struct */ + pVirtualInfo = (struct dev_scatter_dma_virtual_info *)((u8 *)pReq + sgreqSize); + A_MEMZERO(pVirtualInfo, sizeof(struct dev_scatter_dma_virtual_info)); + + pVirtualInfo->pVirtDmaBuffer = &pVirtualInfo->DataArea[0]; + /* align buffer to cache line in case host controller can actually DMA this */ + pVirtualInfo->pVirtDmaBuffer = A_ALIGN_TO_CACHE_LINE(pVirtualInfo->pVirtDmaBuffer); + /* store the structure in the private area */ + pReq->HIFPrivate[0] = pVirtualInfo; + /* we emulate a DMA bounce interface */ + pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE; + pReq->pScatterBounceBuffer = pVirtualInfo->pVirtDmaBuffer; + /* free request to the list */ + DevFreeScatterReq((struct hif_device *)pDev,pReq); + } + + if (status) { + DevCleanupVirtualScatterSupport(pDev); + } else { + pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq; + pDev->HifScatterInfo.pFreeReqFunc = DevFreeScatterReq; + pDev->HifScatterInfo.pReadWriteScatterFunc = DevReadWriteScatter; + if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K: SPI bus requires RX scatter limits\n")); + pDev->HifScatterInfo.MaxScatterEntries = AR6K_MIN_SCATTER_ENTRIES_PER_REQ; + pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MIN_TRANSFER_SIZE_PER_SCATTER; + } else { + pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ; + pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER; + } + pDev->ScatterIsVirtual = true; + } + + return status; +} + +int DevCleanupMsgBundling(struct ar6k_device *pDev) +{ + if(NULL != pDev) + { + DevCleanupVirtualScatterSupport(pDev); + } + + return 0; +} + +int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer) +{ + int status; + + if (pDev->MailBoxInfo.Flags & HIF_MBOX_FLAG_NO_BUNDLING) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n")); + return A_ENOTSUP; + } + + status = HIFConfigureDevice(pDev->HIFDevice, + HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT, + &pDev->HifScatterInfo, + sizeof(pDev->HifScatterInfo)); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("AR6K: ** HIF layer does not support scatter requests (%d) \n",status)); + + /* we can try to use a virtual DMA scatter mechanism using legacy HIFReadWrite() */ + status = DevSetupVirtualScatterSupport(pDev); + + if (!status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR6K: virtual scatter transfers enabled (max scatter items:%d: maxlen:%d) \n", + DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev))); + } + + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR6K: HIF layer supports scatter requests (max scatter items:%d: maxlen:%d) \n", + DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev))); + } + + if (!status) { + /* for the recv path, the maximum number of bytes per recv bundle is just limited + * by the maximum transfer size at the HIF layer */ + pDev->MaxRecvBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq; + + if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K : SPI bus requires TX bundling disabled\n")); + pDev->MaxSendBundleSize = 0; + } else { + /* for the send path, the max transfer size is limited by the existence and size of + * the extended mailbox address range */ + if (pDev->MailBoxInfo.MboxProp[0].ExtendedAddress != 0) { + pDev->MaxSendBundleSize = pDev->MailBoxInfo.MboxProp[0].ExtendedSize; + } else { + /* legacy */ + pDev->MaxSendBundleSize = AR6K_LEGACY_MAX_WRITE_LENGTH; + } + + if (pDev->MaxSendBundleSize > pDev->HifScatterInfo.MaxTransferSizePerScatterReq) { + /* limit send bundle size to what the HIF can support for scatter requests */ + pDev->MaxSendBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR6K: max recv: %d max send: %d \n", + DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev), DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev))); + + } + return status; +} + +int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async) +{ + int status; + + if (Read) { + /* read operation */ + pScatterReq->Request = (Async) ? HIF_RD_ASYNC_BLOCK_FIX : HIF_RD_SYNC_BLOCK_FIX; + pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX]; + A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev)); + } else { + u32 mailboxWidth; + + /* write operation */ + pScatterReq->Request = (Async) ? HIF_WR_ASYNC_BLOCK_INC : HIF_WR_SYNC_BLOCK_INC; + A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)); + if (pScatterReq->TotalLength > AR6K_LEGACY_MAX_WRITE_LENGTH) { + /* for large writes use the extended address */ + pScatterReq->Address = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress; + mailboxWidth = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize; + } else { + pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX]; + mailboxWidth = AR6K_LEGACY_MAX_WRITE_LENGTH; + } + + if (!pDev->ScatterIsVirtual) { + /* we are passing this scatter list down to the HIF layer' scatter request handler, fixup the address + * so that the last byte falls on the EOM, we do this for those HIFs that support the + * scatter API */ + pScatterReq->Address += (mailboxWidth - pScatterReq->TotalLength); + } + + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV | ATH_DEBUG_SEND, + ("DevSubmitScatterRequest, Entries: %d, Total Length: %d Mbox:0x%X (mode: %s : %s)\n", + pScatterReq->ValidScatterEntries, + pScatterReq->TotalLength, + pScatterReq->Address, + Async ? "ASYNC" : "SYNC", + (Read) ? "RD" : "WR")); + + status = DEV_PREPARE_SCATTER_OPERATION(pScatterReq); + + if (status) { + if (Async) { + pScatterReq->CompletionStatus = status; + pScatterReq->CompletionRoutine(pScatterReq); + return 0; + } + return status; + } + + status = pDev->HifScatterInfo.pReadWriteScatterFunc(pDev->ScatterIsVirtual ? pDev : pDev->HIFDevice, + pScatterReq); + if (!Async) { + /* in sync mode, we can touch the scatter request */ + pScatterReq->CompletionStatus = status; + DEV_FINISH_SCATTER_OPERATION(pScatterReq); + } else { + if (status == A_PENDING) { + status = 0; + } + } + + return status; +} + + +#ifdef MBOXHW_UNIT_TEST + + +/* This is a mailbox hardware unit test that must be called in a schedulable context + * This test is very simple, it will send a list of buffers with a counting pattern + * and the target will invert the data and send the message back + * + * the unit test has the following constraints: + * + * The target has at least 8 buffers of 256 bytes each. The host will send + * the following pattern of buffers in rapid succession : + * + * 1 buffer - 128 bytes + * 1 buffer - 256 bytes + * 1 buffer - 512 bytes + * 1 buffer - 1024 bytes + * + * The host will send the buffers to one mailbox and wait for buffers to be reflected + * back from the same mailbox. The target sends the buffers FIFO order. + * Once the final buffer has been received for a mailbox, the next mailbox is tested. + * + * + * Note: To simplifythe test , we assume that the chosen buffer sizes + * will fall on a nice block pad + * + * It is expected that higher-order tests will be written to stress the mailboxes using + * a message-based protocol (with some performance timming) that can create more + * randomness in the packets sent over mailboxes. + * + * */ + +#define A_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1)) + +#define BUFFER_BLOCK_PAD 128 + +#if 0 +#define BUFFER1 128 +#define BUFFER2 256 +#define BUFFER3 512 +#define BUFFER4 1024 +#endif + +#if 1 +#define BUFFER1 80 +#define BUFFER2 200 +#define BUFFER3 444 +#define BUFFER4 800 +#endif + +#define TOTAL_BYTES (A_ROUND_UP_PWR2(BUFFER1,BUFFER_BLOCK_PAD) + \ + A_ROUND_UP_PWR2(BUFFER2,BUFFER_BLOCK_PAD) + \ + A_ROUND_UP_PWR2(BUFFER3,BUFFER_BLOCK_PAD) + \ + A_ROUND_UP_PWR2(BUFFER4,BUFFER_BLOCK_PAD) ) + +#define TEST_BYTES (BUFFER1 + BUFFER2 + BUFFER3 + BUFFER4) + +#define TEST_CREDITS_RECV_TIMEOUT 100 + +static u8 g_Buffer[TOTAL_BYTES]; +static u32 g_MailboxAddrs[AR6K_MAILBOXES]; +static u32 g_BlockSizes[AR6K_MAILBOXES]; + +#define BUFFER_PROC_LIST_DEPTH 4 + +struct buffer_proc_list { + u8 *pBuffer; + u32 length; +}; + + +#define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \ +{ \ + (pList)->pBuffer = (pCurrpos); \ + (pList)->length = (len); \ + (pCurrpos) += (len); \ + (pList)++; \ +} + +/* a simple and crude way to send different "message" sizes */ +static void AssembleBufferList(struct buffer_proc_list *pList) +{ + u8 *pBuffer = g_Buffer; + +#if BUFFER_PROC_LIST_DEPTH < 4 +#error "Buffer processing list depth is not deep enough!!" +#endif + + PUSH_BUFF_PROC_ENTRY(pList,BUFFER1,pBuffer); + PUSH_BUFF_PROC_ENTRY(pList,BUFFER2,pBuffer); + PUSH_BUFF_PROC_ENTRY(pList,BUFFER3,pBuffer); + PUSH_BUFF_PROC_ENTRY(pList,BUFFER4,pBuffer); + +} + +#define FILL_ZERO true +#define FILL_COUNTING false +static void InitBuffers(bool Zero) +{ + u16 *pBuffer16 = (u16 *)g_Buffer; + int i; + + /* fill buffer with 16 bit counting pattern or zeros */ + for (i = 0; i < (TOTAL_BYTES / 2) ; i++) { + if (!Zero) { + pBuffer16[i] = (u16)i; + } else { + pBuffer16[i] = 0; + } + } +} + + +static bool CheckOneBuffer(u16 *pBuffer16, int Length) +{ + int i; + u16 startCount; + bool success = true; + + /* get the starting count */ + startCount = pBuffer16[0]; + /* invert it, this is the expected value */ + startCount = ~startCount; + /* scan the buffer and verify */ + for (i = 0; i < (Length / 2) ; i++,startCount++) { + /* target will invert all the data */ + if ((u16)pBuffer16[i] != (u16)~startCount) { + success = false; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Data Got:0x%X, Expecting:0x%X (offset:%d, total:%d) \n", + pBuffer16[i], ((u16)~startCount), i, Length)); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("0x%X 0x%X 0x%X 0x%X \n", + pBuffer16[i], pBuffer16[i + 1], pBuffer16[i + 2],pBuffer16[i+3])); + break; + } + } + + return success; +} + +static bool CheckBuffers(void) +{ + int i; + bool success = true; + struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH]; + + /* assemble the list */ + AssembleBufferList(checkList); + + /* scan the buffers and verify */ + for (i = 0; i < BUFFER_PROC_LIST_DEPTH ; i++) { + success = CheckOneBuffer((u16 *)checkList[i].pBuffer, checkList[i].length); + if (!success) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n", + (u32)checkList[i].pBuffer, checkList[i].length)); + break; + } + } + + return success; +} + + /* find the end marker for the last buffer we will be sending */ +static u16 GetEndMarker(void) +{ + u8 *pBuffer; + struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH]; + + /* fill up buffers with the normal counting pattern */ + InitBuffers(FILL_COUNTING); + + /* assemble the list we will be sending down */ + AssembleBufferList(checkList); + /* point to the last 2 bytes of the last buffer */ + pBuffer = &(checkList[BUFFER_PROC_LIST_DEPTH - 1].pBuffer[(checkList[BUFFER_PROC_LIST_DEPTH - 1].length) - 2]); + + /* the last count in the last buffer is the marker */ + return (u16)pBuffer[0] | ((u16)pBuffer[1] << 8); +} + +#define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR + +/* send the ordered buffers to the target */ +static int SendBuffers(struct ar6k_device *pDev, int mbox) +{ + int status = 0; + u32 request = HIF_WR_SYNC_BLOCK_INC; + struct buffer_proc_list sendList[BUFFER_PROC_LIST_DEPTH]; + int i; + int totalBytes = 0; + int paddedLength; + int totalwPadding = 0; + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sending buffers on mailbox : %d \n",mbox)); + + /* fill buffer with counting pattern */ + InitBuffers(FILL_COUNTING); + + /* assemble the order in which we send */ + AssembleBufferList(sendList); + + for (i = 0; i < BUFFER_PROC_LIST_DEPTH; i++) { + + /* we are doing block transfers, so we need to pad everything to a block size */ + paddedLength = (sendList[i].length + (g_BlockSizes[mbox] - 1)) & + (~(g_BlockSizes[mbox] - 1)); + + /* send each buffer synchronously */ + status = HIFReadWrite(pDev->HIFDevice, + g_MailboxAddrs[mbox], + sendList[i].pBuffer, + paddedLength, + request, + NULL); + if (status) { + break; + } + totalBytes += sendList[i].length; + totalwPadding += paddedLength; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sent %d bytes (%d padded bytes) to mailbox : %d \n",totalBytes,totalwPadding,mbox)); + + return status; +} + +/* poll the mailbox credit counter until we get a credit or timeout */ +static int GetCredits(struct ar6k_device *pDev, int mbox, int *pCredits) +{ + int status = 0; + int timeout = TEST_CREDITS_RECV_TIMEOUT; + u8 credits = 0; + u32 address; + + while (true) { + + /* Read the counter register to get credits, this auto-decrements */ + address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4; + status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits), + HIF_RD_SYNC_BYTE_FIX, NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Unable to decrement the command credit count register (mbox=%d)\n",mbox)); + status = A_ERROR; + break; + } + + if (credits) { + break; + } + + timeout--; + + if (timeout <= 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" Timeout reading credit registers (mbox=%d, address:0x%X) \n",mbox,address)); + status = A_ERROR; + break; + } + + /* delay a little, target may not be ready */ + A_MDELAY(1000); + + } + + if (status == 0) { + *pCredits = credits; + } + + return status; +} + + +/* wait for the buffers to come back */ +static int RecvBuffers(struct ar6k_device *pDev, int mbox) +{ + int status = 0; + u32 request = HIF_RD_SYNC_BLOCK_INC; + struct buffer_proc_list recvList[BUFFER_PROC_LIST_DEPTH]; + int curBuffer; + int credits; + int i; + int totalBytes = 0; + int paddedLength; + int totalwPadding = 0; + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for buffers on mailbox : %d \n",mbox)); + + /* zero the buffers */ + InitBuffers(FILL_ZERO); + + /* assemble the order in which we should receive */ + AssembleBufferList(recvList); + + curBuffer = 0; + + while (curBuffer < BUFFER_PROC_LIST_DEPTH) { + + /* get number of buffers that have been completed, this blocks + * until we get at least 1 credit or it times out */ + status = GetCredits(pDev, mbox, &credits); + + if (status) { + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got %d messages on mailbox : %d \n",credits, mbox)); + + /* get all the buffers that are sitting on the queue */ + for (i = 0; i < credits; i++) { + A_ASSERT(curBuffer < BUFFER_PROC_LIST_DEPTH); + /* recv the current buffer synchronously, the buffers should come back in + * order... with padding applied by the target */ + paddedLength = (recvList[curBuffer].length + (g_BlockSizes[mbox] - 1)) & + (~(g_BlockSizes[mbox] - 1)); + + status = HIFReadWrite(pDev->HIFDevice, + g_MailboxAddrs[mbox], + recvList[curBuffer].pBuffer, + paddedLength, + request, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to read %d bytes on mailbox:%d : address:0x%X \n", + recvList[curBuffer].length, mbox, g_MailboxAddrs[mbox])); + break; + } + + totalwPadding += paddedLength; + totalBytes += recvList[curBuffer].length; + curBuffer++; + } + + if (status) { + break; + } + /* go back and get some more */ + credits = 0; + } + + if (totalBytes != TEST_BYTES) { + A_ASSERT(false); + } else { + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got all buffers on mbox:%d total recv :%d (w/Padding : %d) \n", + mbox, totalBytes, totalwPadding)); + } + + return status; + + +} + +static int DoOneMboxHWTest(struct ar6k_device *pDev, int mbox) +{ + int status; + + do { + /* send out buffers */ + status = SendBuffers(pDev,mbox); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox)); + break; + } + + /* go get them, this will block */ + status = RecvBuffers(pDev, mbox); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox)); + break; + } + + /* check the returned data patterns */ + if (!CheckBuffers()) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer Verify Failed : mbox:%d\n",mbox)); + status = A_ERROR; + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox)); + + } while (false); + + return status; +} + +/* here is where the test starts */ +int DoMboxHWTest(struct ar6k_device *pDev) +{ + int i; + int status; + int credits = 0; + u8 params[4]; + int numBufs; + int bufferSize; + u16 temp; + + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START - \n")); + + do { + /* get the addresses for all 4 mailboxes */ + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR, + g_MailboxAddrs, sizeof(g_MailboxAddrs)); + + if (status) { + A_ASSERT(false); + break; + } + + /* get the block sizes */ + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + g_BlockSizes, sizeof(g_BlockSizes)); + + if (status) { + A_ASSERT(false); + break; + } + + /* note, the HIF layer usually reports mbox 0 to have a block size of + * 1, but our test wants to run in block-mode for all mailboxes, so we treat all mailboxes + * the same. */ + g_BlockSizes[0] = g_BlockSizes[1]; + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Block Size to use: %d \n",g_BlockSizes[0])); + + if (g_BlockSizes[1] > BUFFER_BLOCK_PAD) { + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("%d Block size is too large for buffer pad %d\n", + g_BlockSizes[1], BUFFER_BLOCK_PAD)); + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for target.... \n")); + + /* the target lets us know it is ready by giving us 1 credit on + * mailbox 0 */ + status = GetCredits(pDev, 0, &credits); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Target is ready ...\n")); + + /* read the first 4 scratch registers */ + status = HIFReadWrite(pDev->HIFDevice, + SCRATCH_ADDRESS, + params, + 4, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n")); + break; + } + + numBufs = params[0]; + bufferSize = (int)(((u16)params[2] << 8) | (u16)params[1]); + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, + ("Target parameters: bufs per mailbox:%d, buffer size:%d bytes (total space: %d, minimum required space (w/padding): %d) \n", + numBufs, bufferSize, (numBufs * bufferSize), TOTAL_BYTES)); + + if ((numBufs * bufferSize) < TOTAL_BYTES) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Not Enough buffer space to run test! need:%d, got:%d \n", + TOTAL_BYTES, (numBufs*bufferSize))); + status = A_ERROR; + break; + } + + temp = GetEndMarker(); + + status = HIFReadWrite(pDev->HIFDevice, + SCRATCH_ADDRESS + 4, + (u8 *)&temp, + 2, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp)); + + temp = (u16)g_BlockSizes[1]; + /* convert to a mask */ + temp = temp - 1; + status = HIFReadWrite(pDev->HIFDevice, + SCRATCH_ADDRESS + 6, + (u8 *)&temp, + 2, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Set Block Mask: 0x%X \n",temp)); + + /* execute the test on each mailbox */ + for (i = 0; i < AR6K_MAILBOXES; i++) { + status = DoOneMboxHWTest(pDev, i); + if (status) { + break; + } + } + + } while (false); + + if (status == 0) { + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! - \n")); + } else { + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! - \n")); + } + /* don't let HTC_Start continue, the target is actually not running any HTC code */ + return A_ERROR; +} +#endif + + + diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.h b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.h new file mode 100644 index 000000000000..e551dbe674dc --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k.h @@ -0,0 +1,401 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// AR6K device layer that handles register level I/O +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef AR6K_H_ +#define AR6K_H_ + +#include "hci_transport_api.h" +#include "../htc_debug.h" + +#define AR6K_MAILBOXES 4 + +/* HTC runs over mailbox 0 */ +#define HTC_MAILBOX 0 + +#define AR6K_TARGET_DEBUG_INTR_MASK 0x01 + +#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \ + INT_STATUS_ENABLE_CPU_MASK | \ + INT_STATUS_ENABLE_COUNTER_MASK) + + +//#define MBOXHW_UNIT_TEST 1 + +PREPACK struct ar6k_irq_proc_registers { + u8 host_int_status; + u8 cpu_int_status; + u8 error_int_status; + u8 counter_int_status; + u8 mbox_frame; + u8 rx_lookahead_valid; + u8 host_int_status2; + u8 gmbox_rx_avail; + u32 rx_lookahead[2]; + u32 rx_gmbox_lookahead_alias[2]; +} POSTPACK; + +#define AR6K_IRQ_PROC_REGS_SIZE sizeof(struct ar6k_irq_proc_registers) + +PREPACK struct ar6k_irq_enable_registers { + u8 int_status_enable; + u8 cpu_int_status_enable; + u8 error_status_enable; + u8 counter_int_status_enable; +} POSTPACK; + +PREPACK struct ar6k_gmbox_ctrl_registers { + u8 int_status_enable; +} POSTPACK; + +#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(struct ar6k_irq_enable_registers) + +#define AR6K_REG_IO_BUFFER_SIZE 32 +#define AR6K_MAX_REG_IO_BUFFERS 8 +#define FROM_DMA_BUFFER true +#define TO_DMA_BUFFER false +#define AR6K_SCATTER_ENTRIES_PER_REQ 16 +#define AR6K_MAX_TRANSFER_SIZE_PER_SCATTER 16*1024 +#define AR6K_SCATTER_REQS 4 +#define AR6K_LEGACY_MAX_WRITE_LENGTH 2048 + +#ifndef A_CACHE_LINE_PAD +#define A_CACHE_LINE_PAD 128 +#endif +#define AR6K_MIN_SCATTER_ENTRIES_PER_REQ 2 +#define AR6K_MIN_TRANSFER_SIZE_PER_SCATTER 4*1024 + +/* buffers for ASYNC I/O */ +struct ar6k_async_reg_io_buffer { + struct htc_packet HtcPacket; /* we use an HTC packet as a wrapper for our async register-based I/O */ + u8 _Pad1[A_CACHE_LINE_PAD]; + u8 Buffer[AR6K_REG_IO_BUFFER_SIZE]; /* cache-line safe with pads around */ + u8 _Pad2[A_CACHE_LINE_PAD]; +}; + +struct ar6k_gmbox_info { + void *pProtocolContext; + int (*pMessagePendingCallBack)(void *pContext, u8 LookAheadBytes[], int ValidBytes); + int (*pCreditsPendingCallback)(void *pContext, int NumCredits, bool CreditIRQEnabled); + void (*pTargetFailureCallback)(void *pContext, int Status); + void (*pStateDumpCallback)(void *pContext); + bool CreditCountIRQEnabled; +}; + +struct ar6k_device { + A_MUTEX_T Lock; + u8 _Pad1[A_CACHE_LINE_PAD]; + struct ar6k_irq_proc_registers IrqProcRegisters; /* cache-line safe with pads around */ + u8 _Pad2[A_CACHE_LINE_PAD]; + struct ar6k_irq_enable_registers IrqEnableRegisters; /* cache-line safe with pads around */ + u8 _Pad3[A_CACHE_LINE_PAD]; + void *HIFDevice; + u32 BlockSize; + u32 BlockMask; + struct hif_device_mbox_info MailBoxInfo; + HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc; + void *HTCContext; + struct htc_packet_queue RegisterIOList; + struct ar6k_async_reg_io_buffer RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS]; + void (*TargetFailureCallback)(void *Context); + int (*MessagePendingCallback)(void *Context, + u32 LookAheads[], + int NumLookAheads, + bool *pAsyncProc, + int *pNumPktsFetched); + HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode; + HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent; + bool HifAttached; + struct hif_device_irq_yield_params HifIRQYieldParams; + bool DSRCanYield; + int CurrentDSRRecvCount; + struct hif_device_scatter_support_info HifScatterInfo; + struct dl_list ScatterReqHead; + bool ScatterIsVirtual; + int MaxRecvBundleSize; + int MaxSendBundleSize; + struct ar6k_gmbox_info GMboxInfo; + bool GMboxEnabled; + struct ar6k_gmbox_ctrl_registers GMboxControlRegisters; + int RecheckIRQStatusCnt; +}; + +#define LOCK_AR6K(p) A_MUTEX_LOCK(&(p)->Lock); +#define UNLOCK_AR6K(p) A_MUTEX_UNLOCK(&(p)->Lock); +#define REF_IRQ_STATUS_RECHECK(p) (p)->RecheckIRQStatusCnt = 1 /* note: no need to lock this, it only gets set */ + +int DevSetup(struct ar6k_device *pDev); +void DevCleanup(struct ar6k_device *pDev); +int DevUnmaskInterrupts(struct ar6k_device *pDev); +int DevMaskInterrupts(struct ar6k_device *pDev); +int DevPollMboxMsgRecv(struct ar6k_device *pDev, + u32 *pLookAhead, + int TimeoutMS); +int DevRWCompletionHandler(void *context, int status); +int DevDsrHandler(void *context); +int DevCheckPendingRecvMsgsAsync(void *context); +void DevAsyncIrqProcessComplete(struct ar6k_device *pDev); +void DevDumpRegisters(struct ar6k_device *pDev, + struct ar6k_irq_proc_registers *pIrqProcRegs, + struct ar6k_irq_enable_registers *pIrqEnableRegs); + +#define DEV_STOP_RECV_ASYNC true +#define DEV_STOP_RECV_SYNC false +#define DEV_ENABLE_RECV_ASYNC true +#define DEV_ENABLE_RECV_SYNC false +int DevStopRecv(struct ar6k_device *pDev, bool ASyncMode); +int DevEnableRecv(struct ar6k_device *pDev, bool ASyncMode); +int DevEnableInterrupts(struct ar6k_device *pDev); +int DevDisableInterrupts(struct ar6k_device *pDev); +int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending); + +#define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) & (~((pDev)->BlockMask))) +#define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,length) +#define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) == 0) + +static INLINE int DevSendPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 SendLength) { + u32 paddedLength; + bool sync = (pPacket->Completion == NULL) ? true : false; + int status; + + /* adjust the length to be a multiple of block size if appropriate */ + paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, SendLength); + +#if 0 + if (paddedLength > pPacket->BufferLength) { + A_ASSERT(false); + if (pPacket->Completion != NULL) { + COMPLETE_HTC_PACKET(pPacket,A_EINVAL); + return 0; + } + return A_EINVAL; + } +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n", + paddedLength, + pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], + sync ? "SYNC" : "ASYNC")); + + status = HIFReadWrite(pDev->HIFDevice, + pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], + pPacket->pBuffer, + paddedLength, /* the padded length */ + sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC, + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ + + if (sync) { + pPacket->Status = status; + } else { + if (status == A_PENDING) { + status = 0; + } + } + + return status; +} + +static INLINE int DevRecvPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 RecvLength) { + u32 paddedLength; + int status; + bool sync = (pPacket->Completion == NULL) ? true : false; + + /* adjust the length to be a multiple of block size if appropriate */ + paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength); + + if (paddedLength > pPacket->BufferLength) { + A_ASSERT(false); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n", + paddedLength,RecvLength,pPacket->BufferLength)); + if (pPacket->Completion != NULL) { + COMPLETE_HTC_PACKET(pPacket,A_EINVAL); + return 0; + } + return A_EINVAL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("DevRecvPacket (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n", + (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr, + paddedLength, + pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], + sync ? "SYNC" : "ASYNC")); + + status = HIFReadWrite(pDev->HIFDevice, + pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX], + pPacket->pBuffer, + paddedLength, + sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX, + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ + + if (sync) { + pPacket->Status = status; + } + + return status; +} + +#define DEV_CHECK_RECV_YIELD(pDev) \ + ((pDev)->CurrentDSRRecvCount >= (pDev)->HifIRQYieldParams.RecvPacketYieldCount) + +#define IS_DEV_IRQ_PROC_SYNC_MODE(pDev) (HIF_DEVICE_IRQ_SYNC_ONLY == (pDev)->HifIRQProcessingMode) +#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY) + +/**************************************************/ +/****** Scatter Function and Definitions + * + * + */ + +int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA); + + /* copy any READ data back into scatter list */ +#define DEV_FINISH_SCATTER_OPERATION(pR) \ +do { \ + if (!((pR)->CompletionStatus) && \ + !((pR)->Request & HIF_WRITE) && \ + ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) { \ + (pR)->CompletionStatus = \ + DevCopyScatterListToFromDMABuffer((pR), \ + FROM_DMA_BUFFER); \ + } \ +} while (0) + + /* copy any WRITE data to bounce buffer */ +static INLINE int DEV_PREPARE_SCATTER_OPERATION(struct hif_scatter_req *pReq) { + if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) { + return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER); + } else { + return 0; + } +} + + +int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer); + +int DevCleanupMsgBundling(struct ar6k_device *pDev); + +#define DEV_GET_MAX_MSG_PER_BUNDLE(pDev) (pDev)->HifScatterInfo.MaxScatterEntries +#define DEV_GET_MAX_BUNDLE_LENGTH(pDev) (pDev)->HifScatterInfo.MaxTransferSizePerScatterReq +#define DEV_ALLOC_SCATTER_REQ(pDev) \ + (pDev)->HifScatterInfo.pAllocateReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice) + +#define DEV_FREE_SCATTER_REQ(pDev,pR) \ + (pDev)->HifScatterInfo.pFreeReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice,(pR)) + +#define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev) (pDev)->MaxRecvBundleSize +#define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev) (pDev)->MaxSendBundleSize + +#define DEV_SCATTER_READ true +#define DEV_SCATTER_WRITE false +#define DEV_SCATTER_ASYNC true +#define DEV_SCATTER_SYNC false +int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async); + +#ifdef MBOXHW_UNIT_TEST +int DoMboxHWTest(struct ar6k_device *pDev); +#endif + + /* completely virtual */ +struct dev_scatter_dma_virtual_info { + u8 *pVirtDmaBuffer; /* dma-able buffer - CPU accessible address */ + u8 DataArea[1]; /* start of data area */ +}; + + + +void DumpAR6KDevState(struct ar6k_device *pDev); + +/**************************************************/ +/****** GMBOX functions and definitions + * + * + */ + +#ifdef ATH_AR6K_ENABLE_GMBOX + +void DevCleanupGMbox(struct ar6k_device *pDev); +int DevSetupGMbox(struct ar6k_device *pDev); +int DevCheckGMboxInterrupts(struct ar6k_device *pDev); +void DevNotifyGMboxTargetFailure(struct ar6k_device *pDev); + +#else + + /* compiled out */ +#define DevCleanupGMbox(p) +#define DevCheckGMboxInterrupts(p) 0 +#define DevNotifyGMboxTargetFailure(p) + +static INLINE int DevSetupGMbox(struct ar6k_device *pDev) { + pDev->GMboxEnabled = false; + return 0; +} + +#endif + +#ifdef ATH_AR6K_ENABLE_GMBOX + + /* GMBOX protocol modules must expose each of these internal APIs */ +HCI_TRANSPORT_HANDLE GMboxAttachProtocol(struct ar6k_device *pDev, struct hci_transport_config_info *pInfo); +int GMboxProtocolInstall(struct ar6k_device *pDev); +void GMboxProtocolUninstall(struct ar6k_device *pDev); + + /* API used by GMBOX protocol modules */ +struct ar6k_device *HTCGetAR6KDevice(void *HTCHandle); +#define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \ +{ \ + (pDev)->GMboxInfo.pProtocolContext = (context); \ + (pDev)->GMboxInfo.pMessagePendingCallBack = (recv_callback); \ + (pDev)->GMboxInfo.pCreditsPendingCallback = (credits_pending); \ + (pDev)->GMboxInfo.pTargetFailureCallback = (failure); \ + (pDev)->GMboxInfo.pStateDumpCallback = (statedump); \ +} + +#define DEV_GMBOX_GET_PROTOCOL(pDev) (pDev)->GMboxInfo.pProtocolContext + +int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength); +int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength); + +#define PROC_IO_ASYNC true +#define PROC_IO_SYNC false +typedef enum GMBOX_IRQ_ACTION_TYPE { + GMBOX_ACTION_NONE = 0, + GMBOX_DISABLE_ALL, + GMBOX_ERRORS_IRQ_ENABLE, + GMBOX_RECV_IRQ_ENABLE, + GMBOX_RECV_IRQ_DISABLE, + GMBOX_CREDIT_IRQ_ENABLE, + GMBOX_CREDIT_IRQ_DISABLE, +} GMBOX_IRQ_ACTION_TYPE; + +int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE, bool AsyncMode); +int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits); +int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize); +int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes); +int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int SignalNumber, int AckTimeoutMS); + +#endif + +#endif /*AR6K_H_*/ diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c new file mode 100644 index 000000000000..d7af68f70560 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c @@ -0,0 +1,783 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// AR6K Driver layer event handling (i.e. interrupts, message polling) +// +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "hw/mbox_host_reg.h" +#include "a_osapi.h" +#include "../htc_debug.h" +#include "hif.h" +#include "htc_packet.h" +#include "ar6k.h" + +extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket); +extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev); + +static int DevServiceDebugInterrupt(struct ar6k_device *pDev); + +#define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */ + +/* completion routine for ALL HIF layer async I/O */ +int DevRWCompletionHandler(void *context, int status) +{ + struct htc_packet *pPacket = (struct htc_packet *)context; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("+DevRWCompletionHandler (Pkt:0x%lX) , Status: %d \n", + (unsigned long)pPacket, + status)); + + COMPLETE_HTC_PACKET(pPacket,status); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("-DevRWCompletionHandler\n")); + + return 0; +} + +/* mailbox recv message polling */ +int DevPollMboxMsgRecv(struct ar6k_device *pDev, + u32 *pLookAhead, + int TimeoutMS) +{ + int status = 0; + int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS; + + A_ASSERT(timeout > 0); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n")); + + while (true) { + + if (pDev->GetPendingEventsFunc != NULL) { + + struct hif_pending_events_info events; + +#ifdef THREAD_X + events.Polling =1; +#endif + + /* the HIF layer uses a special mechanism to get events, do this + * synchronously */ + status = pDev->GetPendingEventsFunc(pDev->HIFDevice, + &events, + NULL); + if (status) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n")); + break; + } + + if (events.Events & HIF_RECV_MSG_AVAIL) + { + /* there is a message available, the lookahead should be valid now */ + *pLookAhead = events.LookAhead; + + break; + } + } else { + + /* this is the standard HIF way.... */ + /* load the register table */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (u8 *)&pDev->IrqProcRegisters, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n")); + break; + } + + /* check for MBOX data and valid lookahead */ + if (pDev->IrqProcRegisters.host_int_status & (1 << HTC_MAILBOX)) { + if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX)) + { + /* mailbox has a message and the look ahead is valid */ + *pLookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX]; + break; + } + } + + } + + timeout--; + + if (timeout <= 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Timeout waiting for recv message \n")); + status = A_ERROR; + + /* check if the target asserted */ + if ( pDev->IrqProcRegisters.counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) { + /* target signaled an assert, process this pending interrupt + * this will call the target failure handler */ + DevServiceDebugInterrupt(pDev); + } + + break; + } + + /* delay a little */ + A_MDELAY(DELAY_PER_INTERVAL_MS); + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Retry Mbox Poll : %d \n",timeout)); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevPollMboxMsgRecv \n")); + + return status; +} + +static int DevServiceCPUInterrupt(struct ar6k_device *pDev) +{ + int status; + u8 cpu_int_status; + u8 regBuffer[4]; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n")); + cpu_int_status = pDev->IrqProcRegisters.cpu_int_status & + pDev->IrqEnableRegisters.cpu_int_status_enable; + A_ASSERT(cpu_int_status); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n", + cpu_int_status)); + + /* Clear the interrupt */ + pDev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status; /* W1C */ + + /* set up the register transfer buffer to hit the register 4 times , this is done + * to make the access 4-byte aligned to mitigate issues with host bus interconnects that + * restrict bus transfer lengths to be a multiple of 4-bytes */ + + /* set W1C value to clear the interrupt, this hits the register first */ + regBuffer[0] = cpu_int_status; + /* the remaining 4 values are set to zero which have no-effect */ + regBuffer[1] = 0; + regBuffer[2] = 0; + regBuffer[3] = 0; + + status = HIFReadWrite(pDev->HIFDevice, + CPU_INT_STATUS_ADDRESS, + regBuffer, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + + A_ASSERT(status == 0); + return status; +} + + +static int DevServiceErrorInterrupt(struct ar6k_device *pDev) +{ + int status; + u8 error_int_status; + u8 regBuffer[4]; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n")); + error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F; + A_ASSERT(error_int_status); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n", + error_int_status)); + + if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) { + /* Wakeup */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n")); + } + + if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) { + /* Rx Underflow */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n")); + } + + if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) { + /* Tx Overflow */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n")); + } + + /* Clear the interrupt */ + pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */ + + /* set up the register transfer buffer to hit the register 4 times , this is done + * to make the access 4-byte aligned to mitigate issues with host bus interconnects that + * restrict bus transfer lengths to be a multiple of 4-bytes */ + + /* set W1C value to clear the interrupt, this hits the register first */ + regBuffer[0] = error_int_status; + /* the remaining 4 values are set to zero which have no-effect */ + regBuffer[1] = 0; + regBuffer[2] = 0; + regBuffer[3] = 0; + + status = HIFReadWrite(pDev->HIFDevice, + ERROR_INT_STATUS_ADDRESS, + regBuffer, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + + A_ASSERT(status == 0); + return status; +} + +static int DevServiceDebugInterrupt(struct ar6k_device *pDev) +{ + u32 dummy; + int status; + + /* Send a target failure event to the application */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n")); + + if (pDev->TargetFailureCallback != NULL) { + pDev->TargetFailureCallback(pDev->HTCContext); + } + + if (pDev->GMboxEnabled) { + DevNotifyGMboxTargetFailure(pDev); + } + + /* clear the interrupt , the debug error interrupt is + * counter 0 */ + /* read counter to clear interrupt */ + status = HIFReadWrite(pDev->HIFDevice, + COUNT_DEC_ADDRESS, + (u8 *)&dummy, + 4, + HIF_RD_SYNC_BYTE_INC, + NULL); + + A_ASSERT(status == 0); + return status; +} + +static int DevServiceCounterInterrupt(struct ar6k_device *pDev) +{ + u8 counter_int_status; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n")); + + counter_int_status = pDev->IrqProcRegisters.counter_int_status & + pDev->IrqEnableRegisters.counter_int_status_enable; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", + counter_int_status)); + + /* Check if the debug interrupt is pending + * NOTE: other modules like GMBOX may use the counter interrupt for + * credit flow control on other counters, we only need to check for the debug assertion + * counter interrupt */ + if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) { + return DevServiceDebugInterrupt(pDev); + } + + return 0; +} + +/* callback when our fetch to get interrupt status registers completes */ +static void DevGetEventAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + u32 lookAhead = 0; + bool otherInts = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + do { + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" GetEvents I/O request failed, status:%d \n", pPacket->Status)); + /* bail out, don't unmask HIF interrupt */ + break; + } + + if (pDev->GetPendingEventsFunc != NULL) { + /* the HIF layer collected the information for us */ + struct hif_pending_events_info *pEvents = (struct hif_pending_events_info *)pPacket->pBuffer; + if (pEvents->Events & HIF_RECV_MSG_AVAIL) { + lookAhead = pEvents->LookAhead; + if (0 == lookAhead) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler1, lookAhead is zero! \n")); + } + } + if (pEvents->Events & HIF_OTHER_EVENTS) { + otherInts = true; + } + } else { + /* standard interrupt table handling.... */ + struct ar6k_irq_proc_registers *pReg = (struct ar6k_irq_proc_registers *)pPacket->pBuffer; + u8 host_int_status; + + host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable; + + if (host_int_status & (1 << HTC_MAILBOX)) { + host_int_status &= ~(1 << HTC_MAILBOX); + if (pReg->rx_lookahead_valid & (1 << HTC_MAILBOX)) { + /* mailbox has a message and the look ahead is valid */ + lookAhead = pReg->rx_lookahead[HTC_MAILBOX]; + if (0 == lookAhead) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler2, lookAhead is zero! \n")); + } + } + } + + if (host_int_status) { + /* there are other interrupts to handle */ + otherInts = true; + } + } + + if (otherInts || (lookAhead == 0)) { + /* if there are other interrupts to process, we cannot do this in the async handler so + * ack the interrupt which will cause our sync handler to run again + * if however there are no more messages, we can now ack the interrupt */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d, lookahead:0x%X)\n", + otherInts, lookAhead)); + HIFAckInterrupt(pDev->HIFDevice); + } else { + int fetched = 0; + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n", + lookAhead)); + /* lookahead is non-zero and there are no other interrupts to service, + * go get the next message */ + status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, NULL, &fetched); + + if (!status && !fetched) { + /* HTC layer could not pull out messages due to lack of resources, stop IRQ processing */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not pull any messages, force-ack \n")); + DevAsyncIrqProcessComplete(pDev); + } + } + + } while (false); + + /* free this IO packet */ + AR6KFreeIOPacket(pDev,pPacket); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n")); +} + +/* called by the HTC layer when it wants us to check if the device has any more pending + * recv messages, this starts off a series of async requests to read interrupt registers */ +int DevCheckPendingRecvMsgsAsync(void *context) +{ + struct ar6k_device *pDev = (struct ar6k_device *)context; + int status = 0; + struct htc_packet *pIOPacket; + + /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can + * cause us to switch contexts */ + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%lX)\n", (unsigned long)pDev)); + + do { + + if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { + /* break the async processing chain right here, no need to continue. + * The DevDsrHandler() will handle things in a loop when things are driven + * synchronously */ + break; + } + + /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake + * the target, if upper layers determine that we are in a low-throughput mode, we can + * rely on taking another interrupt rather than re-checking the status registers which can + * re-wake the target */ + if (pDev->RecheckIRQStatusCnt == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, re-acking HIF interrupts\n")); + /* ack interrupt */ + HIFAckInterrupt(pDev->HIFDevice); + break; + } + + /* first allocate one of our HTC packets we created for async I/O + * we reuse HTC packet definitions so that we can use the completion mechanism + * in DevRWCompletionHandler() */ + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + /* there should be only 1 asynchronous request out at a time to read these registers + * so this should actually never happen */ + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevGetEventAsyncHandler; + pIOPacket->pContext = pDev; + + if (pDev->GetPendingEventsFunc) { + /* HIF layer has it's own mechanism, pass the IO to it.. */ + status = pDev->GetPendingEventsFunc(pDev->HIFDevice, + (struct hif_pending_events_info *)pIOPacket->pBuffer, + pIOPacket); + + } else { + /* standard way, read the interrupt register table asynchronously again */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + pIOPacket->pBuffer, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_ASYNC_BYTE_INC, + pIOPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n")); + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n")); + + return status; +} + +void DevAsyncIrqProcessComplete(struct ar6k_device *pDev) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("DevAsyncIrqProcessComplete - forcing HIF IRQ ACK \n")); + HIFAckInterrupt(pDev->HIFDevice); +} + +/* process pending interrupts synchronously */ +static int ProcessPendingIRQs(struct ar6k_device *pDev, bool *pDone, bool *pASyncProcessing) +{ + int status = 0; + u8 host_int_status = 0; + u32 lookAhead = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%lX)\n", (unsigned long)pDev)); + + /*** NOTE: the HIF implementation guarantees that the context of this call allows + * us to perform SYNCHRONOUS I/O, that is we can block, sleep or call any API that + * can block or switch thread/task ontexts. + * This is a fully schedulable context. + * */ + do { + + if (pDev->IrqEnableRegisters.int_status_enable == 0) { + /* interrupt enables have been cleared, do not try to process any pending interrupts that + * may result in more bus transactions. The target may be unresponsive at this + * point. */ + break; + } + + if (pDev->GetPendingEventsFunc != NULL) { + struct hif_pending_events_info events; + +#ifdef THREAD_X + events.Polling= 0; +#endif + /* the HIF layer uses a special mechanism to get events + * get this synchronously */ + status = pDev->GetPendingEventsFunc(pDev->HIFDevice, + &events, + NULL); + + if (status) { + break; + } + + if (events.Events & HIF_RECV_MSG_AVAIL) { + lookAhead = events.LookAhead; + if (0 == lookAhead) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs1 lookAhead is zero! \n")); + } + } + + if (!(events.Events & HIF_OTHER_EVENTS) || + !(pDev->IrqEnableRegisters.int_status_enable & OTHER_INTS_ENABLED)) { + /* no need to read the register table, no other interesting interrupts. + * Some interfaces (like SPI) can shadow interrupt sources without + * requiring the host to do a full table read */ + break; + } + + /* otherwise fall through and read the register table */ + } + + /* + * Read the first 28 bytes of the HTC register table. This will yield us + * the value of different int status registers and the lookahead + * registers. + * length = sizeof(int_status) + sizeof(cpu_int_status) + + * sizeof(error_int_status) + sizeof(counter_int_status) + + * sizeof(mbox_frame) + sizeof(rx_lookahead_valid) + + * sizeof(hole) + sizeof(rx_lookahead) + + * sizeof(int_status_enable) + sizeof(cpu_int_status_enable) + + * sizeof(error_status_enable) + + * sizeof(counter_int_status_enable); + * + */ +#ifdef CONFIG_MMC_SDHCI_S3C + pDev->IrqProcRegisters.host_int_status = 0; + pDev->IrqProcRegisters.rx_lookahead_valid = 0; + pDev->IrqProcRegisters.host_int_status2 = 0; + pDev->IrqProcRegisters.rx_lookahead[0] = 0; + pDev->IrqProcRegisters.rx_lookahead[1] = 0xaaa5555; +#endif /* CONFIG_MMC_SDHCI_S3C */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (u8 *)&pDev->IrqProcRegisters, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status) { + break; + } + +#ifdef ATH_DEBUG_MODULE + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) { + DevDumpRegisters(pDev, + &pDev->IrqProcRegisters, + &pDev->IrqEnableRegisters); + } +#endif + + /* Update only those registers that are enabled */ + host_int_status = pDev->IrqProcRegisters.host_int_status & + pDev->IrqEnableRegisters.int_status_enable; + + if (NULL == pDev->GetPendingEventsFunc) { + /* only look at mailbox status if the HIF layer did not provide this function, + * on some HIF interfaces reading the RX lookahead is not valid to do */ + if (host_int_status & (1 << HTC_MAILBOX)) { + /* mask out pending mailbox value, we use "lookAhead" as the real flag for + * mailbox processing below */ + host_int_status &= ~(1 << HTC_MAILBOX); + if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX)) { + /* mailbox has a message and the look ahead is valid */ + lookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX]; + if (0 == lookAhead) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs2, lookAhead is zero! \n")); + } + } + } + } else { + /* not valid to check if the HIF has another mechanism for reading mailbox pending status*/ + host_int_status &= ~(1 << HTC_MAILBOX); + } + + if (pDev->GMboxEnabled) { + /*call GMBOX layer to process any interrupts of interest */ + status = DevCheckGMboxInterrupts(pDev); + } + + } while (false); + + + do { + + /* did the interrupt status fetches succeed? */ + if (status) { + break; + } + + if ((0 == host_int_status) && (0 == lookAhead)) { + /* nothing to process, the caller can use this to break out of a loop */ + *pDone = true; + break; + } + + if (lookAhead != 0) { + int fetched = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Pending mailbox message, LookAhead: 0x%X\n",lookAhead)); + /* Mailbox Interrupt, the HTC layer may issue async requests to empty the + * mailbox... + * When emptying the recv mailbox we use the async handler above called from the + * completion routine of the callers read request. This can improve performance + * by reducing context switching when we rapidly pull packets */ + status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, pASyncProcessing, &fetched); + if (status) { + break; + } + + if (!fetched) { + /* HTC could not pull any messages out due to lack of resources */ + /* force DSR handler to ack the interrupt */ + *pASyncProcessing = false; + pDev->RecheckIRQStatusCnt = 0; + } + } + + /* now handle the rest of them */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" Valid interrupt source(s) for OTHER interrupts: 0x%x\n", + host_int_status)); + + if (HOST_INT_STATUS_CPU_GET(host_int_status)) { + /* CPU Interrupt */ + status = DevServiceCPUInterrupt(pDev); + if (status){ + break; + } + } + + if (HOST_INT_STATUS_ERROR_GET(host_int_status)) { + /* Error Interrupt */ + status = DevServiceErrorInterrupt(pDev); + if (status){ + break; + } + } + + if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) { + /* Counter Interrupt */ + status = DevServiceCounterInterrupt(pDev); + if (status){ + break; + } + } + + } while (false); + + /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake + * the target, if upper layers determine that we are in a low-throughput mode, we can + * rely on taking another interrupt rather than re-checking the status registers which can + * re-wake the target. + * + * NOTE : for host interfaces that use the special GetPendingEventsFunc, this optimization cannot + * be used due to possible side-effects. For example, SPI requires the host to drain all + * messages from the mailbox before exiting the ISR routine. */ + if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0) && (pDev->GetPendingEventsFunc == NULL)) { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, forcing done \n")); + *pDone = true; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n", + *pDone, *pASyncProcessing, status)); + + return status; +} + + +/* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/ +int DevDsrHandler(void *context) +{ + struct ar6k_device *pDev = (struct ar6k_device *)context; + int status = 0; + bool done = false; + bool asyncProc = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + /* reset the recv counter that tracks when we need to yield from the DSR */ + pDev->CurrentDSRRecvCount = 0; + /* reset counter used to flag a re-scan of IRQ status registers on the target */ + pDev->RecheckIRQStatusCnt = 0; + + while (!done) { + status = ProcessPendingIRQs(pDev, &done, &asyncProc); + if (status) { + break; + } + + if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { + /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */ + asyncProc = false; + /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers. + * this has a nice side effect of blocking us until all async read requests are completed. + * This behavior is required on some HIF implementations that do not allow ASYNC + * processing in interrupt handlers (like Windows CE) */ + + if (pDev->DSRCanYield && DEV_CHECK_RECV_YIELD(pDev)) { + /* ProcessPendingIRQs() pulled enough recv messages to satisfy the yield count, stop + * checking for more messages and return */ + break; + } + } + + if (asyncProc) { + /* the function performed some async I/O for performance, we + need to exit the ISR immediately, the check below will prevent the interrupt from being + Ack'd while we handle it asynchronously */ + break; + } + + } + + if (!status && !asyncProc) { + /* Ack the interrupt only if : + * 1. we did not get any errors in processing interrupts + * 2. there are no outstanding async processing requests */ + if (pDev->DSRCanYield) { + /* if the DSR can yield do not ACK the interrupt, there could be more pending messages. + * The HIF layer must ACK the interrupt on behalf of HTC */ + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Yield in effect (cur RX count: %d) \n", pDev->CurrentDSRRecvCount)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler \n")); + HIFAckInterrupt(pDev->HIFDevice); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n")); + return status; +} + +#ifdef ATH_DEBUG_MODULE +void DumpAR6KDevState(struct ar6k_device *pDev) +{ + int status; + struct ar6k_irq_enable_registers regs; + struct ar6k_irq_proc_registers procRegs; + + LOCK_AR6K(pDev); + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + UNLOCK_AR6K(pDev); + + /* load the register table from the device */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (u8 *)&procRegs, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DumpAR6KDevState : Failed to read register table (%d) \n",status)); + return; + } + + DevDumpRegisters(pDev,&procRegs,®s); + + if (pDev->GMboxInfo.pStateDumpCallback != NULL) { + pDev->GMboxInfo.pStateDumpCallback(pDev->GMboxInfo.pProtocolContext); + } + + /* dump any bus state at the HIF layer */ + HIFConfigureDevice(pDev->HIFDevice,HIF_DEVICE_DEBUG_BUS_STATE,NULL,0); + +} +#endif + + diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c new file mode 100644 index 000000000000..725540f9adde --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c @@ -0,0 +1,755 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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 MBOX API implementation +// +// Author(s): ="Atheros" +//============================================================================== +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "../htc_debug.h" +#include "hif.h" +#include "htc_packet.h" +#include "ar6k.h" +#include "hw/mbox_host_reg.h" +#include "gmboxif.h" + +/* + * This file provides management functions and a toolbox for GMBOX protocol modules. + * Only one protocol module can be installed at a time. The determination of which protocol + * module is installed is determined at compile time. + * + */ +#ifdef ATH_AR6K_ENABLE_GMBOX + /* GMBOX definitions */ +#define GMBOX_INT_STATUS_ENABLE_REG 0x488 +#define GMBOX_INT_STATUS_RX_DATA (1 << 0) +#define GMBOX_INT_STATUS_TX_OVERFLOW (1 << 1) +#define GMBOX_INT_STATUS_RX_OVERFLOW (1 << 2) + +#define GMBOX_LOOKAHEAD_MUX_REG 0x498 +#define GMBOX_LA_MUX_OVERRIDE_2_3 (1 << 0) + +#define AR6K_GMBOX_CREDIT_DEC_ADDRESS (COUNT_DEC_ADDRESS + 4 * AR6K_GMBOX_CREDIT_COUNTER) +#define AR6K_GMBOX_CREDIT_SIZE_ADDRESS (COUNT_ADDRESS + AR6K_GMBOX_CREDIT_SIZE_COUNTER) + + + /* external APIs for allocating and freeing internal I/O packets to handle ASYNC I/O */ +extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket); +extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev); + + +/* callback when our fetch to enable/disable completes */ +static void DevGMboxIRQActionAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxIRQActionAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("IRQAction Operation (%d) failed! status:%d \n", pPacket->PktInfo.AsRx.HTCRxFlags,pPacket->Status)); + } + /* free this IO packet */ + AR6KFreeIOPacket(pDev,pPacket); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxIRQActionAsyncHandler \n")); +} + +static int DevGMboxCounterEnableDisable(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode) +{ + int status = 0; + struct ar6k_irq_enable_registers regs; + struct htc_packet *pIOPacket = NULL; + + LOCK_AR6K(pDev); + + if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) { + pDev->GMboxInfo.CreditCountIRQEnabled = true; + pDev->IrqEnableRegisters.counter_int_status_enable |= + COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER); + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_COUNTER_SET(0x01); + } else { + pDev->GMboxInfo.CreditCountIRQEnabled = false; + pDev->IrqEnableRegisters.counter_int_status_enable &= + ~(COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER)); + } + /* copy into our temp area */ + memcpy(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + + UNLOCK_AR6K(pDev); + + do { + + if (AsyncMode) { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* copy values to write to our async I/O buffer */ + memcpy(pIOPacket->pBuffer,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevGMboxIRQActionAsyncHandler; + pIOPacket->pContext = pDev; + pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction; + /* write it out asynchronously */ + HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + pIOPacket->pBuffer, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_ASYNC_BYTE_INC, + pIOPacket); + + pIOPacket = NULL; + break; + } + + /* if we get here we are doing it synchronously */ + status = HIFReadWrite(pDev->HIFDevice, + INT_STATUS_ENABLE_ADDRESS, + ®s.int_status_enable, + AR6K_IRQ_ENABLE_REGS_SIZE, + HIF_WR_SYNC_BYTE_INC, + NULL); + } while (false); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status)); + } else { + if (!AsyncMode) { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" IRQAction Operation (%d) success \n", IrqAction)); + } + } + + if (pIOPacket != NULL) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + + return status; +} + + +int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode) +{ + int status = 0; + struct htc_packet *pIOPacket = NULL; + u8 GMboxIntControl[4]; + + if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) { + return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_ENABLE, AsyncMode); + } else if(GMBOX_CREDIT_IRQ_DISABLE == IrqAction) { + return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode); + } + + if (GMBOX_DISABLE_ALL == IrqAction) { + /* disable credit IRQ, those are on a different set of registers */ + DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode); + } + + /* take the lock to protect interrupt enable shadows */ + LOCK_AR6K(pDev); + + switch (IrqAction) { + + case GMBOX_DISABLE_ALL: + pDev->GMboxControlRegisters.int_status_enable = 0; + break; + case GMBOX_ERRORS_IRQ_ENABLE: + pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_TX_OVERFLOW | + GMBOX_INT_STATUS_RX_OVERFLOW; + break; + case GMBOX_RECV_IRQ_ENABLE: + pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_RX_DATA; + break; + case GMBOX_RECV_IRQ_DISABLE: + pDev->GMboxControlRegisters.int_status_enable &= ~GMBOX_INT_STATUS_RX_DATA; + break; + case GMBOX_ACTION_NONE: + default: + A_ASSERT(false); + break; + } + + GMboxIntControl[0] = pDev->GMboxControlRegisters.int_status_enable; + GMboxIntControl[1] = GMboxIntControl[0]; + GMboxIntControl[2] = GMboxIntControl[0]; + GMboxIntControl[3] = GMboxIntControl[0]; + + UNLOCK_AR6K(pDev); + + do { + + if (AsyncMode) { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + /* copy values to write to our async I/O buffer */ + memcpy(pIOPacket->pBuffer,GMboxIntControl,sizeof(GMboxIntControl)); + + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevGMboxIRQActionAsyncHandler; + pIOPacket->pContext = pDev; + pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction; + /* write it out asynchronously */ + HIFReadWrite(pDev->HIFDevice, + GMBOX_INT_STATUS_ENABLE_REG, + pIOPacket->pBuffer, + sizeof(GMboxIntControl), + HIF_WR_ASYNC_BYTE_FIX, + pIOPacket); + pIOPacket = NULL; + break; + } + + /* if we get here we are doing it synchronously */ + + status = HIFReadWrite(pDev->HIFDevice, + GMBOX_INT_STATUS_ENABLE_REG, + GMboxIntControl, + sizeof(GMboxIntControl), + HIF_WR_SYNC_BYTE_FIX, + NULL); + + } while (false); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status)); + } else { + if (!AsyncMode) { + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, + (" IRQAction Operation (%d) success \n", IrqAction)); + } + } + + if (pIOPacket != NULL) { + AR6KFreeIOPacket(pDev,pIOPacket); + } + + return status; +} + +void DevCleanupGMbox(struct ar6k_device *pDev) +{ + if (pDev->GMboxEnabled) { + pDev->GMboxEnabled = false; + GMboxProtocolUninstall(pDev); + } +} + +int DevSetupGMbox(struct ar6k_device *pDev) +{ + int status = 0; + u8 muxControl[4]; + + do { + + if (0 == pDev->MailBoxInfo.GMboxAddress) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" GMBOX Advertised: Address:0x%X , size:%d \n", + pDev->MailBoxInfo.GMboxAddress, pDev->MailBoxInfo.GMboxSize)); + + status = DevGMboxIRQAction(pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC); + + if (status) { + break; + } + + /* write to mailbox look ahead mux control register, we want the + * GMBOX lookaheads to appear on lookaheads 2 and 3 + * the register is 1-byte wide so we need to hit it 4 times to align the operation + * to 4-bytes */ + muxControl[0] = GMBOX_LA_MUX_OVERRIDE_2_3; + muxControl[1] = GMBOX_LA_MUX_OVERRIDE_2_3; + muxControl[2] = GMBOX_LA_MUX_OVERRIDE_2_3; + muxControl[3] = GMBOX_LA_MUX_OVERRIDE_2_3; + + status = HIFReadWrite(pDev->HIFDevice, + GMBOX_LOOKAHEAD_MUX_REG, + muxControl, + sizeof(muxControl), + HIF_WR_SYNC_BYTE_FIX, /* hit this register 4 times */ + NULL); + + if (status) { + break; + } + + status = GMboxProtocolInstall(pDev); + + if (status) { + break; + } + + pDev->GMboxEnabled = true; + + } while (false); + + return status; +} + +int DevCheckGMboxInterrupts(struct ar6k_device *pDev) +{ + int status = 0; + u8 counter_int_status; + int credits; + u8 host_int_status2; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("+DevCheckGMboxInterrupts \n")); + + /* the caller guarantees that this is a context that allows for blocking I/O */ + + do { + + host_int_status2 = pDev->IrqProcRegisters.host_int_status2 & + pDev->GMboxControlRegisters.int_status_enable; + + if (host_int_status2 & GMBOX_INT_STATUS_TX_OVERFLOW) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : TX Overflow \n")); + status = A_ECOMM; + } + + if (host_int_status2 & GMBOX_INT_STATUS_RX_OVERFLOW) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : RX Overflow \n")); + status = A_ECOMM; + } + + if (status) { + if (pDev->GMboxInfo.pTargetFailureCallback != NULL) { + pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, status); + } + break; + } + + if (host_int_status2 & GMBOX_INT_STATUS_RX_DATA) { + if (pDev->IrqProcRegisters.gmbox_rx_avail > 0) { + A_ASSERT(pDev->GMboxInfo.pMessagePendingCallBack != NULL); + status = pDev->GMboxInfo.pMessagePendingCallBack( + pDev->GMboxInfo.pProtocolContext, + (u8 *)&pDev->IrqProcRegisters.rx_gmbox_lookahead_alias[0], + pDev->IrqProcRegisters.gmbox_rx_avail); + } + } + + if (status) { + break; + } + + counter_int_status = pDev->IrqProcRegisters.counter_int_status & + pDev->IrqEnableRegisters.counter_int_status_enable; + + /* check if credit interrupt is pending */ + if (counter_int_status & (COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER))) { + + /* do synchronous read */ + status = DevGMboxReadCreditCounter(pDev, PROC_IO_SYNC, &credits); + + if (status) { + break; + } + + A_ASSERT(pDev->GMboxInfo.pCreditsPendingCallback != NULL); + status = pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext, + credits, + pDev->GMboxInfo.CreditCountIRQEnabled); + } + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("-DevCheckGMboxInterrupts (%d) \n",status)); + + return status; +} + + +int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength) +{ + u32 paddedLength; + bool sync = (pPacket->Completion == NULL) ? true : false; + int status; + u32 address; + + /* adjust the length to be a multiple of block size if appropriate */ + paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, WriteLength); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("DevGMboxWrite, Padded Length: %d Mbox:0x%X (mode:%s)\n", + WriteLength, + pDev->MailBoxInfo.GMboxAddress, + sync ? "SYNC" : "ASYNC")); + + /* last byte of packet has to hit the EOM marker */ + address = pDev->MailBoxInfo.GMboxAddress + pDev->MailBoxInfo.GMboxSize - paddedLength; + + status = HIFReadWrite(pDev->HIFDevice, + address, + pPacket->pBuffer, + paddedLength, /* the padded length */ + sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC, + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ + + if (sync) { + pPacket->Status = status; + } else { + if (status == A_PENDING) { + status = 0; + } + } + + return status; +} + +int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength) +{ + + u32 paddedLength; + int status; + bool sync = (pPacket->Completion == NULL) ? true : false; + + /* adjust the length to be a multiple of block size if appropriate */ + paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, ReadLength); + + if (paddedLength > pPacket->BufferLength) { + A_ASSERT(false); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DevGMboxRead, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n", + paddedLength,ReadLength,pPacket->BufferLength)); + if (pPacket->Completion != NULL) { + COMPLETE_HTC_PACKET(pPacket,A_EINVAL); + return 0; + } + return A_EINVAL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("DevGMboxRead (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n", + (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr, + paddedLength, + pDev->MailBoxInfo.GMboxAddress, + sync ? "SYNC" : "ASYNC")); + + status = HIFReadWrite(pDev->HIFDevice, + pDev->MailBoxInfo.GMboxAddress, + pPacket->pBuffer, + paddedLength, + sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX, + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ + + if (sync) { + pPacket->Status = status; + } + + return status; +} + + +static int ProcessCreditCounterReadBuffer(u8 *pBuffer, int Length) +{ + int credits = 0; + + /* theory of how this works: + * We read the credit decrement register multiple times on a byte-wide basis. + * The number of times (32) aligns the I/O operation to be a multiple of 4 bytes and provides a + * reasonable chance to acquire "all" pending credits in a single I/O operation. + * + * Once we obtain the filled buffer, we can walk through it looking for credit decrement transitions. + * Each non-zero byte represents a single credit decrement (which is a credit given back to the host) + * For example if the target provides 3 credits and added 4 more during the 32-byte read operation the following + * pattern "could" appear: + * + * 0x3 0x2 0x1 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x1 0x0 0x1 0x0 0x1 0x0 ......rest zeros + * <---------> <-----------------------------> + * \_ credits aleady there \_ target adding 4 more credits + * + * The total available credits would be 7, since there are 7 non-zero bytes in the buffer. + * + * */ + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes(pBuffer, Length, "GMBOX Credit read buffer"); + } + + while (Length) { + if (*pBuffer != 0) { + credits++; + } + Length--; + pBuffer++; + } + + return credits; +} + + +/* callback when our fetch to enable/disable completes */ +static void DevGMboxReadCreditsAsyncHandler(void *Context, struct htc_packet *pPacket) +{ + struct ar6k_device *pDev = (struct ar6k_device *)Context; + + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxReadCreditsAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Read Credit Operation failed! status:%d \n", pPacket->Status)); + } else { + int credits = 0; + credits = ProcessCreditCounterReadBuffer(pPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE); + pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext, + credits, + pDev->GMboxInfo.CreditCountIRQEnabled); + + + } + /* free this IO packet */ + AR6KFreeIOPacket(pDev,pPacket); + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxReadCreditsAsyncHandler \n")); +} + +int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits) +{ + int status = 0; + struct htc_packet *pIOPacket = NULL; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+DevGMboxReadCreditCounter (%s) \n", AsyncMode ? "ASYNC" : "SYNC")); + + do { + + pIOPacket = AR6KAllocIOPacket(pDev); + + if (NULL == pIOPacket) { + status = A_NO_MEMORY; + A_ASSERT(false); + break; + } + + A_MEMZERO(pIOPacket->pBuffer,AR6K_REG_IO_BUFFER_SIZE); + + if (AsyncMode) { + /* stick in our completion routine when the I/O operation completes */ + pIOPacket->Completion = DevGMboxReadCreditsAsyncHandler; + pIOPacket->pContext = pDev; + /* read registers asynchronously */ + HIFReadWrite(pDev->HIFDevice, + AR6K_GMBOX_CREDIT_DEC_ADDRESS, + pIOPacket->pBuffer, + AR6K_REG_IO_BUFFER_SIZE, /* hit the register multiple times */ + HIF_RD_ASYNC_BYTE_FIX, + pIOPacket); + pIOPacket = NULL; + break; + } + + pIOPacket->Completion = NULL; + /* if we get here we are doing it synchronously */ + status = HIFReadWrite(pDev->HIFDevice, + AR6K_GMBOX_CREDIT_DEC_ADDRESS, + pIOPacket->pBuffer, + AR6K_REG_IO_BUFFER_SIZE, + HIF_RD_SYNC_BYTE_FIX, + NULL); + } while (false); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" DevGMboxReadCreditCounter failed! status:%d \n", status)); + } + + if (pIOPacket != NULL) { + if (!status) { + /* sync mode processing */ + *pCredits = ProcessCreditCounterReadBuffer(pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE); + } + AR6KFreeIOPacket(pDev,pIOPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-DevGMboxReadCreditCounter (%s) (%d) \n", + AsyncMode ? "ASYNC" : "SYNC", status)); + + return status; +} + +int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize) +{ + int status; + u8 buffer[4]; + + status = HIFReadWrite(pDev->HIFDevice, + AR6K_GMBOX_CREDIT_SIZE_ADDRESS, + buffer, + sizeof(buffer), + HIF_RD_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */ + NULL); + + if (!status) { + if (buffer[0] == 0) { + *pCreditSize = 256; + } else { + *pCreditSize = buffer[0]; + } + + } + + return status; +} + +void DevNotifyGMboxTargetFailure(struct ar6k_device *pDev) +{ + /* Target ASSERTED!!! */ + if (pDev->GMboxInfo.pTargetFailureCallback != NULL) { + pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, A_HARDWARE); + } +} + +int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes) +{ + + int status = 0; + struct ar6k_irq_proc_registers procRegs; + int maxCopy; + + do { + /* on entry the caller provides the length of the lookahead buffer */ + if (*pLookAheadBytes > sizeof(procRegs.rx_gmbox_lookahead_alias)) { + A_ASSERT(false); + status = A_EINVAL; + break; + } + + maxCopy = *pLookAheadBytes; + *pLookAheadBytes = 0; + /* load the register table from the device */ + status = HIFReadWrite(pDev->HIFDevice, + HOST_INT_STATUS_ADDRESS, + (u8 *)&procRegs, + AR6K_IRQ_PROC_REGS_SIZE, + HIF_RD_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DevGMboxRecvLookAheadPeek : Failed to read register table (%d) \n",status)); + break; + } + + if (procRegs.gmbox_rx_avail > 0) { + int bytes = procRegs.gmbox_rx_avail > maxCopy ? maxCopy : procRegs.gmbox_rx_avail; + memcpy(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes); + *pLookAheadBytes = bytes; + } + + } while (false); + + return status; +} + +int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int Signal, int AckTimeoutMS) +{ + int status = 0; + int i; + u8 buffer[4]; + + A_MEMZERO(buffer, sizeof(buffer)); + + do { + + if (Signal >= MBOX_SIG_HCI_BRIDGE_MAX) { + status = A_EINVAL; + break; + } + + /* set the last buffer to do the actual signal trigger */ + buffer[3] = (1 << Signal); + + status = HIFReadWrite(pDev->HIFDevice, + INT_WLAN_ADDRESS, + buffer, + sizeof(buffer), + HIF_WR_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */ + NULL); + + if (status) { + break; + } + + } while (false); + + + if (!status) { + /* now read back the register to see if the bit cleared */ + while (AckTimeoutMS) { + status = HIFReadWrite(pDev->HIFDevice, + INT_WLAN_ADDRESS, + buffer, + sizeof(buffer), + HIF_RD_SYNC_BYTE_FIX, + NULL); + + if (status) { + break; + } + + for (i = 0; i < sizeof(buffer); i++) { + if (buffer[i] & (1 << Signal)) { + /* bit is still set */ + break; + } + } + + if (i >= sizeof(buffer)) { + /* done */ + break; + } + + AckTimeoutMS--; + A_MDELAY(1); + } + + if (0 == AckTimeoutMS) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("DevGMboxSetTargetInterrupt : Ack Timed-out (sig:%d) \n",Signal)); + status = A_ERROR; + } + } + + return status; + +} + +#endif //ATH_AR6K_ENABLE_GMBOX + + + + diff --git a/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c new file mode 100644 index 000000000000..56a0d7143804 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c @@ -0,0 +1,1284 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Protocol module for use in bridging HCI-UART packets over the GMBOX interface +// +// Author(s): ="Atheros" +//============================================================================== +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "../htc_debug.h" +#include "hif.h" +#include "htc_packet.h" +#include "ar6k.h" +#include "hci_transport_api.h" +#include "gmboxif.h" +#include "ar6000_diag.h" +#include "hw/apb_map.h" +#include "hw/mbox_reg.h" + +#ifdef ATH_AR6K_ENABLE_GMBOX +#define HCI_UART_COMMAND_PKT 0x01 +#define HCI_UART_ACL_PKT 0x02 +#define HCI_UART_SCO_PKT 0x03 +#define HCI_UART_EVENT_PKT 0x04 + +#define HCI_RECV_WAIT_BUFFERS (1 << 0) + +#define HCI_SEND_WAIT_CREDITS (1 << 0) + +#define HCI_UART_BRIDGE_CREDIT_SIZE 128 + +#define CREDIT_POLL_COUNT 256 + +#define HCI_DELAY_PER_INTERVAL_MS 10 +#define BTON_TIMEOUT_MS 500 +#define BTOFF_TIMEOUT_MS 500 +#define BAUD_TIMEOUT_MS 1 +#define BTPWRSAV_TIMEOUT_MS 1 + +struct gmbox_proto_hci_uart { + struct hci_transport_config_info HCIConfig; + bool HCIAttached; + bool HCIStopped; + u32 RecvStateFlags; + u32 SendStateFlags; + HCI_TRANSPORT_PACKET_TYPE WaitBufferType; + struct htc_packet_queue SendQueue; /* write queue holding HCI Command and ACL packets */ + struct htc_packet_queue HCIACLRecvBuffers; /* recv queue holding buffers for incomming ACL packets */ + struct htc_packet_queue HCIEventBuffers; /* recv queue holding buffers for incomming event packets */ + struct ar6k_device *pDev; + A_MUTEX_T HCIRxLock; + A_MUTEX_T HCITxLock; + int CreditsMax; + int CreditsConsumed; + int CreditsAvailable; + int CreditSize; + int CreditsCurrentSeek; + int SendProcessCount; +}; + +#define LOCK_HCI_RX(t) A_MUTEX_LOCK(&(t)->HCIRxLock); +#define UNLOCK_HCI_RX(t) A_MUTEX_UNLOCK(&(t)->HCIRxLock); +#define LOCK_HCI_TX(t) A_MUTEX_LOCK(&(t)->HCITxLock); +#define UNLOCK_HCI_TX(t) A_MUTEX_UNLOCK(&(t)->HCITxLock); + +#define DO_HCI_RECV_INDICATION(p, pt) \ +do { \ + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, \ + ("HCI: Indicate Recv on packet:0x%lX status:%d len:%d type:%d \n", \ + (unsigned long)(pt), \ + (pt)->Status, \ + !(pt)->Status ? (pt)->ActualLength : 0, \ + HCI_GET_PACKET_TYPE(pt))); \ + (p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt)); \ +} while (0) + +#define DO_HCI_SEND_INDICATION(p,pt) \ +{ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Indicate Send on packet:0x%lX status:%d type:%d \n", \ + (unsigned long)(pt),(pt)->Status,HCI_GET_PACKET_TYPE(pt))); \ + (p)->HCIConfig.pHCISendComplete((p)->HCIConfig.pContext, (pt)); \ +} + +static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous); + +static void HCIUartCleanup(struct gmbox_proto_hci_uart *pProtocol) +{ + A_ASSERT(pProtocol != NULL); + + A_MUTEX_DELETE(&pProtocol->HCIRxLock); + A_MUTEX_DELETE(&pProtocol->HCITxLock); + + kfree(pProtocol); +} + +static int InitTxCreditState(struct gmbox_proto_hci_uart *pProt) +{ + int status; + int credits; + int creditPollCount = CREDIT_POLL_COUNT; + bool gotCredits = false; + + pProt->CreditsConsumed = 0; + + do { + + if (pProt->CreditsMax != 0) { + /* we can only call this only once per target reset */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI: InitTxCreditState - already called! \n")); + A_ASSERT(false); + status = A_EINVAL; + break; + } + + /* read the credit counter. At startup the target will set the credit counter + * to the max available, we read this in a loop because it may take + * multiple credit counter reads to get all credits */ + + while (creditPollCount) { + + credits = 0; + + status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits); + + if (status) { + break; + } + + if (!gotCredits && (0 == credits)) { + creditPollCount--; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: credit is 0, retrying (%d) \n",creditPollCount)); + A_MDELAY(HCI_DELAY_PER_INTERVAL_MS); + continue; + } else { + gotCredits = true; + } + + if (0 == credits) { + break; + } + + pProt->CreditsMax += credits; + } + + if (status) { + break; + } + + if (0 == creditPollCount) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("** HCI : Failed to get credits! GMBOX Target was not available \n")); + status = A_ERROR; + break; + } + + /* now get the size */ + status = DevGMboxReadCreditSize(pProt->pDev, &pProt->CreditSize); + + if (status) { + break; + } + + } while (false); + + if (!status) { + pProt->CreditsAvailable = pProt->CreditsMax; + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI : InitTxCreditState - credits avail: %d, size: %d \n", + pProt->CreditsAvailable, pProt->CreditSize)); + } + + return status; +} + +static int CreditsAvailableCallback(void *pContext, int Credits, bool CreditIRQEnabled) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext; + bool enableCreditIrq = false; + bool disableCreditIrq = false; + bool doPendingSends = false; + int status = 0; + + /** this callback is called under 2 conditions: + * 1. The credit IRQ interrupt was enabled and signaled. + * 2. A credit counter read completed. + * + * The function must not assume that the calling context can block ! + */ + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback (Credits:%d, IRQ:%s) \n", + Credits, CreditIRQEnabled ? "ON" : "OFF")); + + LOCK_HCI_TX(pProt); + + do { + + if (0 == Credits) { + if (!CreditIRQEnabled) { + /* enable credit IRQ */ + enableCreditIrq = true; + } + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: current credit state, consumed:%d available:%d max:%d seek:%d\n", + pProt->CreditsConsumed, + pProt->CreditsAvailable, + pProt->CreditsMax, + pProt->CreditsCurrentSeek)); + + pProt->CreditsAvailable += Credits; + A_ASSERT(pProt->CreditsAvailable <= pProt->CreditsMax); + pProt->CreditsConsumed -= Credits; + A_ASSERT(pProt->CreditsConsumed >= 0); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state, consumed:%d available:%d max:%d seek:%d\n", + pProt->CreditsConsumed, + pProt->CreditsAvailable, + pProt->CreditsMax, + pProt->CreditsCurrentSeek)); + + if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) { + /* we have enough credits to fulfill at least 1 packet waiting in the queue */ + pProt->CreditsCurrentSeek = 0; + pProt->SendStateFlags &= ~HCI_SEND_WAIT_CREDITS; + doPendingSends = true; + if (CreditIRQEnabled) { + /* credit IRQ was enabled, we shouldn't need it anymore */ + disableCreditIrq = true; + } + } else { + /* not enough credits yet, enable credit IRQ if we haven't already */ + if (!CreditIRQEnabled) { + enableCreditIrq = true; + } + } + + } while (false); + + UNLOCK_HCI_TX(pProt); + + if (enableCreditIrq) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Enabling credit count IRQ...\n")); + /* must use async only */ + status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_ENABLE, PROC_IO_ASYNC); + } else if (disableCreditIrq) { + /* must use async only */ + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Disabling credit count IRQ...\n")); + status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_DISABLE, PROC_IO_ASYNC); + } + + if (doPendingSends) { + HCITrySend(pProt, NULL, false); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback \n")); + return status; +} + +static INLINE void NotifyTransportFailure(struct gmbox_proto_hci_uart *pProt, int status) +{ + if (pProt->HCIConfig.TransportFailure != NULL) { + pProt->HCIConfig.TransportFailure(pProt->HCIConfig.pContext, status); + } +} + +static void FailureCallback(void *pContext, int Status) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext; + + /* target assertion occurred */ + NotifyTransportFailure(pProt, Status); +} + +static void StateDumpCallback(void *pContext) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext; + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("============ HCIUart State ======================\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("RecvStateFlags : 0x%X \n",pProt->RecvStateFlags)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendStateFlags : 0x%X \n",pProt->SendStateFlags)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("WaitBufferType : %d \n",pProt->WaitBufferType)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendQueue Depth : %d \n",HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue))); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsMax : %d \n",pProt->CreditsMax)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsConsumed : %d \n",pProt->CreditsConsumed)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsAvailable : %d \n",pProt->CreditsAvailable)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("==================================================\n")); +} + +static int HCIUartMessagePending(void *pContext, u8 LookAheadBytes[], int ValidBytes) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext; + int status = 0; + int totalRecvLength = 0; + HCI_TRANSPORT_PACKET_TYPE pktType = HCI_PACKET_INVALID; + bool recvRefillCalled = false; + bool blockRecv = false; + struct htc_packet *pPacket = NULL; + + /** caller guarantees that this is a fully block-able context (synch I/O is allowed) */ + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCIUartMessagePending Lookahead Bytes:%d \n",ValidBytes)); + + LOCK_HCI_RX(pProt); + + do { + + if (ValidBytes < 3) { + /* not enough for ACL or event header */ + break; + } + + if ((LookAheadBytes[0] == HCI_UART_ACL_PKT) && (ValidBytes < 5)) { + /* not enough for ACL data header */ + break; + } + + switch (LookAheadBytes[0]) { + case HCI_UART_EVENT_PKT: + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n", + LookAheadBytes[1], LookAheadBytes[2])); + totalRecvLength = LookAheadBytes[2]; + totalRecvLength += 3; /* add type + event code + length field */ + pktType = HCI_EVENT_TYPE; + break; + case HCI_UART_ACL_PKT: + totalRecvLength = (LookAheadBytes[4] << 8) | LookAheadBytes[3]; + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI ACL: conn:0x%X length: %d \n", + ((LookAheadBytes[2] & 0xF0) << 8) | LookAheadBytes[1], totalRecvLength)); + totalRecvLength += 5; /* add type + connection handle + length field */ + pktType = HCI_ACL_TYPE; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",LookAheadBytes[0])); + status = A_EPROTO; + break; + } + + if (status) { + break; + } + + if (pProt->HCIConfig.pHCIPktRecvAlloc != NULL) { + UNLOCK_HCI_RX(pProt); + /* user is using a per-packet allocation callback */ + pPacket = pProt->HCIConfig.pHCIPktRecvAlloc(pProt->HCIConfig.pContext, + pktType, + totalRecvLength); + LOCK_HCI_RX(pProt); + + } else { + struct htc_packet_queue *pQueue; + /* user is using a refill handler that can refill multiple HTC buffers */ + + /* select buffer queue */ + if (pktType == HCI_ACL_TYPE) { + pQueue = &pProt->HCIACLRecvBuffers; + } else { + pQueue = &pProt->HCIEventBuffers; + } + + if (HTC_QUEUE_EMPTY(pQueue)) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("** HCI pkt type: %d has no buffers available calling allocation handler \n", + pktType)); + /* check for refill handler */ + if (pProt->HCIConfig.pHCIPktRecvRefill != NULL) { + recvRefillCalled = true; + UNLOCK_HCI_RX(pProt); + /* call the re-fill handler */ + pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext, + pktType, + 0); + LOCK_HCI_RX(pProt); + /* check if we have more buffers */ + pPacket = HTC_PACKET_DEQUEUE(pQueue); + /* fall through */ + } + } else { + pPacket = HTC_PACKET_DEQUEUE(pQueue); + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HCI pkt type: %d now has %d recv buffers left \n", + pktType, HTC_PACKET_QUEUE_DEPTH(pQueue))); + } + } + + if (NULL == pPacket) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("** HCI pkt type: %d has no buffers available stopping recv...\n", pktType)); + /* this is not an error, we simply need to mark that we are waiting for buffers.*/ + pProt->RecvStateFlags |= HCI_RECV_WAIT_BUFFERS; + pProt->WaitBufferType = pktType; + blockRecv = true; + break; + } + + if (totalRecvLength > (int)pPacket->BufferLength) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI-UART pkt: %d requires %d bytes (%d buffer bytes avail) ! \n", + LookAheadBytes[0], totalRecvLength, pPacket->BufferLength)); + status = A_EINVAL; + break; + } + + } while (false); + + UNLOCK_HCI_RX(pProt); + + /* locks are released, we can go fetch the packet */ + + do { + + if (status || (NULL == pPacket)) { + break; + } + + /* do this synchronously, we don't need to be fast here */ + pPacket->Completion = NULL; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI : getting recv packet len:%d hci-uart-type: %s \n", + totalRecvLength, (LookAheadBytes[0] == HCI_UART_EVENT_PKT) ? "EVENT" : "ACL")); + + status = DevGMboxRead(pProt->pDev, pPacket, totalRecvLength); + + if (status) { + break; + } + + if (pPacket->pBuffer[0] != LookAheadBytes[0]) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not contain expected packet type: %d ! \n", + pPacket->pBuffer[0])); + status = A_EPROTO; + break; + } + + if (pPacket->pBuffer[0] == HCI_UART_EVENT_PKT) { + /* validate event header fields */ + if ((pPacket->pBuffer[1] != LookAheadBytes[1]) || + (pPacket->pBuffer[2] != LookAheadBytes[2])) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n")); + DebugDumpBytes(LookAheadBytes, 3, "Expected HCI-UART Header"); + DebugDumpBytes(pPacket->pBuffer, 3, "** Bad HCI-UART Header"); + status = A_EPROTO; + break; + } + } else if (pPacket->pBuffer[0] == HCI_UART_ACL_PKT) { + /* validate acl header fields */ + if ((pPacket->pBuffer[1] != LookAheadBytes[1]) || + (pPacket->pBuffer[2] != LookAheadBytes[2]) || + (pPacket->pBuffer[3] != LookAheadBytes[3]) || + (pPacket->pBuffer[4] != LookAheadBytes[4])) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n")); + DebugDumpBytes(LookAheadBytes, 5, "Expected HCI-UART Header"); + DebugDumpBytes(pPacket->pBuffer, 5, "** Bad HCI-UART Header"); + status = A_EPROTO; + break; + } + } + + /* adjust buffer to move past packet ID */ + pPacket->pBuffer++; + pPacket->ActualLength = totalRecvLength - 1; + pPacket->Status = 0; + /* indicate packet */ + DO_HCI_RECV_INDICATION(pProt,pPacket); + pPacket = NULL; + + /* check if we need to refill recv buffers */ + if ((pProt->HCIConfig.pHCIPktRecvRefill != NULL) && !recvRefillCalled) { + struct htc_packet_queue *pQueue; + int watermark; + + if (pktType == HCI_ACL_TYPE) { + watermark = pProt->HCIConfig.ACLRecvBufferWaterMark; + pQueue = &pProt->HCIACLRecvBuffers; + } else { + watermark = pProt->HCIConfig.EventRecvBufferWaterMark; + pQueue = &pProt->HCIEventBuffers; + } + + if (HTC_PACKET_QUEUE_DEPTH(pQueue) < watermark) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("** HCI pkt type: %d watermark hit (%d) current:%d \n", + pktType, watermark, HTC_PACKET_QUEUE_DEPTH(pQueue))); + /* call the re-fill handler */ + pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext, + pktType, + HTC_PACKET_QUEUE_DEPTH(pQueue)); + } + } + + } while (false); + + /* check if we need to disable the receiver */ + if (status || blockRecv) { + DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_DISABLE, PROC_IO_SYNC); + } + + /* see if we need to recycle the recv buffer */ + if (status && (pPacket != NULL)) { + struct htc_packet_queue queue; + + if (A_EPROTO == status) { + DebugDumpBytes(pPacket->pBuffer, totalRecvLength, "Bad HCI-UART Recv packet"); + } + /* recycle packet */ + HTC_PACKET_RESET_RX(pPacket); + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); + HCI_TransportAddReceivePkts(pProt,&queue); + NotifyTransportFailure(pProt,status); + } + + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCIUartMessagePending \n")); + + return status; +} + +static void HCISendPacketCompletion(void *Context, struct htc_packet *pPacket) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)Context; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion (pPacket:0x%lX) \n",(unsigned long)pPacket)); + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Send Packet (0x%lX) failed: %d , len:%d \n", + (unsigned long)pPacket, pPacket->Status, pPacket->ActualLength)); + } + + DO_HCI_SEND_INDICATION(pProt,pPacket); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion \n")); +} + +static int SeekCreditsSynch(struct gmbox_proto_hci_uart *pProt) +{ + int status = 0; + int credits; + int retry = 100; + + while (true) { + credits = 0; + status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits); + if (status) { + break; + } + LOCK_HCI_TX(pProt); + pProt->CreditsAvailable += credits; + pProt->CreditsConsumed -= credits; + if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) { + pProt->CreditsCurrentSeek = 0; + UNLOCK_HCI_TX(pProt); + break; + } + UNLOCK_HCI_TX(pProt); + retry--; + if (0 == retry) { + status = A_EBUSY; + break; + } + A_MDELAY(20); + } + + return status; +} + +static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous) +{ + int status = 0; + int transferLength; + int creditsRequired, remainder; + u8 hciUartType; + bool synchSendComplete = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCITrySend (pPacket:0x%lX) %s \n",(unsigned long)pPacket, + Synchronous ? "SYNC" :"ASYNC")); + + LOCK_HCI_TX(pProt); + + /* increment write processing count on entry */ + pProt->SendProcessCount++; + + do { + + if (pProt->HCIStopped) { + status = A_ECANCELED; + break; + } + + if (pPacket != NULL) { + /* packet was supplied */ + if (Synchronous) { + /* in synchronous mode, the send queue can only hold 1 packet */ + if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) { + status = A_EBUSY; + A_ASSERT(false); + break; + } + + if (pProt->SendProcessCount > 1) { + /* another thread or task is draining the TX queues */ + status = A_EBUSY; + A_ASSERT(false); + break; + } + + HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket); + + } else { + /* see if adding this packet hits the max depth (asynchronous mode only) */ + if ((pProt->HCIConfig.MaxSendQueueDepth > 0) && + ((HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue) + 1) >= pProt->HCIConfig.MaxSendQueueDepth)) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("HCI Send queue is full, Depth:%d, Max:%d \n", + HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue), + pProt->HCIConfig.MaxSendQueueDepth)); + /* queue will be full, invoke any callbacks to determine what action to take */ + if (pProt->HCIConfig.pHCISendFull != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("HCI : Calling driver's send full callback.... \n")); + if (pProt->HCIConfig.pHCISendFull(pProt->HCIConfig.pContext, + pPacket) == HCI_SEND_FULL_DROP) { + /* drop it */ + status = A_NO_RESOURCE; + break; + } + } + } + + HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket); + } + + } + + if (pProt->SendStateFlags & HCI_SEND_WAIT_CREDITS) { + break; + } + + if (pProt->SendProcessCount > 1) { + /* another thread or task is draining the TX queues */ + break; + } + + /***** beyond this point only 1 thread may enter ******/ + + /* now drain the send queue for transmission as long as we have enough + * credits */ + while (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) { + + pPacket = HTC_PACKET_DEQUEUE(&pProt->SendQueue); + + switch (HCI_GET_PACKET_TYPE(pPacket)) { + case HCI_COMMAND_TYPE: + hciUartType = HCI_UART_COMMAND_PKT; + break; + case HCI_ACL_TYPE: + hciUartType = HCI_UART_ACL_PKT; + break; + default: + status = A_EINVAL; + A_ASSERT(false); + break; + } + + if (status) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Got head packet:0x%lX , Type:%d Length: %d Remaining Queue Depth: %d\n", + (unsigned long)pPacket, HCI_GET_PACKET_TYPE(pPacket), pPacket->ActualLength, + HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue))); + + transferLength = 1; /* UART type header is 1 byte */ + transferLength += pPacket->ActualLength; + transferLength = DEV_CALC_SEND_PADDED_LEN(pProt->pDev, transferLength); + + /* figure out how many credits this message requires */ + creditsRequired = transferLength / pProt->CreditSize; + remainder = transferLength % pProt->CreditSize; + + if (remainder) { + creditsRequired++; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Creds Required:%d Got:%d\n", + creditsRequired, pProt->CreditsAvailable)); + + if (creditsRequired > pProt->CreditsAvailable) { + if (Synchronous) { + /* in synchronous mode we need to seek credits in synchronously */ + pProt->CreditsCurrentSeek = creditsRequired; + UNLOCK_HCI_TX(pProt); + status = SeekCreditsSynch(pProt); + LOCK_HCI_TX(pProt); + if (status) { + break; + } + /* fall through and continue processing this send op */ + } else { + /* not enough credits, queue back to the head */ + HTC_PACKET_ENQUEUE_TO_HEAD(&pProt->SendQueue,pPacket); + /* waiting for credits */ + pProt->SendStateFlags |= HCI_SEND_WAIT_CREDITS; + /* provide a hint to reduce attempts to re-send if credits are dribbling back + * this hint is the short fall of credits */ + pProt->CreditsCurrentSeek = creditsRequired; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: packet:0x%lX placed back in queue. head packet needs: %d credits \n", + (unsigned long)pPacket, pProt->CreditsCurrentSeek)); + pPacket = NULL; + UNLOCK_HCI_TX(pProt); + + /* schedule a credit counter read, our CreditsAvailableCallback callback will be called + * with the result */ + DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_ASYNC, NULL); + + LOCK_HCI_TX(pProt); + break; + } + } + + /* caller guarantees some head room */ + pPacket->pBuffer--; + pPacket->pBuffer[0] = hciUartType; + + pProt->CreditsAvailable -= creditsRequired; + pProt->CreditsConsumed += creditsRequired; + A_ASSERT(pProt->CreditsConsumed <= pProt->CreditsMax); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state: consumed:%d available:%d max:%d\n", + pProt->CreditsConsumed, pProt->CreditsAvailable, pProt->CreditsMax)); + + UNLOCK_HCI_TX(pProt); + + /* write it out */ + if (Synchronous) { + pPacket->Completion = NULL; + pPacket->pContext = NULL; + } else { + pPacket->Completion = HCISendPacketCompletion; + pPacket->pContext = pProt; + } + + status = DevGMboxWrite(pProt->pDev,pPacket,transferLength); + if (Synchronous) { + synchSendComplete = true; + } else { + pPacket = NULL; + } + + LOCK_HCI_TX(pProt); + + } + + } while (false); + + pProt->SendProcessCount--; + A_ASSERT(pProt->SendProcessCount >= 0); + UNLOCK_HCI_TX(pProt); + + if (Synchronous) { + A_ASSERT(pPacket != NULL); + if (!status && (!synchSendComplete)) { + status = A_EBUSY; + A_ASSERT(false); + LOCK_HCI_TX(pProt); + if (pPacket->ListLink.pNext != NULL) { + /* remove from the queue */ + HTC_PACKET_REMOVE(&pProt->SendQueue,pPacket); + } + UNLOCK_HCI_TX(pProt); + } + } else { + if (status && (pPacket != NULL)) { + pPacket->Status = status; + DO_HCI_SEND_INDICATION(pProt,pPacket); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HCITrySend: \n")); + return status; +} + +static void FlushSendQueue(struct gmbox_proto_hci_uart *pProt) +{ + struct htc_packet *pPacket; + struct htc_packet_queue discardQueue; + + INIT_HTC_PACKET_QUEUE(&discardQueue); + + LOCK_HCI_TX(pProt); + + if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->SendQueue); + } + + UNLOCK_HCI_TX(pProt); + + /* discard packets */ + while (!HTC_QUEUE_EMPTY(&discardQueue)) { + pPacket = HTC_PACKET_DEQUEUE(&discardQueue); + pPacket->Status = A_ECANCELED; + DO_HCI_SEND_INDICATION(pProt,pPacket); + } + +} + +static void FlushRecvBuffers(struct gmbox_proto_hci_uart *pProt) +{ + struct htc_packet_queue discardQueue; + struct htc_packet *pPacket; + + INIT_HTC_PACKET_QUEUE(&discardQueue); + + LOCK_HCI_RX(pProt); + /*transfer list items from ACL and event buffer queues to the discard queue */ + if (!HTC_QUEUE_EMPTY(&pProt->HCIACLRecvBuffers)) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIACLRecvBuffers); + } + if (!HTC_QUEUE_EMPTY(&pProt->HCIEventBuffers)) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIEventBuffers); + } + UNLOCK_HCI_RX(pProt); + + /* now empty the discard queue */ + while (!HTC_QUEUE_EMPTY(&discardQueue)) { + pPacket = HTC_PACKET_DEQUEUE(&discardQueue); + pPacket->Status = A_ECANCELED; + DO_HCI_RECV_INDICATION(pProt,pPacket); + } + +} + +/*** protocol module install entry point ***/ + +int GMboxProtocolInstall(struct ar6k_device *pDev) +{ + int status = 0; + struct gmbox_proto_hci_uart *pProtocol = NULL; + + do { + + pProtocol = A_MALLOC(sizeof(struct gmbox_proto_hci_uart)); + + if (NULL == pProtocol) { + status = A_NO_MEMORY; + break; + } + + A_MEMZERO(pProtocol, sizeof(*pProtocol)); + pProtocol->pDev = pDev; + INIT_HTC_PACKET_QUEUE(&pProtocol->SendQueue); + INIT_HTC_PACKET_QUEUE(&pProtocol->HCIACLRecvBuffers); + INIT_HTC_PACKET_QUEUE(&pProtocol->HCIEventBuffers); + A_MUTEX_INIT(&pProtocol->HCIRxLock); + A_MUTEX_INIT(&pProtocol->HCITxLock); + + } while (false); + + if (!status) { + LOCK_AR6K(pDev); + DEV_GMBOX_SET_PROTOCOL(pDev, + HCIUartMessagePending, + CreditsAvailableCallback, + FailureCallback, + StateDumpCallback, + pProtocol); + UNLOCK_AR6K(pDev); + } else { + if (pProtocol != NULL) { + HCIUartCleanup(pProtocol); + } + } + + return status; +} + +/*** protocol module uninstall entry point ***/ +void GMboxProtocolUninstall(struct ar6k_device *pDev) +{ + struct gmbox_proto_hci_uart *pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev); + + if (pProtocol != NULL) { + + /* notify anyone attached */ + if (pProtocol->HCIAttached) { + A_ASSERT(pProtocol->HCIConfig.TransportRemoved != NULL); + pProtocol->HCIConfig.TransportRemoved(pProtocol->HCIConfig.pContext); + pProtocol->HCIAttached = false; + } + + HCIUartCleanup(pProtocol); + DEV_GMBOX_SET_PROTOCOL(pDev,NULL,NULL,NULL,NULL,NULL); + } + +} + +static int NotifyTransportReady(struct gmbox_proto_hci_uart *pProt) +{ + struct hci_transport_properties props; + int status = 0; + + do { + + A_MEMZERO(&props,sizeof(props)); + + /* HCI UART only needs one extra byte at the head to indicate the packet TYPE */ + props.HeadRoom = 1; + props.TailRoom = 0; + props.IOBlockPad = pProt->pDev->BlockSize; + if (pProt->HCIAttached) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI: notifying attached client to transport... \n")); + A_ASSERT(pProt->HCIConfig.TransportReady != NULL); + status = pProt->HCIConfig.TransportReady(pProt, + &props, + pProt->HCIConfig.pContext); + } + + } while (false); + + return status; +} + +/*********** HCI UART protocol implementation ************************************************/ + +HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo) +{ + struct gmbox_proto_hci_uart *pProtocol = NULL; + struct ar6k_device *pDev; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportAttach \n")); + + pDev = HTCGetAR6KDevice(HTCHandle); + + LOCK_AR6K(pDev); + + do { + + pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev); + + if (NULL == pProtocol) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not installed! \n")); + break; + } + + if (pProtocol->HCIAttached) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol already attached! \n")); + break; + } + + memcpy(&pProtocol->HCIConfig, pInfo, sizeof(struct hci_transport_config_info)); + + A_ASSERT(pProtocol->HCIConfig.pHCIPktRecv != NULL); + A_ASSERT(pProtocol->HCIConfig.pHCISendComplete != NULL); + + pProtocol->HCIAttached = true; + + } while (false); + + UNLOCK_AR6K(pDev); + + if (pProtocol != NULL) { + /* TODO ... should we use a worker? */ + NotifyTransportReady(pProtocol); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach (0x%lX) \n",(unsigned long)pProtocol)); + return (HCI_TRANSPORT_HANDLE)pProtocol; +} + +void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans) +{ + struct gmbox_proto_hci_uart *pProtocol = (struct gmbox_proto_hci_uart *)HciTrans; + struct ar6k_device *pDev = pProtocol->pDev; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportDetach \n")); + + LOCK_AR6K(pDev); + if (!pProtocol->HCIAttached) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not attached! \n")); + UNLOCK_AR6K(pDev); + return; + } + pProtocol->HCIAttached = false; + UNLOCK_AR6K(pDev); + + HCI_TransportStop(HciTrans); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach \n")); +} + +int HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + int status = 0; + bool unblockRecv = false; + struct htc_packet *pPacket; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCI_TransportAddReceivePkt \n")); + + LOCK_HCI_RX(pProt); + + do { + + if (pProt->HCIStopped) { + status = A_ECANCELED; + break; + } + + pPacket = HTC_GET_PKT_AT_HEAD(pQueue); + + if (NULL == pPacket) { + status = A_EINVAL; + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv packet added, type :%d, len:%d num:%d \n", + HCI_GET_PACKET_TYPE(pPacket), pPacket->BufferLength, HTC_PACKET_QUEUE_DEPTH(pQueue))); + + if (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIEventBuffers, pQueue); + } else if (HCI_GET_PACKET_TYPE(pPacket) == HCI_ACL_TYPE) { + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIACLRecvBuffers, pQueue); + } else { + status = A_EINVAL; + break; + } + + if (pProt->RecvStateFlags & HCI_RECV_WAIT_BUFFERS) { + if (pProt->WaitBufferType == HCI_GET_PACKET_TYPE(pPacket)) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv was blocked on packet type :%d, unblocking.. \n", + pProt->WaitBufferType)); + pProt->RecvStateFlags &= ~HCI_RECV_WAIT_BUFFERS; + pProt->WaitBufferType = HCI_PACKET_INVALID; + unblockRecv = true; + } + } + + } while (false); + + UNLOCK_HCI_RX(pProt); + + if (status) { + while (!HTC_QUEUE_EMPTY(pQueue)) { + pPacket = HTC_PACKET_DEQUEUE(pQueue); + pPacket->Status = A_ECANCELED; + DO_HCI_RECV_INDICATION(pProt,pPacket); + } + } + + if (unblockRecv) { + DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_ASYNC); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCI_TransportAddReceivePkt \n")); + + return 0; +} + +int HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + + return HCITrySend(pProt,pPacket,Synchronous); +} + +void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStop \n")); + + LOCK_AR6K(pProt->pDev); + if (pProt->HCIStopped) { + UNLOCK_AR6K(pProt->pDev); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n")); + return; + } + pProt->HCIStopped = true; + UNLOCK_AR6K(pProt->pDev); + + /* disable interrupts */ + DevGMboxIRQAction(pProt->pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC); + FlushSendQueue(pProt); + FlushRecvBuffers(pProt); + + /* signal bridge side to power down BT */ + DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_OFF, BTOFF_TIMEOUT_MS); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n")); +} + +int HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans) +{ + int status; + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStart \n")); + + /* set stopped in case we have a problem in starting */ + pProt->HCIStopped = true; + + do { + + status = InitTxCreditState(pProt); + + if (status) { + break; + } + + status = DevGMboxIRQAction(pProt->pDev, GMBOX_ERRORS_IRQ_ENABLE, PROC_IO_SYNC); + + if (status) { + break; + } + /* enable recv */ + status = DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_SYNC); + + if (status) { + break; + } + /* signal bridge side to power up BT */ + status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_ON, BTON_TIMEOUT_MS); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI_TransportStart : Failed to trigger BT ON \n")); + break; + } + + /* we made it */ + pProt->HCIStopped = false; + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStart \n")); + + return status; +} + +int HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + return DevGMboxIRQAction(pProt->pDev, + Enable ? GMBOX_RECV_IRQ_ENABLE : GMBOX_RECV_IRQ_DISABLE, + PROC_IO_SYNC); + +} + +int HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans, + struct htc_packet *pPacket, + int MaxPollMS) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + int status = 0; + u8 lookAhead[8]; + int bytes; + int totalRecvLength; + + MaxPollMS = MaxPollMS / 16; + + if (MaxPollMS < 2) { + MaxPollMS = 2; + } + + while (MaxPollMS) { + + bytes = sizeof(lookAhead); + status = DevGMboxRecvLookAheadPeek(pProt->pDev,lookAhead,&bytes); + if (status) { + break; + } + + if (bytes < 3) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI recv poll got bytes: %d, retry : %d \n", + bytes, MaxPollMS)); + A_MDELAY(16); + MaxPollMS--; + continue; + } + + totalRecvLength = 0; + switch (lookAhead[0]) { + case HCI_UART_EVENT_PKT: + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n", + lookAhead[1], lookAhead[2])); + totalRecvLength = lookAhead[2]; + totalRecvLength += 3; /* add type + event code + length field */ + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",lookAhead[0])); + status = A_EPROTO; + break; + } + + if (status) { + break; + } + + pPacket->Completion = NULL; + status = DevGMboxRead(pProt->pDev,pPacket,totalRecvLength); + if (status) { + break; + } + + pPacket->pBuffer++; + pPacket->ActualLength = totalRecvLength - 1; + pPacket->Status = 0; + break; + } + + if (MaxPollMS == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI recv poll timeout! \n")); + status = A_ERROR; + } + + return status; +} + +#define LSB_SCRATCH_IDX 4 +#define MSB_SCRATCH_IDX 5 +int HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud) +{ + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + struct hif_device *pHIFDevice = (struct hif_device *)(pProt->pDev->HIFDevice); + u32 scaledBaud, scratchAddr; + int status = 0; + + /* Divide the desired baud rate by 100 + * Store the LSB in the local scratch register 4 and the MSB in the local + * scratch register 5 for the target to read + */ + scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * LSB_SCRATCH_IDX); + scaledBaud = (Baud / 100) & LOCAL_SCRATCH_VALUE_MASK; + status = ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud); + scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * MSB_SCRATCH_IDX); + scaledBaud = ((Baud / 100) >> (LOCAL_SCRATCH_VALUE_MSB+1)) & LOCAL_SCRATCH_VALUE_MASK; + status |= ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud); + if (0 != status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to set up baud rate in scratch register!")); + return status; + } + + /* Now interrupt the target to tell it about the baud rate */ + status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BAUD_SET, BAUD_TIMEOUT_MS); + if (0 != status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to tell target to change baud rate!")); + } + + return status; +} + +int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable) +{ + int status; + struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)HciTrans; + + if (Enable) { + status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON, BTPWRSAV_TIMEOUT_MS); + } else { + status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF, BTPWRSAV_TIMEOUT_MS); + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to enable/disable HCI power management!\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI power management enabled/disabled!\n")); + } + + return status; +} + +#endif //ATH_AR6K_ENABLE_GMBOX + diff --git a/trunk/drivers/staging/ath6kl/htc2/htc.c b/trunk/drivers/staging/ath6kl/htc2/htc.c new file mode 100644 index 000000000000..ae54e64b6243 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc.c @@ -0,0 +1,575 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#include "htc_internal.h" + +#ifdef ATH_DEBUG_MODULE +static struct ath_debug_mask_description g_HTCDebugDescription[] = { + { ATH_DEBUG_SEND , "Send"}, + { ATH_DEBUG_RECV , "Recv"}, + { ATH_DEBUG_SYNC , "Sync"}, + { ATH_DEBUG_DUMP , "Dump Data (RX or TX)"}, + { ATH_DEBUG_IRQ , "Interrupt Processing"} +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc, + "htc", + "Host Target Communications", + ATH_DEBUG_MASK_DEFAULTS, + ATH_DEBUG_DESCRIPTION_COUNT(g_HTCDebugDescription), + g_HTCDebugDescription); + +#endif + +static void HTCReportFailure(void *Context); +static void ResetEndpointStates(struct htc_target *target); + +void HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList) +{ + LOCK_HTC(target); + HTC_PACKET_ENQUEUE(pList,pPacket); + UNLOCK_HTC(target); +} + +struct htc_packet *HTCAllocControlBuffer(struct htc_target *target, struct htc_packet_queue *pList) +{ + struct htc_packet *pPacket; + + LOCK_HTC(target); + pPacket = HTC_PACKET_DEQUEUE(pList); + UNLOCK_HTC(target); + + return pPacket; +} + +/* cleanup the HTC instance */ +static void HTCCleanup(struct htc_target *target) +{ + s32 i; + + DevCleanup(&target->Device); + + for (i = 0;i < NUM_CONTROL_BUFFERS;i++) { + if (target->HTCControlBuffers[i].Buffer) { + kfree(target->HTCControlBuffers[i].Buffer); + } + } + + if (A_IS_MUTEX_VALID(&target->HTCLock)) { + A_MUTEX_DELETE(&target->HTCLock); + } + + if (A_IS_MUTEX_VALID(&target->HTCRxLock)) { + A_MUTEX_DELETE(&target->HTCRxLock); + } + + if (A_IS_MUTEX_VALID(&target->HTCTxLock)) { + A_MUTEX_DELETE(&target->HTCTxLock); + } + /* free our instance */ + kfree(target); +} + +/* registered target arrival callback from the HIF layer */ +HTC_HANDLE HTCCreate(void *hif_handle, struct htc_init_info *pInfo) +{ + struct htc_target *target = NULL; + int status = 0; + int i; + u32 ctrl_bufsz; + u32 blocksizes[HTC_MAILBOX_NUM_MAX]; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Enter\n")); + + A_REGISTER_MODULE_DEBUG_INFO(htc); + + do { + + /* allocate target memory */ + if ((target = (struct htc_target *)A_MALLOC(sizeof(struct htc_target))) == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); + status = A_ERROR; + break; + } + + A_MEMZERO(target, sizeof(struct htc_target)); + A_MUTEX_INIT(&target->HTCLock); + A_MUTEX_INIT(&target->HTCRxLock); + A_MUTEX_INIT(&target->HTCTxLock); + INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList); + INIT_HTC_PACKET_QUEUE(&target->ControlBufferRXFreeList); + + /* give device layer the hif device handle */ + target->Device.HIFDevice = hif_handle; + /* give the device layer our context (for event processing) + * the device layer will register it's own context with HIF + * so we need to set this so we can fetch it in the target remove handler */ + target->Device.HTCContext = target; + /* set device layer target failure callback */ + target->Device.TargetFailureCallback = HTCReportFailure; + /* set device layer recv message pending callback */ + target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler; + target->EpWaitingForBuffers = ENDPOINT_MAX; + + memcpy(&target->HTCInitInfo,pInfo,sizeof(struct htc_init_info)); + + ResetEndpointStates(target); + + /* setup device layer */ + status = DevSetup(&target->Device); + + if (status) { + break; + } + + + /* get the block sizes */ + status = HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + blocksizes, sizeof(blocksizes)); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get block size info from HIF layer...\n")); + break; + } + + /* Set the control buffer size based on the block size */ + if (blocksizes[1] > HTC_MAX_CONTROL_MESSAGE_LENGTH) { + ctrl_bufsz = blocksizes[1] + HTC_HDR_LENGTH; + } else { + ctrl_bufsz = HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH; + } + for (i = 0;i < NUM_CONTROL_BUFFERS;i++) { + target->HTCControlBuffers[i].Buffer = A_MALLOC(ctrl_bufsz); + if (target->HTCControlBuffers[i].Buffer == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); + status = A_ERROR; + break; + } + } + + if (status) { + break; + } + + /* carve up buffers/packets for control messages */ + for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) { + struct htc_packet *pControlPacket; + pControlPacket = &target->HTCControlBuffers[i].HtcPacket; + SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket, + target, + target->HTCControlBuffers[i].Buffer, + ctrl_bufsz, + ENDPOINT_0); + HTC_FREE_CONTROL_RX(target,pControlPacket); + } + + for (;i < NUM_CONTROL_BUFFERS;i++) { + struct htc_packet *pControlPacket; + pControlPacket = &target->HTCControlBuffers[i].HtcPacket; + INIT_HTC_PACKET_INFO(pControlPacket, + target->HTCControlBuffers[i].Buffer, + ctrl_bufsz); + HTC_FREE_CONTROL_TX(target,pControlPacket); + } + + } while (false); + + if (status) { + if (target != NULL) { + HTCCleanup(target); + target = NULL; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Exit\n")); + + return target; +} + +void HTCDestroy(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy .. Destroying :0x%lX \n",(unsigned long)target)); + HTCCleanup(target); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n")); +} + +/* get the low level HIF device for the caller , the caller may wish to do low level + * HIF requests */ +void *HTCGetHifDevice(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + return target->Device.HIFDevice; +} + +/* wait for the target to arrive (sends HTC Ready message) + * this operation is fully synchronous and the message is polled for */ +int HTCWaitTarget(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int status; + struct htc_packet *pPacket = NULL; + HTC_READY_EX_MSG *pRdyMsg; + + struct htc_service_connect_req connect; + struct htc_service_connect_resp resp; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%lX) \n", (unsigned long)target)); + + do { + +#ifdef MBOXHW_UNIT_TEST + + status = DoMboxHWTest(&target->Device); + + if (status) { + break; + } + +#endif + + /* we should be getting 1 control message that the target is ready */ + status = HTCWaitforControlMessage(target, &pPacket); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n")); + break; + } + + /* we controlled the buffer creation so it has to be properly aligned */ + pRdyMsg = (HTC_READY_EX_MSG *)pPacket->pBuffer; + + if ((pRdyMsg->Version2_0_Info.MessageID != HTC_MSG_READY_ID) || + (pPacket->ActualLength < sizeof(HTC_READY_MSG))) { + /* this message is not valid */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + + if (pRdyMsg->Version2_0_Info.CreditCount == 0 || pRdyMsg->Version2_0_Info.CreditSize == 0) { + /* this message is not valid */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + target->TargetCredits = pRdyMsg->Version2_0_Info.CreditCount; + target->TargetCreditSize = pRdyMsg->Version2_0_Info.CreditSize; + + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, (" Target Ready: credits: %d credit size: %d\n", + target->TargetCredits, target->TargetCreditSize)); + + /* check if this is an extended ready message */ + if (pPacket->ActualLength >= sizeof(HTC_READY_EX_MSG)) { + /* this is an extended message */ + target->HTCTargetVersion = pRdyMsg->HTCVersion; + target->MaxMsgPerBundle = pRdyMsg->MaxMsgsPerHTCBundle; + } else { + /* legacy */ + target->HTCTargetVersion = HTC_VERSION_2P0; + target->MaxMsgPerBundle = 0; + } + +#ifdef HTC_FORCE_LEGACY_2P0 + /* for testing and comparison...*/ + target->HTCTargetVersion = HTC_VERSION_2P0; + target->MaxMsgPerBundle = 0; +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("Using HTC Protocol Version : %s (%d)\n ", + (target->HTCTargetVersion == HTC_VERSION_2P0) ? "2.0" : ">= 2.1", + target->HTCTargetVersion)); + + if (target->MaxMsgPerBundle > 0) { + /* limit what HTC can handle */ + target->MaxMsgPerBundle = min(HTC_HOST_MAX_MSG_PER_BUNDLE, target->MaxMsgPerBundle); + /* target supports message bundling, setup device layer */ + if (DevSetupMsgBundling(&target->Device,target->MaxMsgPerBundle)) { + /* device layer can't handle bundling */ + target->MaxMsgPerBundle = 0; + } else { + /* limit bundle what the device layer can handle */ + target->MaxMsgPerBundle = min(DEV_GET_MAX_MSG_PER_BUNDLE(&target->Device), + target->MaxMsgPerBundle); + } + } + + if (target->MaxMsgPerBundle > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + (" HTC bundling allowed. Max Msg Per HTC Bundle: %d\n", target->MaxMsgPerBundle)); + + if (DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device) != 0) { + target->SendBundlingEnabled = true; + } + if (DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device) != 0) { + target->RecvBundlingEnabled = true; + } + + if (!DEV_IS_LEN_BLOCK_ALIGNED(&target->Device,target->TargetCreditSize)) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("*** Credit size: %d is not block aligned! Disabling send bundling \n", + target->TargetCreditSize)); + /* disallow send bundling since the credit size is not aligned to a block size + * the I/O block padding will spill into the next credit buffer which is fatal */ + target->SendBundlingEnabled = false; + } + } + + /* setup our pseudo HTC control endpoint connection */ + A_MEMZERO(&connect,sizeof(connect)); + A_MEMZERO(&resp,sizeof(resp)); + connect.EpCallbacks.pContext = target; + connect.EpCallbacks.EpTxComplete = HTCControlTxComplete; + connect.EpCallbacks.EpRecv = HTCControlRecv; + connect.EpCallbacks.EpRecvRefill = NULL; /* not needed */ + connect.EpCallbacks.EpSendFull = NULL; /* not nedded */ + connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS; + connect.ServiceID = HTC_CTRL_RSVD_SVC; + + /* connect fake service */ + status = HTCConnectService((HTC_HANDLE)target, + &connect, + &resp); + + if (!status) { + break; + } + + } while (false); + + if (pPacket != NULL) { + HTC_FREE_CONTROL_RX(target,pPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n")); + + return status; +} + + + +/* Start HTC, enable interrupts and let the target know host has finished setup */ +int HTCStart(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_packet *pPacket; + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); + + /* make sure interrupts are disabled at the chip level, + * this function can be called again from a reboot of the target without shutting down HTC */ + DevDisableInterrupts(&target->Device); + /* make sure state is cleared again */ + target->OpStateFlags = 0; + target->RecvStateFlags = 0; + + /* now that we are starting, push control receive buffers into the + * HTC control endpoint */ + + while (1) { + pPacket = HTC_ALLOC_CONTROL_RX(target); + if (NULL == pPacket) { + break; + } + HTCAddReceivePkt((HTC_HANDLE)target,pPacket); + } + + do { + + AR_DEBUG_ASSERT(target->InitCredits != NULL); + AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL); + AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL); + + /* call init credits callback to do the distribution , + * NOTE: the first entry in the distribution list is ENDPOINT_0, so + * we pass the start of the list after this one. */ + target->InitCredits(target->pCredDistContext, + target->EpCreditDistributionListHead->pNext, + target->TargetCredits); + +#ifdef ATH_DEBUG_MODULE + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) { + DumpCreditDistStates(target); + } +#endif + + /* the caller is done connecting to services, so we can indicate to the + * target that the setup phase is complete */ + status = HTCSendSetupComplete(target); + + if (status) { + break; + } + + /* unmask interrupts */ + status = DevUnmaskInterrupts(&target->Device); + + if (status) { + HTCStop(target); + } + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); + return status; +} + +static void ResetEndpointStates(struct htc_target *target) +{ + struct htc_endpoint *pEndpoint; + int i; + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + + A_MEMZERO(&pEndpoint->CreditDist, sizeof(pEndpoint->CreditDist)); + pEndpoint->ServiceID = 0; + pEndpoint->MaxMsgLength = 0; + pEndpoint->MaxTxQueueDepth = 0; + A_MEMZERO(&pEndpoint->EndPointStats,sizeof(pEndpoint->EndPointStats)); + INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBuffers); + INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue); + INIT_HTC_PACKET_QUEUE(&pEndpoint->RecvIndicationQueue); + pEndpoint->target = target; + } + /* reset distribution list */ + target->EpCreditDistributionListHead = NULL; +} + +/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */ +void HTCStop(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n")); + + LOCK_HTC(target); + /* mark that we are shutting down .. */ + target->OpStateFlags |= HTC_OP_STATE_STOPPING; + UNLOCK_HTC(target); + + /* Masking interrupts is a synchronous operation, when this function returns + * all pending HIF I/O has completed, we can safely flush the queues */ + DevMaskInterrupts(&target->Device); + +#ifdef THREAD_X + // + // Is this delay required + // + A_MDELAY(200); // wait for IRQ process done +#endif + /* flush all send packets */ + HTCFlushSendPkts(target); + /* flush all recv buffers */ + HTCFlushRecvBuffers(target); + + DevCleanupMsgBundling(&target->Device); + + ResetEndpointStates(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n")); +} + +#ifdef ATH_DEBUG_MODULE +void HTCDumpCreditStates(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + LOCK_HTC_TX(target); + + DumpCreditDistStates(target); + + UNLOCK_HTC_TX(target); + + DumpAR6KDevState(&target->Device); +} +#endif +/* report a target failure from the device, this is a callback from the device layer + * which uses a mechanism to report errors from the target (i.e. special interrupts) */ +static void HTCReportFailure(void *Context) +{ + struct htc_target *target = (struct htc_target *)Context; + + target->TargetFailure = true; + + if (target->HTCInitInfo.TargetFailure != NULL) { + /* let upper layer know, it needs to call HTCStop() */ + target->HTCInitInfo.TargetFailure(target->HTCInitInfo.pContext, A_ERROR); + } +} + +bool HTCGetEndpointStatistics(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + HTC_ENDPOINT_STAT_ACTION Action, + struct htc_endpoint_stats *pStats) +{ + + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + bool clearStats = false; + bool sample = false; + + switch (Action) { + case HTC_EP_STAT_SAMPLE : + sample = true; + break; + case HTC_EP_STAT_SAMPLE_AND_CLEAR : + sample = true; + clearStats = true; + break; + case HTC_EP_STAT_CLEAR : + clearStats = true; + break; + default: + break; + } + + A_ASSERT(Endpoint < ENDPOINT_MAX); + + /* lock out TX and RX while we sample and/or clear */ + LOCK_HTC_TX(target); + LOCK_HTC_RX(target); + + if (sample) { + A_ASSERT(pStats != NULL); + /* return the stats to the caller */ + memcpy(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats)); + } + + if (clearStats) { + /* reset stats */ + A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats)); + } + + UNLOCK_HTC_RX(target); + UNLOCK_HTC_TX(target); + + return true; +} + +struct ar6k_device *HTCGetAR6KDevice(void *HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + return &target->Device; +} + diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_debug.h b/trunk/drivers/staging/ath6kl/htc2/htc_debug.h new file mode 100644 index 000000000000..8455703e221c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_debug.h @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef HTC_DEBUG_H_ +#define HTC_DEBUG_H_ + +#define ATH_MODULE_NAME htc +#include "a_debug.h" + +/* ------- Debug related stuff ------- */ + +#define ATH_DEBUG_SEND ATH_DEBUG_MAKE_MODULE_MASK(0) +#define ATH_DEBUG_RECV ATH_DEBUG_MAKE_MODULE_MASK(1) +#define ATH_DEBUG_SYNC ATH_DEBUG_MAKE_MODULE_MASK(2) +#define ATH_DEBUG_DUMP ATH_DEBUG_MAKE_MODULE_MASK(3) +#define ATH_DEBUG_IRQ ATH_DEBUG_MAKE_MODULE_MASK(4) + + +#endif /*HTC_DEBUG_H_*/ diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_internal.h b/trunk/drivers/staging/ath6kl/htc2/htc_internal.h new file mode 100644 index 000000000000..cac97351769a --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_internal.h @@ -0,0 +1,211 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HTC_INTERNAL_H_ +#define _HTC_INTERNAL_H_ + +/* for debugging, uncomment this to capture the last frame header, on frame header + * processing errors, the last frame header is dump for comparison */ +//#define HTC_CAPTURE_LAST_FRAME + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "htc_debug.h" +#include "htc.h" +#include "htc_api.h" +#include "bmi_msg.h" +#include "hif.h" +#include "AR6000/ar6k.h" + +/* HTC operational parameters */ +#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ +#define HTC_TARGET_DEBUG_INTR_MASK 0x01 +#define HTC_TARGET_CREDIT_INTR_MASK 0xF0 + +#define HTC_HOST_MAX_MSG_PER_BUNDLE 8 +#define HTC_MIN_HTC_MSGS_TO_BUNDLE 2 + +/* packet flags */ + +#define HTC_RX_PKT_IGNORE_LOOKAHEAD (1 << 0) +#define HTC_RX_PKT_REFRESH_HDR (1 << 1) +#define HTC_RX_PKT_PART_OF_BUNDLE (1 << 2) +#define HTC_RX_PKT_NO_RECYCLE (1 << 3) + +/* scatter request flags */ + +#define HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE (1 << 0) + +struct htc_endpoint { + HTC_ENDPOINT_ID Id; + HTC_SERVICE_ID ServiceID; /* service ID this endpoint is bound to + non-zero value means this endpoint is in use */ + struct htc_packet_queue TxQueue; /* HTC frame buffer TX queue */ + struct htc_packet_queue RxBuffers; /* HTC frame buffer RX list */ + struct htc_endpoint_credit_dist CreditDist; /* credit distribution structure (exposed to driver layer) */ + struct htc_ep_callbacks EpCallBacks; /* callbacks associated with this endpoint */ + int MaxTxQueueDepth; /* max depth of the TX queue before we need to + call driver's full handler */ + int MaxMsgLength; /* max length of endpoint message */ + int TxProcessCount; /* reference count to continue tx processing */ + struct htc_packet_queue RecvIndicationQueue; /* recv packets ready to be indicated */ + int RxProcessCount; /* reference count to allow single processing context */ + struct htc_target *target; /* back pointer to target */ + u8 SeqNo; /* TX seq no (helpful) for debugging */ + u32 LocalConnectionFlags; /* local connection flags */ + struct htc_endpoint_stats EndPointStats; /* endpoint statistics */ +}; + +#define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count); +#define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL + +#define NUM_CONTROL_BUFFERS 8 +#define NUM_CONTROL_TX_BUFFERS 2 +#define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS) + +struct htc_control_buffer { + struct htc_packet HtcPacket; + u8 *Buffer; +}; + +#define HTC_RECV_WAIT_BUFFERS (1 << 0) +#define HTC_OP_STATE_STOPPING (1 << 0) + +/* our HTC target state */ +struct htc_target { + struct htc_endpoint EndPoint[ENDPOINT_MAX]; + struct htc_control_buffer HTCControlBuffers[NUM_CONTROL_BUFFERS]; + struct htc_endpoint_credit_dist *EpCreditDistributionListHead; + struct htc_packet_queue ControlBufferTXFreeList; + struct htc_packet_queue ControlBufferRXFreeList; + HTC_CREDIT_DIST_CALLBACK DistributeCredits; + HTC_CREDIT_INIT_CALLBACK InitCredits; + void *pCredDistContext; + int TargetCredits; + unsigned int TargetCreditSize; + A_MUTEX_T HTCLock; + A_MUTEX_T HTCRxLock; + A_MUTEX_T HTCTxLock; + struct ar6k_device Device; /* AR6K - specific state */ + u32 OpStateFlags; + u32 RecvStateFlags; + HTC_ENDPOINT_ID EpWaitingForBuffers; + bool TargetFailure; +#ifdef HTC_CAPTURE_LAST_FRAME + struct htc_frame_hdr LastFrameHdr; /* useful for debugging */ + u8 LastTrailer[256]; + u8 LastTrailerLength; +#endif + struct htc_init_info HTCInitInfo; + u8 HTCTargetVersion; + int MaxMsgPerBundle; /* max messages per bundle for HTC */ + bool SendBundlingEnabled; /* run time enable for send bundling (dynamic) */ + int RecvBundlingEnabled; /* run time enable for recv bundling (dynamic) */ +}; + +#define HTC_STOPPING(t) ((t)->OpStateFlags & HTC_OP_STATE_STOPPING) +#define LOCK_HTC(t) A_MUTEX_LOCK(&(t)->HTCLock); +#define UNLOCK_HTC(t) A_MUTEX_UNLOCK(&(t)->HTCLock); +#define LOCK_HTC_RX(t) A_MUTEX_LOCK(&(t)->HTCRxLock); +#define UNLOCK_HTC_RX(t) A_MUTEX_UNLOCK(&(t)->HTCRxLock); +#define LOCK_HTC_TX(t) A_MUTEX_LOCK(&(t)->HTCTxLock); +#define UNLOCK_HTC_TX(t) A_MUTEX_UNLOCK(&(t)->HTCTxLock); + +#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((struct htc_target *)(hnd)) +#define HTC_RECYCLE_RX_PKT(target,p,e) \ +{ \ + if ((p)->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_NO_RECYCLE) { \ + HTC_PACKET_RESET_RX(pPacket); \ + pPacket->Status = A_ECANCELED; \ + (e)->EpCallBacks.EpRecv((e)->EpCallBacks.pContext, \ + (p)); \ + } else { \ + HTC_PACKET_RESET_RX(pPacket); \ + HTCAddReceivePkt((HTC_HANDLE)(target),(p)); \ + } \ +} + +/* internal HTC functions */ +void HTCControlTxComplete(void *Context, struct htc_packet *pPacket); +void HTCControlRecv(void *Context, struct htc_packet *pPacket); +int HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket); +struct htc_packet *HTCAllocControlBuffer(struct htc_target *target, struct htc_packet_queue *pList); +void HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList); +int HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket); +void HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket); +int HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched); +void HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint); +int HTCSendSetupComplete(struct htc_target *target); +void HTCFlushRecvBuffers(struct htc_target *target); +void HTCFlushSendPkts(struct htc_target *target); + +#ifdef ATH_DEBUG_MODULE +void DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist); +void DumpCreditDistStates(struct htc_target *target); +void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription); +#endif + +static INLINE struct htc_packet *HTC_ALLOC_CONTROL_TX(struct htc_target *target) { + struct htc_packet *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList); + if (pPacket != NULL) { + /* set payload pointer area with some headroom */ + pPacket->pBuffer = pPacket->pBufferStart + HTC_HDR_LENGTH; + } + return pPacket; +} + +#define HTC_FREE_CONTROL_TX(t,p) HTCFreeControlBuffer((t),(p),&(t)->ControlBufferTXFreeList) +#define HTC_ALLOC_CONTROL_RX(t) HTCAllocControlBuffer((t),&(t)->ControlBufferRXFreeList) +#define HTC_FREE_CONTROL_RX(t,p) \ +{ \ + HTC_PACKET_RESET_RX(p); \ + HTCFreeControlBuffer((t),(p),&(t)->ControlBufferRXFreeList); \ +} + +#define HTC_PREPARE_SEND_PKT(pP,sendflags,ctrl0,ctrl1) \ +{ \ + u8 *pHdrBuf; \ + (pP)->pBuffer -= HTC_HDR_LENGTH; \ + pHdrBuf = (pP)->pBuffer; \ + A_SET_UINT16_FIELD(pHdrBuf,struct htc_frame_hdr,PayloadLen,(u16)(pP)->ActualLength); \ + A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,Flags,(sendflags)); \ + A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,EndpointID, (u8)(pP)->Endpoint); \ + A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[0], (u8)(ctrl0)); \ + A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[1], (u8)(ctrl1)); \ +} + +#define HTC_UNPREPARE_SEND_PKT(pP) \ + (pP)->pBuffer += HTC_HDR_LENGTH; \ + +#ifdef __cplusplus +} +#endif + +#endif /* _HTC_INTERNAL_H_ */ diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_recv.c b/trunk/drivers/staging/ath6kl/htc2/htc_recv.c new file mode 100644 index 000000000000..974cc8cd6936 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_recv.c @@ -0,0 +1,1572 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#include "htc_internal.h" + +#define HTCIssueRecv(t, p) \ + DevRecvPacket(&(t)->Device, \ + (p), \ + (p)->ActualLength) + +#define DO_RCV_COMPLETION(e,q) DoRecvCompletion(e,q) + +#define DUMP_RECV_PKT_INFO(pP) \ + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC RECV packet 0x%lX (%d bytes) (hdr:0x%X) on ep : %d \n", \ + (unsigned long)(pP), \ + (pP)->ActualLength, \ + (pP)->PktInfo.AsRx.ExpectedHdr, \ + (pP)->Endpoint)) + +#define HTC_RX_STAT_PROFILE(t,ep,numLookAheads) \ +{ \ + INC_HTC_EP_STAT((ep), RxReceived, 1); \ + if ((numLookAheads) == 1) { \ + INC_HTC_EP_STAT((ep), RxLookAheads, 1); \ + } else if ((numLookAheads) > 1) { \ + INC_HTC_EP_STAT((ep), RxBundleLookAheads, 1); \ + } \ +} + +static void DoRecvCompletion(struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueueToIndicate) +{ + + do { + + if (HTC_QUEUE_EMPTY(pQueueToIndicate)) { + /* nothing to indicate */ + break; + } + + if (pEndpoint->EpCallBacks.EpRecvPktMultiple != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d, recv multiple callback (%d pkts) \n", + pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate))); + /* a recv multiple handler is being used, pass the queue to the handler */ + pEndpoint->EpCallBacks.EpRecvPktMultiple(pEndpoint->EpCallBacks.pContext, + pQueueToIndicate); + INIT_HTC_PACKET_QUEUE(pQueueToIndicate); + } else { + struct htc_packet *pPacket; + /* using legacy EpRecv */ + do { + pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate); + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d recv callback on packet 0x%lX \n", \ + pEndpoint->Id, (unsigned long)(pPacket))); + pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket); + } while (!HTC_QUEUE_EMPTY(pQueueToIndicate)); + } + + } while (false); + +} + +static INLINE int HTCProcessTrailer(struct htc_target *target, + u8 *pBuffer, + int Length, + u32 *pNextLookAheads, + int *pNumLookAheads, + HTC_ENDPOINT_ID FromEndpoint) +{ + HTC_RECORD_HDR *pRecord; + u8 *pRecordBuf; + HTC_LOOKAHEAD_REPORT *pLookAhead; + u8 *pOrigBuffer; + int origLength; + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length)); + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer"); + } + + pOrigBuffer = pBuffer; + origLength = Length; + status = 0; + + while (Length > 0) { + + if (Length < sizeof(HTC_RECORD_HDR)) { + status = A_EPROTO; + break; + } + /* these are byte aligned structs */ + pRecord = (HTC_RECORD_HDR *)pBuffer; + Length -= sizeof(HTC_RECORD_HDR); + pBuffer += sizeof(HTC_RECORD_HDR); + + if (pRecord->Length > Length) { + /* no room left in buffer for record */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" invalid record length: %d (id:%d) buffer has: %d bytes left \n", + pRecord->Length, pRecord->RecordID, Length)); + status = A_EPROTO; + break; + } + /* start of record follows the header */ + pRecordBuf = pBuffer; + + switch (pRecord->RecordID) { + case HTC_RECORD_CREDITS: + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_CREDIT_REPORT)); + HTCProcessCreditRpt(target, + (HTC_CREDIT_REPORT *)pRecordBuf, + pRecord->Length / (sizeof(HTC_CREDIT_REPORT)), + FromEndpoint); + break; + case HTC_RECORD_LOOKAHEAD: + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_LOOKAHEAD_REPORT)); + pLookAhead = (HTC_LOOKAHEAD_REPORT *)pRecordBuf; + if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) && + (pNextLookAheads != NULL)) { + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) \n", + pLookAhead->PreValid, + pLookAhead->PostValid)); + + /* look ahead bytes are valid, copy them over */ + ((u8 *)(&pNextLookAheads[0]))[0] = pLookAhead->LookAhead[0]; + ((u8 *)(&pNextLookAheads[0]))[1] = pLookAhead->LookAhead[1]; + ((u8 *)(&pNextLookAheads[0]))[2] = pLookAhead->LookAhead[2]; + ((u8 *)(&pNextLookAheads[0]))[3] = pLookAhead->LookAhead[3]; + +#ifdef ATH_DEBUG_MODULE + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes((u8 *)pNextLookAheads,4,"Next Look Ahead"); + } +#endif + /* just one normal lookahead */ + *pNumLookAheads = 1; + } + break; + case HTC_RECORD_LOOKAHEAD_BUNDLE: + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)); + if (pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT) && + (pNextLookAheads != NULL)) { + HTC_BUNDLED_LOOKAHEAD_REPORT *pBundledLookAheadRpt; + int i; + + pBundledLookAheadRpt = (HTC_BUNDLED_LOOKAHEAD_REPORT *)pRecordBuf; + +#ifdef ATH_DEBUG_MODULE + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + DebugDumpBytes(pRecordBuf,pRecord->Length,"Bundle LookAhead"); + } +#endif + + if ((pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))) > + HTC_HOST_MAX_MSG_PER_BUNDLE) { + /* this should never happen, the target restricts the number + * of messages per bundle configured by the host */ + A_ASSERT(false); + status = A_EPROTO; + break; + } + + for (i = 0; i < (int)(pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))); i++) { + ((u8 *)(&pNextLookAheads[i]))[0] = pBundledLookAheadRpt->LookAhead[0]; + ((u8 *)(&pNextLookAheads[i]))[1] = pBundledLookAheadRpt->LookAhead[1]; + ((u8 *)(&pNextLookAheads[i]))[2] = pBundledLookAheadRpt->LookAhead[2]; + ((u8 *)(&pNextLookAheads[i]))[3] = pBundledLookAheadRpt->LookAhead[3]; + pBundledLookAheadRpt++; + } + + *pNumLookAheads = i; + } + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n", + pRecord->RecordID, pRecord->Length)); + break; + } + + if (status) { + break; + } + + /* advance buffer past this record for next time around */ + pBuffer += pRecord->Length; + Length -= pRecord->Length; + } + +#ifdef ATH_DEBUG_MODULE + if (status) { + DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer"); + } +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n")); + return status; + +} + +/* process a received message (i.e. strip off header, process any trailer data) + * note : locks must be released when this function is called */ +static int HTCProcessRecvHeader(struct htc_target *target, + struct htc_packet *pPacket, + u32 *pNextLookAheads, + int *pNumLookAheads) +{ + u8 temp; + u8 *pBuf; + int status = 0; + u16 payloadLen; + u32 lookAhead; + + pBuf = pPacket->pBuffer; + + if (pNumLookAheads != NULL) { + *pNumLookAheads = 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader \n")); + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + AR_DEBUG_PRINTBUF(pBuf,pPacket->ActualLength,"HTC Recv PKT"); + } + + do { + /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to + * retrieve 16 bit fields */ + payloadLen = A_GET_UINT16_FIELD(pBuf, struct htc_frame_hdr, PayloadLen); + + ((u8 *)&lookAhead)[0] = pBuf[0]; + ((u8 *)&lookAhead)[1] = pBuf[1]; + ((u8 *)&lookAhead)[2] = pBuf[2]; + ((u8 *)&lookAhead)[3] = pBuf[3]; + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) { + /* refresh expected hdr, since this was unknown at the time we grabbed the packets + * as part of a bundle */ + pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead; + /* refresh actual length since we now have the real header */ + pPacket->ActualLength = payloadLen + HTC_HDR_LENGTH; + + /* validate the actual header that was refreshed */ + if (pPacket->ActualLength > pPacket->BufferLength) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Refreshed HDR payload length (%d) in bundled RECV is invalid (hdr: 0x%X) \n", + payloadLen, lookAhead)); + /* limit this to max buffer just to print out some of the buffer */ + pPacket->ActualLength = min(pPacket->ActualLength, pPacket->BufferLength); + status = A_EPROTO; + break; + } + + if (pPacket->Endpoint != A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Refreshed HDR endpoint (%d) does not match expected endpoint (%d) \n", + A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID), pPacket->Endpoint)); + status = A_EPROTO; + break; + } + } + + if (lookAhead != pPacket->PktInfo.AsRx.ExpectedHdr) { + /* somehow the lookahead that gave us the full read length did not + * reflect the actual header in the pending message */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCProcessRecvHeader, lookahead mismatch! (pPkt:0x%lX flags:0x%X) \n", + (unsigned long)pPacket, pPacket->PktInfo.AsRx.HTCRxFlags)); +#ifdef ATH_DEBUG_MODULE + DebugDumpBytes((u8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead"); + DebugDumpBytes(pBuf,sizeof(struct htc_frame_hdr),"Current Frame Header"); +#ifdef HTC_CAPTURE_LAST_FRAME + DebugDumpBytes((u8 *)&target->LastFrameHdr,sizeof(struct htc_frame_hdr),"Last Frame Header"); + if (target->LastTrailerLength != 0) { + DebugDumpBytes(target->LastTrailer, + target->LastTrailerLength, + "Last trailer"); + } +#endif +#endif + status = A_EPROTO; + break; + } + + /* get flags */ + temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, Flags); + + if (temp & HTC_FLAGS_RECV_TRAILER) { + /* this packet has a trailer */ + + /* extract the trailer length in control byte 0 */ + temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, ControlBytes[0]); + + if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n", + payloadLen, temp)); + status = A_EPROTO; + break; + } + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) { + /* this packet was fetched as part of an HTC bundle, the embedded lookahead is + * not valid since the next packet may have already been fetched as part of the + * bundle */ + pNextLookAheads = NULL; + pNumLookAheads = NULL; + } + + /* process trailer data that follows HDR + application payload */ + status = HTCProcessTrailer(target, + (pBuf + HTC_HDR_LENGTH + payloadLen - temp), + temp, + pNextLookAheads, + pNumLookAheads, + pPacket->Endpoint); + + if (status) { + break; + } + +#ifdef HTC_CAPTURE_LAST_FRAME + memcpy(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp); + target->LastTrailerLength = temp; +#endif + /* trim length by trailer bytes */ + pPacket->ActualLength -= temp; + } +#ifdef HTC_CAPTURE_LAST_FRAME + else { + target->LastTrailerLength = 0; + } +#endif + + /* if we get to this point, the packet is good */ + /* remove header and adjust length */ + pPacket->pBuffer += HTC_HDR_LENGTH; + pPacket->ActualLength -= HTC_HDR_LENGTH; + + } while (false); + + if (status) { + /* dump the whole packet */ +#ifdef ATH_DEBUG_MODULE + DebugDumpBytes(pBuf,pPacket->ActualLength < 256 ? pPacket->ActualLength : 256 ,"BAD HTC Recv PKT"); +#endif + } else { +#ifdef HTC_CAPTURE_LAST_FRAME + memcpy(&target->LastFrameHdr,pBuf,sizeof(struct htc_frame_hdr)); +#endif + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { + if (pPacket->ActualLength > 0) { + AR_DEBUG_PRINTBUF(pPacket->pBuffer,pPacket->ActualLength,"HTC - Application Msg"); + } + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessRecvHeader \n")); + return status; +} + +static INLINE void HTCAsyncRecvCheckMorePackets(struct htc_target *target, + u32 NextLookAheads[], + int NumLookAheads, + bool CheckMoreMsgs) +{ + /* was there a lookahead for the next packet? */ + if (NumLookAheads > 0) { + int nextStatus; + int fetched = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HTCAsyncRecvCheckMorePackets - num lookaheads were non-zero : %d \n", + NumLookAheads)); + /* force status re-check */ + REF_IRQ_STATUS_RECHECK(&target->Device); + /* we have more packets, get the next packet fetch started */ + nextStatus = HTCRecvMessagePendingHandler(target, NextLookAheads, NumLookAheads, NULL, &fetched); + if (A_EPROTO == nextStatus) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Next look ahead from recv header was INVALID\n")); +#ifdef ATH_DEBUG_MODULE + DebugDumpBytes((u8 *)NextLookAheads, + NumLookAheads * (sizeof(u32)), + "BAD lookaheads from lookahead report"); +#endif + } + if (!nextStatus && !fetched) { + /* we could not fetch any more packets due to resources */ + DevAsyncIrqProcessComplete(&target->Device); + } + } else { + if (CheckMoreMsgs) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HTCAsyncRecvCheckMorePackets - rechecking for more messages...\n")); + /* if we did not get anything on the look-ahead, + * call device layer to asynchronously re-check for messages. If we can keep the async + * processing going we get better performance. If there is a pending message we will keep processing + * messages asynchronously which should pipeline things nicely */ + DevCheckPendingRecvMsgsAsync(&target->Device); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("HTCAsyncRecvCheckMorePackets - no check \n")); + } + } + + +} + + /* unload the recv completion queue */ +static INLINE void DrainRecvIndicationQueue(struct htc_target *target, struct htc_endpoint *pEndpoint) +{ + struct htc_packet_queue recvCompletions; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+DrainRecvIndicationQueue \n")); + + INIT_HTC_PACKET_QUEUE(&recvCompletions); + + LOCK_HTC_RX(target); + + /* increment rx processing count on entry */ + pEndpoint->RxProcessCount++; + if (pEndpoint->RxProcessCount > 1) { + pEndpoint->RxProcessCount--; + /* another thread or task is draining the RX completion queue on this endpoint + * that thread will reset the rx processing count when the queue is drained */ + UNLOCK_HTC_RX(target); + return; + } + + /******* at this point only 1 thread may enter ******/ + + while (true) { + + /* transfer items from main recv queue to the local one so we can release the lock */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&recvCompletions, &pEndpoint->RecvIndicationQueue); + + if (HTC_QUEUE_EMPTY(&recvCompletions)) { + /* all drained */ + break; + } + + /* release lock while we do the recv completions + * other threads can now queue more recv completions */ + UNLOCK_HTC_RX(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("DrainRecvIndicationQueue : completing %d RECV packets \n", + HTC_PACKET_QUEUE_DEPTH(&recvCompletions))); + /* do completion */ + DO_RCV_COMPLETION(pEndpoint,&recvCompletions); + + /* re-acquire lock to grab some more completions */ + LOCK_HTC_RX(target); + } + + /* reset count */ + pEndpoint->RxProcessCount = 0; + UNLOCK_HTC_RX(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-DrainRecvIndicationQueue \n")); + +} + + /* optimization for recv packets, we can indicate a "hint" that there are more + * single-packets to fetch on this endpoint */ +#define SET_MORE_RX_PACKET_INDICATION_FLAG(L,N,E,P) \ + if ((N) > 0) { SetRxPacketIndicationFlags((L)[0],(E),(P)); } + + /* for bundled frames, we can force the flag to indicate there are more packets */ +#define FORCE_MORE_RX_PACKET_INDICATION_FLAG(P) \ + (P)->PktInfo.AsRx.IndicationFlags |= HTC_RX_FLAGS_INDICATE_MORE_PKTS; + + /* note: this function can be called with the RX lock held */ +static INLINE void SetRxPacketIndicationFlags(u32 LookAhead, + struct htc_endpoint *pEndpoint, + struct htc_packet *pPacket) +{ + struct htc_frame_hdr *pHdr = (struct htc_frame_hdr *)&LookAhead; + /* check to see if the "next" packet is from the same endpoint of the + completing packet */ + if (pHdr->EndpointID == pPacket->Endpoint) { + /* check that there is a buffer available to actually fetch it */ + if (!HTC_QUEUE_EMPTY(&pEndpoint->RxBuffers)) { + /* provide a hint that there are more RX packets to fetch */ + FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket); + } + } +} + + +/* asynchronous completion handler for recv packet fetching, when the device layer + * completes a read request, it will call this completion handler */ +void HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket) +{ + struct htc_target *target = (struct htc_target *)Context; + struct htc_endpoint *pEndpoint; + u32 nextLookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE]; + int numLookAheads = 0; + int status; + bool checkMorePkts = true; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (pkt:0x%lX, status:%d, ep:%d) \n", + (unsigned long)pPacket, pPacket->Status, pPacket->Endpoint)); + + A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device)); + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + pPacket->Completion = NULL; + + /* get completion status */ + status = pPacket->Status; + + do { + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRecvCompleteHandler: request failed (status:%d, ep:%d) \n", + pPacket->Status, pPacket->Endpoint)); + break; + } + /* process the header for any trailer data */ + status = HTCProcessRecvHeader(target,pPacket,nextLookAheads,&numLookAheads); + + if (status) { + break; + } + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) { + /* this packet was part of a bundle that had to be broken up. + * It was fetched one message at a time. There may be other asynchronous reads queued behind this one. + * Do no issue another check for more packets since the last one in the series of requests + * will handle it */ + checkMorePkts = false; + } + + DUMP_RECV_PKT_INFO(pPacket); + LOCK_HTC_RX(target); + SET_MORE_RX_PACKET_INDICATION_FLAG(nextLookAheads,numLookAheads,pEndpoint,pPacket); + /* we have a good packet, queue it to the completion queue */ + HTC_PACKET_ENQUEUE(&pEndpoint->RecvIndicationQueue,pPacket); + HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads); + UNLOCK_HTC_RX(target); + + /* check for more recv packets before indicating */ + HTCAsyncRecvCheckMorePackets(target,nextLookAheads,numLookAheads,checkMorePkts); + + } while (false); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n", + status)); + /* recycle this packet */ + HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint); + } else { + /* a good packet was queued, drain the queue */ + DrainRecvIndicationQueue(target,pEndpoint); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvCompleteHandler\n")); +} + +/* synchronously wait for a control message from the target, + * This function is used at initialization time ONLY. At init messages + * on ENDPOINT 0 are expected. */ +int HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket) +{ + int status; + u32 lookAhead; + struct htc_packet *pPacket = NULL; + struct htc_frame_hdr *pHdr; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n")); + + do { + + *ppControlPacket = NULL; + + /* call the polling function to see if we have a message */ + status = DevPollMboxMsgRecv(&target->Device, + &lookAhead, + HTC_TARGET_RESPONSE_TIMEOUT); + + if (status) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead)); + + /* check the lookahead */ + pHdr = (struct htc_frame_hdr *)&lookAhead; + + if (pHdr->EndpointID != ENDPOINT_0) { + /* unexpected endpoint number, should be zero */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + if (status) { + /* bad message */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + pPacket = HTC_ALLOC_CONTROL_RX(target); + + if (pPacket == NULL) { + AR_DEBUG_ASSERT(false); + status = A_NO_MEMORY; + break; + } + + pPacket->PktInfo.AsRx.HTCRxFlags = 0; + pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead; + pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH; + + if (pPacket->ActualLength > pPacket->BufferLength) { + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + /* we want synchronous operation */ + pPacket->Completion = NULL; + + /* get the message from the device, this will block */ + status = HTCIssueRecv(target, pPacket); + + if (status) { + break; + } + + /* process receive header */ + status = HTCProcessRecvHeader(target,pPacket,NULL,NULL); + + pPacket->Status = status; + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n", + status)); + break; + } + + /* give the caller this control message packet, they are responsible to free */ + *ppControlPacket = pPacket; + + } while (false); + + if (status) { + if (pPacket != NULL) { + /* cleanup buffer on error */ + HTC_FREE_CONTROL_RX(target,pPacket); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCWaitforControlMessage \n")); + + return status; +} + +static int AllocAndPrepareRxPackets(struct htc_target *target, + u32 LookAheads[], + int Messages, + struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueue) +{ + int status = 0; + struct htc_packet *pPacket; + struct htc_frame_hdr *pHdr; + int i,j; + int numMessages; + int fullLength; + bool noRecycle; + + /* lock RX while we assemble the packet buffers */ + LOCK_HTC_RX(target); + + for (i = 0; i < Messages; i++) { + + pHdr = (struct htc_frame_hdr *)&LookAheads[i]; + + if (pHdr->EndpointID >= ENDPOINT_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID)); + /* invalid endpoint */ + status = A_EPROTO; + break; + } + + if (pHdr->EndpointID != pEndpoint->Id) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d should be : %d (index:%d)\n", + pHdr->EndpointID, pEndpoint->Id, i)); + /* invalid endpoint */ + status = A_EPROTO; + break; + } + + if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n", + pHdr->PayloadLen, (u32)HTC_MAX_PAYLOAD_LENGTH)); + status = A_EPROTO; + break; + } + + if (0 == pEndpoint->ServiceID) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Endpoint %d is not connected !\n",pHdr->EndpointID)); + /* endpoint isn't even connected */ + status = A_EPROTO; + break; + } + + if ((pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) == 0) { + /* HTC header only indicates 1 message to fetch */ + numMessages = 1; + } else { + /* HTC header indicates that every packet to follow has the same padded length so that it can + * be optimally fetched as a full bundle */ + numMessages = (pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) >> HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT; + /* the count doesn't include the starter frame, just a count of frames to follow */ + numMessages++; + A_ASSERT(numMessages <= target->MaxMsgPerBundle); + INC_HTC_EP_STAT(pEndpoint, RxBundleIndFromHdr, 1); + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages)); + } + + fullLength = DEV_CALC_RECV_PADDED_LEN(&target->Device,pHdr->PayloadLen + sizeof(struct htc_frame_hdr)); + + /* get packet buffers for each message, if there was a bundle detected in the header, + * use pHdr as a template to fetch all packets in the bundle */ + for (j = 0; j < numMessages; j++) { + + /* reset flag, any packets allocated using the RecvAlloc() API cannot be recycled on cleanup, + * they must be explicitly returned */ + noRecycle = false; + + if (pEndpoint->EpCallBacks.EpRecvAlloc != NULL) { + UNLOCK_HTC_RX(target); + noRecycle = true; + /* user is using a per-packet allocation callback */ + pPacket = pEndpoint->EpCallBacks.EpRecvAlloc(pEndpoint->EpCallBacks.pContext, + pEndpoint->Id, + fullLength); + LOCK_HTC_RX(target); + + } else if ((pEndpoint->EpCallBacks.EpRecvAllocThresh != NULL) && + (fullLength > pEndpoint->EpCallBacks.RecvAllocThreshold)) { + INC_HTC_EP_STAT(pEndpoint,RxAllocThreshHit,1); + INC_HTC_EP_STAT(pEndpoint,RxAllocThreshBytes,pHdr->PayloadLen); + /* threshold was hit, call the special recv allocation callback */ + UNLOCK_HTC_RX(target); + noRecycle = true; + /* user wants to allocate packets above a certain threshold */ + pPacket = pEndpoint->EpCallBacks.EpRecvAllocThresh(pEndpoint->EpCallBacks.pContext, + pEndpoint->Id, + fullLength); + LOCK_HTC_RX(target); + + } else { + /* user is using a refill handler that can refill multiple HTC buffers */ + + /* get a packet from the endpoint recv queue */ + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers); + + if (NULL == pPacket) { + /* check for refill handler */ + if (pEndpoint->EpCallBacks.EpRecvRefill != NULL) { + UNLOCK_HTC_RX(target); + /* call the re-fill handler */ + pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext, + pEndpoint->Id); + LOCK_HTC_RX(target); + /* check if we have more buffers */ + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers); + /* fall through */ + } + } + } + + if (NULL == pPacket) { + /* this is not an error, we simply need to mark that we are waiting for buffers.*/ + target->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS; + target->EpWaitingForBuffers = pEndpoint->Id; + status = A_NO_RESOURCE; + break; + } + + AR_DEBUG_ASSERT(pPacket->Endpoint == pEndpoint->Id); + /* clear flags */ + pPacket->PktInfo.AsRx.HTCRxFlags = 0; + pPacket->PktInfo.AsRx.IndicationFlags = 0; + pPacket->Status = 0; + + if (noRecycle) { + /* flag that these packets cannot be recycled, they have to be returned to the + * user */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_NO_RECYCLE; + } + /* add packet to queue (also incase we need to cleanup down below) */ + HTC_PACKET_ENQUEUE(pQueue,pPacket); + + if (HTC_STOPPING(target)) { + status = A_ECANCELED; + break; + } + + /* make sure this message can fit in the endpoint buffer */ + if ((u32)fullLength > pPacket->BufferLength) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Payload Length Error : header reports payload of: %d (%d) endpoint buffer size: %d \n", + pHdr->PayloadLen, fullLength, pPacket->BufferLength)); + status = A_EPROTO; + break; + } + + if (j > 0) { + /* for messages fetched in a bundle the expected lookahead is unknown since we + * are only using the lookahead of the first packet as a template of what to + * expect for lengths */ + /* flag that once we get the real HTC header we need to refesh the information */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_REFRESH_HDR; + /* set it to something invalid */ + pPacket->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF; + } else { + + pPacket->PktInfo.AsRx.ExpectedHdr = LookAheads[i]; /* set expected look ahead */ + } + /* set the amount of data to fetch */ + pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH; + } + + if (status) { + if (A_NO_RESOURCE == status) { + /* this is actually okay */ + status = 0; + } + break; + } + + } + + UNLOCK_HTC_RX(target); + + if (status) { + while (!HTC_QUEUE_EMPTY(pQueue)) { + pPacket = HTC_PACKET_DEQUEUE(pQueue); + /* recycle all allocated packets */ + HTC_RECYCLE_RX_PKT(target,pPacket,&target->EndPoint[pPacket->Endpoint]); + } + } + + return status; +} + +static void HTCAsyncRecvScatterCompletion(struct hif_scatter_req *pScatterReq) +{ + int i; + struct htc_packet *pPacket; + struct htc_endpoint *pEndpoint; + u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE]; + int numLookAheads = 0; + struct htc_target *target = (struct htc_target *)pScatterReq->Context; + int status; + bool partialBundle = false; + struct htc_packet_queue localRecvQueue; + bool procError = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCAsyncRecvScatterCompletion TotLen: %d Entries: %d\n", + pScatterReq->TotalLength, pScatterReq->ValidScatterEntries)); + + A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device)); + + if (pScatterReq->CompletionStatus) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Recv Scatter Request Failed: %d \n",pScatterReq->CompletionStatus)); + } + + if (pScatterReq->CallerFlags & HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE) { + partialBundle = true; + } + + DEV_FINISH_SCATTER_OPERATION(pScatterReq); + + INIT_HTC_PACKET_QUEUE(&localRecvQueue); + + pPacket = (struct htc_packet *)pScatterReq->ScatterList[0].pCallerContexts[0]; + /* note: all packets in a scatter req are for the same endpoint ! */ + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + + /* walk through the scatter list and process */ + /* **** NOTE: DO NOT HOLD ANY LOCKS here, HTCProcessRecvHeader can take the TX lock + * as it processes credit reports */ + for (i = 0; i < pScatterReq->ValidScatterEntries; i++) { + pPacket = (struct htc_packet *)pScatterReq->ScatterList[i].pCallerContexts[0]; + A_ASSERT(pPacket != NULL); + /* reset count, we are only interested in the look ahead in the last packet when we + * break out of this loop */ + numLookAheads = 0; + + if (!pScatterReq->CompletionStatus) { + /* process header for each of the recv packets */ + status = HTCProcessRecvHeader(target,pPacket,lookAheads,&numLookAheads); + } else { + status = A_ERROR; + } + + if (!status) { + LOCK_HTC_RX(target); + HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads); + INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1); + UNLOCK_HTC_RX(target); + if (i == (pScatterReq->ValidScatterEntries - 1)) { + /* last packet's more packets flag is set based on the lookahead */ + SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,numLookAheads,pEndpoint,pPacket); + } else { + /* packets in a bundle automatically have this flag set */ + FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket); + } + + DUMP_RECV_PKT_INFO(pPacket); + /* since we can't hold a lock in this loop, we insert into our local recv queue for + * storage until we can transfer them to the recv completion queue */ + HTC_PACKET_ENQUEUE(&localRecvQueue,pPacket); + + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Recv packet scatter entry %d failed (out of %d) \n", + i, pScatterReq->ValidScatterEntries)); + /* recycle failed recv */ + HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint); + /* set flag and continue processing the remaining scatter entries */ + procError = true; + } + + } + + /* free scatter request */ + DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq); + + LOCK_HTC_RX(target); + /* transfer the packets in the local recv queue to the recv completion queue */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RecvIndicationQueue, &localRecvQueue); + + UNLOCK_HTC_RX(target); + + if (!procError) { + /* pipeline the next check (asynchronously) for more packets */ + HTCAsyncRecvCheckMorePackets(target, + lookAheads, + numLookAheads, + partialBundle ? false : true); + } + + /* now drain the indication queue */ + DrainRecvIndicationQueue(target,pEndpoint); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCAsyncRecvScatterCompletion \n")); +} + +static int HTCIssueRecvPacketBundle(struct htc_target *target, + struct htc_packet_queue *pRecvPktQueue, + struct htc_packet_queue *pSyncCompletionQueue, + int *pNumPacketsFetched, + bool PartialBundle) +{ + int status = 0; + struct hif_scatter_req *pScatterReq; + int i, totalLength; + int pktsToScatter; + struct htc_packet *pPacket; + bool asyncMode = (pSyncCompletionQueue == NULL) ? true : false; + int scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device); + + pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue); + pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle); + + if ((HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue) - pktsToScatter) > 0) { + /* we were forced to split this bundle receive operation + * all packets in this partial bundle must have their lookaheads ignored */ + PartialBundle = true; + /* this would only happen if the target ignored our max bundle limit */ + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + ("HTCIssueRecvPacketBundle : partial bundle detected num:%d , %d \n", + HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter)); + } + + totalLength = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCIssueRecvPacketBundle (Numpackets: %d , actual : %d) \n", + HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter)); + + do { + + pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device); + + if (pScatterReq == NULL) { + /* no scatter resources left, just let caller handle it the legacy way */ + break; + } + + pScatterReq->CallerFlags = 0; + + if (PartialBundle) { + /* mark that this is a partial bundle, this has special ramifications to the + * scatter completion routine */ + pScatterReq->CallerFlags |= HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE; + } + + /* convert HTC packets to scatter list */ + for (i = 0; i < pktsToScatter; i++) { + int paddedLength; + + pPacket = HTC_PACKET_DEQUEUE(pRecvPktQueue); + A_ASSERT(pPacket != NULL); + + paddedLength = DEV_CALC_RECV_PADDED_LEN(&target->Device, pPacket->ActualLength); + + if ((scatterSpaceRemaining - paddedLength) < 0) { + /* exceeds what we can transfer, put the packet back */ + HTC_PACKET_ENQUEUE_TO_HEAD(pRecvPktQueue,pPacket); + break; + } + + scatterSpaceRemaining -= paddedLength; + + if (PartialBundle || (i < (pktsToScatter - 1))) { + /* packet 0..n-1 cannot be checked for look-aheads since we are fetching a bundle + * the last packet however can have it's lookahead used */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD; + } + + /* note: 1 HTC packet per scatter entry */ + /* setup packet into */ + pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer; + pScatterReq->ScatterList[i].Length = paddedLength; + + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_PART_OF_BUNDLE; + + if (asyncMode) { + /* save HTC packet for async completion routine */ + pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket; + } else { + /* queue to caller's sync completion queue, caller will unload this when we return */ + HTC_PACKET_ENQUEUE(pSyncCompletionQueue,pPacket); + } + + A_ASSERT(pScatterReq->ScatterList[i].Length); + totalLength += pScatterReq->ScatterList[i].Length; + } + + pScatterReq->TotalLength = totalLength; + pScatterReq->ValidScatterEntries = i; + + if (asyncMode) { + pScatterReq->CompletionRoutine = HTCAsyncRecvScatterCompletion; + pScatterReq->Context = target; + } + + status = DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_READ, asyncMode); + + if (!status) { + *pNumPacketsFetched = i; + } + + if (!asyncMode) { + /* free scatter request */ + DEV_FREE_SCATTER_REQ(&target->Device, pScatterReq); + } + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCIssueRecvPacketBundle (status:%d) (fetched:%d) \n", + status,*pNumPacketsFetched)); + + return status; +} + +static INLINE void CheckRecvWaterMark(struct htc_endpoint *pEndpoint) +{ + /* see if endpoint is using a refill watermark + * ** no need to use a lock here, since we are only inspecting... + * caller may must not hold locks when calling this function */ + if (pEndpoint->EpCallBacks.RecvRefillWaterMark > 0) { + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBuffers) < pEndpoint->EpCallBacks.RecvRefillWaterMark) { + /* call the re-fill handler before we continue */ + pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext, + pEndpoint->Id); + } + } +} + +/* callback when device layer or lookahead report parsing detects a pending message */ +int HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched) +{ + struct htc_target *target = (struct htc_target *)Context; + int status = 0; + struct htc_packet *pPacket; + struct htc_endpoint *pEndpoint; + bool asyncProc = false; + u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE]; + int pktsFetched; + struct htc_packet_queue recvPktQueue, syncCompletedPktsQueue; + bool partialBundle; + HTC_ENDPOINT_ID id; + int totalFetched = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCRecvMessagePendingHandler NumLookAheads: %d \n",NumLookAheads)); + + if (pNumPktsFetched != NULL) { + *pNumPktsFetched = 0; + } + + if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(&target->Device)) { + /* We use async mode to get the packets if the device layer supports it. + * The device layer interfaces with HIF in which HIF may have restrictions on + * how interrupts are processed */ + asyncProc = true; + } + + if (pAsyncProc != NULL) { + /* indicate to caller how we decided to process this */ + *pAsyncProc = asyncProc; + } + + if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) { + A_ASSERT(false); + return A_EPROTO; + } + + /* on first entry copy the lookaheads into our temp array for processing */ + memcpy(lookAheads, MsgLookAheads, (sizeof(u32)) * NumLookAheads); + + while (true) { + + /* reset packets queues */ + INIT_HTC_PACKET_QUEUE(&recvPktQueue); + INIT_HTC_PACKET_QUEUE(&syncCompletedPktsQueue); + + if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) { + status = A_EPROTO; + A_ASSERT(false); + break; + } + + /* first lookahead sets the expected endpoint IDs for all packets in a bundle */ + id = ((struct htc_frame_hdr *)&lookAheads[0])->EndpointID; + pEndpoint = &target->EndPoint[id]; + + if (id >= ENDPOINT_MAX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MsgPend, Invalid Endpoint in look-ahead: %d \n",id)); + status = A_EPROTO; + break; + } + + /* try to allocate as many HTC RX packets indicated by the lookaheads + * these packets are stored in the recvPkt queue */ + status = AllocAndPrepareRxPackets(target, + lookAheads, + NumLookAheads, + pEndpoint, + &recvPktQueue); + if (status) { + break; + } + + if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) >= 2) { + /* a recv bundle was detected, force IRQ status re-check again */ + REF_IRQ_STATUS_RECHECK(&target->Device); + } + + totalFetched += HTC_PACKET_QUEUE_DEPTH(&recvPktQueue); + + /* we've got packet buffers for all we can currently fetch, + * this count is not valid anymore */ + NumLookAheads = 0; + partialBundle = false; + + /* now go fetch the list of HTC packets */ + while (!HTC_QUEUE_EMPTY(&recvPktQueue)) { + + pktsFetched = 0; + + if (target->RecvBundlingEnabled && (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 1)) { + /* there are enough packets to attempt a bundle transfer and recv bundling is allowed */ + status = HTCIssueRecvPacketBundle(target, + &recvPktQueue, + asyncProc ? NULL : &syncCompletedPktsQueue, + &pktsFetched, + partialBundle); + if (status) { + break; + } + + if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) != 0) { + /* we couldn't fetch all packets at one time, this creates a broken + * bundle */ + partialBundle = true; + } + } + + /* see if the previous operation fetched any packets using bundling */ + if (0 == pktsFetched) { + /* dequeue one packet */ + pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue); + A_ASSERT(pPacket != NULL); + + if (asyncProc) { + /* we use async mode to get the packet if the device layer supports it + * set our callback and context */ + pPacket->Completion = HTCRecvCompleteHandler; + pPacket->pContext = target; + } else { + /* fully synchronous */ + pPacket->Completion = NULL; + } + + if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 0) { + /* lookaheads in all packets except the last one in the bundle must be ignored */ + pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD; + } + + /* go fetch the packet */ + status = HTCIssueRecv(target, pPacket); + if (status) { + break; + } + + if (!asyncProc) { + /* sent synchronously, queue this packet for synchronous completion */ + HTC_PACKET_ENQUEUE(&syncCompletedPktsQueue,pPacket); + } + + } + + } + + if (!status) { + CheckRecvWaterMark(pEndpoint); + } + + if (asyncProc) { + /* we did this asynchronously so we can get out of the loop, the asynch processing + * creates a chain of requests to continue processing pending messages in the + * context of callbacks */ + break; + } + + /* synchronous handling */ + if (target->Device.DSRCanYield) { + /* for the SYNC case, increment count that tracks when the DSR should yield */ + target->Device.CurrentDSRRecvCount++; + } + + /* in the sync case, all packet buffers are now filled, + * we can process each packet, check lookaheads and then repeat */ + + /* unload sync completion queue */ + while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) { + struct htc_packet_queue container; + + pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue); + A_ASSERT(pPacket != NULL); + + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + /* reset count on each iteration, we are only interested in the last packet's lookahead + * information when we break out of this loop */ + NumLookAheads = 0; + /* process header for each of the recv packets + * note: the lookahead of the last packet is useful for us to continue in this loop */ + status = HTCProcessRecvHeader(target,pPacket,lookAheads,&NumLookAheads); + if (status) { + break; + } + + if (HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) { + /* last packet's more packets flag is set based on the lookahead */ + SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,NumLookAheads,pEndpoint,pPacket); + } else { + /* packets in a bundle automatically have this flag set */ + FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket); + } + /* good packet, indicate it */ + HTC_RX_STAT_PROFILE(target,pEndpoint,NumLookAheads); + + if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_PART_OF_BUNDLE) { + INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1); + } + + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + DO_RCV_COMPLETION(pEndpoint,&container); + } + + if (status) { + break; + } + + if (NumLookAheads == 0) { + /* no more look aheads */ + break; + } + + /* when we process recv synchronously we need to check if we should yield and stop + * fetching more packets indicated by the embedded lookaheads */ + if (target->Device.DSRCanYield) { + if (DEV_CHECK_RECV_YIELD(&target->Device)) { + /* break out, don't fetch any more packets */ + break; + } + } + + + /* check whether other OS contexts have queued any WMI command/data for WLAN. + * This check is needed only if WLAN Tx and Rx happens in same thread context */ + A_CHECK_DRV_TX(); + + /* for SYNCH processing, if we get here, we are running through the loop again due to a detected lookahead. + * Set flag that we should re-check IRQ status registers again before leaving IRQ processing, + * this can net better performance in high throughput situations */ + REF_IRQ_STATUS_RECHECK(&target->Device); + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Failed to get pending recv messages (%d) \n",status)); + /* cleanup any packets we allocated but didn't use to actually fetch any packets */ + while (!HTC_QUEUE_EMPTY(&recvPktQueue)) { + pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue); + /* clean up packets */ + HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]); + } + /* cleanup any packets in sync completion queue */ + while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) { + pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue); + /* clean up packets */ + HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]); + } + if (HTC_STOPPING(target)) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + (" Host is going to stop. blocking receiver for HTCStop.. \n")); + DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC); + } + } + /* before leaving, check to see if host ran out of buffers and needs to stop the + * receiver */ + if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, + (" Host has no RX buffers, blocking receiver to prevent overrun.. \n")); + /* try to stop receive at the device layer */ + DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC); + } + + if (pNumPktsFetched != NULL) { + *pNumPktsFetched = totalFetched; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCRecvMessagePendingHandler \n")); + + return status; +} + +int HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint; + bool unblockRecv = false; + int status = 0; + struct htc_packet *pFirstPacket; + + pFirstPacket = HTC_GET_PKT_AT_HEAD(pPktQueue); + + if (NULL == pFirstPacket) { + A_ASSERT(false); + return A_EINVAL; + } + + AR_DEBUG_ASSERT(pFirstPacket->Endpoint < ENDPOINT_MAX); + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, + ("+- HTCAddReceivePktMultiple : endPointId: %d, cnt:%d, length: %d\n", + pFirstPacket->Endpoint, + HTC_PACKET_QUEUE_DEPTH(pPktQueue), + pFirstPacket->BufferLength)); + + do { + + pEndpoint = &target->EndPoint[pFirstPacket->Endpoint]; + + LOCK_HTC_RX(target); + + if (HTC_STOPPING(target)) { + struct htc_packet *pPacket; + + UNLOCK_HTC_RX(target); + + /* walk through queue and mark each one canceled */ + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) { + pPacket->Status = A_ECANCELED; + } HTC_PACKET_QUEUE_ITERATE_END; + + DO_RCV_COMPLETION(pEndpoint,pPktQueue); + break; + } + + /* store receive packets */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBuffers, pPktQueue); + + /* check if we are blocked waiting for a new buffer */ + if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) { + if (target->EpWaitingForBuffers == pFirstPacket->Endpoint) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" receiver was blocked on ep:%d, unblocking.. \n", + target->EpWaitingForBuffers)); + target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS; + target->EpWaitingForBuffers = ENDPOINT_MAX; + unblockRecv = true; + } + } + + UNLOCK_HTC_RX(target); + + if (unblockRecv && !HTC_STOPPING(target)) { + /* TODO : implement a buffer threshold count? */ + DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC); + } + + } while (false); + + return status; +} + +/* Makes a buffer available to the HTC module */ +int HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket) +{ + struct htc_packet_queue queue; + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); + return HTCAddReceivePktMultiple(HTCHandle, &queue); +} + +void HTCUnblockRecv(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + bool unblockRecv = false; + + LOCK_HTC_RX(target); + + /* check if we are blocked waiting for a new buffer */ + if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) { + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HTCUnblockRx : receiver was blocked on ep:%d, unblocking.. \n", + target->EpWaitingForBuffers)); + target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS; + target->EpWaitingForBuffers = ENDPOINT_MAX; + unblockRecv = true; + } + + UNLOCK_HTC_RX(target); + + if (unblockRecv && !HTC_STOPPING(target)) { + /* re-enable */ + DevEnableRecv(&target->Device,DEV_ENABLE_RECV_ASYNC); + } +} + +static void HTCFlushRxQueue(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet_queue *pQueue) +{ + struct htc_packet *pPacket; + struct htc_packet_queue container; + + LOCK_HTC_RX(target); + + while (1) { + pPacket = HTC_PACKET_DEQUEUE(pQueue); + if (NULL == pPacket) { + break; + } + UNLOCK_HTC_RX(target); + pPacket->Status = A_ECANCELED; + pPacket->ActualLength = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" Flushing RX packet:0x%lX, length:%d, ep:%d \n", + (unsigned long)pPacket, pPacket->BufferLength, pPacket->Endpoint)); + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + /* give the packet back */ + DO_RCV_COMPLETION(pEndpoint,&container); + LOCK_HTC_RX(target); + } + + UNLOCK_HTC_RX(target); +} + +static void HTCFlushEndpointRX(struct htc_target *target, struct htc_endpoint *pEndpoint) +{ + /* flush any recv indications not already made */ + HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RecvIndicationQueue); + /* flush any rx buffers */ + HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RxBuffers); +} + +void HTCFlushRecvBuffers(struct htc_target *target) +{ + struct htc_endpoint *pEndpoint; + int i; + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + if (pEndpoint->ServiceID == 0) { + /* not in use.. */ + continue; + } + HTCFlushEndpointRX(target,pEndpoint); + } +} + + +void HTCEnableRecv(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + if (!HTC_STOPPING(target)) { + /* re-enable */ + DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC); + } +} + +void HTCDisableRecv(HTC_HANDLE HTCHandle) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + if (!HTC_STOPPING(target)) { + /* disable */ + DevStopRecv(&target->Device,DEV_ENABLE_RECV_SYNC); + } +} + +int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + return HTC_PACKET_QUEUE_DEPTH(&(target->EndPoint[Endpoint].RxBuffers)); +} + +int HTCWaitForPendingRecv(HTC_HANDLE HTCHandle, + u32 TimeoutInMs, + bool *pbIsRecvPending) +{ + int status = 0; + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + + status = DevWaitForPendingRecv(&target->Device, + TimeoutInMs, + pbIsRecvPending); + + return status; +} diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_send.c b/trunk/drivers/staging/ath6kl/htc2/htc_send.c new file mode 100644 index 000000000000..9310d4d5c992 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_send.c @@ -0,0 +1,1018 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#include "htc_internal.h" + +typedef enum _HTC_SEND_QUEUE_RESULT { + HTC_SEND_QUEUE_OK = 0, /* packet was queued */ + HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */ +} HTC_SEND_QUEUE_RESULT; + +#define DO_EP_TX_COMPLETION(ep,q) DoSendCompletion(ep,q) + +/* call the distribute credits callback with the distribution */ +#define DO_DISTRIBUTION(t,reason,description,pList) \ +{ \ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \ + (" calling distribute function (%s) (dfn:0x%lX, ctxt:0x%lX, dist:0x%lX) \n", \ + (description), \ + (unsigned long)(t)->DistributeCredits, \ + (unsigned long)(t)->pCredDistContext, \ + (unsigned long)pList)); \ + (t)->DistributeCredits((t)->pCredDistContext, \ + (pList), \ + (reason)); \ +} + +static void DoSendCompletion(struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueueToIndicate) +{ + do { + + if (HTC_QUEUE_EMPTY(pQueueToIndicate)) { + /* nothing to indicate */ + break; + } + + if (pEndpoint->EpCallBacks.EpTxCompleteMultiple != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d, send complete multiple callback (%d pkts) \n", + pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate))); + /* a multiple send complete handler is being used, pass the queue to the handler */ + pEndpoint->EpCallBacks.EpTxCompleteMultiple(pEndpoint->EpCallBacks.pContext, + pQueueToIndicate); + /* all packets are now owned by the callback, reset queue to be safe */ + INIT_HTC_PACKET_QUEUE(pQueueToIndicate); + } else { + struct htc_packet *pPacket; + /* using legacy EpTxComplete */ + do { + pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d send complete callback on packet 0x%lX \n", \ + pEndpoint->Id, (unsigned long)(pPacket))); + pEndpoint->EpCallBacks.EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket); + } while (!HTC_QUEUE_EMPTY(pQueueToIndicate)); + } + + } while (false); + +} + +/* do final completion on sent packet */ +static INLINE void CompleteSentPacket(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet *pPacket) +{ + pPacket->Completion = NULL; + + if (pPacket->Status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("CompleteSentPacket: request failed (status:%d, ep:%d, length:%d creds:%d) \n", + pPacket->Status, pPacket->Endpoint, pPacket->ActualLength, pPacket->PktInfo.AsTx.CreditsUsed)); + /* on failure to submit, reclaim credits for this packet */ + LOCK_HTC_TX(target); + pEndpoint->CreditDist.TxCreditsToDist += pPacket->PktInfo.AsTx.CreditsUsed; + pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_SEND_COMPLETE, + "Send Complete", + target->EpCreditDistributionListHead->pNext); + UNLOCK_HTC_TX(target); + } + /* first, fixup the head room we allocated */ + pPacket->pBuffer += HTC_HDR_LENGTH; +} + +/* our internal send packet completion handler when packets are submited to the AR6K device + * layer */ +static void HTCSendPktCompletionHandler(void *Context, struct htc_packet *pPacket) +{ + struct htc_target *target = (struct htc_target *)Context; + struct htc_endpoint *pEndpoint = &target->EndPoint[pPacket->Endpoint]; + struct htc_packet_queue container; + + CompleteSentPacket(target,pEndpoint,pPacket); + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + /* do completion */ + DO_EP_TX_COMPLETION(pEndpoint,&container); +} + +int HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket) +{ + int status; + bool sync = false; + + if (pPacket->Completion == NULL) { + /* mark that this request was synchronously issued */ + sync = true; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("+-HTCIssueSend: transmit length : %d (%s) \n", + pPacket->ActualLength + (u32)HTC_HDR_LENGTH, + sync ? "SYNC" : "ASYNC" )); + + /* send message to device */ + status = DevSendPacket(&target->Device, + pPacket, + pPacket->ActualLength + HTC_HDR_LENGTH); + + if (sync) { + /* use local sync variable. If this was issued asynchronously, pPacket is no longer + * safe to access. */ + pPacket->pBuffer += HTC_HDR_LENGTH; + } + + /* if this request was asynchronous, the packet completion routine will be invoked by + * the device layer when the HIF layer completes the request */ + + return status; +} + + /* get HTC send packets from the TX queue on an endpoint */ +static INLINE void GetHTCSendPackets(struct htc_target *target, + struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueue) +{ + int creditsRequired; + int remainder; + u8 sendFlags; + struct htc_packet *pPacket; + unsigned int transferLength; + + /****** NOTE : the TX lock is held when this function is called *****************/ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPackets \n")); + + /* loop until we can grab as many packets out of the queue as we can */ + while (true) { + + sendFlags = 0; + /* get packet at head, but don't remove it */ + pPacket = HTC_GET_PKT_AT_HEAD(&pEndpoint->TxQueue); + if (pPacket == NULL) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:0x%lX , Queue Depth: %d\n", + (unsigned long)pPacket, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); + + transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device, pPacket->ActualLength + HTC_HDR_LENGTH); + + if (transferLength <= target->TargetCreditSize) { + creditsRequired = 1; + } else { + /* figure out how many credits this message requires */ + creditsRequired = transferLength / target->TargetCreditSize; + remainder = transferLength % target->TargetCreditSize; + + if (remainder) { + creditsRequired++; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n", + creditsRequired, pEndpoint->CreditDist.TxCredits)); + + if (pEndpoint->CreditDist.TxCredits < creditsRequired) { + + /* not enough credits */ + if (pPacket->Endpoint == ENDPOINT_0) { + /* leave it in the queue */ + break; + } + /* invoke the registered distribution function only if this is not + * endpoint 0, we let the driver layer provide more credits if it can. + * We pass the credit distribution list starting at the endpoint in question + * */ + + /* set how many credits we need */ + pEndpoint->CreditDist.TxCreditsSeek = + creditsRequired - pEndpoint->CreditDist.TxCredits; + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_SEEK_CREDITS, + "Seek Credits", + &pEndpoint->CreditDist); + pEndpoint->CreditDist.TxCreditsSeek = 0; + + if (pEndpoint->CreditDist.TxCredits < creditsRequired) { + /* still not enough credits to send, leave packet in the queue */ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + (" Not enough credits for ep %d leaving packet in queue..\n", + pPacket->Endpoint)); + break; + } + + } + + pEndpoint->CreditDist.TxCredits -= creditsRequired; + INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired); + + /* check if we need credits back from the target */ + if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) { + /* we are getting low on credits, see if we can ask for more from the distribution function */ + pEndpoint->CreditDist.TxCreditsSeek = + pEndpoint->CreditDist.TxCreditsPerMaxMsg - pEndpoint->CreditDist.TxCredits; + + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_SEEK_CREDITS, + "Seek Credits", + &pEndpoint->CreditDist); + + pEndpoint->CreditDist.TxCreditsSeek = 0; + /* see if we were successful in getting more */ + if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) { + /* tell the target we need credits ASAP! */ + sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE; + INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Host Needs Credits \n")); + } + } + + /* now we can fully dequeue */ + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue); + /* save the number of credits this packet consumed */ + pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired; + /* all TX packets are handled asynchronously */ + pPacket->Completion = HTCSendPktCompletionHandler; + pPacket->pContext = target; + INC_HTC_EP_STAT(pEndpoint, TxIssued, 1); + /* save send flags */ + pPacket->PktInfo.AsTx.SendFlags = sendFlags; + pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo; + pEndpoint->SeqNo++; + /* queue this packet into the caller's queue */ + HTC_PACKET_ENQUEUE(pQueue,pPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-GetHTCSendPackets \n")); + +} + +static void HTCAsyncSendScatterCompletion(struct hif_scatter_req *pScatterReq) +{ + int i; + struct htc_packet *pPacket; + struct htc_endpoint *pEndpoint = (struct htc_endpoint *)pScatterReq->Context; + struct htc_target *target = (struct htc_target *)pEndpoint->target; + int status = 0; + struct htc_packet_queue sendCompletes; + + INIT_HTC_PACKET_QUEUE(&sendCompletes); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCAsyncSendScatterCompletion TotLen: %d Entries: %d\n", + pScatterReq->TotalLength, pScatterReq->ValidScatterEntries)); + + DEV_FINISH_SCATTER_OPERATION(pScatterReq); + + if (pScatterReq->CompletionStatus) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Send Scatter Request Failed: %d \n",pScatterReq->CompletionStatus)); + status = A_ERROR; + } + + /* walk through the scatter list and process */ + for (i = 0; i < pScatterReq->ValidScatterEntries; i++) { + pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]); + A_ASSERT(pPacket != NULL); + pPacket->Status = status; + CompleteSentPacket(target,pEndpoint,pPacket); + /* add it to the completion queue */ + HTC_PACKET_ENQUEUE(&sendCompletes, pPacket); + } + + /* free scatter request */ + DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq); + /* complete all packets */ + DO_EP_TX_COMPLETION(pEndpoint,&sendCompletes); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCAsyncSendScatterCompletion \n")); +} + + /* drain a queue and send as bundles + * this function may return without fully draining the queue under the following conditions : + * - scatter resources are exhausted + * - a message that will consume a partial credit will stop the bundling process early + * - we drop below the minimum number of messages for a bundle + * */ +static void HTCIssueSendBundle(struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pQueue, + int *pBundlesSent, + int *pTotalBundlesPkts) +{ + int pktsToScatter; + unsigned int scatterSpaceRemaining; + struct hif_scatter_req *pScatterReq = NULL; + int i, packetsInScatterReq; + unsigned int transferLength; + struct htc_packet *pPacket; + bool done = false; + int bundlesSent = 0; + int totalPktsInBundle = 0; + struct htc_target *target = pEndpoint->target; + int creditRemainder = 0; + int creditPad; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCIssueSendBundle \n")); + + while (!done) { + + pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pQueue); + pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle); + + if (pktsToScatter < HTC_MIN_HTC_MSGS_TO_BUNDLE) { + /* not enough to bundle */ + break; + } + + pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device); + + if (pScatterReq == NULL) { + /* no scatter resources */ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" No more scatter resources \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" pkts to scatter: %d \n", pktsToScatter)); + + pScatterReq->TotalLength = 0; + pScatterReq->ValidScatterEntries = 0; + + packetsInScatterReq = 0; + scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device); + + for (i = 0; i < pktsToScatter; i++) { + + pScatterReq->ScatterList[i].pCallerContexts[0] = NULL; + + pPacket = HTC_GET_PKT_AT_HEAD(pQueue); + if (pPacket == NULL) { + A_ASSERT(false); + break; + } + + creditPad = 0; + transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device, + pPacket->ActualLength + HTC_HDR_LENGTH); + /* see if the padded transfer length falls on a credit boundary */ + creditRemainder = transferLength % target->TargetCreditSize; + + if (creditRemainder != 0) { + /* the transfer consumes a "partial" credit, this packet cannot be bundled unless + * we add additional "dummy" padding (max 255 bytes) to consume the entire credit + *** NOTE: only allow the send padding if the endpoint is allowed to */ + if (pEndpoint->LocalConnectionFlags & HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING) { + if (transferLength < target->TargetCreditSize) { + /* special case where the transfer is less than a credit */ + creditPad = target->TargetCreditSize - transferLength; + } else { + creditPad = creditRemainder; + } + + /* now check to see if we can indicate padding in the HTC header */ + if ((creditPad > 0) && (creditPad <= 255)) { + /* adjust the transferlength of this packet with the new credit padding */ + transferLength += creditPad; + } else { + /* the amount to pad is too large, bail on this packet, we have to + * send it using the non-bundled method */ + pPacket = NULL; + } + } else { + /* bail on this packet, user does not want padding applied */ + pPacket = NULL; + } + } + + if (NULL == pPacket) { + /* can't bundle */ + done = true; + break; + } + + if (scatterSpaceRemaining < transferLength) { + /* exceeds what we can transfer */ + break; + } + + scatterSpaceRemaining -= transferLength; + /* now remove it from the queue */ + pPacket = HTC_PACKET_DEQUEUE(pQueue); + /* save it in the scatter list */ + pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket; + /* prepare packet and flag message as part of a send bundle */ + HTC_PREPARE_SEND_PKT(pPacket, + pPacket->PktInfo.AsTx.SendFlags | HTC_FLAGS_SEND_BUNDLE, + creditPad, + pPacket->PktInfo.AsTx.SeqNo); + pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer; + pScatterReq->ScatterList[i].Length = transferLength; + A_ASSERT(transferLength); + pScatterReq->TotalLength += transferLength; + pScatterReq->ValidScatterEntries++; + packetsInScatterReq++; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" %d, Adding packet : 0x%lX, len:%d (remaining space:%d) \n", + i, (unsigned long)pPacket,transferLength,scatterSpaceRemaining)); + } + + if (packetsInScatterReq >= HTC_MIN_HTC_MSGS_TO_BUNDLE) { + /* send path is always asynchronous */ + pScatterReq->CompletionRoutine = HTCAsyncSendScatterCompletion; + pScatterReq->Context = pEndpoint; + bundlesSent++; + totalPktsInBundle += packetsInScatterReq; + packetsInScatterReq = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Send Scatter total bytes: %d , entries: %d\n", + pScatterReq->TotalLength,pScatterReq->ValidScatterEntries)); + DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_WRITE, DEV_SCATTER_ASYNC); + /* we don't own this anymore */ + pScatterReq = NULL; + /* try to send some more */ + continue; + } + + /* not enough packets to use the scatter request, cleanup */ + if (pScatterReq != NULL) { + if (packetsInScatterReq > 0) { + /* work backwards to requeue requests */ + for (i = (packetsInScatterReq - 1); i >= 0; i--) { + pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]); + if (pPacket != NULL) { + /* undo any prep */ + HTC_UNPREPARE_SEND_PKT(pPacket); + /* queue back to the head */ + HTC_PACKET_ENQUEUE_TO_HEAD(pQueue,pPacket); + } + } + } + DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq); + } + + /* if we get here, we sent all that we could, get out */ + break; + + } + + *pBundlesSent = bundlesSent; + *pTotalBundlesPkts = totalPktsInBundle; + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCIssueSendBundle (sent:%d) \n",bundlesSent)); + + return; +} + +/* + * if there are no credits, the packet(s) remains in the queue. + * this function returns the result of the attempt to send a queue of HTC packets */ +static HTC_SEND_QUEUE_RESULT HTCTrySend(struct htc_target *target, + struct htc_endpoint *pEndpoint, + struct htc_packet_queue *pCallersSendQueue) +{ + struct htc_packet_queue sendQueue; /* temp queue to hold packets at various stages */ + struct htc_packet *pPacket; + int bundlesSent; + int pktsInBundles; + int overflow; + HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (Queue:0x%lX Depth:%d)\n", + (unsigned long)pCallersSendQueue, + (pCallersSendQueue == NULL) ? 0 : HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue))); + + /* init the local send queue */ + INIT_HTC_PACKET_QUEUE(&sendQueue); + + do { + + if (NULL == pCallersSendQueue) { + /* caller didn't provide a queue, just wants us to check queues and send */ + break; + } + + if (HTC_QUEUE_EMPTY(pCallersSendQueue)) { + /* empty queue */ + result = HTC_SEND_QUEUE_DROP; + break; + } + + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >= pEndpoint->MaxTxQueueDepth) { + /* we've already overflowed */ + overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue); + } else { + /* figure out how much we will overflow by */ + overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue); + /* figure out how much we will overflow the TX queue by */ + overflow -= pEndpoint->MaxTxQueueDepth; + } + + /* if overflow is negative or zero, we are okay */ + if (overflow > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + (" Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d \n", + pEndpoint->Id, overflow, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue), pEndpoint->MaxTxQueueDepth)); + } + if ((overflow <= 0) || (pEndpoint->EpCallBacks.EpSendFull == NULL)) { + /* all packets will fit or caller did not provide send full indication handler + * -- just move all of them to the local sendQueue object */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue, pCallersSendQueue); + } else { + int i; + int goodPkts = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) - overflow; + + A_ASSERT(goodPkts >= 0); + /* we have overflowed, and a callback is provided */ + /* dequeue all non-overflow packets into the sendqueue */ + for (i = 0; i < goodPkts; i++) { + /* pop off caller's queue*/ + pPacket = HTC_PACKET_DEQUEUE(pCallersSendQueue); + A_ASSERT(pPacket != NULL); + /* insert into local queue */ + HTC_PACKET_ENQUEUE(&sendQueue,pPacket); + } + + /* the caller's queue has all the packets that won't fit*/ + /* walk through the caller's queue and indicate each one to the send full handler */ + ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, struct htc_packet, ListLink) { + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Indicating overflowed TX packet: 0x%lX \n", + (unsigned long)pPacket)); + if (pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext, + pPacket) == HTC_SEND_FULL_DROP) { + /* callback wants the packet dropped */ + INC_HTC_EP_STAT(pEndpoint, TxDropped, 1); + /* leave this one in the caller's queue for cleanup */ + } else { + /* callback wants to keep this packet, remove from caller's queue */ + HTC_PACKET_REMOVE(pCallersSendQueue, pPacket); + /* put it in the send queue */ + HTC_PACKET_ENQUEUE(&sendQueue,pPacket); + } + + } ITERATE_END; + + if (HTC_QUEUE_EMPTY(&sendQueue)) { + /* no packets made it in, caller will cleanup */ + result = HTC_SEND_QUEUE_DROP; + break; + } + } + + } while (false); + + if (result != HTC_SEND_QUEUE_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n")); + return result; + } + + LOCK_HTC_TX(target); + + if (!HTC_QUEUE_EMPTY(&sendQueue)) { + /* transfer packets */ + HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,&sendQueue); + A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue)); + INIT_HTC_PACKET_QUEUE(&sendQueue); + } + + /* increment tx processing count on entry */ + pEndpoint->TxProcessCount++; + if (pEndpoint->TxProcessCount > 1) { + /* another thread or task is draining the TX queues on this endpoint + * that thread will reset the tx processing count when the queue is drained */ + pEndpoint->TxProcessCount--; + UNLOCK_HTC_TX(target); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend (busy) \n")); + return HTC_SEND_QUEUE_OK; + } + + /***** beyond this point only 1 thread may enter ******/ + + /* now drain the endpoint TX queue for transmission as long as we have enough + * credits */ + while (true) { + + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) { + break; + } + + /* get all the packets for this endpoint that we can for this pass */ + GetHTCSendPackets(target, pEndpoint, &sendQueue); + + if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) { + /* didn't get any packets due to a lack of credits */ + break; + } + + UNLOCK_HTC_TX(target); + + /* any packets to send are now in our local send queue */ + + bundlesSent = 0; + pktsInBundles = 0; + + while (true) { + + /* try to send a bundle on each pass */ + if ((target->SendBundlingEnabled) && + (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >= HTC_MIN_HTC_MSGS_TO_BUNDLE)) { + int temp1,temp2; + /* bundling is enabled and there is at least a minimum number of packets in the send queue + * send what we can in this pass */ + HTCIssueSendBundle(pEndpoint, &sendQueue, &temp1, &temp2); + bundlesSent += temp1; + pktsInBundles += temp2; + } + + /* if not bundling or there was a packet that could not be placed in a bundle, pull it out + * and send it the normal way */ + pPacket = HTC_PACKET_DEQUEUE(&sendQueue); + if (NULL == pPacket) { + /* local queue is fully drained */ + break; + } + HTC_PREPARE_SEND_PKT(pPacket, + pPacket->PktInfo.AsTx.SendFlags, + 0, + pPacket->PktInfo.AsTx.SeqNo); + HTCIssueSend(target, pPacket); + + /* go back and see if we can bundle some more */ + } + + LOCK_HTC_TX(target); + + INC_HTC_EP_STAT(pEndpoint, TxBundles, bundlesSent); + INC_HTC_EP_STAT(pEndpoint, TxPacketsBundled, pktsInBundles); + + } + + /* done with this endpoint, we can clear the count */ + pEndpoint->TxProcessCount = 0; + UNLOCK_HTC_TX(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n")); + + return HTC_SEND_QUEUE_OK; +} + +int HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint; + struct htc_packet *pPacket; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCSendPktsMultiple: Queue: 0x%lX, Pkts %d \n", + (unsigned long)pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue))); + + /* get packet at head to figure out which endpoint these packets will go into */ + pPacket = HTC_GET_PKT_AT_HEAD(pPktQueue); + if (NULL == pPacket) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n")); + return A_EINVAL; + } + + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); + pEndpoint = &target->EndPoint[pPacket->Endpoint]; + + HTCTrySend(target, pEndpoint, pPktQueue); + + /* do completion on any packets that couldn't get in */ + if (!HTC_QUEUE_EMPTY(pPktQueue)) { + + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) { + if (HTC_STOPPING(target)) { + pPacket->Status = A_ECANCELED; + } else { + pPacket->Status = A_NO_RESOURCE; + } + } HTC_PACKET_QUEUE_ITERATE_END; + + DO_EP_TX_COMPLETION(pEndpoint,pPktQueue); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n")); + + return 0; +} + +/* HTC API - HTCSendPkt */ +int HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket) +{ + struct htc_packet_queue queue; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("+-HTCSendPkt: Enter endPointId: %d, buffer: 0x%lX, length: %d \n", + pPacket->Endpoint, (unsigned long)pPacket->pBuffer, pPacket->ActualLength)); + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); + return HTCSendPktsMultiple(HTCHandle, &queue); +} + +/* check TX queues to drain because of credit distribution update */ +static INLINE void HTCCheckEndpointTxQueues(struct htc_target *target) +{ + struct htc_endpoint *pEndpoint; + struct htc_endpoint_credit_dist *pDistItem; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n")); + pDistItem = target->EpCreditDistributionListHead; + + /* run through the credit distribution list to see + * if there are packets queued + * NOTE: no locks need to be taken since the distribution list + * is not dynamic (cannot be re-ordered) and we are not modifying any state */ + while (pDistItem != NULL) { + pEndpoint = (struct htc_endpoint *)pDistItem->pHTCReserved; + + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n", + pDistItem->Endpoint, pEndpoint->CreditDist.TxCredits, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); + /* try to start the stalled queue, this list is ordered by priority. + * Highest priority queue get's processed first, if there are credits available the + * highest priority queue will get a chance to reclaim credits from lower priority + * ones */ + HTCTrySend(target, pEndpoint, NULL); + } + + pDistItem = pDistItem->pNext; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n")); +} + +/* process credit reports and call distribution function */ +void HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint) +{ + int i; + struct htc_endpoint *pEndpoint; + int totalCredits = 0; + bool doDist = false; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries)); + + /* lock out TX while we update credits */ + LOCK_HTC_TX(target); + + for (i = 0; i < NumEntries; i++, pRpt++) { + if (pRpt->EndpointID >= ENDPOINT_MAX) { + AR_DEBUG_ASSERT(false); + break; + } + + pEndpoint = &target->EndPoint[pRpt->EndpointID]; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n", + pRpt->EndpointID, pRpt->Credits)); + + INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1); + INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits); + + if (FromEndpoint == pRpt->EndpointID) { + /* this credit report arrived on the same endpoint indicating it arrived in an RX + * packet */ + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, pRpt->Credits); + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1); + } else if (FromEndpoint == ENDPOINT_0) { + /* this credit arrived on endpoint 0 as a NULL message */ + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, pRpt->Credits); + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1); + } else { + /* arrived on another endpoint */ + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits); + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1); + } + + if (ENDPOINT_0 == pRpt->EndpointID) { + /* always give endpoint 0 credits back */ + pEndpoint->CreditDist.TxCredits += pRpt->Credits; + } else { + /* for all other endpoints, update credits to distribute, the distribution function + * will handle giving out credits back to the endpoints */ + pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits; + /* flag that we have to do the distribution */ + doDist = true; + } + + /* refresh tx depth for distribution function that will recover these credits + * NOTE: this is only valid when there are credits to recover! */ + pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + + totalCredits += pRpt->Credits; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits)); + + if (doDist) { + /* this was a credit return based on a completed send operations + * note, this is done with the lock held */ + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_SEND_COMPLETE, + "Send Complete", + target->EpCreditDistributionListHead->pNext); + } + + UNLOCK_HTC_TX(target); + + if (totalCredits) { + HTCCheckEndpointTxQueues(target); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n")); +} + +/* flush endpoint TX queue */ +static void HTCFlushEndpointTX(struct htc_target *target, struct htc_endpoint *pEndpoint, HTC_TX_TAG Tag) +{ + struct htc_packet *pPacket; + struct htc_packet_queue discardQueue; + struct htc_packet_queue container; + + /* initialize the discard queue */ + INIT_HTC_PACKET_QUEUE(&discardQueue); + + LOCK_HTC_TX(target); + + /* interate from the front of the TX queue and flush out packets */ + ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, struct htc_packet, ListLink) { + + /* check for removal */ + if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) { + /* remove from queue */ + HTC_PACKET_REMOVE(&pEndpoint->TxQueue, pPacket); + /* add it to the discard pile */ + HTC_PACKET_ENQUEUE(&discardQueue, pPacket); + } + + } ITERATE_END; + + UNLOCK_HTC_TX(target); + + /* empty the discard queue */ + while (1) { + pPacket = HTC_PACKET_DEQUEUE(&discardQueue); + if (NULL == pPacket) { + break; + } + pPacket->Status = A_ECANCELED; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Flushing TX packet:0x%lX, length:%d, ep:%d tag:0x%X \n", + (unsigned long)pPacket, pPacket->ActualLength, pPacket->Endpoint, pPacket->PktInfo.AsTx.Tag)); + INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket); + DO_EP_TX_COMPLETION(pEndpoint,&container); + } + +} + +void DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n", + pEPDist->Endpoint, pEPDist->ServiceID)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" this:0x%lX next:0x%lX prev:0x%lX\n", + (unsigned long)pEPDist, (unsigned long)pEPDist->pNext, (unsigned long)pEPDist->pPrev)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" DistFlags : 0x%X \n", pEPDist->DistFlags)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsNorm : %d \n", pEPDist->TxCreditsNorm)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsMin : %d \n", pEPDist->TxCreditsMin)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEPDist->TxCredits)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsAssigned : %d \n", pEPDist->TxCreditsAssigned)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsSeek : %d \n", pEPDist->TxCreditsSeek)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEPDist->TxCreditSize)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist : %d \n", pEPDist->TxCreditsToDist)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n", + HTC_PACKET_QUEUE_DEPTH(&((struct htc_endpoint *)pEPDist->pHTCReserved)->TxQueue))); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n")); +} + +void DumpCreditDistStates(struct htc_target *target) +{ + struct htc_endpoint_credit_dist *pEPList = target->EpCreditDistributionListHead; + + while (pEPList != NULL) { + DumpCreditDist(pEPList); + pEPList = pEPList->pNext; + } + + if (target->DistributeCredits != NULL) { + DO_DISTRIBUTION(target, + HTC_DUMP_CREDIT_STATE, + "Dump State", + NULL); + } +} + +/* flush all send packets from all endpoint queues */ +void HTCFlushSendPkts(struct htc_target *target) +{ + struct htc_endpoint *pEndpoint; + int i; + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) { + DumpCreditDistStates(target); + } + + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + if (pEndpoint->ServiceID == 0) { + /* not in use.. */ + continue; + } + HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL); + } + + +} + +/* HTC API to flush an endpoint's TX queue*/ +void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint = &target->EndPoint[Endpoint]; + + if (pEndpoint->ServiceID == 0) { + AR_DEBUG_ASSERT(false); + /* not in use.. */ + return; + } + + HTCFlushEndpointTX(target, pEndpoint, Tag); +} + +/* HTC API to indicate activity to the credit distribution function */ +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + bool Active) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint = &target->EndPoint[Endpoint]; + bool doDist = false; + + if (pEndpoint->ServiceID == 0) { + AR_DEBUG_ASSERT(false); + /* not in use.. */ + return; + } + + LOCK_HTC_TX(target); + + if (Active) { + if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) { + /* mark active now */ + pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE; + doDist = true; + } + } else { + if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) { + /* mark inactive now */ + pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE; + doDist = true; + } + } + + if (doDist) { + /* indicate current Tx Queue depth to the credit distribution function */ + pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + /* do distribution again based on activity change + * note, this is done with the lock held */ + DO_DISTRIBUTION(target, + HTC_CREDIT_DIST_ACTIVITY_CHANGE, + "Activity Change", + target->EpCreditDistributionListHead->pNext); + } + + UNLOCK_HTC_TX(target); + + if (doDist && !Active) { + /* if a stream went inactive and this resulted in a credit distribution change, + * some credits may now be available for HTC packets that are stuck in + * HTC queues */ + HTCCheckEndpointTxQueues(target); + } +} + +bool HTCIsEndpointActive(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + struct htc_endpoint *pEndpoint = &target->EndPoint[Endpoint]; + + if (pEndpoint->ServiceID == 0) { + return false; + } + + if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) { + return true; + } + + return false; +} diff --git a/trunk/drivers/staging/ath6kl/htc2/htc_services.c b/trunk/drivers/staging/ath6kl/htc2/htc_services.c new file mode 100644 index 000000000000..c48070cbd54f --- /dev/null +++ b/trunk/drivers/staging/ath6kl/htc2/htc_services.c @@ -0,0 +1,450 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#include "htc_internal.h" + +void HTCControlTxComplete(void *Context, struct htc_packet *pPacket) +{ + /* not implemented + * we do not send control TX frames during normal runtime, only during setup */ + AR_DEBUG_ASSERT(false); +} + + /* callback when a control message arrives on this endpoint */ +void HTCControlRecv(void *Context, struct htc_packet *pPacket) +{ + AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0); + + if (pPacket->Status == A_ECANCELED) { + /* this is a flush operation, return the control packet back to the pool */ + HTC_FREE_CONTROL_RX((struct htc_target*)Context,pPacket); + return; + } + + /* the only control messages we are expecting are NULL messages (credit resports) */ + if (pPacket->ActualLength > 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("HTCControlRecv, got message with length:%d \n", + pPacket->ActualLength + (u32)HTC_HDR_LENGTH)); + +#ifdef ATH_DEBUG_MODULE + /* dump header and message */ + DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH, + pPacket->ActualLength + HTC_HDR_LENGTH, + "Unexpected ENDPOINT 0 Message"); +#endif + } + + HTC_RECYCLE_RX_PKT((struct htc_target*)Context,pPacket,&((struct htc_target*)Context)->EndPoint[0]); +} + +int HTCSendSetupComplete(struct htc_target *target) +{ + struct htc_packet *pSendPacket = NULL; + int status; + + do { + /* allocate a packet to send to the target */ + pSendPacket = HTC_ALLOC_CONTROL_TX(target); + + if (NULL == pSendPacket) { + status = A_NO_MEMORY; + break; + } + + if (target->HTCTargetVersion >= HTC_VERSION_2P1) { + HTC_SETUP_COMPLETE_EX_MSG *pSetupCompleteEx; + u32 setupFlags = 0; + + pSetupCompleteEx = (HTC_SETUP_COMPLETE_EX_MSG *)pSendPacket->pBuffer; + A_MEMZERO(pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); + pSetupCompleteEx->MessageID = HTC_MSG_SETUP_COMPLETE_EX_ID; + if (target->MaxMsgPerBundle > 0) { + /* host can do HTC bundling, indicate this to the target */ + setupFlags |= HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; + pSetupCompleteEx->MaxMsgsPerBundledRecv = target->MaxMsgPerBundle; + } + memcpy(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags)); + SET_HTC_PACKET_INFO_TX(pSendPacket, + NULL, + (u8 *)pSetupCompleteEx, + sizeof(HTC_SETUP_COMPLETE_EX_MSG), + ENDPOINT_0, + HTC_SERVICE_TX_PACKET_TAG); + + } else { + HTC_SETUP_COMPLETE_MSG *pSetupComplete; + /* assemble setup complete message */ + pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer; + A_MEMZERO(pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG)); + pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID; + SET_HTC_PACKET_INFO_TX(pSendPacket, + NULL, + (u8 *)pSetupComplete, + sizeof(HTC_SETUP_COMPLETE_MSG), + ENDPOINT_0, + HTC_SERVICE_TX_PACKET_TAG); + } + + /* we want synchronous operation */ + pSendPacket->Completion = NULL; + HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0); + /* send the message */ + status = HTCIssueSend(target,pSendPacket); + + } while (false); + + if (pSendPacket != NULL) { + HTC_FREE_CONTROL_TX(target,pSendPacket); + } + + return status; +} + + +int HTCConnectService(HTC_HANDLE HTCHandle, + struct htc_service_connect_req *pConnectReq, + struct htc_service_connect_resp *pConnectResp) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int status = 0; + struct htc_packet *pRecvPacket = NULL; + struct htc_packet *pSendPacket = NULL; + HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg; + HTC_CONNECT_SERVICE_MSG *pConnectMsg; + HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX; + struct htc_endpoint *pEndpoint; + unsigned int maxMsgSize = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%lX SvcID:0x%X \n", + (unsigned long)target, pConnectReq->ServiceID)); + + do { + + AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0); + + if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) { + /* special case for pseudo control service */ + assignedEndpoint = ENDPOINT_0; + maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH; + } else { + /* allocate a packet to send to the target */ + pSendPacket = HTC_ALLOC_CONTROL_TX(target); + + if (NULL == pSendPacket) { + AR_DEBUG_ASSERT(false); + status = A_NO_MEMORY; + break; + } + /* assemble connect service message */ + pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)pSendPacket->pBuffer; + AR_DEBUG_ASSERT(pConnectMsg != NULL); + A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG)); + pConnectMsg->MessageID = HTC_MSG_CONNECT_SERVICE_ID; + pConnectMsg->ServiceID = pConnectReq->ServiceID; + pConnectMsg->ConnectionFlags = pConnectReq->ConnectionFlags; + /* check caller if it wants to transfer meta data */ + if ((pConnectReq->pMetaData != NULL) && + (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { + /* copy meta data into message buffer (after header ) */ + memcpy((u8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG), + pConnectReq->pMetaData, + pConnectReq->MetaDataLength); + pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength; + } + + SET_HTC_PACKET_INFO_TX(pSendPacket, + NULL, + (u8 *)pConnectMsg, + sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength, + ENDPOINT_0, + HTC_SERVICE_TX_PACKET_TAG); + + /* we want synchronous operation */ + pSendPacket->Completion = NULL; + HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0); + status = HTCIssueSend(target,pSendPacket); + + if (status) { + break; + } + + /* wait for response */ + status = HTCWaitforControlMessage(target, &pRecvPacket); + + if (status) { + break; + } + /* we controlled the buffer creation so it has to be properly aligned */ + pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer; + + if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) || + (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) { + /* this message is not valid */ + AR_DEBUG_ASSERT(false); + status = A_EPROTO; + break; + } + + pConnectResp->ConnectRespCode = pResponseMsg->Status; + /* check response status */ + if (pResponseMsg->Status != HTC_SERVICE_SUCCESS) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + (" Target failed service 0x%X connect request (status:%d)\n", + pResponseMsg->ServiceID, pResponseMsg->Status)); + status = A_EPROTO; + break; + } + + assignedEndpoint = (HTC_ENDPOINT_ID) pResponseMsg->EndpointID; + maxMsgSize = pResponseMsg->MaxMsgSize; + + if ((pConnectResp->pMetaData != NULL) && + (pResponseMsg->ServiceMetaLength > 0) && + (pResponseMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { + /* caller supplied a buffer and the target responded with data */ + int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength); + /* copy the meta data */ + memcpy(pConnectResp->pMetaData, + ((u8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG), + copyLength); + pConnectResp->ActualLength = copyLength; + } + + } + + /* the rest of these are parameter checks so set the error status */ + status = A_EPROTO; + + if (assignedEndpoint >= ENDPOINT_MAX) { + AR_DEBUG_ASSERT(false); + break; + } + + if (0 == maxMsgSize) { + AR_DEBUG_ASSERT(false); + break; + } + + pEndpoint = &target->EndPoint[assignedEndpoint]; + pEndpoint->Id = assignedEndpoint; + if (pEndpoint->ServiceID != 0) { + /* endpoint already in use! */ + AR_DEBUG_ASSERT(false); + break; + } + + /* return assigned endpoint to caller */ + pConnectResp->Endpoint = assignedEndpoint; + pConnectResp->MaxMsgLength = maxMsgSize; + + /* setup the endpoint */ + pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */ + pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth; + pEndpoint->MaxMsgLength = maxMsgSize; + /* copy all the callbacks */ + pEndpoint->EpCallBacks = pConnectReq->EpCallbacks; + /* set the credit distribution info for this endpoint, this information is + * passed back to the credit distribution callback function */ + pEndpoint->CreditDist.ServiceID = pConnectReq->ServiceID; + pEndpoint->CreditDist.pHTCReserved = pEndpoint; + pEndpoint->CreditDist.Endpoint = assignedEndpoint; + pEndpoint->CreditDist.TxCreditSize = target->TargetCreditSize; + + if (pConnectReq->MaxSendMsgSize != 0) { + /* override TxCreditsPerMaxMsg calculation, this optimizes the credit-low indications + * since the host will actually issue smaller messages in the Send path */ + if (pConnectReq->MaxSendMsgSize > maxMsgSize) { + /* can't be larger than the maximum the target can support */ + AR_DEBUG_ASSERT(false); + break; + } + pEndpoint->CreditDist.TxCreditsPerMaxMsg = pConnectReq->MaxSendMsgSize / target->TargetCreditSize; + } else { + pEndpoint->CreditDist.TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize; + } + + if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) { + pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1; + } + + /* save local connection flags */ + pEndpoint->LocalConnectionFlags = pConnectReq->LocalConnectionFlags; + + status = 0; + + } while (false); + + if (pSendPacket != NULL) { + HTC_FREE_CONTROL_TX(target,pSendPacket); + } + + if (pRecvPacket != NULL) { + HTC_FREE_CONTROL_RX(target,pRecvPacket); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n")); + + return status; +} + +static void AddToEndpointDistList(struct htc_target *target, struct htc_endpoint_credit_dist *pEpDist) +{ + struct htc_endpoint_credit_dist *pCurEntry,*pLastEntry; + + if (NULL == target->EpCreditDistributionListHead) { + target->EpCreditDistributionListHead = pEpDist; + pEpDist->pNext = NULL; + pEpDist->pPrev = NULL; + return; + } + + /* queue to the end of the list, this does not have to be very + * fast since this list is built at startup time */ + pCurEntry = target->EpCreditDistributionListHead; + + while (pCurEntry) { + pLastEntry = pCurEntry; + pCurEntry = pCurEntry->pNext; + } + + pLastEntry->pNext = pEpDist; + pEpDist->pPrev = pLastEntry; + pEpDist->pNext = NULL; +} + + + +/* default credit init callback */ +static void HTCDefaultCreditInit(void *Context, + struct htc_endpoint_credit_dist *pEPList, + int TotalCredits) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + int totalEps = 0; + int creditsPerEndpoint; + + pCurEpDist = pEPList; + /* first run through the list and figure out how many endpoints we are dealing with */ + while (pCurEpDist != NULL) { + pCurEpDist = pCurEpDist->pNext; + totalEps++; + } + + /* even distribution */ + creditsPerEndpoint = TotalCredits/totalEps; + + pCurEpDist = pEPList; + /* run through the list and set minimum and normal credits and + * provide the endpoint with some credits to start */ + while (pCurEpDist != NULL) { + + if (creditsPerEndpoint < pCurEpDist->TxCreditsPerMaxMsg) { + /* too many endpoints and not enough credits */ + AR_DEBUG_ASSERT(false); + break; + } + /* our minimum is set for at least 1 max message */ + pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg; + /* this value is ignored by our credit alg, since we do + * not dynamically adjust credits, this is the policy of + * the "default" credit distribution, something simple and easy */ + pCurEpDist->TxCreditsNorm = 0xFFFF; + /* give the endpoint minimum credits */ + pCurEpDist->TxCredits = creditsPerEndpoint; + pCurEpDist->TxCreditsAssigned = creditsPerEndpoint; + pCurEpDist = pCurEpDist->pNext; + } + +} + +/* default credit distribution callback, NOTE, this callback holds the TX lock */ +void HTCDefaultCreditDist(void *Context, + struct htc_endpoint_credit_dist *pEPDistList, + HTC_CREDIT_DIST_REASON Reason) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + + if (Reason == HTC_CREDIT_DIST_SEND_COMPLETE) { + pCurEpDist = pEPDistList; + /* simple distribution */ + while (pCurEpDist != NULL) { + if (pCurEpDist->TxCreditsToDist > 0) { + /* just give the endpoint back the credits */ + pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist; + pCurEpDist->TxCreditsToDist = 0; + } + pCurEpDist = pCurEpDist->pNext; + } + } + + /* note we do not need to handle the other reason codes as this is a very + * simple distribution scheme, no need to seek for more credits or handle inactivity */ +} + +void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, + void *pCreditDistContext, + HTC_CREDIT_DIST_CALLBACK CreditDistFunc, + HTC_CREDIT_INIT_CALLBACK CreditInitFunc, + HTC_SERVICE_ID ServicePriorityOrder[], + int ListLength) +{ + struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int i; + int ep; + + if (CreditInitFunc != NULL) { + /* caller has supplied their own distribution functions */ + target->InitCredits = CreditInitFunc; + AR_DEBUG_ASSERT(CreditDistFunc != NULL); + target->DistributeCredits = CreditDistFunc; + target->pCredDistContext = pCreditDistContext; + } else { + /* caller wants HTC to do distribution */ + /* if caller wants service to handle distributions then + * it must set both of these to NULL! */ + AR_DEBUG_ASSERT(CreditDistFunc == NULL); + target->InitCredits = HTCDefaultCreditInit; + target->DistributeCredits = HTCDefaultCreditDist; + target->pCredDistContext = target; + } + + /* always add HTC control endpoint first, we only expose the list after the + * first one, this is added for TX queue checking */ + AddToEndpointDistList(target, &target->EndPoint[ENDPOINT_0].CreditDist); + + /* build the list of credit distribution structures in priority order + * supplied by the caller, these will follow endpoint 0 */ + for (i = 0; i < ListLength; i++) { + /* match services with endpoints and add the endpoints to the distribution list + * in FIFO order */ + for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) { + if (target->EndPoint[ep].ServiceID == ServicePriorityOrder[i]) { + /* queue this one to the list */ + AddToEndpointDistList(target, &target->EndPoint[ep].CreditDist); + break; + } + } + AR_DEBUG_ASSERT(ep < ENDPOINT_MAX); + } + +} diff --git a/trunk/drivers/staging/ath6kl/include/a_config.h b/trunk/drivers/staging/ath6kl/include/a_config.h new file mode 100644 index 000000000000..f7c09319433f --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_config.h @@ -0,0 +1,31 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains software configuration options that enables +// specific software "features" +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_CONFIG_H_ +#define _A_CONFIG_H_ + +#include "../os/linux/include/config_linux.h" + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/a_debug.h b/trunk/drivers/staging/ath6kl/include/a_debug.h new file mode 100644 index 000000000000..5154fcb1ca64 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_debug.h @@ -0,0 +1,195 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_DEBUG_H_ +#define _A_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + + /* standard debug print masks bits 0..7 */ +#define ATH_DEBUG_ERR (1 << 0) /* errors */ +#define ATH_DEBUG_WARN (1 << 1) /* warnings */ +#define ATH_DEBUG_INFO (1 << 2) /* informational (module startup info) */ +#define ATH_DEBUG_TRC (1 << 3) /* generic function call tracing */ +#define ATH_DEBUG_RSVD1 (1 << 4) +#define ATH_DEBUG_RSVD2 (1 << 5) +#define ATH_DEBUG_RSVD3 (1 << 6) +#define ATH_DEBUG_RSVD4 (1 << 7) + +#define ATH_DEBUG_MASK_DEFAULTS (ATH_DEBUG_ERR | ATH_DEBUG_WARN) +#define ATH_DEBUG_ANY 0xFFFF + + /* other aliases used throughout */ +#define ATH_DEBUG_ERROR ATH_DEBUG_ERR +#define ATH_LOG_ERR ATH_DEBUG_ERR +#define ATH_LOG_INF ATH_DEBUG_INFO +#define ATH_LOG_TRC ATH_DEBUG_TRC +#define ATH_DEBUG_TRACE ATH_DEBUG_TRC +#define ATH_DEBUG_INIT ATH_DEBUG_INFO + + /* bits 8..31 are module-specific masks */ +#define ATH_DEBUG_MODULE_MASK_SHIFT 8 + + /* macro to make a module-specific masks */ +#define ATH_DEBUG_MAKE_MODULE_MASK(index) (1 << (ATH_DEBUG_MODULE_MASK_SHIFT + (index))) + +void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription); + +/* Debug support on a per-module basis + * + * Usage: + * + * Each module can utilize it's own debug mask variable. A set of commonly used + * masks are provided (ERRORS, WARNINGS, TRACE etc..). It is up to each module + * to define module-specific masks using the macros above. + * + * Each module defines a single debug mask variable debug_XXX where the "name" of the module is + * common to all C-files within that module. This requires every C-file that includes a_debug.h + * to define the module name in that file. + * + * Example: + * + * #define ATH_MODULE_NAME htc + * #include "a_debug.h" + * + * This will define a debug mask structure called debug_htc and all debug macros will reference this + * variable. + * + * A module can define module-specific bit masks using the ATH_DEBUG_MAKE_MODULE_MASK() macro: + * + * #define ATH_DEBUG_MY_MASK1 ATH_DEBUG_MAKE_MODULE_MASK(0) + * #define ATH_DEBUG_MY_MASK2 ATH_DEBUG_MAKE_MODULE_MASK(1) + * + * The instantiation of the debug structure should be made by the module. When a module is + * instantiated, the module can set a description string, a default mask and an array of description + * entries containing information on each module-defined debug mask. + * NOTE: The instantiation is statically allocated, only one instance can exist per module. + * + * Example: + * + * + * #define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0) + * + * #ifdef DEBUG + * static struct ath_debug_mask_description bmi_debug_desc[] = { + * { ATH_DEBUG_BMI , "BMI Tracing"}, <== description of the module specific mask + * }; + * + * ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi, + * "bmi" <== module name + * "Boot Manager Interface", <== description of module + * ATH_DEBUG_MASK_DEFAULTS, <== defaults + * ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc), + * bmi_debug_desc); + * + * #endif + * + * A module can optionally register it's debug module information in order for other tools to change the + * bit mask at runtime. A module can call A_REGISTER_MODULE_DEBUG_INFO() in it's module + * init code. This macro can be called multiple times without consequence. The debug info maintains + * state to indicate whether the information was previously registered. + * + * */ + +#define ATH_DEBUG_MAX_MASK_DESC_LENGTH 32 +#define ATH_DEBUG_MAX_MOD_DESC_LENGTH 64 + +struct ath_debug_mask_description { + u32 Mask; + char Description[ATH_DEBUG_MAX_MASK_DESC_LENGTH]; +}; + +#define ATH_DEBUG_INFO_FLAGS_REGISTERED (1 << 0) + +typedef struct _ATH_DEBUG_MODULE_DBG_INFO{ + struct _ATH_DEBUG_MODULE_DBG_INFO *pNext; + char ModuleName[16]; + char ModuleDescription[ATH_DEBUG_MAX_MOD_DESC_LENGTH]; + u32 Flags; + u32 CurrentMask; + int MaxDescriptions; + struct ath_debug_mask_description *pMaskDescriptions; /* pointer to array of descriptions */ +} ATH_DEBUG_MODULE_DBG_INFO; + +#define ATH_DEBUG_DESCRIPTION_COUNT(d) (int)((sizeof((d))) / (sizeof(struct ath_debug_mask_description))) + +#define GET_ATH_MODULE_DEBUG_VAR_NAME(s) _XGET_ATH_MODULE_NAME_DEBUG_(s) +#define GET_ATH_MODULE_DEBUG_VAR_MASK(s) _XGET_ATH_MODULE_NAME_DEBUG_(s).CurrentMask +#define _XGET_ATH_MODULE_NAME_DEBUG_(s) debug_ ## s + +#ifdef ATH_DEBUG_MODULE + + /* for source files that will instantiate the debug variables */ +#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions) \ +ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s) = \ + {NULL,(name),(moddesc),0,(initmask),count,(descriptions)} + +#ifdef ATH_MODULE_NAME +extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(ATH_MODULE_NAME); +#define AR_DEBUG_LVL_CHECK(lvl) (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (lvl)) +#endif /* ATH_MODULE_NAME */ + +#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl) GET_ATH_MODULE_DEBUG_VAR_MASK(s) = (lvl) + +#define ATH_DEBUG_DECLARE_EXTERN(s) \ + extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s) + +#define AR_DEBUG_PRINTBUF(buffer, length, desc) DebugDumpBytes(buffer,length,desc) + + +#define AR_DEBUG_ASSERT A_ASSERT + +void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo); +void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo); +#define A_DUMP_MODULE_DEBUG_INFO(s) a_dump_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s))) +#define A_REGISTER_MODULE_DEBUG_INFO(s) a_register_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s))) + +#else /* !ATH_DEBUG_MODULE */ + /* NON ATH_DEBUG_MODULE */ +#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions) +#define AR_DEBUG_LVL_CHECK(lvl) 0 +#define AR_DEBUG_PRINTBUF(buffer, length, desc) +#define AR_DEBUG_ASSERT(test) +#define ATH_DEBUG_DECLARE_EXTERN(s) +#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl) +#define A_DUMP_MODULE_DEBUG_INFO(s) +#define A_REGISTER_MODULE_DEBUG_INFO(s) + +#endif + +int a_get_module_mask(char *module_name, u32 *pMask); +int a_set_module_mask(char *module_name, u32 Mask); +void a_dump_module_debug_info_by_name(char *module_name); +void a_module_debug_support_init(void); +void a_module_debug_support_cleanup(void); + +#include "../os/linux/include/debug_linux.h" + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/a_drv.h b/trunk/drivers/staging/ath6kl/include/a_drv.h new file mode 100644 index 000000000000..1548604e8465 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_drv.h @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the definitions of the basic atheros data types. +// It is used to map the data types in atheros files to a platform specific +// type. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_DRV_H_ +#define _A_DRV_H_ + +#include "../os/linux/include/athdrv_linux.h" + +#endif /* _ADRV_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/a_drv_api.h b/trunk/drivers/staging/ath6kl/include/a_drv_api.h new file mode 100644 index 000000000000..a40d97a84ffc --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_drv_api.h @@ -0,0 +1,204 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_DRV_API_H_ +#define _A_DRV_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************/ +/****************************************************************************/ +/** **/ +/** WMI related hooks **/ +/** **/ +/****************************************************************************/ +/****************************************************************************/ + +#include + +#define A_WMI_CHANNELLIST_RX(devt, numChan, chanList) \ + ar6000_channelList_rx((devt), (numChan), (chanList)) + +#define A_WMI_SET_NUMDATAENDPTS(devt, num) \ + ar6000_set_numdataendpts((devt), (num)) + +#define A_WMI_CONTROL_TX(devt, osbuf, streamID) \ + ar6000_control_tx((devt), (osbuf), (streamID)) + +#define A_WMI_TARGETSTATS_EVENT(devt, pStats, len) \ + ar6000_targetStats_event((devt), (pStats), (len)) + +#define A_WMI_SCANCOMPLETE_EVENT(devt, status) \ + ar6000_scanComplete_event((devt), (status)) + +#ifdef CONFIG_HOST_DSET_SUPPORT + +#define A_WMI_DSET_DATA_REQ(devt, access_cookie, offset, length, targ_buf, targ_reply_fn, targ_reply_arg) \ + ar6000_dset_data_req((devt), (access_cookie), (offset), (length), (targ_buf), (targ_reply_fn), (targ_reply_arg)) + +#define A_WMI_DSET_CLOSE(devt, access_cookie) \ + ar6000_dset_close((devt), (access_cookie)) + +#endif + +#define A_WMI_DSET_OPEN_REQ(devt, id, targ_handle, targ_reply_fn, targ_reply_arg) \ + ar6000_dset_open_req((devt), (id), (targ_handle), (targ_reply_fn), (targ_reply_arg)) + +#define A_WMI_CONNECT_EVENT(devt, channel, bssid, listenInterval, beaconInterval, networkType, beaconIeLen, assocReqLen, assocRespLen, assocInfo) \ + ar6000_connect_event((devt), (channel), (bssid), (listenInterval), (beaconInterval), (networkType), (beaconIeLen), (assocReqLen), (assocRespLen), (assocInfo)) + +#define A_WMI_PSPOLL_EVENT(devt, aid)\ + ar6000_pspoll_event((devt),(aid)) + +#define A_WMI_DTIMEXPIRY_EVENT(devt)\ + ar6000_dtimexpiry_event((devt)) + +#ifdef WAPI_ENABLE +#define A_WMI_WAPI_REKEY_EVENT(devt, type, mac)\ + ap_wapi_rekey_event((devt),(type),(mac)) +#endif + +#define A_WMI_REGDOMAIN_EVENT(devt, regCode) \ + ar6000_regDomain_event((devt), (regCode)) + +#define A_WMI_NEIGHBORREPORT_EVENT(devt, numAps, info) \ + ar6000_neighborReport_event((devt), (numAps), (info)) + +#define A_WMI_DISCONNECT_EVENT(devt, reason, bssid, assocRespLen, assocInfo, protocolReasonStatus) \ + ar6000_disconnect_event((devt), (reason), (bssid), (assocRespLen), (assocInfo), (protocolReasonStatus)) + +#define A_WMI_TKIP_MICERR_EVENT(devt, keyid, ismcast) \ + ar6000_tkip_micerr_event((devt), (keyid), (ismcast)) + +#define A_WMI_BITRATE_RX(devt, rateKbps) \ + ar6000_bitrate_rx((devt), (rateKbps)) + +#define A_WMI_TXPWR_RX(devt, txPwr) \ + ar6000_txPwr_rx((devt), (txPwr)) + +#define A_WMI_READY_EVENT(devt, datap, phyCap, sw_ver, abi_ver) \ + ar6000_ready_event((devt), (datap), (phyCap), (sw_ver), (abi_ver)) + +#define A_WMI_DBGLOG_INIT_DONE(ar) \ + ar6000_dbglog_init_done(ar); + +#define A_WMI_RSSI_THRESHOLD_EVENT(devt, newThreshold, rssi) \ + ar6000_rssiThreshold_event((devt), (newThreshold), (rssi)) + +#define A_WMI_REPORT_ERROR_EVENT(devt, errorVal) \ + ar6000_reportError_event((devt), (errorVal)) + +#define A_WMI_ROAM_TABLE_EVENT(devt, pTbl) \ + ar6000_roam_tbl_event((devt), (pTbl)) + +#define A_WMI_ROAM_DATA_EVENT(devt, p) \ + ar6000_roam_data_event((devt), (p)) + +#define A_WMI_WOW_LIST_EVENT(devt, num_filters, wow_filters) \ + ar6000_wow_list_event((devt), (num_filters), (wow_filters)) + +#define A_WMI_CAC_EVENT(devt, ac, cac_indication, statusCode, tspecSuggestion) \ + ar6000_cac_event((devt), (ac), (cac_indication), (statusCode), (tspecSuggestion)) + +#define A_WMI_CHANNEL_CHANGE_EVENT(devt, oldChannel, newChannel) \ + ar6000_channel_change_event((devt), (oldChannel), (newChannel)) + +#define A_WMI_PMKID_LIST_EVENT(devt, num_pmkid, pmkid_list, bssid_list) \ + ar6000_pmkid_list_event((devt), (num_pmkid), (pmkid_list), (bssid_list)) + +#define A_WMI_PEER_EVENT(devt, eventCode, bssid) \ + ar6000_peer_event ((devt), (eventCode), (bssid)) + +#ifdef CONFIG_HOST_TCMD_SUPPORT +#define A_WMI_TCMD_RX_REPORT_EVENT(devt, results, len) \ + ar6000_tcmd_rx_report_event((devt), (results), (len)) +#endif + +#define A_WMI_HBCHALLENGERESP_EVENT(devt, cookie, source) \ + ar6000_hbChallengeResp_event((devt), (cookie), (source)) + +#define A_WMI_TX_RETRY_ERR_EVENT(devt) \ + ar6000_tx_retry_err_event((devt)) + +#define A_WMI_SNR_THRESHOLD_EVENT_RX(devt, newThreshold, snr) \ + ar6000_snrThresholdEvent_rx((devt), (newThreshold), (snr)) + +#define A_WMI_LQ_THRESHOLD_EVENT_RX(devt, range, lqVal) \ + ar6000_lqThresholdEvent_rx((devt), (range), (lqVal)) + +#define A_WMI_RATEMASK_RX(devt, ratemask) \ + ar6000_ratemask_rx((devt), (ratemask)) + +#define A_WMI_KEEPALIVE_RX(devt, configured) \ + ar6000_keepalive_rx((devt), (configured)) + +#define A_WMI_BSSINFO_EVENT_RX(ar, datp, len) \ + ar6000_bssInfo_event_rx((ar), (datap), (len)) + +#define A_WMI_DBGLOG_EVENT(ar, dropped, buffer, length) \ + ar6000_dbglog_event((ar), (dropped), (buffer), (length)); + +#define A_WMI_STREAM_TX_ACTIVE(devt,trafficClass) \ + ar6000_indicate_tx_activity((devt),(trafficClass), true) + +#define A_WMI_STREAM_TX_INACTIVE(devt,trafficClass) \ + ar6000_indicate_tx_activity((devt),(trafficClass), false) +#define A_WMI_Ac2EndpointID(devht, ac)\ + ar6000_ac2_endpoint_id((devht), (ac)) + +#define A_WMI_AGGR_RECV_ADDBA_REQ_EVT(devt, cmd)\ + ar6000_aggr_rcv_addba_req_evt((devt), (cmd)) +#define A_WMI_AGGR_RECV_ADDBA_RESP_EVT(devt, cmd)\ + ar6000_aggr_rcv_addba_resp_evt((devt), (cmd)) +#define A_WMI_AGGR_RECV_DELBA_REQ_EVT(devt, cmd)\ + ar6000_aggr_rcv_delba_req_evt((devt), (cmd)) +#define A_WMI_HCI_EVENT_EVT(devt, cmd)\ + ar6000_hci_event_rcv_evt((devt), (cmd)) + +#define A_WMI_Endpoint2Ac(devt, ep) \ + ar6000_endpoint_id2_ac((devt), (ep)) + +#define A_WMI_BTCOEX_CONFIG_EVENT(devt, evt, len)\ + ar6000_btcoex_config_event((devt), (evt), (len)) + +#define A_WMI_BTCOEX_STATS_EVENT(devt, datap, len)\ + ar6000_btcoex_stats_event((devt), (datap), (len)) + +/****************************************************************************/ +/****************************************************************************/ +/** **/ +/** HTC related hooks **/ +/** **/ +/****************************************************************************/ +/****************************************************************************/ + +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +#define A_WMI_PROF_COUNT_RX(addr, count) prof_count_rx((addr), (count)) +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/a_osapi.h b/trunk/drivers/staging/ath6kl/include/a_osapi.h new file mode 100644 index 000000000000..fd7ae0d612c6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/a_osapi.h @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the definitions of the basic atheros data types. +// It is used to map the data types in atheros files to a platform specific +// type. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _A_OSAPI_H_ +#define _A_OSAPI_H_ + +#include "../os/linux/include/osapi_linux.h" + +#endif /* _OSAPI_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/aggr_recv_api.h b/trunk/drivers/staging/ath6kl/include/aggr_recv_api.h new file mode 100644 index 000000000000..5ead58d5febd --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/aggr_recv_api.h @@ -0,0 +1,140 @@ +/* + * + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * +// +// Permission to use, copy, modify, and/or 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. +// +// + * + */ + +#ifndef __AGGR_RECV_API_H__ +#define __AGGR_RECV_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (* RX_CALLBACK)(void * dev, void *osbuf); + +typedef void (* ALLOC_NETBUFS)(A_NETBUF_QUEUE_T *q, u16 num); + +/* + * aggr_init: + * Initialises the data structures, allocates data queues and + * os buffers. Netbuf allocator is the input param, used by the + * aggr module for allocation of NETBUFs from driver context. + * These NETBUFs are used for AMSDU processing. + * Returns the context for the aggr module. + */ +void * +aggr_init(ALLOC_NETBUFS netbuf_allocator); + + +/* + * aggr_register_rx_dispatcher: + * Registers OS call back function to deliver the + * frames to OS. This is generally the topmost layer of + * the driver context, after which the frames go to + * IP stack via the call back function. + * This dispatcher is active only when aggregation is ON. + */ +void +aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn); + + +/* + * aggr_process_bar: + * When target receives BAR, it communicates to host driver + * for modifying window parameters. Target indicates this via the + * event: WMI_ADDBA_REQ_EVENTID. Host will dequeue all frames + * up to the indicated sequence number. + */ +void +aggr_process_bar(void *cntxt, u8 tid, u16 seq_no); + + +/* + * aggr_recv_addba_req_evt: + * This event is to initiate/modify the receive side window. + * Target will send WMI_ADDBA_REQ_EVENTID event to host - to setup + * recv re-ordering queues. Target will negotiate ADDBA with peer, + * and indicate via this event after successfully completing the + * negotiation. This happens in two situations: + * 1. Initial setup of aggregation + * 2. Renegotiation of current recv window. + * Window size for re-ordering is limited by target buffer + * space, which is reflected in win_sz. + * (Re)Start the periodic timer to deliver long standing frames, + * in hold_q to OS. + */ +void +aggr_recv_addba_req_evt(void * cntxt, u8 tid, u16 seq_no, u8 win_sz); + + +/* + * aggr_recv_delba_req_evt: + * Target indicates deletion of a BA window for a tid via the + * WMI_DELBA_EVENTID. Host would deliver all the frames in the + * hold_q, reset tid config and disable the periodic timer, if + * aggr is not enabled on any tid. + */ +void +aggr_recv_delba_req_evt(void * cntxt, u8 tid); + + + +/* + * aggr_process_recv_frm: + * Called only for data frames. When aggr is ON for a tid, the buffer + * is always consumed, and osbuf would be NULL. For a non-aggr case, + * osbuf is not modified. + * AMSDU frames are consumed and are later freed. They are sliced and + * diced to individual frames and dispatched to stack. + * After consuming a osbuf(when aggr is ON), a previously registered + * callback may be called to deliver frames in order. + */ +void +aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf); + + +/* + * aggr_module_destroy: + * Frees up all the queues and frames in them. Releases the cntxt to OS. + */ +void +aggr_module_destroy(void *cntxt); + +/* + * Dumps the aggregation stats + */ +void +aggr_dump_stats(void *cntxt, PACKET_LOG **log_buf); + +/* + * aggr_reset_state -- Called when it is deemed necessary to clear the aggregate + * hold Q state. Examples include when a Connect event or disconnect event is + * received. + */ +void +aggr_reset_state(void *cntxt); + + +#ifdef __cplusplus +} +#endif + +#endif /*__AGGR_RECV_API_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/ar3kconfig.h b/trunk/drivers/staging/ath6kl/include/ar3kconfig.h new file mode 100644 index 000000000000..91bc4ee3512d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/ar3kconfig.h @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +/* AR3K module configuration APIs for HCI-bridge operation */ + +#ifndef AR3KCONFIG_H_ +#define AR3KCONFIG_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT (1 << 0) +#define AR3K_CONFIG_FLAG_SET_AR3K_BAUD (1 << 1) +#define AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY (1 << 2) +#define AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP (1 << 3) + + +struct ar3k_config_info { + u32 Flags; /* config flags */ + void *pHCIDev; /* HCI bridge device */ + struct hci_transport_properties *pHCIProps; /* HCI bridge props */ + struct hif_device *pHIFDevice; /* HIF layer device */ + + u32 AR3KBaudRate; /* AR3K operational baud rate */ + u16 AR6KScale; /* AR6K UART scale value */ + u16 AR6KStep; /* AR6K UART step value */ + struct hci_dev *pBtStackHCIDev; /* BT Stack HCI dev */ + u32 PwrMgmtEnabled; /* TLPM enabled? */ + u16 IdleTimeout; /* TLPM idle timeout */ + u16 WakeupTimeout; /* TLPM wakeup timeout */ + u8 bdaddr[6]; /* Bluetooth device address */ +}; + +int AR3KConfigure(struct ar3k_config_info *pConfigInfo); + +int AR3KConfigureExit(void *config); + +#ifdef __cplusplus +} +#endif + +#endif /*AR3KCONFIG_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/ar6000_api.h b/trunk/drivers/staging/ath6kl/include/ar6000_api.h new file mode 100644 index 000000000000..e9460800272c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/ar6000_api.h @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the API to access the OS dependent atheros host driver +// by the WMI or WLAN generic modules. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _AR6000_API_H_ +#define _AR6000_API_H_ + +#include "../os/linux/include/ar6xapi_linux.h" + +#endif /* _AR6000_API_H */ + diff --git a/trunk/drivers/staging/ath6kl/include/ar6000_diag.h b/trunk/drivers/staging/ath6kl/include/ar6000_diag.h new file mode 100644 index 000000000000..739c01c53f08 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/ar6000_diag.h @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef AR6000_DIAG_H_ +#define AR6000_DIAG_H_ + + +int +ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +int +ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +int +ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address, + u8 *data, u32 length); + +int +ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address, + u8 *data, u32 length); + +int +ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval); + +void +ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs); + +#endif /*AR6000_DIAG_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/ar6kap_common.h b/trunk/drivers/staging/ath6kl/include/ar6kap_common.h new file mode 100644 index 000000000000..532d8eba9326 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/ar6kap_common.h @@ -0,0 +1,44 @@ +//------------------------------------------------------------------------------ + +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ + +//============================================================================== + +// This file contains the definitions of common AP mode data structures. +// +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _AR6KAP_COMMON_H_ +#define _AR6KAP_COMMON_H_ +/* + * Used with AR6000_XIOCTL_AP_GET_STA_LIST + */ +typedef struct { + u8 mac[ATH_MAC_LEN]; + u8 aid; + u8 keymgmt; + u8 ucipher; + u8 auth; +} station_t; +typedef struct { + station_t sta[AP_MAX_NUM_STA]; +} ap_get_sta_t; +#endif /* _AR6KAP_COMMON_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/athbtfilter.h b/trunk/drivers/staging/ath6kl/include/athbtfilter.h new file mode 100644 index 000000000000..81456eea3b0b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/athbtfilter.h @@ -0,0 +1,135 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Public Bluetooth filter APIs +// Author(s): ="Atheros" +//============================================================================== +#ifndef ATHBTFILTER_H_ +#define ATHBTFILTER_H_ + +#define ATH_DEBUG_INFO (1 << 2) +#define ATH_DEBUG_INF ATH_DEBUG_INFO + +typedef enum _ATHBT_HCI_CTRL_TYPE { + ATHBT_HCI_COMMAND = 0, + ATHBT_HCI_EVENT = 1, +} ATHBT_HCI_CTRL_TYPE; + +typedef enum _ATHBT_STATE_INDICATION { + ATH_BT_NOOP = 0, + ATH_BT_INQUIRY = 1, + ATH_BT_CONNECT = 2, + ATH_BT_SCO = 3, + ATH_BT_ACL = 4, + ATH_BT_A2DP = 5, + ATH_BT_ESCO = 6, + /* new states go here.. */ + + ATH_BT_MAX_STATE_INDICATION +} ATHBT_STATE_INDICATION; + + /* filter function for OUTGOING commands and INCOMMING events */ +typedef void (*ATHBT_FILTER_CMD_EVENTS_FN)(void *pContext, ATHBT_HCI_CTRL_TYPE Type, unsigned char *pBuffer, int Length); + + /* filter function for OUTGOING data HCI packets */ +typedef void (*ATHBT_FILTER_DATA_FN)(void *pContext, unsigned char *pBuffer, int Length); + +typedef enum _ATHBT_STATE { + STATE_OFF = 0, + STATE_ON = 1, + STATE_MAX +} ATHBT_STATE; + + /* BT state indication (when filter functions are not used) */ + +typedef void (*ATHBT_INDICATE_STATE_FN)(void *pContext, ATHBT_STATE_INDICATION Indication, ATHBT_STATE State, unsigned char LMPVersion); + +struct athbt_filter_instance { +#ifdef UNDER_CE + WCHAR *pWlanAdapterName; /* filled in by user */ +#else + char *pWlanAdapterName; /* filled in by user */ +#endif /* UNDER_CE */ + int FilterEnabled; /* filtering is enabled */ + int Attached; /* filter library is attached */ + void *pContext; /* private context for filter library */ + ATHBT_FILTER_CMD_EVENTS_FN pFilterCmdEvents; /* function ptr to filter a command or event */ + ATHBT_FILTER_DATA_FN pFilterAclDataOut; /* function ptr to filter ACL data out (to radio) */ + ATHBT_FILTER_DATA_FN pFilterAclDataIn; /* function ptr to filter ACL data in (from radio) */ + ATHBT_INDICATE_STATE_FN pIndicateState; /* function ptr to indicate a state */ +}; /* XXX: unused ? */ + + +/* API MACROS */ + +#define AthBtFilterHciCommand(instance,packet,length) \ + if ((instance)->FilterEnabled) { \ + (instance)->pFilterCmdEvents((instance)->pContext, \ + ATHBT_HCI_COMMAND, \ + (unsigned char *)(packet), \ + (length)); \ + } + +#define AthBtFilterHciEvent(instance,packet,length) \ + if ((instance)->FilterEnabled) { \ + (instance)->pFilterCmdEvents((instance)->pContext, \ + ATHBT_HCI_EVENT, \ + (unsigned char *)(packet), \ + (length)); \ + } + +#define AthBtFilterHciAclDataOut(instance,packet,length) \ + if ((instance)->FilterEnabled) { \ + (instance)->pFilterAclDataOut((instance)->pContext, \ + (unsigned char *)(packet), \ + (length)); \ + } + +#define AthBtFilterHciAclDataIn(instance,packet,length) \ + if ((instance)->FilterEnabled) { \ + (instance)->pFilterAclDataIn((instance)->pContext, \ + (unsigned char *)(packet), \ + (length)); \ + } + +/* if filtering is not desired, the application can indicate the state directly using this + * macro: + */ +#define AthBtIndicateState(instance,indication,state) \ + if ((instance)->FilterEnabled) { \ + (instance)->pIndicateState((instance)->pContext, \ + (indication), \ + (state), \ + 0); \ + } + +#ifdef __cplusplus +extern "C" { +#endif + +/* API prototypes */ +int AthBtFilter_Attach(ATH_BT_FILTER_INSTANCE *pInstance, unsigned int flags); +void AthBtFilter_Detach(ATH_BT_FILTER_INSTANCE *pInstance); + +#ifdef __cplusplus +} +#endif + +#endif /*ATHBTFILTER_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/bmi.h b/trunk/drivers/staging/ath6kl/include/bmi.h new file mode 100644 index 000000000000..d3227f77fa5d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/bmi.h @@ -0,0 +1,134 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// BMI declarations and prototypes +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _BMI_H_ +#define _BMI_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ +#include "a_config.h" +#include "athdefs.h" +#include "hif.h" +#include "a_osapi.h" +#include "bmi_msg.h" + +void +BMIInit(void); + +void +BMICleanup(void); + +int +BMIDone(struct hif_device *device); + +int +BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info); + +int +BMIReadMemory(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length); + +int +BMIWriteMemory(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length); + +int +BMIExecute(struct hif_device *device, + u32 address, + u32 *param); + +int +BMISetAppStart(struct hif_device *device, + u32 address); + +int +BMIReadSOCRegister(struct hif_device *device, + u32 address, + u32 *param); + +int +BMIWriteSOCRegister(struct hif_device *device, + u32 address, + u32 param); + +int +BMIrompatchInstall(struct hif_device *device, + u32 ROM_addr, + u32 RAM_addr, + u32 nbytes, + u32 do_activate, + u32 *patch_id); + +int +BMIrompatchUninstall(struct hif_device *device, + u32 rompatch_id); + +int +BMIrompatchActivate(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list); + +int +BMIrompatchDeactivate(struct hif_device *device, + u32 rompatch_count, + u32 *rompatch_list); + +int +BMILZStreamStart(struct hif_device *device, + u32 address); + +int +BMILZData(struct hif_device *device, + u8 *buffer, + u32 length); + +int +BMIFastDownload(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length); + +int +BMIRawWrite(struct hif_device *device, + u8 *buffer, + u32 length); + +int +BMIRawRead(struct hif_device *device, + u8 *buffer, + u32 length, + bool want_timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* _BMI_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h new file mode 100644 index 000000000000..5407e05d9b05 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#define __VER_MAJOR_ 3 +#define __VER_MINOR_ 0 +#define __VER_PATCH_ 0 + +/* The makear6ksdk script (used for release builds) modifies the following line. */ +#define __BUILD_NUMBER_ 233 + + +/* Format of the version number. */ +#define VER_MAJOR_BIT_OFFSET 28 +#define VER_MINOR_BIT_OFFSET 24 +#define VER_PATCH_BIT_OFFSET 16 +#define VER_BUILD_NUM_BIT_OFFSET 0 + + +/* + * The version has the following format: + * Bits 28-31: Major version + * Bits 24-27: Minor version + * Bits 16-23: Patch version + * Bits 0-15: Build number (automatically generated during build process ) + * E.g. Build 1.1.3.7 would be represented as 0x11030007. + * + * DO NOT split the following macro into multiple lines as this may confuse the build scripts. + */ +#define AR6K_SW_VERSION ( ( __VER_MAJOR_ << VER_MAJOR_BIT_OFFSET ) + ( __VER_MINOR_ << VER_MINOR_BIT_OFFSET ) + ( __VER_PATCH_ << VER_PATCH_BIT_OFFSET ) + ( __BUILD_NUMBER_ << VER_BUILD_NUM_BIT_OFFSET ) ) + +/* ABI Version. Reflects the version of binary interface exposed by AR6K target firmware. Needs to be incremented by 1 for any change in the firmware that requires upgrade of the driver on the host side for the change to work correctly */ +#define AR6K_ABI_VERSION 1 diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/addrs.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/addrs.h new file mode 100644 index 000000000000..bbf8d42828c1 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/addrs.h @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef __ADDRS_H__ +#define __ADDRS_H__ + +/* + * Special AR6002 Addresses that may be needed by special + * applications (e.g. ART) on the Host as well as Target. + */ + +#if defined(AR6002_REV2) +#define AR6K_RAM_START 0x00500000 +#define TARG_RAM_OFFSET(vaddr) ((u32)(vaddr) & 0xfffff) +#define TARG_RAM_SZ (184*1024) +#define TARG_ROM_SZ (80*1024) +#endif +#if defined(AR6002_REV4) || defined(AR6003) +#define AR6K_RAM_START 0x00540000 +#define TARG_RAM_OFFSET(vaddr) (((u32)(vaddr) & 0xfffff) - 0x40000) +#define TARG_RAM_SZ (256*1024) +#define TARG_ROM_SZ (256*1024) +#endif + +#define AR6002_BOARD_DATA_SZ 768 +#define AR6002_BOARD_EXT_DATA_SZ 0 +#define AR6003_BOARD_DATA_SZ 1024 +#define AR6003_BOARD_EXT_DATA_SZ 768 + +#define AR6K_RAM_ADDR(byte_offset) (AR6K_RAM_START+(byte_offset)) +#define TARG_RAM_ADDRS(byte_offset) AR6K_RAM_ADDR(byte_offset) + +#define AR6K_ROM_START 0x004e0000 +#define TARG_ROM_OFFSET(vaddr) (((u32)(vaddr) & 0x1fffff) - 0xe0000) +#define AR6K_ROM_ADDR(byte_offset) (AR6K_ROM_START+(byte_offset)) +#define TARG_ROM_ADDRS(byte_offset) AR6K_ROM_ADDR(byte_offset) + +/* + * At this ROM address is a pointer to the start of the ROM DataSet Index. + * If there are no ROM DataSets, there's a 0 at this address. + */ +#define ROM_DATASET_INDEX_ADDR (TARG_ROM_ADDRS(TARG_ROM_SZ)-8) +#define ROM_MBIST_CKSUM_ADDR (TARG_ROM_ADDRS(TARG_ROM_SZ)-4) + +/* + * The API A_BOARD_DATA_ADDR() is the proper way to get a read pointer to + * board data. + */ + +/* Size of Board Data, in bytes */ +#if defined(AR6002_REV4) || defined(AR6003) +#define BOARD_DATA_SZ AR6003_BOARD_DATA_SZ +#else +#define BOARD_DATA_SZ AR6002_BOARD_DATA_SZ +#endif + + +/* + * Constants used by ASM code to access fields of host_interest_s, + * which is at a fixed location in RAM. + */ +#if defined(AR6002_REV4) || defined(AR6003) +#define HOST_INTEREST_FLASH_IS_PRESENT_ADDR (AR6K_RAM_START + 0x60c) +#else +#define HOST_INTEREST_FLASH_IS_PRESENT_ADDR (AR6K_RAM_START + 0x40c) +#endif +#define FLASH_IS_PRESENT_TARGADDR HOST_INTEREST_FLASH_IS_PRESENT_ADDR + +#endif /* __ADDRS_H__ */ + + + diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h new file mode 100644 index 000000000000..609eb9841f59 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h @@ -0,0 +1,40 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _APB_ATHR_WLAN_MAP_H_ +#define _APB_ATHR_WLAN_MAP_H_ + +#define WLAN_RTC_BASE_ADDRESS 0x00004000 +#define WLAN_VMC_BASE_ADDRESS 0x00008000 +#define WLAN_UART_BASE_ADDRESS 0x0000c000 +#define WLAN_DBG_UART_BASE_ADDRESS 0x0000d000 +#define WLAN_UMBOX_BASE_ADDRESS 0x0000e000 +#define WLAN_SI_BASE_ADDRESS 0x00010000 +#define WLAN_GPIO_BASE_ADDRESS 0x00014000 +#define WLAN_MBOX_BASE_ADDRESS 0x00018000 +#define WLAN_ANALOG_INTF_BASE_ADDRESS 0x0001c000 +#define WLAN_MAC_BASE_ADDRESS 0x00020000 +#define WLAN_RDMA_BASE_ADDRESS 0x00030100 +#define EFUSE_BASE_ADDRESS 0x00031000 + +#endif /* _APB_ATHR_WLAN_MAP_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h new file mode 100644 index 000000000000..0068ca31b051 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h @@ -0,0 +1,40 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#include "apb_athr_wlan_map.h" + +#ifndef BT_HEADERS + +#define RTC_BASE_ADDRESS WLAN_RTC_BASE_ADDRESS +#define VMC_BASE_ADDRESS WLAN_VMC_BASE_ADDRESS +#define UART_BASE_ADDRESS WLAN_UART_BASE_ADDRESS +#define DBG_UART_BASE_ADDRESS WLAN_DBG_UART_BASE_ADDRESS +#define UMBOX_BASE_ADDRESS WLAN_UMBOX_BASE_ADDRESS +#define SI_BASE_ADDRESS WLAN_SI_BASE_ADDRESS +#define GPIO_BASE_ADDRESS WLAN_GPIO_BASE_ADDRESS +#define MBOX_BASE_ADDRESS WLAN_MBOX_BASE_ADDRESS +#define ANALOG_INTF_BASE_ADDRESS WLAN_ANALOG_INTF_BASE_ADDRESS +#define MAC_BASE_ADDRESS WLAN_MAC_BASE_ADDRESS +#define RDMA_BASE_ADDRESS WLAN_RDMA_BASE_ADDRESS + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h new file mode 100644 index 000000000000..109f24e10a65 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h @@ -0,0 +1,24 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#include "mbox_wlan_host_reg.h" diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h new file mode 100644 index 000000000000..72fa483450d6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h @@ -0,0 +1,552 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#include "mbox_wlan_reg.h" + +#ifndef BT_HEADERS + +#define MBOX_FIFO_ADDRESS WLAN_MBOX_FIFO_ADDRESS +#define MBOX_FIFO_OFFSET WLAN_MBOX_FIFO_OFFSET +#define MBOX_FIFO_DATA_MSB WLAN_MBOX_FIFO_DATA_MSB +#define MBOX_FIFO_DATA_LSB WLAN_MBOX_FIFO_DATA_LSB +#define MBOX_FIFO_DATA_MASK WLAN_MBOX_FIFO_DATA_MASK +#define MBOX_FIFO_DATA_GET(x) WLAN_MBOX_FIFO_DATA_GET(x) +#define MBOX_FIFO_DATA_SET(x) WLAN_MBOX_FIFO_DATA_SET(x) +#define MBOX_FIFO_STATUS_ADDRESS WLAN_MBOX_FIFO_STATUS_ADDRESS +#define MBOX_FIFO_STATUS_OFFSET WLAN_MBOX_FIFO_STATUS_OFFSET +#define MBOX_FIFO_STATUS_EMPTY_MSB WLAN_MBOX_FIFO_STATUS_EMPTY_MSB +#define MBOX_FIFO_STATUS_EMPTY_LSB WLAN_MBOX_FIFO_STATUS_EMPTY_LSB +#define MBOX_FIFO_STATUS_EMPTY_MASK WLAN_MBOX_FIFO_STATUS_EMPTY_MASK +#define MBOX_FIFO_STATUS_EMPTY_GET(x) WLAN_MBOX_FIFO_STATUS_EMPTY_GET(x) +#define MBOX_FIFO_STATUS_EMPTY_SET(x) WLAN_MBOX_FIFO_STATUS_EMPTY_SET(x) +#define MBOX_FIFO_STATUS_FULL_MSB WLAN_MBOX_FIFO_STATUS_FULL_MSB +#define MBOX_FIFO_STATUS_FULL_LSB WLAN_MBOX_FIFO_STATUS_FULL_LSB +#define MBOX_FIFO_STATUS_FULL_MASK WLAN_MBOX_FIFO_STATUS_FULL_MASK +#define MBOX_FIFO_STATUS_FULL_GET(x) WLAN_MBOX_FIFO_STATUS_FULL_GET(x) +#define MBOX_FIFO_STATUS_FULL_SET(x) WLAN_MBOX_FIFO_STATUS_FULL_SET(x) +#define MBOX_DMA_POLICY_ADDRESS WLAN_MBOX_DMA_POLICY_ADDRESS +#define MBOX_DMA_POLICY_OFFSET WLAN_MBOX_DMA_POLICY_OFFSET +#define MBOX_DMA_POLICY_TX_QUANTUM_MSB WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MSB +#define MBOX_DMA_POLICY_TX_QUANTUM_LSB WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB +#define MBOX_DMA_POLICY_TX_QUANTUM_MASK WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK +#define MBOX_DMA_POLICY_TX_QUANTUM_GET(x) WLAN_MBOX_DMA_POLICY_TX_QUANTUM_GET(x) +#define MBOX_DMA_POLICY_TX_QUANTUM_SET(x) WLAN_MBOX_DMA_POLICY_TX_QUANTUM_SET(x) +#define MBOX_DMA_POLICY_TX_ORDER_MSB WLAN_MBOX_DMA_POLICY_TX_ORDER_MSB +#define MBOX_DMA_POLICY_TX_ORDER_LSB WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB +#define MBOX_DMA_POLICY_TX_ORDER_MASK WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK +#define MBOX_DMA_POLICY_TX_ORDER_GET(x) WLAN_MBOX_DMA_POLICY_TX_ORDER_GET(x) +#define MBOX_DMA_POLICY_TX_ORDER_SET(x) WLAN_MBOX_DMA_POLICY_TX_ORDER_SET(x) +#define MBOX_DMA_POLICY_RX_QUANTUM_MSB WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MSB +#define MBOX_DMA_POLICY_RX_QUANTUM_LSB WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB +#define MBOX_DMA_POLICY_RX_QUANTUM_MASK WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK +#define MBOX_DMA_POLICY_RX_QUANTUM_GET(x) WLAN_MBOX_DMA_POLICY_RX_QUANTUM_GET(x) +#define MBOX_DMA_POLICY_RX_QUANTUM_SET(x) WLAN_MBOX_DMA_POLICY_RX_QUANTUM_SET(x) +#define MBOX_DMA_POLICY_RX_ORDER_MSB WLAN_MBOX_DMA_POLICY_RX_ORDER_MSB +#define MBOX_DMA_POLICY_RX_ORDER_LSB WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB +#define MBOX_DMA_POLICY_RX_ORDER_MASK WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK +#define MBOX_DMA_POLICY_RX_ORDER_GET(x) WLAN_MBOX_DMA_POLICY_RX_ORDER_GET(x) +#define MBOX_DMA_POLICY_RX_ORDER_SET(x) WLAN_MBOX_DMA_POLICY_RX_ORDER_SET(x) +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX0_DMA_RX_CONTROL_ADDRESS WLAN_MBOX0_DMA_RX_CONTROL_ADDRESS +#define MBOX0_DMA_RX_CONTROL_OFFSET WLAN_MBOX0_DMA_RX_CONTROL_OFFSET +#define MBOX0_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MSB +#define MBOX0_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB +#define MBOX0_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK +#define MBOX0_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX0_DMA_RX_CONTROL_RESUME_GET(x) +#define MBOX0_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX0_DMA_RX_CONTROL_RESUME_SET(x) +#define MBOX0_DMA_RX_CONTROL_START_MSB WLAN_MBOX0_DMA_RX_CONTROL_START_MSB +#define MBOX0_DMA_RX_CONTROL_START_LSB WLAN_MBOX0_DMA_RX_CONTROL_START_LSB +#define MBOX0_DMA_RX_CONTROL_START_MASK WLAN_MBOX0_DMA_RX_CONTROL_START_MASK +#define MBOX0_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX0_DMA_RX_CONTROL_START_GET(x) +#define MBOX0_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX0_DMA_RX_CONTROL_START_SET(x) +#define MBOX0_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX0_DMA_RX_CONTROL_STOP_MSB +#define MBOX0_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB +#define MBOX0_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK +#define MBOX0_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX0_DMA_RX_CONTROL_STOP_GET(x) +#define MBOX0_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX0_DMA_RX_CONTROL_STOP_SET(x) +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX0_DMA_TX_CONTROL_ADDRESS WLAN_MBOX0_DMA_TX_CONTROL_ADDRESS +#define MBOX0_DMA_TX_CONTROL_OFFSET WLAN_MBOX0_DMA_TX_CONTROL_OFFSET +#define MBOX0_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MSB +#define MBOX0_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB +#define MBOX0_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK +#define MBOX0_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX0_DMA_TX_CONTROL_RESUME_GET(x) +#define MBOX0_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX0_DMA_TX_CONTROL_RESUME_SET(x) +#define MBOX0_DMA_TX_CONTROL_START_MSB WLAN_MBOX0_DMA_TX_CONTROL_START_MSB +#define MBOX0_DMA_TX_CONTROL_START_LSB WLAN_MBOX0_DMA_TX_CONTROL_START_LSB +#define MBOX0_DMA_TX_CONTROL_START_MASK WLAN_MBOX0_DMA_TX_CONTROL_START_MASK +#define MBOX0_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX0_DMA_TX_CONTROL_START_GET(x) +#define MBOX0_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX0_DMA_TX_CONTROL_START_SET(x) +#define MBOX0_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX0_DMA_TX_CONTROL_STOP_MSB +#define MBOX0_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB +#define MBOX0_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK +#define MBOX0_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX0_DMA_TX_CONTROL_STOP_GET(x) +#define MBOX0_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX0_DMA_TX_CONTROL_STOP_SET(x) +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX1_DMA_RX_CONTROL_ADDRESS WLAN_MBOX1_DMA_RX_CONTROL_ADDRESS +#define MBOX1_DMA_RX_CONTROL_OFFSET WLAN_MBOX1_DMA_RX_CONTROL_OFFSET +#define MBOX1_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MSB +#define MBOX1_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB +#define MBOX1_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK +#define MBOX1_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX1_DMA_RX_CONTROL_RESUME_GET(x) +#define MBOX1_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX1_DMA_RX_CONTROL_RESUME_SET(x) +#define MBOX1_DMA_RX_CONTROL_START_MSB WLAN_MBOX1_DMA_RX_CONTROL_START_MSB +#define MBOX1_DMA_RX_CONTROL_START_LSB WLAN_MBOX1_DMA_RX_CONTROL_START_LSB +#define MBOX1_DMA_RX_CONTROL_START_MASK WLAN_MBOX1_DMA_RX_CONTROL_START_MASK +#define MBOX1_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX1_DMA_RX_CONTROL_START_GET(x) +#define MBOX1_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX1_DMA_RX_CONTROL_START_SET(x) +#define MBOX1_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX1_DMA_RX_CONTROL_STOP_MSB +#define MBOX1_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB +#define MBOX1_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK +#define MBOX1_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX1_DMA_RX_CONTROL_STOP_GET(x) +#define MBOX1_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX1_DMA_RX_CONTROL_STOP_SET(x) +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX1_DMA_TX_CONTROL_ADDRESS WLAN_MBOX1_DMA_TX_CONTROL_ADDRESS +#define MBOX1_DMA_TX_CONTROL_OFFSET WLAN_MBOX1_DMA_TX_CONTROL_OFFSET +#define MBOX1_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MSB +#define MBOX1_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB +#define MBOX1_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK +#define MBOX1_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX1_DMA_TX_CONTROL_RESUME_GET(x) +#define MBOX1_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX1_DMA_TX_CONTROL_RESUME_SET(x) +#define MBOX1_DMA_TX_CONTROL_START_MSB WLAN_MBOX1_DMA_TX_CONTROL_START_MSB +#define MBOX1_DMA_TX_CONTROL_START_LSB WLAN_MBOX1_DMA_TX_CONTROL_START_LSB +#define MBOX1_DMA_TX_CONTROL_START_MASK WLAN_MBOX1_DMA_TX_CONTROL_START_MASK +#define MBOX1_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX1_DMA_TX_CONTROL_START_GET(x) +#define MBOX1_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX1_DMA_TX_CONTROL_START_SET(x) +#define MBOX1_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX1_DMA_TX_CONTROL_STOP_MSB +#define MBOX1_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB +#define MBOX1_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK +#define MBOX1_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX1_DMA_TX_CONTROL_STOP_GET(x) +#define MBOX1_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX1_DMA_TX_CONTROL_STOP_SET(x) +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX2_DMA_RX_CONTROL_ADDRESS WLAN_MBOX2_DMA_RX_CONTROL_ADDRESS +#define MBOX2_DMA_RX_CONTROL_OFFSET WLAN_MBOX2_DMA_RX_CONTROL_OFFSET +#define MBOX2_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MSB +#define MBOX2_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB +#define MBOX2_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK +#define MBOX2_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX2_DMA_RX_CONTROL_RESUME_GET(x) +#define MBOX2_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX2_DMA_RX_CONTROL_RESUME_SET(x) +#define MBOX2_DMA_RX_CONTROL_START_MSB WLAN_MBOX2_DMA_RX_CONTROL_START_MSB +#define MBOX2_DMA_RX_CONTROL_START_LSB WLAN_MBOX2_DMA_RX_CONTROL_START_LSB +#define MBOX2_DMA_RX_CONTROL_START_MASK WLAN_MBOX2_DMA_RX_CONTROL_START_MASK +#define MBOX2_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX2_DMA_RX_CONTROL_START_GET(x) +#define MBOX2_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX2_DMA_RX_CONTROL_START_SET(x) +#define MBOX2_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX2_DMA_RX_CONTROL_STOP_MSB +#define MBOX2_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB +#define MBOX2_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK +#define MBOX2_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX2_DMA_RX_CONTROL_STOP_GET(x) +#define MBOX2_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX2_DMA_RX_CONTROL_STOP_SET(x) +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX2_DMA_TX_CONTROL_ADDRESS WLAN_MBOX2_DMA_TX_CONTROL_ADDRESS +#define MBOX2_DMA_TX_CONTROL_OFFSET WLAN_MBOX2_DMA_TX_CONTROL_OFFSET +#define MBOX2_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MSB +#define MBOX2_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB +#define MBOX2_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK +#define MBOX2_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX2_DMA_TX_CONTROL_RESUME_GET(x) +#define MBOX2_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX2_DMA_TX_CONTROL_RESUME_SET(x) +#define MBOX2_DMA_TX_CONTROL_START_MSB WLAN_MBOX2_DMA_TX_CONTROL_START_MSB +#define MBOX2_DMA_TX_CONTROL_START_LSB WLAN_MBOX2_DMA_TX_CONTROL_START_LSB +#define MBOX2_DMA_TX_CONTROL_START_MASK WLAN_MBOX2_DMA_TX_CONTROL_START_MASK +#define MBOX2_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX2_DMA_TX_CONTROL_START_GET(x) +#define MBOX2_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX2_DMA_TX_CONTROL_START_SET(x) +#define MBOX2_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX2_DMA_TX_CONTROL_STOP_MSB +#define MBOX2_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB +#define MBOX2_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK +#define MBOX2_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX2_DMA_TX_CONTROL_STOP_GET(x) +#define MBOX2_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX2_DMA_TX_CONTROL_STOP_SET(x) +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX3_DMA_RX_CONTROL_ADDRESS WLAN_MBOX3_DMA_RX_CONTROL_ADDRESS +#define MBOX3_DMA_RX_CONTROL_OFFSET WLAN_MBOX3_DMA_RX_CONTROL_OFFSET +#define MBOX3_DMA_RX_CONTROL_RESUME_MSB WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MSB +#define MBOX3_DMA_RX_CONTROL_RESUME_LSB WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB +#define MBOX3_DMA_RX_CONTROL_RESUME_MASK WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK +#define MBOX3_DMA_RX_CONTROL_RESUME_GET(x) WLAN_MBOX3_DMA_RX_CONTROL_RESUME_GET(x) +#define MBOX3_DMA_RX_CONTROL_RESUME_SET(x) WLAN_MBOX3_DMA_RX_CONTROL_RESUME_SET(x) +#define MBOX3_DMA_RX_CONTROL_START_MSB WLAN_MBOX3_DMA_RX_CONTROL_START_MSB +#define MBOX3_DMA_RX_CONTROL_START_LSB WLAN_MBOX3_DMA_RX_CONTROL_START_LSB +#define MBOX3_DMA_RX_CONTROL_START_MASK WLAN_MBOX3_DMA_RX_CONTROL_START_MASK +#define MBOX3_DMA_RX_CONTROL_START_GET(x) WLAN_MBOX3_DMA_RX_CONTROL_START_GET(x) +#define MBOX3_DMA_RX_CONTROL_START_SET(x) WLAN_MBOX3_DMA_RX_CONTROL_START_SET(x) +#define MBOX3_DMA_RX_CONTROL_STOP_MSB WLAN_MBOX3_DMA_RX_CONTROL_STOP_MSB +#define MBOX3_DMA_RX_CONTROL_STOP_LSB WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB +#define MBOX3_DMA_RX_CONTROL_STOP_MASK WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK +#define MBOX3_DMA_RX_CONTROL_STOP_GET(x) WLAN_MBOX3_DMA_RX_CONTROL_STOP_GET(x) +#define MBOX3_DMA_RX_CONTROL_STOP_SET(x) WLAN_MBOX3_DMA_RX_CONTROL_STOP_SET(x) +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define MBOX3_DMA_TX_CONTROL_ADDRESS WLAN_MBOX3_DMA_TX_CONTROL_ADDRESS +#define MBOX3_DMA_TX_CONTROL_OFFSET WLAN_MBOX3_DMA_TX_CONTROL_OFFSET +#define MBOX3_DMA_TX_CONTROL_RESUME_MSB WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MSB +#define MBOX3_DMA_TX_CONTROL_RESUME_LSB WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB +#define MBOX3_DMA_TX_CONTROL_RESUME_MASK WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK +#define MBOX3_DMA_TX_CONTROL_RESUME_GET(x) WLAN_MBOX3_DMA_TX_CONTROL_RESUME_GET(x) +#define MBOX3_DMA_TX_CONTROL_RESUME_SET(x) WLAN_MBOX3_DMA_TX_CONTROL_RESUME_SET(x) +#define MBOX3_DMA_TX_CONTROL_START_MSB WLAN_MBOX3_DMA_TX_CONTROL_START_MSB +#define MBOX3_DMA_TX_CONTROL_START_LSB WLAN_MBOX3_DMA_TX_CONTROL_START_LSB +#define MBOX3_DMA_TX_CONTROL_START_MASK WLAN_MBOX3_DMA_TX_CONTROL_START_MASK +#define MBOX3_DMA_TX_CONTROL_START_GET(x) WLAN_MBOX3_DMA_TX_CONTROL_START_GET(x) +#define MBOX3_DMA_TX_CONTROL_START_SET(x) WLAN_MBOX3_DMA_TX_CONTROL_START_SET(x) +#define MBOX3_DMA_TX_CONTROL_STOP_MSB WLAN_MBOX3_DMA_TX_CONTROL_STOP_MSB +#define MBOX3_DMA_TX_CONTROL_STOP_LSB WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB +#define MBOX3_DMA_TX_CONTROL_STOP_MASK WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK +#define MBOX3_DMA_TX_CONTROL_STOP_GET(x) WLAN_MBOX3_DMA_TX_CONTROL_STOP_GET(x) +#define MBOX3_DMA_TX_CONTROL_STOP_SET(x) WLAN_MBOX3_DMA_TX_CONTROL_STOP_SET(x) +#define MBOX_INT_STATUS_ADDRESS WLAN_MBOX_INT_STATUS_ADDRESS +#define MBOX_INT_STATUS_OFFSET WLAN_MBOX_INT_STATUS_OFFSET +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_MSB WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MSB +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) +#define MBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) +#define MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_MSB WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MSB +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) +#define MBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) +#define MBOX_INT_STATUS_TX_OVERFLOW_MSB WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MSB +#define MBOX_INT_STATUS_TX_OVERFLOW_LSB WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB +#define MBOX_INT_STATUS_TX_OVERFLOW_MASK WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK +#define MBOX_INT_STATUS_TX_OVERFLOW_GET(x) WLAN_MBOX_INT_STATUS_TX_OVERFLOW_GET(x) +#define MBOX_INT_STATUS_TX_OVERFLOW_SET(x) WLAN_MBOX_INT_STATUS_TX_OVERFLOW_SET(x) +#define MBOX_INT_STATUS_RX_UNDERFLOW_MSB WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MSB +#define MBOX_INT_STATUS_RX_UNDERFLOW_LSB WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB +#define MBOX_INT_STATUS_RX_UNDERFLOW_MASK WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK +#define MBOX_INT_STATUS_RX_UNDERFLOW_GET(x) WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_GET(x) +#define MBOX_INT_STATUS_RX_UNDERFLOW_SET(x) WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_SET(x) +#define MBOX_INT_STATUS_TX_NOT_EMPTY_MSB WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MSB +#define MBOX_INT_STATUS_TX_NOT_EMPTY_LSB WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB +#define MBOX_INT_STATUS_TX_NOT_EMPTY_MASK WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK +#define MBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) +#define MBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) +#define MBOX_INT_STATUS_RX_NOT_FULL_MSB WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MSB +#define MBOX_INT_STATUS_RX_NOT_FULL_LSB WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB +#define MBOX_INT_STATUS_RX_NOT_FULL_MASK WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK +#define MBOX_INT_STATUS_RX_NOT_FULL_GET(x) WLAN_MBOX_INT_STATUS_RX_NOT_FULL_GET(x) +#define MBOX_INT_STATUS_RX_NOT_FULL_SET(x) WLAN_MBOX_INT_STATUS_RX_NOT_FULL_SET(x) +#define MBOX_INT_STATUS_HOST_MSB WLAN_MBOX_INT_STATUS_HOST_MSB +#define MBOX_INT_STATUS_HOST_LSB WLAN_MBOX_INT_STATUS_HOST_LSB +#define MBOX_INT_STATUS_HOST_MASK WLAN_MBOX_INT_STATUS_HOST_MASK +#define MBOX_INT_STATUS_HOST_GET(x) WLAN_MBOX_INT_STATUS_HOST_GET(x) +#define MBOX_INT_STATUS_HOST_SET(x) WLAN_MBOX_INT_STATUS_HOST_SET(x) +#define MBOX_INT_ENABLE_ADDRESS WLAN_MBOX_INT_ENABLE_ADDRESS +#define MBOX_INT_ENABLE_OFFSET WLAN_MBOX_INT_ENABLE_OFFSET +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) +#define MBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) +#define MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) +#define MBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) +#define MBOX_INT_ENABLE_TX_OVERFLOW_MSB WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MSB +#define MBOX_INT_ENABLE_TX_OVERFLOW_LSB WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB +#define MBOX_INT_ENABLE_TX_OVERFLOW_MASK WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK +#define MBOX_INT_ENABLE_TX_OVERFLOW_GET(x) WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_GET(x) +#define MBOX_INT_ENABLE_TX_OVERFLOW_SET(x) WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_SET(x) +#define MBOX_INT_ENABLE_RX_UNDERFLOW_MSB WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MSB +#define MBOX_INT_ENABLE_RX_UNDERFLOW_LSB WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB +#define MBOX_INT_ENABLE_RX_UNDERFLOW_MASK WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK +#define MBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) +#define MBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_MSB WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MSB +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) +#define MBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) +#define MBOX_INT_ENABLE_RX_NOT_FULL_MSB WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MSB +#define MBOX_INT_ENABLE_RX_NOT_FULL_LSB WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB +#define MBOX_INT_ENABLE_RX_NOT_FULL_MASK WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK +#define MBOX_INT_ENABLE_RX_NOT_FULL_GET(x) WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_GET(x) +#define MBOX_INT_ENABLE_RX_NOT_FULL_SET(x) WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_SET(x) +#define MBOX_INT_ENABLE_HOST_MSB WLAN_MBOX_INT_ENABLE_HOST_MSB +#define MBOX_INT_ENABLE_HOST_LSB WLAN_MBOX_INT_ENABLE_HOST_LSB +#define MBOX_INT_ENABLE_HOST_MASK WLAN_MBOX_INT_ENABLE_HOST_MASK +#define MBOX_INT_ENABLE_HOST_GET(x) WLAN_MBOX_INT_ENABLE_HOST_GET(x) +#define MBOX_INT_ENABLE_HOST_SET(x) WLAN_MBOX_INT_ENABLE_HOST_SET(x) +#define INT_HOST_ADDRESS WLAN_INT_HOST_ADDRESS +#define INT_HOST_OFFSET WLAN_INT_HOST_OFFSET +#define INT_HOST_VECTOR_MSB WLAN_INT_HOST_VECTOR_MSB +#define INT_HOST_VECTOR_LSB WLAN_INT_HOST_VECTOR_LSB +#define INT_HOST_VECTOR_MASK WLAN_INT_HOST_VECTOR_MASK +#define INT_HOST_VECTOR_GET(x) WLAN_INT_HOST_VECTOR_GET(x) +#define INT_HOST_VECTOR_SET(x) WLAN_INT_HOST_VECTOR_SET(x) +#define LOCAL_COUNT_ADDRESS WLAN_LOCAL_COUNT_ADDRESS +#define LOCAL_COUNT_OFFSET WLAN_LOCAL_COUNT_OFFSET +#define LOCAL_COUNT_VALUE_MSB WLAN_LOCAL_COUNT_VALUE_MSB +#define LOCAL_COUNT_VALUE_LSB WLAN_LOCAL_COUNT_VALUE_LSB +#define LOCAL_COUNT_VALUE_MASK WLAN_LOCAL_COUNT_VALUE_MASK +#define LOCAL_COUNT_VALUE_GET(x) WLAN_LOCAL_COUNT_VALUE_GET(x) +#define LOCAL_COUNT_VALUE_SET(x) WLAN_LOCAL_COUNT_VALUE_SET(x) +#define COUNT_INC_ADDRESS WLAN_COUNT_INC_ADDRESS +#define COUNT_INC_OFFSET WLAN_COUNT_INC_OFFSET +#define COUNT_INC_VALUE_MSB WLAN_COUNT_INC_VALUE_MSB +#define COUNT_INC_VALUE_LSB WLAN_COUNT_INC_VALUE_LSB +#define COUNT_INC_VALUE_MASK WLAN_COUNT_INC_VALUE_MASK +#define COUNT_INC_VALUE_GET(x) WLAN_COUNT_INC_VALUE_GET(x) +#define COUNT_INC_VALUE_SET(x) WLAN_COUNT_INC_VALUE_SET(x) +#define LOCAL_SCRATCH_ADDRESS WLAN_LOCAL_SCRATCH_ADDRESS +#define LOCAL_SCRATCH_OFFSET WLAN_LOCAL_SCRATCH_OFFSET +#define LOCAL_SCRATCH_VALUE_MSB WLAN_LOCAL_SCRATCH_VALUE_MSB +#define LOCAL_SCRATCH_VALUE_LSB WLAN_LOCAL_SCRATCH_VALUE_LSB +#define LOCAL_SCRATCH_VALUE_MASK WLAN_LOCAL_SCRATCH_VALUE_MASK +#define LOCAL_SCRATCH_VALUE_GET(x) WLAN_LOCAL_SCRATCH_VALUE_GET(x) +#define LOCAL_SCRATCH_VALUE_SET(x) WLAN_LOCAL_SCRATCH_VALUE_SET(x) +#define USE_LOCAL_BUS_ADDRESS WLAN_USE_LOCAL_BUS_ADDRESS +#define USE_LOCAL_BUS_OFFSET WLAN_USE_LOCAL_BUS_OFFSET +#define USE_LOCAL_BUS_PIN_INIT_MSB WLAN_USE_LOCAL_BUS_PIN_INIT_MSB +#define USE_LOCAL_BUS_PIN_INIT_LSB WLAN_USE_LOCAL_BUS_PIN_INIT_LSB +#define USE_LOCAL_BUS_PIN_INIT_MASK WLAN_USE_LOCAL_BUS_PIN_INIT_MASK +#define USE_LOCAL_BUS_PIN_INIT_GET(x) WLAN_USE_LOCAL_BUS_PIN_INIT_GET(x) +#define USE_LOCAL_BUS_PIN_INIT_SET(x) WLAN_USE_LOCAL_BUS_PIN_INIT_SET(x) +#define SDIO_CONFIG_ADDRESS WLAN_SDIO_CONFIG_ADDRESS +#define SDIO_CONFIG_OFFSET WLAN_SDIO_CONFIG_OFFSET +#define SDIO_CONFIG_CCCR_IOR1_MSB WLAN_SDIO_CONFIG_CCCR_IOR1_MSB +#define SDIO_CONFIG_CCCR_IOR1_LSB WLAN_SDIO_CONFIG_CCCR_IOR1_LSB +#define SDIO_CONFIG_CCCR_IOR1_MASK WLAN_SDIO_CONFIG_CCCR_IOR1_MASK +#define SDIO_CONFIG_CCCR_IOR1_GET(x) WLAN_SDIO_CONFIG_CCCR_IOR1_GET(x) +#define SDIO_CONFIG_CCCR_IOR1_SET(x) WLAN_SDIO_CONFIG_CCCR_IOR1_SET(x) +#define MBOX_DEBUG_ADDRESS WLAN_MBOX_DEBUG_ADDRESS +#define MBOX_DEBUG_OFFSET WLAN_MBOX_DEBUG_OFFSET +#define MBOX_DEBUG_SEL_MSB WLAN_MBOX_DEBUG_SEL_MSB +#define MBOX_DEBUG_SEL_LSB WLAN_MBOX_DEBUG_SEL_LSB +#define MBOX_DEBUG_SEL_MASK WLAN_MBOX_DEBUG_SEL_MASK +#define MBOX_DEBUG_SEL_GET(x) WLAN_MBOX_DEBUG_SEL_GET(x) +#define MBOX_DEBUG_SEL_SET(x) WLAN_MBOX_DEBUG_SEL_SET(x) +#define MBOX_FIFO_RESET_ADDRESS WLAN_MBOX_FIFO_RESET_ADDRESS +#define MBOX_FIFO_RESET_OFFSET WLAN_MBOX_FIFO_RESET_OFFSET +#define MBOX_FIFO_RESET_INIT_MSB WLAN_MBOX_FIFO_RESET_INIT_MSB +#define MBOX_FIFO_RESET_INIT_LSB WLAN_MBOX_FIFO_RESET_INIT_LSB +#define MBOX_FIFO_RESET_INIT_MASK WLAN_MBOX_FIFO_RESET_INIT_MASK +#define MBOX_FIFO_RESET_INIT_GET(x) WLAN_MBOX_FIFO_RESET_INIT_GET(x) +#define MBOX_FIFO_RESET_INIT_SET(x) WLAN_MBOX_FIFO_RESET_INIT_SET(x) +#define MBOX_TXFIFO_POP_ADDRESS WLAN_MBOX_TXFIFO_POP_ADDRESS +#define MBOX_TXFIFO_POP_OFFSET WLAN_MBOX_TXFIFO_POP_OFFSET +#define MBOX_TXFIFO_POP_DATA_MSB WLAN_MBOX_TXFIFO_POP_DATA_MSB +#define MBOX_TXFIFO_POP_DATA_LSB WLAN_MBOX_TXFIFO_POP_DATA_LSB +#define MBOX_TXFIFO_POP_DATA_MASK WLAN_MBOX_TXFIFO_POP_DATA_MASK +#define MBOX_TXFIFO_POP_DATA_GET(x) WLAN_MBOX_TXFIFO_POP_DATA_GET(x) +#define MBOX_TXFIFO_POP_DATA_SET(x) WLAN_MBOX_TXFIFO_POP_DATA_SET(x) +#define MBOX_RXFIFO_POP_ADDRESS WLAN_MBOX_RXFIFO_POP_ADDRESS +#define MBOX_RXFIFO_POP_OFFSET WLAN_MBOX_RXFIFO_POP_OFFSET +#define MBOX_RXFIFO_POP_DATA_MSB WLAN_MBOX_RXFIFO_POP_DATA_MSB +#define MBOX_RXFIFO_POP_DATA_LSB WLAN_MBOX_RXFIFO_POP_DATA_LSB +#define MBOX_RXFIFO_POP_DATA_MASK WLAN_MBOX_RXFIFO_POP_DATA_MASK +#define MBOX_RXFIFO_POP_DATA_GET(x) WLAN_MBOX_RXFIFO_POP_DATA_GET(x) +#define MBOX_RXFIFO_POP_DATA_SET(x) WLAN_MBOX_RXFIFO_POP_DATA_SET(x) +#define SDIO_DEBUG_ADDRESS WLAN_SDIO_DEBUG_ADDRESS +#define SDIO_DEBUG_OFFSET WLAN_SDIO_DEBUG_OFFSET +#define SDIO_DEBUG_SEL_MSB WLAN_SDIO_DEBUG_SEL_MSB +#define SDIO_DEBUG_SEL_LSB WLAN_SDIO_DEBUG_SEL_LSB +#define SDIO_DEBUG_SEL_MASK WLAN_SDIO_DEBUG_SEL_MASK +#define SDIO_DEBUG_SEL_GET(x) WLAN_SDIO_DEBUG_SEL_GET(x) +#define SDIO_DEBUG_SEL_SET(x) WLAN_SDIO_DEBUG_SEL_SET(x) +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define GMBOX0_DMA_RX_CONTROL_ADDRESS WLAN_GMBOX0_DMA_RX_CONTROL_ADDRESS +#define GMBOX0_DMA_RX_CONTROL_OFFSET WLAN_GMBOX0_DMA_RX_CONTROL_OFFSET +#define GMBOX0_DMA_RX_CONTROL_RESUME_MSB WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MSB +#define GMBOX0_DMA_RX_CONTROL_RESUME_LSB WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB +#define GMBOX0_DMA_RX_CONTROL_RESUME_MASK WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK +#define GMBOX0_DMA_RX_CONTROL_RESUME_GET(x) WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_GET(x) +#define GMBOX0_DMA_RX_CONTROL_RESUME_SET(x) WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_SET(x) +#define GMBOX0_DMA_RX_CONTROL_START_MSB WLAN_GMBOX0_DMA_RX_CONTROL_START_MSB +#define GMBOX0_DMA_RX_CONTROL_START_LSB WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB +#define GMBOX0_DMA_RX_CONTROL_START_MASK WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK +#define GMBOX0_DMA_RX_CONTROL_START_GET(x) WLAN_GMBOX0_DMA_RX_CONTROL_START_GET(x) +#define GMBOX0_DMA_RX_CONTROL_START_SET(x) WLAN_GMBOX0_DMA_RX_CONTROL_START_SET(x) +#define GMBOX0_DMA_RX_CONTROL_STOP_MSB WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MSB +#define GMBOX0_DMA_RX_CONTROL_STOP_LSB WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB +#define GMBOX0_DMA_RX_CONTROL_STOP_MASK WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK +#define GMBOX0_DMA_RX_CONTROL_STOP_GET(x) WLAN_GMBOX0_DMA_RX_CONTROL_STOP_GET(x) +#define GMBOX0_DMA_RX_CONTROL_STOP_SET(x) WLAN_GMBOX0_DMA_RX_CONTROL_STOP_SET(x) +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) +#define GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) +#define GMBOX0_DMA_TX_CONTROL_ADDRESS WLAN_GMBOX0_DMA_TX_CONTROL_ADDRESS +#define GMBOX0_DMA_TX_CONTROL_OFFSET WLAN_GMBOX0_DMA_TX_CONTROL_OFFSET +#define GMBOX0_DMA_TX_CONTROL_RESUME_MSB WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MSB +#define GMBOX0_DMA_TX_CONTROL_RESUME_LSB WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB +#define GMBOX0_DMA_TX_CONTROL_RESUME_MASK WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK +#define GMBOX0_DMA_TX_CONTROL_RESUME_GET(x) WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_GET(x) +#define GMBOX0_DMA_TX_CONTROL_RESUME_SET(x) WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_SET(x) +#define GMBOX0_DMA_TX_CONTROL_START_MSB WLAN_GMBOX0_DMA_TX_CONTROL_START_MSB +#define GMBOX0_DMA_TX_CONTROL_START_LSB WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB +#define GMBOX0_DMA_TX_CONTROL_START_MASK WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK +#define GMBOX0_DMA_TX_CONTROL_START_GET(x) WLAN_GMBOX0_DMA_TX_CONTROL_START_GET(x) +#define GMBOX0_DMA_TX_CONTROL_START_SET(x) WLAN_GMBOX0_DMA_TX_CONTROL_START_SET(x) +#define GMBOX0_DMA_TX_CONTROL_STOP_MSB WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MSB +#define GMBOX0_DMA_TX_CONTROL_STOP_LSB WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB +#define GMBOX0_DMA_TX_CONTROL_STOP_MASK WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK +#define GMBOX0_DMA_TX_CONTROL_STOP_GET(x) WLAN_GMBOX0_DMA_TX_CONTROL_STOP_GET(x) +#define GMBOX0_DMA_TX_CONTROL_STOP_SET(x) WLAN_GMBOX0_DMA_TX_CONTROL_STOP_SET(x) +#define GMBOX_INT_STATUS_ADDRESS WLAN_GMBOX_INT_STATUS_ADDRESS +#define GMBOX_INT_STATUS_OFFSET WLAN_GMBOX_INT_STATUS_OFFSET +#define GMBOX_INT_STATUS_TX_OVERFLOW_MSB WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MSB +#define GMBOX_INT_STATUS_TX_OVERFLOW_LSB WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB +#define GMBOX_INT_STATUS_TX_OVERFLOW_MASK WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK +#define GMBOX_INT_STATUS_TX_OVERFLOW_GET(x) WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_GET(x) +#define GMBOX_INT_STATUS_TX_OVERFLOW_SET(x) WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_SET(x) +#define GMBOX_INT_STATUS_RX_UNDERFLOW_MSB WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MSB +#define GMBOX_INT_STATUS_RX_UNDERFLOW_LSB WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB +#define GMBOX_INT_STATUS_RX_UNDERFLOW_MASK WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK +#define GMBOX_INT_STATUS_RX_UNDERFLOW_GET(x) WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_GET(x) +#define GMBOX_INT_STATUS_RX_UNDERFLOW_SET(x) WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_SET(x) +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MSB +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) +#define GMBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) +#define GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MSB +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) +#define GMBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_MSB WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MSB +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) +#define GMBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) +#define GMBOX_INT_STATUS_RX_NOT_FULL_MSB WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MSB +#define GMBOX_INT_STATUS_RX_NOT_FULL_LSB WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB +#define GMBOX_INT_STATUS_RX_NOT_FULL_MASK WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK +#define GMBOX_INT_STATUS_RX_NOT_FULL_GET(x) WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_GET(x) +#define GMBOX_INT_STATUS_RX_NOT_FULL_SET(x) WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_SET(x) +#define GMBOX_INT_ENABLE_ADDRESS WLAN_GMBOX_INT_ENABLE_ADDRESS +#define GMBOX_INT_ENABLE_OFFSET WLAN_GMBOX_INT_ENABLE_OFFSET +#define GMBOX_INT_ENABLE_TX_OVERFLOW_MSB WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MSB +#define GMBOX_INT_ENABLE_TX_OVERFLOW_LSB WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB +#define GMBOX_INT_ENABLE_TX_OVERFLOW_MASK WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK +#define GMBOX_INT_ENABLE_TX_OVERFLOW_GET(x) WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_GET(x) +#define GMBOX_INT_ENABLE_TX_OVERFLOW_SET(x) WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_SET(x) +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_MSB WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MSB +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) +#define GMBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) +#define GMBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) +#define GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) +#define GMBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_MSB WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MSB +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) +#define GMBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) +#define GMBOX_INT_ENABLE_RX_NOT_FULL_MSB WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MSB +#define GMBOX_INT_ENABLE_RX_NOT_FULL_LSB WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB +#define GMBOX_INT_ENABLE_RX_NOT_FULL_MASK WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK +#define GMBOX_INT_ENABLE_RX_NOT_FULL_GET(x) WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_GET(x) +#define GMBOX_INT_ENABLE_RX_NOT_FULL_SET(x) WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_SET(x) +#define HOST_IF_WINDOW_ADDRESS WLAN_HOST_IF_WINDOW_ADDRESS +#define HOST_IF_WINDOW_OFFSET WLAN_HOST_IF_WINDOW_OFFSET +#define HOST_IF_WINDOW_DATA_MSB WLAN_HOST_IF_WINDOW_DATA_MSB +#define HOST_IF_WINDOW_DATA_LSB WLAN_HOST_IF_WINDOW_DATA_LSB +#define HOST_IF_WINDOW_DATA_MASK WLAN_HOST_IF_WINDOW_DATA_MASK +#define HOST_IF_WINDOW_DATA_GET(x) WLAN_HOST_IF_WINDOW_DATA_GET(x) +#define HOST_IF_WINDOW_DATA_SET(x) WLAN_HOST_IF_WINDOW_DATA_SET(x) + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h new file mode 100644 index 000000000000..038d0d019273 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h @@ -0,0 +1,471 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _MBOX_WLAN_HOST_REG_REG_H_ +#define _MBOX_WLAN_HOST_REG_REG_H_ + +#define HOST_INT_STATUS_ADDRESS 0x00000400 +#define HOST_INT_STATUS_OFFSET 0x00000400 +#define HOST_INT_STATUS_ERROR_MSB 7 +#define HOST_INT_STATUS_ERROR_LSB 7 +#define HOST_INT_STATUS_ERROR_MASK 0x00000080 +#define HOST_INT_STATUS_ERROR_GET(x) (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_ERROR_SET(x) (((x) << HOST_INT_STATUS_ERROR_LSB) & HOST_INT_STATUS_ERROR_MASK) +#define HOST_INT_STATUS_CPU_MSB 6 +#define HOST_INT_STATUS_CPU_LSB 6 +#define HOST_INT_STATUS_CPU_MASK 0x00000040 +#define HOST_INT_STATUS_CPU_GET(x) (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_CPU_SET(x) (((x) << HOST_INT_STATUS_CPU_LSB) & HOST_INT_STATUS_CPU_MASK) +#define HOST_INT_STATUS_INT_MSB 5 +#define HOST_INT_STATUS_INT_LSB 5 +#define HOST_INT_STATUS_INT_MASK 0x00000020 +#define HOST_INT_STATUS_INT_GET(x) (((x) & HOST_INT_STATUS_INT_MASK) >> HOST_INT_STATUS_INT_LSB) +#define HOST_INT_STATUS_INT_SET(x) (((x) << HOST_INT_STATUS_INT_LSB) & HOST_INT_STATUS_INT_MASK) +#define HOST_INT_STATUS_COUNTER_MSB 4 +#define HOST_INT_STATUS_COUNTER_LSB 4 +#define HOST_INT_STATUS_COUNTER_MASK 0x00000010 +#define HOST_INT_STATUS_COUNTER_GET(x) (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB) +#define HOST_INT_STATUS_COUNTER_SET(x) (((x) << HOST_INT_STATUS_COUNTER_LSB) & HOST_INT_STATUS_COUNTER_MASK) +#define HOST_INT_STATUS_MBOX_DATA_MSB 3 +#define HOST_INT_STATUS_MBOX_DATA_LSB 0 +#define HOST_INT_STATUS_MBOX_DATA_MASK 0x0000000f +#define HOST_INT_STATUS_MBOX_DATA_GET(x) (((x) & HOST_INT_STATUS_MBOX_DATA_MASK) >> HOST_INT_STATUS_MBOX_DATA_LSB) +#define HOST_INT_STATUS_MBOX_DATA_SET(x) (((x) << HOST_INT_STATUS_MBOX_DATA_LSB) & HOST_INT_STATUS_MBOX_DATA_MASK) + +#define CPU_INT_STATUS_ADDRESS 0x00000401 +#define CPU_INT_STATUS_OFFSET 0x00000401 +#define CPU_INT_STATUS_BIT_MSB 7 +#define CPU_INT_STATUS_BIT_LSB 0 +#define CPU_INT_STATUS_BIT_MASK 0x000000ff +#define CPU_INT_STATUS_BIT_GET(x) (((x) & CPU_INT_STATUS_BIT_MASK) >> CPU_INT_STATUS_BIT_LSB) +#define CPU_INT_STATUS_BIT_SET(x) (((x) << CPU_INT_STATUS_BIT_LSB) & CPU_INT_STATUS_BIT_MASK) + +#define ERROR_INT_STATUS_ADDRESS 0x00000402 +#define ERROR_INT_STATUS_OFFSET 0x00000402 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MSB 6 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_LSB 6 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MASK 0x00000040 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_GET(x) (((x) & ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MASK) >> ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_LSB) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_SET(x) (((x) << ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_LSB) & ERROR_INT_STATUS_UART_HCI_FRAMER_SYNC_ERROR_MASK) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MSB 5 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_LSB 5 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MASK 0x00000020 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MASK) >> ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_LSB) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_SET(x) (((x) << ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_LSB) & ERROR_INT_STATUS_UART_HCI_FRAMER_OVERFLOW_MASK) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MSB 4 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_LSB 4 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MASK 0x00000010 +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MASK) >> ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_SET(x) (((x) << ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_LSB) & ERROR_INT_STATUS_UART_HCI_FRAMER_UNDERFLOW_MASK) +#define ERROR_INT_STATUS_SPI_MSB 3 +#define ERROR_INT_STATUS_SPI_LSB 3 +#define ERROR_INT_STATUS_SPI_MASK 0x00000008 +#define ERROR_INT_STATUS_SPI_GET(x) (((x) & ERROR_INT_STATUS_SPI_MASK) >> ERROR_INT_STATUS_SPI_LSB) +#define ERROR_INT_STATUS_SPI_SET(x) (((x) << ERROR_INT_STATUS_SPI_LSB) & ERROR_INT_STATUS_SPI_MASK) +#define ERROR_INT_STATUS_WAKEUP_MSB 2 +#define ERROR_INT_STATUS_WAKEUP_LSB 2 +#define ERROR_INT_STATUS_WAKEUP_MASK 0x00000004 +#define ERROR_INT_STATUS_WAKEUP_GET(x) (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_WAKEUP_SET(x) (((x) << ERROR_INT_STATUS_WAKEUP_LSB) & ERROR_INT_STATUS_WAKEUP_MASK) +#define ERROR_INT_STATUS_RX_UNDERFLOW_MSB 1 +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB 1 +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00000002 +#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << ERROR_INT_STATUS_RX_UNDERFLOW_LSB) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) +#define ERROR_INT_STATUS_TX_OVERFLOW_MSB 0 +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB 0 +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00000001 +#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << ERROR_INT_STATUS_TX_OVERFLOW_LSB) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) + +#define COUNTER_INT_STATUS_ADDRESS 0x00000403 +#define COUNTER_INT_STATUS_OFFSET 0x00000403 +#define COUNTER_INT_STATUS_COUNTER_MSB 7 +#define COUNTER_INT_STATUS_COUNTER_LSB 0 +#define COUNTER_INT_STATUS_COUNTER_MASK 0x000000ff +#define COUNTER_INT_STATUS_COUNTER_GET(x) (((x) & COUNTER_INT_STATUS_COUNTER_MASK) >> COUNTER_INT_STATUS_COUNTER_LSB) +#define COUNTER_INT_STATUS_COUNTER_SET(x) (((x) << COUNTER_INT_STATUS_COUNTER_LSB) & COUNTER_INT_STATUS_COUNTER_MASK) + +#define MBOX_FRAME_ADDRESS 0x00000404 +#define MBOX_FRAME_OFFSET 0x00000404 +#define MBOX_FRAME_RX_EOM_MSB 7 +#define MBOX_FRAME_RX_EOM_LSB 4 +#define MBOX_FRAME_RX_EOM_MASK 0x000000f0 +#define MBOX_FRAME_RX_EOM_GET(x) (((x) & MBOX_FRAME_RX_EOM_MASK) >> MBOX_FRAME_RX_EOM_LSB) +#define MBOX_FRAME_RX_EOM_SET(x) (((x) << MBOX_FRAME_RX_EOM_LSB) & MBOX_FRAME_RX_EOM_MASK) +#define MBOX_FRAME_RX_SOM_MSB 3 +#define MBOX_FRAME_RX_SOM_LSB 0 +#define MBOX_FRAME_RX_SOM_MASK 0x0000000f +#define MBOX_FRAME_RX_SOM_GET(x) (((x) & MBOX_FRAME_RX_SOM_MASK) >> MBOX_FRAME_RX_SOM_LSB) +#define MBOX_FRAME_RX_SOM_SET(x) (((x) << MBOX_FRAME_RX_SOM_LSB) & MBOX_FRAME_RX_SOM_MASK) + +#define RX_LOOKAHEAD_VALID_ADDRESS 0x00000405 +#define RX_LOOKAHEAD_VALID_OFFSET 0x00000405 +#define RX_LOOKAHEAD_VALID_MBOX_MSB 3 +#define RX_LOOKAHEAD_VALID_MBOX_LSB 0 +#define RX_LOOKAHEAD_VALID_MBOX_MASK 0x0000000f +#define RX_LOOKAHEAD_VALID_MBOX_GET(x) (((x) & RX_LOOKAHEAD_VALID_MBOX_MASK) >> RX_LOOKAHEAD_VALID_MBOX_LSB) +#define RX_LOOKAHEAD_VALID_MBOX_SET(x) (((x) << RX_LOOKAHEAD_VALID_MBOX_LSB) & RX_LOOKAHEAD_VALID_MBOX_MASK) + +#define HOST_INT_STATUS2_ADDRESS 0x00000406 +#define HOST_INT_STATUS2_OFFSET 0x00000406 +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MSB 2 +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_LSB 2 +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MASK 0x00000004 +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_GET(x) (((x) & HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MASK) >> HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_LSB) +#define HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_SET(x) (((x) << HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_LSB) & HOST_INT_STATUS2_GMBOX_RX_UNDERFLOW_MASK) +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MSB 1 +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_LSB 1 +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MASK 0x00000002 +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_GET(x) (((x) & HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MASK) >> HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_LSB) +#define HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_SET(x) (((x) << HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_LSB) & HOST_INT_STATUS2_GMBOX_TX_OVERFLOW_MASK) +#define HOST_INT_STATUS2_GMBOX_DATA_MSB 0 +#define HOST_INT_STATUS2_GMBOX_DATA_LSB 0 +#define HOST_INT_STATUS2_GMBOX_DATA_MASK 0x00000001 +#define HOST_INT_STATUS2_GMBOX_DATA_GET(x) (((x) & HOST_INT_STATUS2_GMBOX_DATA_MASK) >> HOST_INT_STATUS2_GMBOX_DATA_LSB) +#define HOST_INT_STATUS2_GMBOX_DATA_SET(x) (((x) << HOST_INT_STATUS2_GMBOX_DATA_LSB) & HOST_INT_STATUS2_GMBOX_DATA_MASK) + +#define GMBOX_RX_AVAIL_ADDRESS 0x00000407 +#define GMBOX_RX_AVAIL_OFFSET 0x00000407 +#define GMBOX_RX_AVAIL_BYTE_MSB 6 +#define GMBOX_RX_AVAIL_BYTE_LSB 0 +#define GMBOX_RX_AVAIL_BYTE_MASK 0x0000007f +#define GMBOX_RX_AVAIL_BYTE_GET(x) (((x) & GMBOX_RX_AVAIL_BYTE_MASK) >> GMBOX_RX_AVAIL_BYTE_LSB) +#define GMBOX_RX_AVAIL_BYTE_SET(x) (((x) << GMBOX_RX_AVAIL_BYTE_LSB) & GMBOX_RX_AVAIL_BYTE_MASK) + +#define RX_LOOKAHEAD0_ADDRESS 0x00000408 +#define RX_LOOKAHEAD0_OFFSET 0x00000408 +#define RX_LOOKAHEAD0_DATA_MSB 7 +#define RX_LOOKAHEAD0_DATA_LSB 0 +#define RX_LOOKAHEAD0_DATA_MASK 0x000000ff +#define RX_LOOKAHEAD0_DATA_GET(x) (((x) & RX_LOOKAHEAD0_DATA_MASK) >> RX_LOOKAHEAD0_DATA_LSB) +#define RX_LOOKAHEAD0_DATA_SET(x) (((x) << RX_LOOKAHEAD0_DATA_LSB) & RX_LOOKAHEAD0_DATA_MASK) + +#define RX_LOOKAHEAD1_ADDRESS 0x0000040c +#define RX_LOOKAHEAD1_OFFSET 0x0000040c +#define RX_LOOKAHEAD1_DATA_MSB 7 +#define RX_LOOKAHEAD1_DATA_LSB 0 +#define RX_LOOKAHEAD1_DATA_MASK 0x000000ff +#define RX_LOOKAHEAD1_DATA_GET(x) (((x) & RX_LOOKAHEAD1_DATA_MASK) >> RX_LOOKAHEAD1_DATA_LSB) +#define RX_LOOKAHEAD1_DATA_SET(x) (((x) << RX_LOOKAHEAD1_DATA_LSB) & RX_LOOKAHEAD1_DATA_MASK) + +#define RX_LOOKAHEAD2_ADDRESS 0x00000410 +#define RX_LOOKAHEAD2_OFFSET 0x00000410 +#define RX_LOOKAHEAD2_DATA_MSB 7 +#define RX_LOOKAHEAD2_DATA_LSB 0 +#define RX_LOOKAHEAD2_DATA_MASK 0x000000ff +#define RX_LOOKAHEAD2_DATA_GET(x) (((x) & RX_LOOKAHEAD2_DATA_MASK) >> RX_LOOKAHEAD2_DATA_LSB) +#define RX_LOOKAHEAD2_DATA_SET(x) (((x) << RX_LOOKAHEAD2_DATA_LSB) & RX_LOOKAHEAD2_DATA_MASK) + +#define RX_LOOKAHEAD3_ADDRESS 0x00000414 +#define RX_LOOKAHEAD3_OFFSET 0x00000414 +#define RX_LOOKAHEAD3_DATA_MSB 7 +#define RX_LOOKAHEAD3_DATA_LSB 0 +#define RX_LOOKAHEAD3_DATA_MASK 0x000000ff +#define RX_LOOKAHEAD3_DATA_GET(x) (((x) & RX_LOOKAHEAD3_DATA_MASK) >> RX_LOOKAHEAD3_DATA_LSB) +#define RX_LOOKAHEAD3_DATA_SET(x) (((x) << RX_LOOKAHEAD3_DATA_LSB) & RX_LOOKAHEAD3_DATA_MASK) + +#define INT_STATUS_ENABLE_ADDRESS 0x00000418 +#define INT_STATUS_ENABLE_OFFSET 0x00000418 +#define INT_STATUS_ENABLE_ERROR_MSB 7 +#define INT_STATUS_ENABLE_ERROR_LSB 7 +#define INT_STATUS_ENABLE_ERROR_MASK 0x00000080 +#define INT_STATUS_ENABLE_ERROR_GET(x) (((x) & INT_STATUS_ENABLE_ERROR_MASK) >> INT_STATUS_ENABLE_ERROR_LSB) +#define INT_STATUS_ENABLE_ERROR_SET(x) (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_MSB 6 +#define INT_STATUS_ENABLE_CPU_LSB 6 +#define INT_STATUS_ENABLE_CPU_MASK 0x00000040 +#define INT_STATUS_ENABLE_CPU_GET(x) (((x) & INT_STATUS_ENABLE_CPU_MASK) >> INT_STATUS_ENABLE_CPU_LSB) +#define INT_STATUS_ENABLE_CPU_SET(x) (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_INT_MSB 5 +#define INT_STATUS_ENABLE_INT_LSB 5 +#define INT_STATUS_ENABLE_INT_MASK 0x00000020 +#define INT_STATUS_ENABLE_INT_GET(x) (((x) & INT_STATUS_ENABLE_INT_MASK) >> INT_STATUS_ENABLE_INT_LSB) +#define INT_STATUS_ENABLE_INT_SET(x) (((x) << INT_STATUS_ENABLE_INT_LSB) & INT_STATUS_ENABLE_INT_MASK) +#define INT_STATUS_ENABLE_COUNTER_MSB 4 +#define INT_STATUS_ENABLE_COUNTER_LSB 4 +#define INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 +#define INT_STATUS_ENABLE_COUNTER_GET(x) (((x) & INT_STATUS_ENABLE_COUNTER_MASK) >> INT_STATUS_ENABLE_COUNTER_LSB) +#define INT_STATUS_ENABLE_COUNTER_SET(x) (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_MSB 3 +#define INT_STATUS_ENABLE_MBOX_DATA_LSB 0 +#define INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f +#define INT_STATUS_ENABLE_MBOX_DATA_GET(x) (((x) & INT_STATUS_ENABLE_MBOX_DATA_MASK) >> INT_STATUS_ENABLE_MBOX_DATA_LSB) +#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & INT_STATUS_ENABLE_MBOX_DATA_MASK) + +#define CPU_INT_STATUS_ENABLE_ADDRESS 0x00000419 +#define CPU_INT_STATUS_ENABLE_OFFSET 0x00000419 +#define CPU_INT_STATUS_ENABLE_BIT_MSB 7 +#define CPU_INT_STATUS_ENABLE_BIT_LSB 0 +#define CPU_INT_STATUS_ENABLE_BIT_MASK 0x000000ff +#define CPU_INT_STATUS_ENABLE_BIT_GET(x) (((x) & CPU_INT_STATUS_ENABLE_BIT_MASK) >> CPU_INT_STATUS_ENABLE_BIT_LSB) +#define CPU_INT_STATUS_ENABLE_BIT_SET(x) (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & CPU_INT_STATUS_ENABLE_BIT_MASK) + +#define ERROR_STATUS_ENABLE_ADDRESS 0x0000041a +#define ERROR_STATUS_ENABLE_OFFSET 0x0000041a +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MSB 6 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_LSB 6 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MASK 0x00000040 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_GET(x) (((x) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MASK) >> ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_LSB) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_SET(x) (((x) << ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_LSB) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_SYNC_ERROR_MASK) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MSB 5 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_LSB 5 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MASK 0x00000020 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MASK) >> ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_LSB) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_OVERFLOW_MASK) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MSB 4 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_LSB 4 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MASK 0x00000010 +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MASK) >> ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_LSB) +#define ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_UART_HCI_FRAMER_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_WAKEUP_MSB 2 +#define ERROR_STATUS_ENABLE_WAKEUP_LSB 2 +#define ERROR_STATUS_ENABLE_WAKEUP_MASK 0x00000004 +#define ERROR_STATUS_ENABLE_WAKEUP_GET(x) (((x) & ERROR_STATUS_ENABLE_WAKEUP_MASK) >> ERROR_STATUS_ENABLE_WAKEUP_LSB) +#define ERROR_STATUS_ENABLE_WAKEUP_SET(x) (((x) << ERROR_STATUS_ENABLE_WAKEUP_LSB) & ERROR_STATUS_ENABLE_WAKEUP_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MSB 1 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 1 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) >> ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MSB 0 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 0 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00000001 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) >> ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) + +#define COUNTER_INT_STATUS_ENABLE_ADDRESS 0x0000041b +#define COUNTER_INT_STATUS_ENABLE_OFFSET 0x0000041b +#define COUNTER_INT_STATUS_ENABLE_BIT_MSB 7 +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB 0 +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK 0x000000ff +#define COUNTER_INT_STATUS_ENABLE_BIT_GET(x) (((x) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) >> COUNTER_INT_STATUS_ENABLE_BIT_LSB) +#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) + +#define COUNT_ADDRESS 0x00000420 +#define COUNT_OFFSET 0x00000420 +#define COUNT_VALUE_MSB 7 +#define COUNT_VALUE_LSB 0 +#define COUNT_VALUE_MASK 0x000000ff +#define COUNT_VALUE_GET(x) (((x) & COUNT_VALUE_MASK) >> COUNT_VALUE_LSB) +#define COUNT_VALUE_SET(x) (((x) << COUNT_VALUE_LSB) & COUNT_VALUE_MASK) + +#define COUNT_DEC_ADDRESS 0x00000440 +#define COUNT_DEC_OFFSET 0x00000440 +#define COUNT_DEC_VALUE_MSB 7 +#define COUNT_DEC_VALUE_LSB 0 +#define COUNT_DEC_VALUE_MASK 0x000000ff +#define COUNT_DEC_VALUE_GET(x) (((x) & COUNT_DEC_VALUE_MASK) >> COUNT_DEC_VALUE_LSB) +#define COUNT_DEC_VALUE_SET(x) (((x) << COUNT_DEC_VALUE_LSB) & COUNT_DEC_VALUE_MASK) + +#define SCRATCH_ADDRESS 0x00000460 +#define SCRATCH_OFFSET 0x00000460 +#define SCRATCH_VALUE_MSB 7 +#define SCRATCH_VALUE_LSB 0 +#define SCRATCH_VALUE_MASK 0x000000ff +#define SCRATCH_VALUE_GET(x) (((x) & SCRATCH_VALUE_MASK) >> SCRATCH_VALUE_LSB) +#define SCRATCH_VALUE_SET(x) (((x) << SCRATCH_VALUE_LSB) & SCRATCH_VALUE_MASK) + +#define FIFO_TIMEOUT_ADDRESS 0x00000468 +#define FIFO_TIMEOUT_OFFSET 0x00000468 +#define FIFO_TIMEOUT_VALUE_MSB 7 +#define FIFO_TIMEOUT_VALUE_LSB 0 +#define FIFO_TIMEOUT_VALUE_MASK 0x000000ff +#define FIFO_TIMEOUT_VALUE_GET(x) (((x) & FIFO_TIMEOUT_VALUE_MASK) >> FIFO_TIMEOUT_VALUE_LSB) +#define FIFO_TIMEOUT_VALUE_SET(x) (((x) << FIFO_TIMEOUT_VALUE_LSB) & FIFO_TIMEOUT_VALUE_MASK) + +#define FIFO_TIMEOUT_ENABLE_ADDRESS 0x00000469 +#define FIFO_TIMEOUT_ENABLE_OFFSET 0x00000469 +#define FIFO_TIMEOUT_ENABLE_SET_MSB 0 +#define FIFO_TIMEOUT_ENABLE_SET_LSB 0 +#define FIFO_TIMEOUT_ENABLE_SET_MASK 0x00000001 +#define FIFO_TIMEOUT_ENABLE_SET_GET(x) (((x) & FIFO_TIMEOUT_ENABLE_SET_MASK) >> FIFO_TIMEOUT_ENABLE_SET_LSB) +#define FIFO_TIMEOUT_ENABLE_SET_SET(x) (((x) << FIFO_TIMEOUT_ENABLE_SET_LSB) & FIFO_TIMEOUT_ENABLE_SET_MASK) + +#define DISABLE_SLEEP_ADDRESS 0x0000046a +#define DISABLE_SLEEP_OFFSET 0x0000046a +#define DISABLE_SLEEP_FOR_INT_MSB 1 +#define DISABLE_SLEEP_FOR_INT_LSB 1 +#define DISABLE_SLEEP_FOR_INT_MASK 0x00000002 +#define DISABLE_SLEEP_FOR_INT_GET(x) (((x) & DISABLE_SLEEP_FOR_INT_MASK) >> DISABLE_SLEEP_FOR_INT_LSB) +#define DISABLE_SLEEP_FOR_INT_SET(x) (((x) << DISABLE_SLEEP_FOR_INT_LSB) & DISABLE_SLEEP_FOR_INT_MASK) +#define DISABLE_SLEEP_ON_MSB 0 +#define DISABLE_SLEEP_ON_LSB 0 +#define DISABLE_SLEEP_ON_MASK 0x00000001 +#define DISABLE_SLEEP_ON_GET(x) (((x) & DISABLE_SLEEP_ON_MASK) >> DISABLE_SLEEP_ON_LSB) +#define DISABLE_SLEEP_ON_SET(x) (((x) << DISABLE_SLEEP_ON_LSB) & DISABLE_SLEEP_ON_MASK) + +#define LOCAL_BUS_ADDRESS 0x00000470 +#define LOCAL_BUS_OFFSET 0x00000470 +#define LOCAL_BUS_STATE_MSB 1 +#define LOCAL_BUS_STATE_LSB 0 +#define LOCAL_BUS_STATE_MASK 0x00000003 +#define LOCAL_BUS_STATE_GET(x) (((x) & LOCAL_BUS_STATE_MASK) >> LOCAL_BUS_STATE_LSB) +#define LOCAL_BUS_STATE_SET(x) (((x) << LOCAL_BUS_STATE_LSB) & LOCAL_BUS_STATE_MASK) + +#define INT_WLAN_ADDRESS 0x00000472 +#define INT_WLAN_OFFSET 0x00000472 +#define INT_WLAN_VECTOR_MSB 7 +#define INT_WLAN_VECTOR_LSB 0 +#define INT_WLAN_VECTOR_MASK 0x000000ff +#define INT_WLAN_VECTOR_GET(x) (((x) & INT_WLAN_VECTOR_MASK) >> INT_WLAN_VECTOR_LSB) +#define INT_WLAN_VECTOR_SET(x) (((x) << INT_WLAN_VECTOR_LSB) & INT_WLAN_VECTOR_MASK) + +#define WINDOW_DATA_ADDRESS 0x00000474 +#define WINDOW_DATA_OFFSET 0x00000474 +#define WINDOW_DATA_DATA_MSB 7 +#define WINDOW_DATA_DATA_LSB 0 +#define WINDOW_DATA_DATA_MASK 0x000000ff +#define WINDOW_DATA_DATA_GET(x) (((x) & WINDOW_DATA_DATA_MASK) >> WINDOW_DATA_DATA_LSB) +#define WINDOW_DATA_DATA_SET(x) (((x) << WINDOW_DATA_DATA_LSB) & WINDOW_DATA_DATA_MASK) + +#define WINDOW_WRITE_ADDR_ADDRESS 0x00000478 +#define WINDOW_WRITE_ADDR_OFFSET 0x00000478 +#define WINDOW_WRITE_ADDR_ADDR_MSB 7 +#define WINDOW_WRITE_ADDR_ADDR_LSB 0 +#define WINDOW_WRITE_ADDR_ADDR_MASK 0x000000ff +#define WINDOW_WRITE_ADDR_ADDR_GET(x) (((x) & WINDOW_WRITE_ADDR_ADDR_MASK) >> WINDOW_WRITE_ADDR_ADDR_LSB) +#define WINDOW_WRITE_ADDR_ADDR_SET(x) (((x) << WINDOW_WRITE_ADDR_ADDR_LSB) & WINDOW_WRITE_ADDR_ADDR_MASK) + +#define WINDOW_READ_ADDR_ADDRESS 0x0000047c +#define WINDOW_READ_ADDR_OFFSET 0x0000047c +#define WINDOW_READ_ADDR_ADDR_MSB 7 +#define WINDOW_READ_ADDR_ADDR_LSB 0 +#define WINDOW_READ_ADDR_ADDR_MASK 0x000000ff +#define WINDOW_READ_ADDR_ADDR_GET(x) (((x) & WINDOW_READ_ADDR_ADDR_MASK) >> WINDOW_READ_ADDR_ADDR_LSB) +#define WINDOW_READ_ADDR_ADDR_SET(x) (((x) << WINDOW_READ_ADDR_ADDR_LSB) & WINDOW_READ_ADDR_ADDR_MASK) + +#define HOST_CTRL_SPI_CONFIG_ADDRESS 0x00000480 +#define HOST_CTRL_SPI_CONFIG_OFFSET 0x00000480 +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_MSB 4 +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_LSB 4 +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_MASK 0x00000010 +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_SPI_RESET_MASK) >> HOST_CTRL_SPI_CONFIG_SPI_RESET_LSB) +#define HOST_CTRL_SPI_CONFIG_SPI_RESET_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_SPI_RESET_LSB) & HOST_CTRL_SPI_CONFIG_SPI_RESET_MASK) +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MSB 3 +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_LSB 3 +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MASK 0x00000008 +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MASK) >> HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_LSB) +#define HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_LSB) & HOST_CTRL_SPI_CONFIG_INTERRUPT_ENABLE_MASK) +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_MSB 2 +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_LSB 2 +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_MASK 0x00000004 +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_TEST_MODE_MASK) >> HOST_CTRL_SPI_CONFIG_TEST_MODE_LSB) +#define HOST_CTRL_SPI_CONFIG_TEST_MODE_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_TEST_MODE_LSB) & HOST_CTRL_SPI_CONFIG_TEST_MODE_MASK) +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_MSB 1 +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_LSB 0 +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_MASK 0x00000003 +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_GET(x) (((x) & HOST_CTRL_SPI_CONFIG_DATA_SIZE_MASK) >> HOST_CTRL_SPI_CONFIG_DATA_SIZE_LSB) +#define HOST_CTRL_SPI_CONFIG_DATA_SIZE_SET(x) (((x) << HOST_CTRL_SPI_CONFIG_DATA_SIZE_LSB) & HOST_CTRL_SPI_CONFIG_DATA_SIZE_MASK) + +#define HOST_CTRL_SPI_STATUS_ADDRESS 0x00000481 +#define HOST_CTRL_SPI_STATUS_OFFSET 0x00000481 +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_MSB 3 +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_LSB 3 +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_MASK 0x00000008 +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_GET(x) (((x) & HOST_CTRL_SPI_STATUS_ADDR_ERR_MASK) >> HOST_CTRL_SPI_STATUS_ADDR_ERR_LSB) +#define HOST_CTRL_SPI_STATUS_ADDR_ERR_SET(x) (((x) << HOST_CTRL_SPI_STATUS_ADDR_ERR_LSB) & HOST_CTRL_SPI_STATUS_ADDR_ERR_MASK) +#define HOST_CTRL_SPI_STATUS_RD_ERR_MSB 2 +#define HOST_CTRL_SPI_STATUS_RD_ERR_LSB 2 +#define HOST_CTRL_SPI_STATUS_RD_ERR_MASK 0x00000004 +#define HOST_CTRL_SPI_STATUS_RD_ERR_GET(x) (((x) & HOST_CTRL_SPI_STATUS_RD_ERR_MASK) >> HOST_CTRL_SPI_STATUS_RD_ERR_LSB) +#define HOST_CTRL_SPI_STATUS_RD_ERR_SET(x) (((x) << HOST_CTRL_SPI_STATUS_RD_ERR_LSB) & HOST_CTRL_SPI_STATUS_RD_ERR_MASK) +#define HOST_CTRL_SPI_STATUS_WR_ERR_MSB 1 +#define HOST_CTRL_SPI_STATUS_WR_ERR_LSB 1 +#define HOST_CTRL_SPI_STATUS_WR_ERR_MASK 0x00000002 +#define HOST_CTRL_SPI_STATUS_WR_ERR_GET(x) (((x) & HOST_CTRL_SPI_STATUS_WR_ERR_MASK) >> HOST_CTRL_SPI_STATUS_WR_ERR_LSB) +#define HOST_CTRL_SPI_STATUS_WR_ERR_SET(x) (((x) << HOST_CTRL_SPI_STATUS_WR_ERR_LSB) & HOST_CTRL_SPI_STATUS_WR_ERR_MASK) +#define HOST_CTRL_SPI_STATUS_READY_MSB 0 +#define HOST_CTRL_SPI_STATUS_READY_LSB 0 +#define HOST_CTRL_SPI_STATUS_READY_MASK 0x00000001 +#define HOST_CTRL_SPI_STATUS_READY_GET(x) (((x) & HOST_CTRL_SPI_STATUS_READY_MASK) >> HOST_CTRL_SPI_STATUS_READY_LSB) +#define HOST_CTRL_SPI_STATUS_READY_SET(x) (((x) << HOST_CTRL_SPI_STATUS_READY_LSB) & HOST_CTRL_SPI_STATUS_READY_MASK) + +#define NON_ASSOC_SLEEP_EN_ADDRESS 0x00000482 +#define NON_ASSOC_SLEEP_EN_OFFSET 0x00000482 +#define NON_ASSOC_SLEEP_EN_BIT_MSB 0 +#define NON_ASSOC_SLEEP_EN_BIT_LSB 0 +#define NON_ASSOC_SLEEP_EN_BIT_MASK 0x00000001 +#define NON_ASSOC_SLEEP_EN_BIT_GET(x) (((x) & NON_ASSOC_SLEEP_EN_BIT_MASK) >> NON_ASSOC_SLEEP_EN_BIT_LSB) +#define NON_ASSOC_SLEEP_EN_BIT_SET(x) (((x) << NON_ASSOC_SLEEP_EN_BIT_LSB) & NON_ASSOC_SLEEP_EN_BIT_MASK) + +#define CPU_DBG_SEL_ADDRESS 0x00000483 +#define CPU_DBG_SEL_OFFSET 0x00000483 +#define CPU_DBG_SEL_BIT_MSB 5 +#define CPU_DBG_SEL_BIT_LSB 0 +#define CPU_DBG_SEL_BIT_MASK 0x0000003f +#define CPU_DBG_SEL_BIT_GET(x) (((x) & CPU_DBG_SEL_BIT_MASK) >> CPU_DBG_SEL_BIT_LSB) +#define CPU_DBG_SEL_BIT_SET(x) (((x) << CPU_DBG_SEL_BIT_LSB) & CPU_DBG_SEL_BIT_MASK) + +#define CPU_DBG_ADDRESS 0x00000484 +#define CPU_DBG_OFFSET 0x00000484 +#define CPU_DBG_DATA_MSB 7 +#define CPU_DBG_DATA_LSB 0 +#define CPU_DBG_DATA_MASK 0x000000ff +#define CPU_DBG_DATA_GET(x) (((x) & CPU_DBG_DATA_MASK) >> CPU_DBG_DATA_LSB) +#define CPU_DBG_DATA_SET(x) (((x) << CPU_DBG_DATA_LSB) & CPU_DBG_DATA_MASK) + +#define INT_STATUS2_ENABLE_ADDRESS 0x00000488 +#define INT_STATUS2_ENABLE_OFFSET 0x00000488 +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MSB 2 +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_LSB 2 +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MASK 0x00000004 +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_GET(x) (((x) & INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MASK) >> INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_LSB) +#define INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_SET(x) (((x) << INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_LSB) & INT_STATUS2_ENABLE_GMBOX_RX_UNDERFLOW_MASK) +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MSB 1 +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_LSB 1 +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MASK 0x00000002 +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_GET(x) (((x) & INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MASK) >> INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_LSB) +#define INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_SET(x) (((x) << INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_LSB) & INT_STATUS2_ENABLE_GMBOX_TX_OVERFLOW_MASK) +#define INT_STATUS2_ENABLE_GMBOX_DATA_MSB 0 +#define INT_STATUS2_ENABLE_GMBOX_DATA_LSB 0 +#define INT_STATUS2_ENABLE_GMBOX_DATA_MASK 0x00000001 +#define INT_STATUS2_ENABLE_GMBOX_DATA_GET(x) (((x) & INT_STATUS2_ENABLE_GMBOX_DATA_MASK) >> INT_STATUS2_ENABLE_GMBOX_DATA_LSB) +#define INT_STATUS2_ENABLE_GMBOX_DATA_SET(x) (((x) << INT_STATUS2_ENABLE_GMBOX_DATA_LSB) & INT_STATUS2_ENABLE_GMBOX_DATA_MASK) + +#define GMBOX_RX_LOOKAHEAD_ADDRESS 0x00000490 +#define GMBOX_RX_LOOKAHEAD_OFFSET 0x00000490 +#define GMBOX_RX_LOOKAHEAD_DATA_MSB 7 +#define GMBOX_RX_LOOKAHEAD_DATA_LSB 0 +#define GMBOX_RX_LOOKAHEAD_DATA_MASK 0x000000ff +#define GMBOX_RX_LOOKAHEAD_DATA_GET(x) (((x) & GMBOX_RX_LOOKAHEAD_DATA_MASK) >> GMBOX_RX_LOOKAHEAD_DATA_LSB) +#define GMBOX_RX_LOOKAHEAD_DATA_SET(x) (((x) << GMBOX_RX_LOOKAHEAD_DATA_LSB) & GMBOX_RX_LOOKAHEAD_DATA_MASK) + +#define GMBOX_RX_LOOKAHEAD_MUX_ADDRESS 0x00000498 +#define GMBOX_RX_LOOKAHEAD_MUX_OFFSET 0x00000498 +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_MSB 0 +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_LSB 0 +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_MASK 0x00000001 +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_GET(x) (((x) & GMBOX_RX_LOOKAHEAD_MUX_SEL_MASK) >> GMBOX_RX_LOOKAHEAD_MUX_SEL_LSB) +#define GMBOX_RX_LOOKAHEAD_MUX_SEL_SET(x) (((x) << GMBOX_RX_LOOKAHEAD_MUX_SEL_LSB) & GMBOX_RX_LOOKAHEAD_MUX_SEL_MASK) + +#define CIS_WINDOW_ADDRESS 0x00000600 +#define CIS_WINDOW_OFFSET 0x00000600 +#define CIS_WINDOW_DATA_MSB 7 +#define CIS_WINDOW_DATA_LSB 0 +#define CIS_WINDOW_DATA_MASK 0x000000ff +#define CIS_WINDOW_DATA_GET(x) (((x) & CIS_WINDOW_DATA_MASK) >> CIS_WINDOW_DATA_LSB) +#define CIS_WINDOW_DATA_SET(x) (((x) << CIS_WINDOW_DATA_LSB) & CIS_WINDOW_DATA_MASK) + + +#endif /* _MBOX_WLAN_HOST_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h new file mode 100644 index 000000000000..f5167b9ae8d0 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h @@ -0,0 +1,589 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _MBOX_WLAN_REG_REG_H_ +#define _MBOX_WLAN_REG_REG_H_ + +#define WLAN_MBOX_FIFO_ADDRESS 0x00000000 +#define WLAN_MBOX_FIFO_OFFSET 0x00000000 +#define WLAN_MBOX_FIFO_DATA_MSB 19 +#define WLAN_MBOX_FIFO_DATA_LSB 0 +#define WLAN_MBOX_FIFO_DATA_MASK 0x000fffff +#define WLAN_MBOX_FIFO_DATA_GET(x) (((x) & WLAN_MBOX_FIFO_DATA_MASK) >> WLAN_MBOX_FIFO_DATA_LSB) +#define WLAN_MBOX_FIFO_DATA_SET(x) (((x) << WLAN_MBOX_FIFO_DATA_LSB) & WLAN_MBOX_FIFO_DATA_MASK) + +#define WLAN_MBOX_FIFO_STATUS_ADDRESS 0x00000010 +#define WLAN_MBOX_FIFO_STATUS_OFFSET 0x00000010 +#define WLAN_MBOX_FIFO_STATUS_EMPTY_MSB 19 +#define WLAN_MBOX_FIFO_STATUS_EMPTY_LSB 16 +#define WLAN_MBOX_FIFO_STATUS_EMPTY_MASK 0x000f0000 +#define WLAN_MBOX_FIFO_STATUS_EMPTY_GET(x) (((x) & WLAN_MBOX_FIFO_STATUS_EMPTY_MASK) >> WLAN_MBOX_FIFO_STATUS_EMPTY_LSB) +#define WLAN_MBOX_FIFO_STATUS_EMPTY_SET(x) (((x) << WLAN_MBOX_FIFO_STATUS_EMPTY_LSB) & WLAN_MBOX_FIFO_STATUS_EMPTY_MASK) +#define WLAN_MBOX_FIFO_STATUS_FULL_MSB 15 +#define WLAN_MBOX_FIFO_STATUS_FULL_LSB 12 +#define WLAN_MBOX_FIFO_STATUS_FULL_MASK 0x0000f000 +#define WLAN_MBOX_FIFO_STATUS_FULL_GET(x) (((x) & WLAN_MBOX_FIFO_STATUS_FULL_MASK) >> WLAN_MBOX_FIFO_STATUS_FULL_LSB) +#define WLAN_MBOX_FIFO_STATUS_FULL_SET(x) (((x) << WLAN_MBOX_FIFO_STATUS_FULL_LSB) & WLAN_MBOX_FIFO_STATUS_FULL_MASK) + +#define WLAN_MBOX_DMA_POLICY_ADDRESS 0x00000014 +#define WLAN_MBOX_DMA_POLICY_OFFSET 0x00000014 +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MSB 3 +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB 3 +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK 0x00000008 +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK) >> WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB) +#define WLAN_MBOX_DMA_POLICY_TX_QUANTUM_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_TX_QUANTUM_LSB) & WLAN_MBOX_DMA_POLICY_TX_QUANTUM_MASK) +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_MSB 2 +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB 2 +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK 0x00000004 +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK) >> WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB) +#define WLAN_MBOX_DMA_POLICY_TX_ORDER_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_TX_ORDER_LSB) & WLAN_MBOX_DMA_POLICY_TX_ORDER_MASK) +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MSB 1 +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB 1 +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK 0x00000002 +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK) >> WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB) +#define WLAN_MBOX_DMA_POLICY_RX_QUANTUM_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_RX_QUANTUM_LSB) & WLAN_MBOX_DMA_POLICY_RX_QUANTUM_MASK) +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_MSB 0 +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB 0 +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK 0x00000001 +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_GET(x) (((x) & WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK) >> WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB) +#define WLAN_MBOX_DMA_POLICY_RX_ORDER_SET(x) (((x) << WLAN_MBOX_DMA_POLICY_RX_ORDER_LSB) & WLAN_MBOX_DMA_POLICY_RX_ORDER_MASK) + +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000018 +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000018 +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX0_DMA_RX_CONTROL_ADDRESS 0x0000001c +#define WLAN_MBOX0_DMA_RX_CONTROL_OFFSET 0x0000001c +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_MBOX0_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX0_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX0_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_MBOX0_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_MBOX0_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_MBOX0_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX0_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX0_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX0_DMA_RX_CONTROL_START_LSB) +#define WLAN_MBOX0_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX0_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX0_DMA_RX_CONTROL_START_MASK) +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_MBOX0_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX0_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX0_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000020 +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000020 +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX0_DMA_TX_CONTROL_ADDRESS 0x00000024 +#define WLAN_MBOX0_DMA_TX_CONTROL_OFFSET 0x00000024 +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_MBOX0_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX0_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX0_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_MBOX0_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_MBOX0_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_MBOX0_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX0_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX0_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX0_DMA_TX_CONTROL_START_LSB) +#define WLAN_MBOX0_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX0_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX0_DMA_TX_CONTROL_START_MASK) +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_MBOX0_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX0_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX0_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000028 +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000028 +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX1_DMA_RX_CONTROL_ADDRESS 0x0000002c +#define WLAN_MBOX1_DMA_RX_CONTROL_OFFSET 0x0000002c +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_MBOX1_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX1_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX1_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_MBOX1_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_MBOX1_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_MBOX1_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX1_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX1_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX1_DMA_RX_CONTROL_START_LSB) +#define WLAN_MBOX1_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX1_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX1_DMA_RX_CONTROL_START_MASK) +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_MBOX1_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX1_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX1_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000030 +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000030 +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX1_DMA_TX_CONTROL_ADDRESS 0x00000034 +#define WLAN_MBOX1_DMA_TX_CONTROL_OFFSET 0x00000034 +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_MBOX1_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX1_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX1_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_MBOX1_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_MBOX1_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_MBOX1_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX1_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX1_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX1_DMA_TX_CONTROL_START_LSB) +#define WLAN_MBOX1_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX1_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX1_DMA_TX_CONTROL_START_MASK) +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_MBOX1_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX1_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX1_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000038 +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000038 +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX2_DMA_RX_CONTROL_ADDRESS 0x0000003c +#define WLAN_MBOX2_DMA_RX_CONTROL_OFFSET 0x0000003c +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_MBOX2_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX2_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX2_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_MBOX2_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_MBOX2_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_MBOX2_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX2_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX2_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX2_DMA_RX_CONTROL_START_LSB) +#define WLAN_MBOX2_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX2_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX2_DMA_RX_CONTROL_START_MASK) +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_MBOX2_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX2_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX2_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000040 +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000040 +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX2_DMA_TX_CONTROL_ADDRESS 0x00000044 +#define WLAN_MBOX2_DMA_TX_CONTROL_OFFSET 0x00000044 +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_MBOX2_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX2_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX2_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_MBOX2_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_MBOX2_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_MBOX2_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX2_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX2_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX2_DMA_TX_CONTROL_START_LSB) +#define WLAN_MBOX2_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX2_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX2_DMA_TX_CONTROL_START_MASK) +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_MBOX2_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX2_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX2_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000048 +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000048 +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX3_DMA_RX_CONTROL_ADDRESS 0x0000004c +#define WLAN_MBOX3_DMA_RX_CONTROL_OFFSET 0x0000004c +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_MBOX3_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX3_DMA_RX_CONTROL_RESUME_LSB) & WLAN_MBOX3_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_MBOX3_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_MBOX3_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_MBOX3_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX3_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_MBOX3_DMA_RX_CONTROL_START_MASK) >> WLAN_MBOX3_DMA_RX_CONTROL_START_LSB) +#define WLAN_MBOX3_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_MBOX3_DMA_RX_CONTROL_START_LSB) & WLAN_MBOX3_DMA_RX_CONTROL_START_MASK) +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK) >> WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_MBOX3_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX3_DMA_RX_CONTROL_STOP_LSB) & WLAN_MBOX3_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x00000050 +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x00000050 +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_MBOX3_DMA_TX_CONTROL_ADDRESS 0x00000054 +#define WLAN_MBOX3_DMA_TX_CONTROL_OFFSET 0x00000054 +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_MBOX3_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_MBOX3_DMA_TX_CONTROL_RESUME_LSB) & WLAN_MBOX3_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_MBOX3_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_MBOX3_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_MBOX3_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_MBOX3_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_MBOX3_DMA_TX_CONTROL_START_MASK) >> WLAN_MBOX3_DMA_TX_CONTROL_START_LSB) +#define WLAN_MBOX3_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_MBOX3_DMA_TX_CONTROL_START_LSB) & WLAN_MBOX3_DMA_TX_CONTROL_START_MASK) +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK) >> WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_MBOX3_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_MBOX3_DMA_TX_CONTROL_STOP_LSB) & WLAN_MBOX3_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_MBOX_INT_STATUS_ADDRESS 0x00000058 +#define WLAN_MBOX_INT_STATUS_OFFSET 0x00000058 +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MSB 31 +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB 28 +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK 0xf0000000 +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) +#define WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB 27 +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB 24 +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK 0x0f000000 +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) +#define WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) & WLAN_MBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MSB 23 +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB 20 +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK 0x00f00000 +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) +#define WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MSB 17 +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB 17 +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK 0x00020000 +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK) >> WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB) +#define WLAN_MBOX_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_OVERFLOW_LSB) & WLAN_MBOX_INT_STATUS_TX_OVERFLOW_MASK) +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MSB 16 +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB 16 +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK 0x00010000 +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK) >> WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB) +#define WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_LSB) & WLAN_MBOX_INT_STATUS_RX_UNDERFLOW_MASK) +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MSB 15 +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB 12 +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK 0x0000f000 +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) (((x) & WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK) >> WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB) +#define WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) (((x) << WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_LSB) & WLAN_MBOX_INT_STATUS_TX_NOT_EMPTY_MASK) +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MSB 11 +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB 8 +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK 0x00000f00 +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_GET(x) (((x) & WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK) >> WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB) +#define WLAN_MBOX_INT_STATUS_RX_NOT_FULL_SET(x) (((x) << WLAN_MBOX_INT_STATUS_RX_NOT_FULL_LSB) & WLAN_MBOX_INT_STATUS_RX_NOT_FULL_MASK) +#define WLAN_MBOX_INT_STATUS_HOST_MSB 7 +#define WLAN_MBOX_INT_STATUS_HOST_LSB 0 +#define WLAN_MBOX_INT_STATUS_HOST_MASK 0x000000ff +#define WLAN_MBOX_INT_STATUS_HOST_GET(x) (((x) & WLAN_MBOX_INT_STATUS_HOST_MASK) >> WLAN_MBOX_INT_STATUS_HOST_LSB) +#define WLAN_MBOX_INT_STATUS_HOST_SET(x) (((x) << WLAN_MBOX_INT_STATUS_HOST_LSB) & WLAN_MBOX_INT_STATUS_HOST_MASK) + +#define WLAN_MBOX_INT_ENABLE_ADDRESS 0x0000005c +#define WLAN_MBOX_INT_ENABLE_OFFSET 0x0000005c +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB 31 +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB 28 +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK 0xf0000000 +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) +#define WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB 27 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB 24 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK 0x0f000000 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) +#define WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) & WLAN_MBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB 23 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB 20 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK 0x00f00000 +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) >> WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) +#define WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) & WLAN_MBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MSB 17 +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB 17 +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK 0x00020000 +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK) >> WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB) +#define WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_LSB) & WLAN_MBOX_INT_ENABLE_TX_OVERFLOW_MASK) +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MSB 16 +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB 16 +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK 0x00010000 +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK) >> WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB) +#define WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_LSB) & WLAN_MBOX_INT_ENABLE_RX_UNDERFLOW_MASK) +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MSB 15 +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB 12 +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK 0x0000f000 +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) >> WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) +#define WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) & WLAN_MBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MSB 11 +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB 8 +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK 0x00000f00 +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK) >> WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB) +#define WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_LSB) & WLAN_MBOX_INT_ENABLE_RX_NOT_FULL_MASK) +#define WLAN_MBOX_INT_ENABLE_HOST_MSB 7 +#define WLAN_MBOX_INT_ENABLE_HOST_LSB 0 +#define WLAN_MBOX_INT_ENABLE_HOST_MASK 0x000000ff +#define WLAN_MBOX_INT_ENABLE_HOST_GET(x) (((x) & WLAN_MBOX_INT_ENABLE_HOST_MASK) >> WLAN_MBOX_INT_ENABLE_HOST_LSB) +#define WLAN_MBOX_INT_ENABLE_HOST_SET(x) (((x) << WLAN_MBOX_INT_ENABLE_HOST_LSB) & WLAN_MBOX_INT_ENABLE_HOST_MASK) + +#define WLAN_INT_HOST_ADDRESS 0x00000060 +#define WLAN_INT_HOST_OFFSET 0x00000060 +#define WLAN_INT_HOST_VECTOR_MSB 7 +#define WLAN_INT_HOST_VECTOR_LSB 0 +#define WLAN_INT_HOST_VECTOR_MASK 0x000000ff +#define WLAN_INT_HOST_VECTOR_GET(x) (((x) & WLAN_INT_HOST_VECTOR_MASK) >> WLAN_INT_HOST_VECTOR_LSB) +#define WLAN_INT_HOST_VECTOR_SET(x) (((x) << WLAN_INT_HOST_VECTOR_LSB) & WLAN_INT_HOST_VECTOR_MASK) + +#define WLAN_LOCAL_COUNT_ADDRESS 0x00000080 +#define WLAN_LOCAL_COUNT_OFFSET 0x00000080 +#define WLAN_LOCAL_COUNT_VALUE_MSB 7 +#define WLAN_LOCAL_COUNT_VALUE_LSB 0 +#define WLAN_LOCAL_COUNT_VALUE_MASK 0x000000ff +#define WLAN_LOCAL_COUNT_VALUE_GET(x) (((x) & WLAN_LOCAL_COUNT_VALUE_MASK) >> WLAN_LOCAL_COUNT_VALUE_LSB) +#define WLAN_LOCAL_COUNT_VALUE_SET(x) (((x) << WLAN_LOCAL_COUNT_VALUE_LSB) & WLAN_LOCAL_COUNT_VALUE_MASK) + +#define WLAN_COUNT_INC_ADDRESS 0x000000a0 +#define WLAN_COUNT_INC_OFFSET 0x000000a0 +#define WLAN_COUNT_INC_VALUE_MSB 7 +#define WLAN_COUNT_INC_VALUE_LSB 0 +#define WLAN_COUNT_INC_VALUE_MASK 0x000000ff +#define WLAN_COUNT_INC_VALUE_GET(x) (((x) & WLAN_COUNT_INC_VALUE_MASK) >> WLAN_COUNT_INC_VALUE_LSB) +#define WLAN_COUNT_INC_VALUE_SET(x) (((x) << WLAN_COUNT_INC_VALUE_LSB) & WLAN_COUNT_INC_VALUE_MASK) + +#define WLAN_LOCAL_SCRATCH_ADDRESS 0x000000c0 +#define WLAN_LOCAL_SCRATCH_OFFSET 0x000000c0 +#define WLAN_LOCAL_SCRATCH_VALUE_MSB 7 +#define WLAN_LOCAL_SCRATCH_VALUE_LSB 0 +#define WLAN_LOCAL_SCRATCH_VALUE_MASK 0x000000ff +#define WLAN_LOCAL_SCRATCH_VALUE_GET(x) (((x) & WLAN_LOCAL_SCRATCH_VALUE_MASK) >> WLAN_LOCAL_SCRATCH_VALUE_LSB) +#define WLAN_LOCAL_SCRATCH_VALUE_SET(x) (((x) << WLAN_LOCAL_SCRATCH_VALUE_LSB) & WLAN_LOCAL_SCRATCH_VALUE_MASK) + +#define WLAN_USE_LOCAL_BUS_ADDRESS 0x000000e0 +#define WLAN_USE_LOCAL_BUS_OFFSET 0x000000e0 +#define WLAN_USE_LOCAL_BUS_PIN_INIT_MSB 0 +#define WLAN_USE_LOCAL_BUS_PIN_INIT_LSB 0 +#define WLAN_USE_LOCAL_BUS_PIN_INIT_MASK 0x00000001 +#define WLAN_USE_LOCAL_BUS_PIN_INIT_GET(x) (((x) & WLAN_USE_LOCAL_BUS_PIN_INIT_MASK) >> WLAN_USE_LOCAL_BUS_PIN_INIT_LSB) +#define WLAN_USE_LOCAL_BUS_PIN_INIT_SET(x) (((x) << WLAN_USE_LOCAL_BUS_PIN_INIT_LSB) & WLAN_USE_LOCAL_BUS_PIN_INIT_MASK) + +#define WLAN_SDIO_CONFIG_ADDRESS 0x000000e4 +#define WLAN_SDIO_CONFIG_OFFSET 0x000000e4 +#define WLAN_SDIO_CONFIG_CCCR_IOR1_MSB 0 +#define WLAN_SDIO_CONFIG_CCCR_IOR1_LSB 0 +#define WLAN_SDIO_CONFIG_CCCR_IOR1_MASK 0x00000001 +#define WLAN_SDIO_CONFIG_CCCR_IOR1_GET(x) (((x) & WLAN_SDIO_CONFIG_CCCR_IOR1_MASK) >> WLAN_SDIO_CONFIG_CCCR_IOR1_LSB) +#define WLAN_SDIO_CONFIG_CCCR_IOR1_SET(x) (((x) << WLAN_SDIO_CONFIG_CCCR_IOR1_LSB) & WLAN_SDIO_CONFIG_CCCR_IOR1_MASK) + +#define WLAN_MBOX_DEBUG_ADDRESS 0x000000e8 +#define WLAN_MBOX_DEBUG_OFFSET 0x000000e8 +#define WLAN_MBOX_DEBUG_SEL_MSB 2 +#define WLAN_MBOX_DEBUG_SEL_LSB 0 +#define WLAN_MBOX_DEBUG_SEL_MASK 0x00000007 +#define WLAN_MBOX_DEBUG_SEL_GET(x) (((x) & WLAN_MBOX_DEBUG_SEL_MASK) >> WLAN_MBOX_DEBUG_SEL_LSB) +#define WLAN_MBOX_DEBUG_SEL_SET(x) (((x) << WLAN_MBOX_DEBUG_SEL_LSB) & WLAN_MBOX_DEBUG_SEL_MASK) + +#define WLAN_MBOX_FIFO_RESET_ADDRESS 0x000000ec +#define WLAN_MBOX_FIFO_RESET_OFFSET 0x000000ec +#define WLAN_MBOX_FIFO_RESET_INIT_MSB 0 +#define WLAN_MBOX_FIFO_RESET_INIT_LSB 0 +#define WLAN_MBOX_FIFO_RESET_INIT_MASK 0x00000001 +#define WLAN_MBOX_FIFO_RESET_INIT_GET(x) (((x) & WLAN_MBOX_FIFO_RESET_INIT_MASK) >> WLAN_MBOX_FIFO_RESET_INIT_LSB) +#define WLAN_MBOX_FIFO_RESET_INIT_SET(x) (((x) << WLAN_MBOX_FIFO_RESET_INIT_LSB) & WLAN_MBOX_FIFO_RESET_INIT_MASK) + +#define WLAN_MBOX_TXFIFO_POP_ADDRESS 0x000000f0 +#define WLAN_MBOX_TXFIFO_POP_OFFSET 0x000000f0 +#define WLAN_MBOX_TXFIFO_POP_DATA_MSB 0 +#define WLAN_MBOX_TXFIFO_POP_DATA_LSB 0 +#define WLAN_MBOX_TXFIFO_POP_DATA_MASK 0x00000001 +#define WLAN_MBOX_TXFIFO_POP_DATA_GET(x) (((x) & WLAN_MBOX_TXFIFO_POP_DATA_MASK) >> WLAN_MBOX_TXFIFO_POP_DATA_LSB) +#define WLAN_MBOX_TXFIFO_POP_DATA_SET(x) (((x) << WLAN_MBOX_TXFIFO_POP_DATA_LSB) & WLAN_MBOX_TXFIFO_POP_DATA_MASK) + +#define WLAN_MBOX_RXFIFO_POP_ADDRESS 0x00000100 +#define WLAN_MBOX_RXFIFO_POP_OFFSET 0x00000100 +#define WLAN_MBOX_RXFIFO_POP_DATA_MSB 0 +#define WLAN_MBOX_RXFIFO_POP_DATA_LSB 0 +#define WLAN_MBOX_RXFIFO_POP_DATA_MASK 0x00000001 +#define WLAN_MBOX_RXFIFO_POP_DATA_GET(x) (((x) & WLAN_MBOX_RXFIFO_POP_DATA_MASK) >> WLAN_MBOX_RXFIFO_POP_DATA_LSB) +#define WLAN_MBOX_RXFIFO_POP_DATA_SET(x) (((x) << WLAN_MBOX_RXFIFO_POP_DATA_LSB) & WLAN_MBOX_RXFIFO_POP_DATA_MASK) + +#define WLAN_SDIO_DEBUG_ADDRESS 0x00000110 +#define WLAN_SDIO_DEBUG_OFFSET 0x00000110 +#define WLAN_SDIO_DEBUG_SEL_MSB 3 +#define WLAN_SDIO_DEBUG_SEL_LSB 0 +#define WLAN_SDIO_DEBUG_SEL_MASK 0x0000000f +#define WLAN_SDIO_DEBUG_SEL_GET(x) (((x) & WLAN_SDIO_DEBUG_SEL_MASK) >> WLAN_SDIO_DEBUG_SEL_LSB) +#define WLAN_SDIO_DEBUG_SEL_SET(x) (((x) << WLAN_SDIO_DEBUG_SEL_LSB) & WLAN_SDIO_DEBUG_SEL_MASK) + +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS 0x00000114 +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_OFFSET 0x00000114 +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_GMBOX0_DMA_RX_CONTROL_ADDRESS 0x00000118 +#define WLAN_GMBOX0_DMA_RX_CONTROL_OFFSET 0x00000118 +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MSB 2 +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB 2 +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK) >> WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB) +#define WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_LSB) & WLAN_GMBOX0_DMA_RX_CONTROL_RESUME_MASK) +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_MSB 1 +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB 1 +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK 0x00000002 +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK) >> WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB) +#define WLAN_GMBOX0_DMA_RX_CONTROL_START_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_CONTROL_START_LSB) & WLAN_GMBOX0_DMA_RX_CONTROL_START_MASK) +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MSB 0 +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB 0 +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_GET(x) (((x) & WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK) >> WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB) +#define WLAN_GMBOX0_DMA_RX_CONTROL_STOP_SET(x) (((x) << WLAN_GMBOX0_DMA_RX_CONTROL_STOP_LSB) & WLAN_GMBOX0_DMA_RX_CONTROL_STOP_MASK) + +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS 0x0000011c +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_OFFSET 0x0000011c +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MSB 27 +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB 2 +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK 0x0ffffffc +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) >> WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) +#define WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_LSB) & WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE_ADDRESS_MASK) + +#define WLAN_GMBOX0_DMA_TX_CONTROL_ADDRESS 0x00000120 +#define WLAN_GMBOX0_DMA_TX_CONTROL_OFFSET 0x00000120 +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MSB 2 +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB 2 +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK 0x00000004 +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK) >> WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB) +#define WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_LSB) & WLAN_GMBOX0_DMA_TX_CONTROL_RESUME_MASK) +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_MSB 1 +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB 1 +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK 0x00000002 +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK) >> WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB) +#define WLAN_GMBOX0_DMA_TX_CONTROL_START_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_CONTROL_START_LSB) & WLAN_GMBOX0_DMA_TX_CONTROL_START_MASK) +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MSB 0 +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB 0 +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK 0x00000001 +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_GET(x) (((x) & WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK) >> WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB) +#define WLAN_GMBOX0_DMA_TX_CONTROL_STOP_SET(x) (((x) << WLAN_GMBOX0_DMA_TX_CONTROL_STOP_LSB) & WLAN_GMBOX0_DMA_TX_CONTROL_STOP_MASK) + +#define WLAN_GMBOX_INT_STATUS_ADDRESS 0x00000124 +#define WLAN_GMBOX_INT_STATUS_OFFSET 0x00000124 +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MSB 6 +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB 6 +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK 0x00000040 +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK) >> WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB) +#define WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_LSB) & WLAN_GMBOX_INT_STATUS_TX_OVERFLOW_MASK) +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MSB 5 +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB 5 +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK 0x00000020 +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK) >> WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB) +#define WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_LSB) & WLAN_GMBOX_INT_STATUS_RX_UNDERFLOW_MASK) +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MSB 4 +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB 4 +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK 0x00000010 +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) +#define WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_STATUS_RX_DMA_COMPLETE_MASK) +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MSB 3 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB 3 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK 0x00000008 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) +#define WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_LSB) & WLAN_GMBOX_INT_STATUS_TX_DMA_EOM_COMPLETE_MASK) +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MSB 2 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB 2 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK 0x00000004 +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) +#define WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_STATUS_TX_DMA_COMPLETE_MASK) +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MSB 1 +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB 1 +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK 0x00000002 +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK) >> WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB) +#define WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_LSB) & WLAN_GMBOX_INT_STATUS_TX_NOT_EMPTY_MASK) +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MSB 0 +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB 0 +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK 0x00000001 +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_GET(x) (((x) & WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK) >> WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB) +#define WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_SET(x) (((x) << WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_LSB) & WLAN_GMBOX_INT_STATUS_RX_NOT_FULL_MASK) + +#define WLAN_GMBOX_INT_ENABLE_ADDRESS 0x00000128 +#define WLAN_GMBOX_INT_ENABLE_OFFSET 0x00000128 +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MSB 6 +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB 6 +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK 0x00000040 +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB) +#define WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_LSB) & WLAN_GMBOX_INT_ENABLE_TX_OVERFLOW_MASK) +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MSB 5 +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB 5 +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK 0x00000020 +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK) >> WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB) +#define WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_LSB) & WLAN_GMBOX_INT_ENABLE_RX_UNDERFLOW_MASK) +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MSB 4 +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB 4 +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK 0x00000010 +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) +#define WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_ENABLE_RX_DMA_COMPLETE_MASK) +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MSB 3 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB 3 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK 0x00000008 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_LSB) & WLAN_GMBOX_INT_ENABLE_TX_DMA_EOM_COMPLETE_MASK) +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MSB 2 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB 2 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK 0x00000004 +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) +#define WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_LSB) & WLAN_GMBOX_INT_ENABLE_TX_DMA_COMPLETE_MASK) +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MSB 1 +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB 1 +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK 0x00000002 +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) >> WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) +#define WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_LSB) & WLAN_GMBOX_INT_ENABLE_TX_NOT_EMPTY_MASK) +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MSB 0 +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB 0 +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK 0x00000001 +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_GET(x) (((x) & WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK) >> WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB) +#define WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_SET(x) (((x) << WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_LSB) & WLAN_GMBOX_INT_ENABLE_RX_NOT_FULL_MASK) + +#define WLAN_HOST_IF_WINDOW_ADDRESS 0x00002000 +#define WLAN_HOST_IF_WINDOW_OFFSET 0x00002000 +#define WLAN_HOST_IF_WINDOW_DATA_MSB 7 +#define WLAN_HOST_IF_WINDOW_DATA_LSB 0 +#define WLAN_HOST_IF_WINDOW_DATA_MASK 0x000000ff +#define WLAN_HOST_IF_WINDOW_DATA_GET(x) (((x) & WLAN_HOST_IF_WINDOW_DATA_MASK) >> WLAN_HOST_IF_WINDOW_DATA_LSB) +#define WLAN_HOST_IF_WINDOW_DATA_SET(x) (((x) << WLAN_HOST_IF_WINDOW_DATA_LSB) & WLAN_HOST_IF_WINDOW_DATA_MASK) + +#endif /* _MBOX_WLAN_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h new file mode 100644 index 000000000000..fcafec88a6b9 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h @@ -0,0 +1,187 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#include "rtc_wlan_reg.h" + +#ifndef BT_HEADERS + +#define RESET_CONTROL_ADDRESS WLAN_RESET_CONTROL_ADDRESS +#define RESET_CONTROL_OFFSET WLAN_RESET_CONTROL_OFFSET +#define RESET_CONTROL_DEBUG_UART_RST_MSB WLAN_RESET_CONTROL_DEBUG_UART_RST_MSB +#define RESET_CONTROL_DEBUG_UART_RST_LSB WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB +#define RESET_CONTROL_DEBUG_UART_RST_MASK WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK +#define RESET_CONTROL_DEBUG_UART_RST_GET(x) WLAN_RESET_CONTROL_DEBUG_UART_RST_GET(x) +#define RESET_CONTROL_DEBUG_UART_RST_SET(x) WLAN_RESET_CONTROL_DEBUG_UART_RST_SET(x) +#define RESET_CONTROL_BB_COLD_RST_MSB WLAN_RESET_CONTROL_BB_COLD_RST_MSB +#define RESET_CONTROL_BB_COLD_RST_LSB WLAN_RESET_CONTROL_BB_COLD_RST_LSB +#define RESET_CONTROL_BB_COLD_RST_MASK WLAN_RESET_CONTROL_BB_COLD_RST_MASK +#define RESET_CONTROL_BB_COLD_RST_GET(x) WLAN_RESET_CONTROL_BB_COLD_RST_GET(x) +#define RESET_CONTROL_BB_COLD_RST_SET(x) WLAN_RESET_CONTROL_BB_COLD_RST_SET(x) +#define RESET_CONTROL_BB_WARM_RST_MSB WLAN_RESET_CONTROL_BB_WARM_RST_MSB +#define RESET_CONTROL_BB_WARM_RST_LSB WLAN_RESET_CONTROL_BB_WARM_RST_LSB +#define RESET_CONTROL_BB_WARM_RST_MASK WLAN_RESET_CONTROL_BB_WARM_RST_MASK +#define RESET_CONTROL_BB_WARM_RST_GET(x) WLAN_RESET_CONTROL_BB_WARM_RST_GET(x) +#define RESET_CONTROL_BB_WARM_RST_SET(x) WLAN_RESET_CONTROL_BB_WARM_RST_SET(x) +#define RESET_CONTROL_CPU_INIT_RESET_MSB WLAN_RESET_CONTROL_CPU_INIT_RESET_MSB +#define RESET_CONTROL_CPU_INIT_RESET_LSB WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB +#define RESET_CONTROL_CPU_INIT_RESET_MASK WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK +#define RESET_CONTROL_CPU_INIT_RESET_GET(x) WLAN_RESET_CONTROL_CPU_INIT_RESET_GET(x) +#define RESET_CONTROL_CPU_INIT_RESET_SET(x) WLAN_RESET_CONTROL_CPU_INIT_RESET_SET(x) +#define RESET_CONTROL_VMC_REMAP_RESET_MSB WLAN_RESET_CONTROL_VMC_REMAP_RESET_MSB +#define RESET_CONTROL_VMC_REMAP_RESET_LSB WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB +#define RESET_CONTROL_VMC_REMAP_RESET_MASK WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK +#define RESET_CONTROL_VMC_REMAP_RESET_GET(x) WLAN_RESET_CONTROL_VMC_REMAP_RESET_GET(x) +#define RESET_CONTROL_VMC_REMAP_RESET_SET(x) WLAN_RESET_CONTROL_VMC_REMAP_RESET_SET(x) +#define RESET_CONTROL_RST_OUT_MSB WLAN_RESET_CONTROL_RST_OUT_MSB +#define RESET_CONTROL_RST_OUT_LSB WLAN_RESET_CONTROL_RST_OUT_LSB +#define RESET_CONTROL_RST_OUT_MASK WLAN_RESET_CONTROL_RST_OUT_MASK +#define RESET_CONTROL_RST_OUT_GET(x) WLAN_RESET_CONTROL_RST_OUT_GET(x) +#define RESET_CONTROL_RST_OUT_SET(x) WLAN_RESET_CONTROL_RST_OUT_SET(x) +#define RESET_CONTROL_COLD_RST_MSB WLAN_RESET_CONTROL_COLD_RST_MSB +#define RESET_CONTROL_COLD_RST_LSB WLAN_RESET_CONTROL_COLD_RST_LSB +#define RESET_CONTROL_COLD_RST_MASK WLAN_RESET_CONTROL_COLD_RST_MASK +#define RESET_CONTROL_COLD_RST_GET(x) WLAN_RESET_CONTROL_COLD_RST_GET(x) +#define RESET_CONTROL_COLD_RST_SET(x) WLAN_RESET_CONTROL_COLD_RST_SET(x) +#define RESET_CONTROL_WARM_RST_MSB WLAN_RESET_CONTROL_WARM_RST_MSB +#define RESET_CONTROL_WARM_RST_LSB WLAN_RESET_CONTROL_WARM_RST_LSB +#define RESET_CONTROL_WARM_RST_MASK WLAN_RESET_CONTROL_WARM_RST_MASK +#define RESET_CONTROL_WARM_RST_GET(x) WLAN_RESET_CONTROL_WARM_RST_GET(x) +#define RESET_CONTROL_WARM_RST_SET(x) WLAN_RESET_CONTROL_WARM_RST_SET(x) +#define RESET_CONTROL_CPU_WARM_RST_MSB WLAN_RESET_CONTROL_CPU_WARM_RST_MSB +#define RESET_CONTROL_CPU_WARM_RST_LSB WLAN_RESET_CONTROL_CPU_WARM_RST_LSB +#define RESET_CONTROL_CPU_WARM_RST_MASK WLAN_RESET_CONTROL_CPU_WARM_RST_MASK +#define RESET_CONTROL_CPU_WARM_RST_GET(x) WLAN_RESET_CONTROL_CPU_WARM_RST_GET(x) +#define RESET_CONTROL_CPU_WARM_RST_SET(x) WLAN_RESET_CONTROL_CPU_WARM_RST_SET(x) +#define RESET_CONTROL_MAC_COLD_RST_MSB WLAN_RESET_CONTROL_MAC_COLD_RST_MSB +#define RESET_CONTROL_MAC_COLD_RST_LSB WLAN_RESET_CONTROL_MAC_COLD_RST_LSB +#define RESET_CONTROL_MAC_COLD_RST_MASK WLAN_RESET_CONTROL_MAC_COLD_RST_MASK +#define RESET_CONTROL_MAC_COLD_RST_GET(x) WLAN_RESET_CONTROL_MAC_COLD_RST_GET(x) +#define RESET_CONTROL_MAC_COLD_RST_SET(x) WLAN_RESET_CONTROL_MAC_COLD_RST_SET(x) +#define RESET_CONTROL_MAC_WARM_RST_MSB WLAN_RESET_CONTROL_MAC_WARM_RST_MSB +#define RESET_CONTROL_MAC_WARM_RST_LSB WLAN_RESET_CONTROL_MAC_WARM_RST_LSB +#define RESET_CONTROL_MAC_WARM_RST_MASK WLAN_RESET_CONTROL_MAC_WARM_RST_MASK +#define RESET_CONTROL_MAC_WARM_RST_GET(x) WLAN_RESET_CONTROL_MAC_WARM_RST_GET(x) +#define RESET_CONTROL_MAC_WARM_RST_SET(x) WLAN_RESET_CONTROL_MAC_WARM_RST_SET(x) +#define RESET_CONTROL_MBOX_RST_MSB WLAN_RESET_CONTROL_MBOX_RST_MSB +#define RESET_CONTROL_MBOX_RST_LSB WLAN_RESET_CONTROL_MBOX_RST_LSB +#define RESET_CONTROL_MBOX_RST_MASK WLAN_RESET_CONTROL_MBOX_RST_MASK +#define RESET_CONTROL_MBOX_RST_GET(x) WLAN_RESET_CONTROL_MBOX_RST_GET(x) +#define RESET_CONTROL_MBOX_RST_SET(x) WLAN_RESET_CONTROL_MBOX_RST_SET(x) +#define RESET_CONTROL_UART_RST_MSB WLAN_RESET_CONTROL_UART_RST_MSB +#define RESET_CONTROL_UART_RST_LSB WLAN_RESET_CONTROL_UART_RST_LSB +#define RESET_CONTROL_UART_RST_MASK WLAN_RESET_CONTROL_UART_RST_MASK +#define RESET_CONTROL_UART_RST_GET(x) WLAN_RESET_CONTROL_UART_RST_GET(x) +#define RESET_CONTROL_UART_RST_SET(x) WLAN_RESET_CONTROL_UART_RST_SET(x) +#define RESET_CONTROL_SI0_RST_MSB WLAN_RESET_CONTROL_SI0_RST_MSB +#define RESET_CONTROL_SI0_RST_LSB WLAN_RESET_CONTROL_SI0_RST_LSB +#define RESET_CONTROL_SI0_RST_MASK WLAN_RESET_CONTROL_SI0_RST_MASK +#define RESET_CONTROL_SI0_RST_GET(x) WLAN_RESET_CONTROL_SI0_RST_GET(x) +#define RESET_CONTROL_SI0_RST_SET(x) WLAN_RESET_CONTROL_SI0_RST_SET(x) +#define CPU_CLOCK_ADDRESS WLAN_CPU_CLOCK_ADDRESS +#define CPU_CLOCK_OFFSET WLAN_CPU_CLOCK_OFFSET +#define CPU_CLOCK_STANDARD_MSB WLAN_CPU_CLOCK_STANDARD_MSB +#define CPU_CLOCK_STANDARD_LSB WLAN_CPU_CLOCK_STANDARD_LSB +#define CPU_CLOCK_STANDARD_MASK WLAN_CPU_CLOCK_STANDARD_MASK +#define CPU_CLOCK_STANDARD_GET(x) WLAN_CPU_CLOCK_STANDARD_GET(x) +#define CPU_CLOCK_STANDARD_SET(x) WLAN_CPU_CLOCK_STANDARD_SET(x) +#define CLOCK_OUT_ADDRESS WLAN_CLOCK_OUT_ADDRESS +#define CLOCK_OUT_OFFSET WLAN_CLOCK_OUT_OFFSET +#define CLOCK_OUT_SELECT_MSB WLAN_CLOCK_OUT_SELECT_MSB +#define CLOCK_OUT_SELECT_LSB WLAN_CLOCK_OUT_SELECT_LSB +#define CLOCK_OUT_SELECT_MASK WLAN_CLOCK_OUT_SELECT_MASK +#define CLOCK_OUT_SELECT_GET(x) WLAN_CLOCK_OUT_SELECT_GET(x) +#define CLOCK_OUT_SELECT_SET(x) WLAN_CLOCK_OUT_SELECT_SET(x) +#define CLOCK_CONTROL_ADDRESS WLAN_CLOCK_CONTROL_ADDRESS +#define CLOCK_CONTROL_OFFSET WLAN_CLOCK_CONTROL_OFFSET +#define CLOCK_CONTROL_LF_CLK32_MSB WLAN_CLOCK_CONTROL_LF_CLK32_MSB +#define CLOCK_CONTROL_LF_CLK32_LSB WLAN_CLOCK_CONTROL_LF_CLK32_LSB +#define CLOCK_CONTROL_LF_CLK32_MASK WLAN_CLOCK_CONTROL_LF_CLK32_MASK +#define CLOCK_CONTROL_LF_CLK32_GET(x) WLAN_CLOCK_CONTROL_LF_CLK32_GET(x) +#define CLOCK_CONTROL_LF_CLK32_SET(x) WLAN_CLOCK_CONTROL_LF_CLK32_SET(x) +#define CLOCK_CONTROL_SI0_CLK_MSB WLAN_CLOCK_CONTROL_SI0_CLK_MSB +#define CLOCK_CONTROL_SI0_CLK_LSB WLAN_CLOCK_CONTROL_SI0_CLK_LSB +#define CLOCK_CONTROL_SI0_CLK_MASK WLAN_CLOCK_CONTROL_SI0_CLK_MASK +#define CLOCK_CONTROL_SI0_CLK_GET(x) WLAN_CLOCK_CONTROL_SI0_CLK_GET(x) +#define CLOCK_CONTROL_SI0_CLK_SET(x) WLAN_CLOCK_CONTROL_SI0_CLK_SET(x) +#define RESET_CAUSE_ADDRESS WLAN_RESET_CAUSE_ADDRESS +#define RESET_CAUSE_OFFSET WLAN_RESET_CAUSE_OFFSET +#define RESET_CAUSE_LAST_MSB WLAN_RESET_CAUSE_LAST_MSB +#define RESET_CAUSE_LAST_LSB WLAN_RESET_CAUSE_LAST_LSB +#define RESET_CAUSE_LAST_MASK WLAN_RESET_CAUSE_LAST_MASK +#define RESET_CAUSE_LAST_GET(x) WLAN_RESET_CAUSE_LAST_GET(x) +#define RESET_CAUSE_LAST_SET(x) WLAN_RESET_CAUSE_LAST_SET(x) +#define SYSTEM_SLEEP_ADDRESS WLAN_SYSTEM_SLEEP_ADDRESS +#define SYSTEM_SLEEP_OFFSET WLAN_SYSTEM_SLEEP_OFFSET +#define SYSTEM_SLEEP_HOST_IF_MSB WLAN_SYSTEM_SLEEP_HOST_IF_MSB +#define SYSTEM_SLEEP_HOST_IF_LSB WLAN_SYSTEM_SLEEP_HOST_IF_LSB +#define SYSTEM_SLEEP_HOST_IF_MASK WLAN_SYSTEM_SLEEP_HOST_IF_MASK +#define SYSTEM_SLEEP_HOST_IF_GET(x) WLAN_SYSTEM_SLEEP_HOST_IF_GET(x) +#define SYSTEM_SLEEP_HOST_IF_SET(x) WLAN_SYSTEM_SLEEP_HOST_IF_SET(x) +#define SYSTEM_SLEEP_MBOX_MSB WLAN_SYSTEM_SLEEP_MBOX_MSB +#define SYSTEM_SLEEP_MBOX_LSB WLAN_SYSTEM_SLEEP_MBOX_LSB +#define SYSTEM_SLEEP_MBOX_MASK WLAN_SYSTEM_SLEEP_MBOX_MASK +#define SYSTEM_SLEEP_MBOX_GET(x) WLAN_SYSTEM_SLEEP_MBOX_GET(x) +#define SYSTEM_SLEEP_MBOX_SET(x) WLAN_SYSTEM_SLEEP_MBOX_SET(x) +#define SYSTEM_SLEEP_MAC_IF_MSB WLAN_SYSTEM_SLEEP_MAC_IF_MSB +#define SYSTEM_SLEEP_MAC_IF_LSB WLAN_SYSTEM_SLEEP_MAC_IF_LSB +#define SYSTEM_SLEEP_MAC_IF_MASK WLAN_SYSTEM_SLEEP_MAC_IF_MASK +#define SYSTEM_SLEEP_MAC_IF_GET(x) WLAN_SYSTEM_SLEEP_MAC_IF_GET(x) +#define SYSTEM_SLEEP_MAC_IF_SET(x) WLAN_SYSTEM_SLEEP_MAC_IF_SET(x) +#define SYSTEM_SLEEP_LIGHT_MSB WLAN_SYSTEM_SLEEP_LIGHT_MSB +#define SYSTEM_SLEEP_LIGHT_LSB WLAN_SYSTEM_SLEEP_LIGHT_LSB +#define SYSTEM_SLEEP_LIGHT_MASK WLAN_SYSTEM_SLEEP_LIGHT_MASK +#define SYSTEM_SLEEP_LIGHT_GET(x) WLAN_SYSTEM_SLEEP_LIGHT_GET(x) +#define SYSTEM_SLEEP_LIGHT_SET(x) WLAN_SYSTEM_SLEEP_LIGHT_SET(x) +#define SYSTEM_SLEEP_DISABLE_MSB WLAN_SYSTEM_SLEEP_DISABLE_MSB +#define SYSTEM_SLEEP_DISABLE_LSB WLAN_SYSTEM_SLEEP_DISABLE_LSB +#define SYSTEM_SLEEP_DISABLE_MASK WLAN_SYSTEM_SLEEP_DISABLE_MASK +#define SYSTEM_SLEEP_DISABLE_GET(x) WLAN_SYSTEM_SLEEP_DISABLE_GET(x) +#define SYSTEM_SLEEP_DISABLE_SET(x) WLAN_SYSTEM_SLEEP_DISABLE_SET(x) +#define LPO_INIT_DIVIDEND_INT_ADDRESS WLAN_LPO_INIT_DIVIDEND_INT_ADDRESS +#define LPO_INIT_DIVIDEND_INT_OFFSET WLAN_LPO_INIT_DIVIDEND_INT_OFFSET +#define LPO_INIT_DIVIDEND_INT_VALUE_MSB WLAN_LPO_INIT_DIVIDEND_INT_VALUE_MSB +#define LPO_INIT_DIVIDEND_INT_VALUE_LSB WLAN_LPO_INIT_DIVIDEND_INT_VALUE_LSB +#define LPO_INIT_DIVIDEND_INT_VALUE_MASK WLAN_LPO_INIT_DIVIDEND_INT_VALUE_MASK +#define LPO_INIT_DIVIDEND_INT_VALUE_GET(x) WLAN_LPO_INIT_DIVIDEND_INT_VALUE_GET(x) +#define LPO_INIT_DIVIDEND_INT_VALUE_SET(x) WLAN_LPO_INIT_DIVIDEND_INT_VALUE_SET(x) +#define LPO_INIT_DIVIDEND_FRACTION_ADDRESS WLAN_LPO_INIT_DIVIDEND_FRACTION_ADDRESS +#define LPO_INIT_DIVIDEND_FRACTION_OFFSET WLAN_LPO_INIT_DIVIDEND_FRACTION_OFFSET +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_MSB WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_MSB +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_LSB WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_LSB +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_MASK WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_MASK +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_GET(x) WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_GET(x) +#define LPO_INIT_DIVIDEND_FRACTION_VALUE_SET(x) WLAN_LPO_INIT_DIVIDEND_FRACTION_VALUE_SET(x) +#define LPO_CAL_ADDRESS WLAN_LPO_CAL_ADDRESS +#define LPO_CAL_OFFSET WLAN_LPO_CAL_OFFSET +#define LPO_CAL_ENABLE_MSB WLAN_LPO_CAL_ENABLE_MSB +#define LPO_CAL_ENABLE_LSB WLAN_LPO_CAL_ENABLE_LSB +#define LPO_CAL_ENABLE_MASK WLAN_LPO_CAL_ENABLE_MASK +#define LPO_CAL_ENABLE_GET(x) WLAN_LPO_CAL_ENABLE_GET(x) +#define LPO_CAL_ENABLE_SET(x) WLAN_LPO_CAL_ENABLE_SET(x) +#define LPO_CAL_COUNT_MSB WLAN_LPO_CAL_COUNT_MSB +#define LPO_CAL_COUNT_LSB WLAN_LPO_CAL_COUNT_LSB +#define LPO_CAL_COUNT_MASK WLAN_LPO_CAL_COUNT_MASK +#define LPO_CAL_COUNT_GET(x) WLAN_LPO_CAL_COUNT_GET(x) +#define LPO_CAL_COUNT_SET(x) WLAN_LPO_CAL_COUNT_SET(x) + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h new file mode 100644 index 000000000000..5c048ff51b07 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h @@ -0,0 +1,162 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _RTC_WLAN_REG_REG_H_ +#define _RTC_WLAN_REG_REG_H_ + +#define WLAN_RESET_CONTROL_ADDRESS 0x00000000 +#define WLAN_RESET_CONTROL_OFFSET 0x00000000 +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_MSB 14 +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB 14 +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK 0x00004000 +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_GET(x) (((x) & WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK) >> WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB) +#define WLAN_RESET_CONTROL_DEBUG_UART_RST_SET(x) (((x) << WLAN_RESET_CONTROL_DEBUG_UART_RST_LSB) & WLAN_RESET_CONTROL_DEBUG_UART_RST_MASK) +#define WLAN_RESET_CONTROL_BB_COLD_RST_MSB 13 +#define WLAN_RESET_CONTROL_BB_COLD_RST_LSB 13 +#define WLAN_RESET_CONTROL_BB_COLD_RST_MASK 0x00002000 +#define WLAN_RESET_CONTROL_BB_COLD_RST_GET(x) (((x) & WLAN_RESET_CONTROL_BB_COLD_RST_MASK) >> WLAN_RESET_CONTROL_BB_COLD_RST_LSB) +#define WLAN_RESET_CONTROL_BB_COLD_RST_SET(x) (((x) << WLAN_RESET_CONTROL_BB_COLD_RST_LSB) & WLAN_RESET_CONTROL_BB_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_BB_WARM_RST_MSB 12 +#define WLAN_RESET_CONTROL_BB_WARM_RST_LSB 12 +#define WLAN_RESET_CONTROL_BB_WARM_RST_MASK 0x00001000 +#define WLAN_RESET_CONTROL_BB_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_BB_WARM_RST_MASK) >> WLAN_RESET_CONTROL_BB_WARM_RST_LSB) +#define WLAN_RESET_CONTROL_BB_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_BB_WARM_RST_LSB) & WLAN_RESET_CONTROL_BB_WARM_RST_MASK) +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_MSB 11 +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB 11 +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK 0x00000800 +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_GET(x) (((x) & WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK) >> WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB) +#define WLAN_RESET_CONTROL_CPU_INIT_RESET_SET(x) (((x) << WLAN_RESET_CONTROL_CPU_INIT_RESET_LSB) & WLAN_RESET_CONTROL_CPU_INIT_RESET_MASK) +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_MSB 10 +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB 10 +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK 0x00000400 +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_GET(x) (((x) & WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK) >> WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB) +#define WLAN_RESET_CONTROL_VMC_REMAP_RESET_SET(x) (((x) << WLAN_RESET_CONTROL_VMC_REMAP_RESET_LSB) & WLAN_RESET_CONTROL_VMC_REMAP_RESET_MASK) +#define WLAN_RESET_CONTROL_RST_OUT_MSB 9 +#define WLAN_RESET_CONTROL_RST_OUT_LSB 9 +#define WLAN_RESET_CONTROL_RST_OUT_MASK 0x00000200 +#define WLAN_RESET_CONTROL_RST_OUT_GET(x) (((x) & WLAN_RESET_CONTROL_RST_OUT_MASK) >> WLAN_RESET_CONTROL_RST_OUT_LSB) +#define WLAN_RESET_CONTROL_RST_OUT_SET(x) (((x) << WLAN_RESET_CONTROL_RST_OUT_LSB) & WLAN_RESET_CONTROL_RST_OUT_MASK) +#define WLAN_RESET_CONTROL_COLD_RST_MSB 8 +#define WLAN_RESET_CONTROL_COLD_RST_LSB 8 +#define WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000100 +#define WLAN_RESET_CONTROL_COLD_RST_GET(x) (((x) & WLAN_RESET_CONTROL_COLD_RST_MASK) >> WLAN_RESET_CONTROL_COLD_RST_LSB) +#define WLAN_RESET_CONTROL_COLD_RST_SET(x) (((x) << WLAN_RESET_CONTROL_COLD_RST_LSB) & WLAN_RESET_CONTROL_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_WARM_RST_MSB 7 +#define WLAN_RESET_CONTROL_WARM_RST_LSB 7 +#define WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000080 +#define WLAN_RESET_CONTROL_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_WARM_RST_MASK) >> WLAN_RESET_CONTROL_WARM_RST_LSB) +#define WLAN_RESET_CONTROL_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_WARM_RST_LSB) & WLAN_RESET_CONTROL_WARM_RST_MASK) +#define WLAN_RESET_CONTROL_CPU_WARM_RST_MSB 6 +#define WLAN_RESET_CONTROL_CPU_WARM_RST_LSB 6 +#define WLAN_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define WLAN_RESET_CONTROL_CPU_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_CPU_WARM_RST_MASK) >> WLAN_RESET_CONTROL_CPU_WARM_RST_LSB) +#define WLAN_RESET_CONTROL_CPU_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_CPU_WARM_RST_LSB) & WLAN_RESET_CONTROL_CPU_WARM_RST_MASK) +#define WLAN_RESET_CONTROL_MAC_COLD_RST_MSB 5 +#define WLAN_RESET_CONTROL_MAC_COLD_RST_LSB 5 +#define WLAN_RESET_CONTROL_MAC_COLD_RST_MASK 0x00000020 +#define WLAN_RESET_CONTROL_MAC_COLD_RST_GET(x) (((x) & WLAN_RESET_CONTROL_MAC_COLD_RST_MASK) >> WLAN_RESET_CONTROL_MAC_COLD_RST_LSB) +#define WLAN_RESET_CONTROL_MAC_COLD_RST_SET(x) (((x) << WLAN_RESET_CONTROL_MAC_COLD_RST_LSB) & WLAN_RESET_CONTROL_MAC_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_MAC_WARM_RST_MSB 4 +#define WLAN_RESET_CONTROL_MAC_WARM_RST_LSB 4 +#define WLAN_RESET_CONTROL_MAC_WARM_RST_MASK 0x00000010 +#define WLAN_RESET_CONTROL_MAC_WARM_RST_GET(x) (((x) & WLAN_RESET_CONTROL_MAC_WARM_RST_MASK) >> WLAN_RESET_CONTROL_MAC_WARM_RST_LSB) +#define WLAN_RESET_CONTROL_MAC_WARM_RST_SET(x) (((x) << WLAN_RESET_CONTROL_MAC_WARM_RST_LSB) & WLAN_RESET_CONTROL_MAC_WARM_RST_MASK) +#define WLAN_RESET_CONTROL_MBOX_RST_MSB 2 +#define WLAN_RESET_CONTROL_MBOX_RST_LSB 2 +#define WLAN_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define WLAN_RESET_CONTROL_MBOX_RST_GET(x) (((x) & WLAN_RESET_CONTROL_MBOX_RST_MASK) >> WLAN_RESET_CONTROL_MBOX_RST_LSB) +#define WLAN_RESET_CONTROL_MBOX_RST_SET(x) (((x) << WLAN_RESET_CONTROL_MBOX_RST_LSB) & WLAN_RESET_CONTROL_MBOX_RST_MASK) +#define WLAN_RESET_CONTROL_UART_RST_MSB 1 +#define WLAN_RESET_CONTROL_UART_RST_LSB 1 +#define WLAN_RESET_CONTROL_UART_RST_MASK 0x00000002 +#define WLAN_RESET_CONTROL_UART_RST_GET(x) (((x) & WLAN_RESET_CONTROL_UART_RST_MASK) >> WLAN_RESET_CONTROL_UART_RST_LSB) +#define WLAN_RESET_CONTROL_UART_RST_SET(x) (((x) << WLAN_RESET_CONTROL_UART_RST_LSB) & WLAN_RESET_CONTROL_UART_RST_MASK) +#define WLAN_RESET_CONTROL_SI0_RST_MSB 0 +#define WLAN_RESET_CONTROL_SI0_RST_LSB 0 +#define WLAN_RESET_CONTROL_SI0_RST_MASK 0x00000001 +#define WLAN_RESET_CONTROL_SI0_RST_GET(x) (((x) & WLAN_RESET_CONTROL_SI0_RST_MASK) >> WLAN_RESET_CONTROL_SI0_RST_LSB) +#define WLAN_RESET_CONTROL_SI0_RST_SET(x) (((x) << WLAN_RESET_CONTROL_SI0_RST_LSB) & WLAN_RESET_CONTROL_SI0_RST_MASK) + +#define WLAN_CPU_CLOCK_ADDRESS 0x00000020 +#define WLAN_CPU_CLOCK_OFFSET 0x00000020 +#define WLAN_CPU_CLOCK_STANDARD_MSB 1 +#define WLAN_CPU_CLOCK_STANDARD_LSB 0 +#define WLAN_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define WLAN_CPU_CLOCK_STANDARD_GET(x) (((x) & WLAN_CPU_CLOCK_STANDARD_MASK) >> WLAN_CPU_CLOCK_STANDARD_LSB) +#define WLAN_CPU_CLOCK_STANDARD_SET(x) (((x) << WLAN_CPU_CLOCK_STANDARD_LSB) & WLAN_CPU_CLOCK_STANDARD_MASK) + +#define WLAN_CLOCK_CONTROL_ADDRESS 0x00000028 +#define WLAN_CLOCK_CONTROL_OFFSET 0x00000028 +#define WLAN_CLOCK_CONTROL_LF_CLK32_MSB 2 +#define WLAN_CLOCK_CONTROL_LF_CLK32_LSB 2 +#define WLAN_CLOCK_CONTROL_LF_CLK32_MASK 0x00000004 +#define WLAN_CLOCK_CONTROL_LF_CLK32_GET(x) (((x) & WLAN_CLOCK_CONTROL_LF_CLK32_MASK) >> WLAN_CLOCK_CONTROL_LF_CLK32_LSB) +#define WLAN_CLOCK_CONTROL_LF_CLK32_SET(x) (((x) << WLAN_CLOCK_CONTROL_LF_CLK32_LSB) & WLAN_CLOCK_CONTROL_LF_CLK32_MASK) +#define WLAN_CLOCK_CONTROL_SI0_CLK_MSB 0 +#define WLAN_CLOCK_CONTROL_SI0_CLK_LSB 0 +#define WLAN_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define WLAN_CLOCK_CONTROL_SI0_CLK_GET(x) (((x) & WLAN_CLOCK_CONTROL_SI0_CLK_MASK) >> WLAN_CLOCK_CONTROL_SI0_CLK_LSB) +#define WLAN_CLOCK_CONTROL_SI0_CLK_SET(x) (((x) << WLAN_CLOCK_CONTROL_SI0_CLK_LSB) & WLAN_CLOCK_CONTROL_SI0_CLK_MASK) + +#define WLAN_SYSTEM_SLEEP_ADDRESS 0x000000c4 +#define WLAN_SYSTEM_SLEEP_OFFSET 0x000000c4 +#define WLAN_SYSTEM_SLEEP_HOST_IF_MSB 4 +#define WLAN_SYSTEM_SLEEP_HOST_IF_LSB 4 +#define WLAN_SYSTEM_SLEEP_HOST_IF_MASK 0x00000010 +#define WLAN_SYSTEM_SLEEP_HOST_IF_GET(x) (((x) & WLAN_SYSTEM_SLEEP_HOST_IF_MASK) >> WLAN_SYSTEM_SLEEP_HOST_IF_LSB) +#define WLAN_SYSTEM_SLEEP_HOST_IF_SET(x) (((x) << WLAN_SYSTEM_SLEEP_HOST_IF_LSB) & WLAN_SYSTEM_SLEEP_HOST_IF_MASK) +#define WLAN_SYSTEM_SLEEP_MBOX_MSB 3 +#define WLAN_SYSTEM_SLEEP_MBOX_LSB 3 +#define WLAN_SYSTEM_SLEEP_MBOX_MASK 0x00000008 +#define WLAN_SYSTEM_SLEEP_MBOX_GET(x) (((x) & WLAN_SYSTEM_SLEEP_MBOX_MASK) >> WLAN_SYSTEM_SLEEP_MBOX_LSB) +#define WLAN_SYSTEM_SLEEP_MBOX_SET(x) (((x) << WLAN_SYSTEM_SLEEP_MBOX_LSB) & WLAN_SYSTEM_SLEEP_MBOX_MASK) +#define WLAN_SYSTEM_SLEEP_MAC_IF_MSB 2 +#define WLAN_SYSTEM_SLEEP_MAC_IF_LSB 2 +#define WLAN_SYSTEM_SLEEP_MAC_IF_MASK 0x00000004 +#define WLAN_SYSTEM_SLEEP_MAC_IF_GET(x) (((x) & WLAN_SYSTEM_SLEEP_MAC_IF_MASK) >> WLAN_SYSTEM_SLEEP_MAC_IF_LSB) +#define WLAN_SYSTEM_SLEEP_MAC_IF_SET(x) (((x) << WLAN_SYSTEM_SLEEP_MAC_IF_LSB) & WLAN_SYSTEM_SLEEP_MAC_IF_MASK) +#define WLAN_SYSTEM_SLEEP_LIGHT_MSB 1 +#define WLAN_SYSTEM_SLEEP_LIGHT_LSB 1 +#define WLAN_SYSTEM_SLEEP_LIGHT_MASK 0x00000002 +#define WLAN_SYSTEM_SLEEP_LIGHT_GET(x) (((x) & WLAN_SYSTEM_SLEEP_LIGHT_MASK) >> WLAN_SYSTEM_SLEEP_LIGHT_LSB) +#define WLAN_SYSTEM_SLEEP_LIGHT_SET(x) (((x) << WLAN_SYSTEM_SLEEP_LIGHT_LSB) & WLAN_SYSTEM_SLEEP_LIGHT_MASK) +#define WLAN_SYSTEM_SLEEP_DISABLE_MSB 0 +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define WLAN_SYSTEM_SLEEP_DISABLE_GET(x) (((x) & WLAN_SYSTEM_SLEEP_DISABLE_MASK) >> WLAN_SYSTEM_SLEEP_DISABLE_LSB) +#define WLAN_SYSTEM_SLEEP_DISABLE_SET(x) (((x) << WLAN_SYSTEM_SLEEP_DISABLE_LSB) & WLAN_SYSTEM_SLEEP_DISABLE_MASK) + +#define WLAN_LPO_CAL_ADDRESS 0x000000e0 +#define WLAN_LPO_CAL_OFFSET 0x000000e0 +#define WLAN_LPO_CAL_ENABLE_MSB 20 +#define WLAN_LPO_CAL_ENABLE_LSB 20 +#define WLAN_LPO_CAL_ENABLE_MASK 0x00100000 +#define WLAN_LPO_CAL_ENABLE_GET(x) (((x) & WLAN_LPO_CAL_ENABLE_MASK) >> WLAN_LPO_CAL_ENABLE_LSB) +#define WLAN_LPO_CAL_ENABLE_SET(x) (((x) << WLAN_LPO_CAL_ENABLE_LSB) & WLAN_LPO_CAL_ENABLE_MASK) +#define WLAN_LPO_CAL_COUNT_MSB 19 +#define WLAN_LPO_CAL_COUNT_LSB 0 +#define WLAN_LPO_CAL_COUNT_MASK 0x000fffff +#define WLAN_LPO_CAL_COUNT_GET(x) (((x) & WLAN_LPO_CAL_COUNT_MASK) >> WLAN_LPO_CAL_COUNT_LSB) +#define WLAN_LPO_CAL_COUNT_SET(x) (((x) << WLAN_LPO_CAL_COUNT_LSB) & WLAN_LPO_CAL_COUNT_MASK) + +#endif /* _RTC_WLAN_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h new file mode 100644 index 000000000000..302b20bc1bad --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h @@ -0,0 +1,40 @@ +// ------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// ------------------------------------------------------------------ +//=================================================================== +// Author(s): ="Atheros" +//=================================================================== + + +#ifndef _UART_REG_REG_H_ +#define _UART_REG_REG_H_ + +#define UART_CLKDIV_ADDRESS 0x00000008 +#define UART_CLKDIV_OFFSET 0x00000008 +#define UART_CLKDIV_CLK_SCALE_MSB 23 +#define UART_CLKDIV_CLK_SCALE_LSB 16 +#define UART_CLKDIV_CLK_SCALE_MASK 0x00ff0000 +#define UART_CLKDIV_CLK_SCALE_GET(x) (((x) & UART_CLKDIV_CLK_SCALE_MASK) >> UART_CLKDIV_CLK_SCALE_LSB) +#define UART_CLKDIV_CLK_SCALE_SET(x) (((x) << UART_CLKDIV_CLK_SCALE_LSB) & UART_CLKDIV_CLK_SCALE_MASK) +#define UART_CLKDIV_CLK_STEP_MSB 15 +#define UART_CLKDIV_CLK_STEP_LSB 0 +#define UART_CLKDIV_CLK_STEP_MASK 0x0000ffff +#define UART_CLKDIV_CLK_STEP_GET(x) (((x) & UART_CLKDIV_CLK_STEP_MASK) >> UART_CLKDIV_CLK_STEP_LSB) +#define UART_CLKDIV_CLK_STEP_SET(x) (((x) << UART_CLKDIV_CLK_STEP_LSB) & UART_CLKDIV_CLK_STEP_MASK) + +#endif /* _UART_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/athdefs.h b/trunk/drivers/staging/ath6kl/include/common/athdefs.h new file mode 100644 index 000000000000..74922481e065 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/athdefs.h @@ -0,0 +1,75 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef __ATHDEFS_H__ +#define __ATHDEFS_H__ + +/* + * This file contains definitions that may be used across both + * Host and Target software. Nothing here is module-dependent + * or platform-dependent. + */ + +/* + * Generic error codes that can be used by hw, sta, ap, sim, dk + * and any other environments. + * Feel free to add any more non-zero codes that you need. + */ + +#define A_ERROR (-1) /* Generic error return */ +#define A_DEVICE_NOT_FOUND 1 /* not able to find PCI device */ +#define A_NO_MEMORY 2 /* not able to allocate memory, + * not avail#defineable */ +#define A_MEMORY_NOT_AVAIL 3 /* memory region is not free for + * mapping */ +#define A_NO_FREE_DESC 4 /* no free descriptors available */ +#define A_BAD_ADDRESS 5 /* address does not match descriptor */ +#define A_WIN_DRIVER_ERROR 6 /* used in NT_HW version, + * if problem at init */ +#define A_REGS_NOT_MAPPED 7 /* registers not correctly mapped */ +#define A_EPERM 8 /* Not superuser */ +#define A_EACCES 0 /* Access denied */ +#define A_ENOENT 10 /* No such entry, search failed, etc. */ +#define A_EEXIST 11 /* The object already exists + * (can't create) */ +#define A_EFAULT 12 /* Bad address fault */ +#define A_EBUSY 13 /* Object is busy */ +#define A_EINVAL 14 /* Invalid parameter */ +#define A_EMSGSIZE 15 /* Bad message buffer length */ +#define A_ECANCELED 16 /* Operation canceled */ +#define A_ENOTSUP 17 /* Operation not supported */ +#define A_ECOMM 18 /* Communication error on send */ +#define A_EPROTO 19 /* Protocol error */ +#define A_ENODEV 20 /* No such device */ +#define A_EDEVNOTUP 21 /* device is not UP */ +#define A_NO_RESOURCE 22 /* No resources for + * requested operation */ +#define A_HARDWARE 23 /* Hardware failure */ +#define A_PENDING 24 /* Asynchronous routine; will send up + * results later + * (typically in callback) */ +#define A_EBADCHANNEL 25 /* The channel cannot be used */ +#define A_DECRYPT_ERROR 26 /* Decryption error */ +#define A_PHY_ERROR 27 /* RX PHY error */ +#define A_CONSUMED 28 /* Object was consumed */ + +#endif /* __ATHDEFS_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/bmi_msg.h b/trunk/drivers/staging/ath6kl/include/common/bmi_msg.h new file mode 100644 index 000000000000..84e8db569a9f --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/bmi_msg.h @@ -0,0 +1,233 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef __BMI_MSG_H__ +#define __BMI_MSG_H__ + +/* + * Bootloader Messaging Interface (BMI) + * + * BMI is a very simple messaging interface used during initialization + * to read memory, write memory, execute code, and to define an + * application entry PC. + * + * It is used to download an application to AR6K, to provide + * patches to code that is already resident on AR6K, and generally + * to examine and modify state. The Host has an opportunity to use + * BMI only once during bootup. Once the Host issues a BMI_DONE + * command, this opportunity ends. + * + * The Host writes BMI requests to mailbox0, and reads BMI responses + * from mailbox0. BMI requests all begin with a command + * (see below for specific commands), and are followed by + * command-specific data. + * + * Flow control: + * The Host can only issue a command once the Target gives it a + * "BMI Command Credit", using AR6K Counter #4. As soon as the + * Target has completed a command, it issues another BMI Command + * Credit (so the Host can issue the next command). + * + * BMI handles all required Target-side cache flushing. + */ + + +/* Maximum data size used for BMI transfers */ +#define BMI_DATASZ_MAX 256 + +/* BMI Commands */ + +#define BMI_NO_COMMAND 0 + +#define BMI_DONE 1 + /* + * Semantics: Host is done using BMI + * Request format: + * u32 command (BMI_DONE) + * Response format: none + */ + +#define BMI_READ_MEMORY 2 + /* + * Semantics: Host reads AR6K memory + * Request format: + * u32 command (BMI_READ_MEMORY) + * u32 address + * u32 length, at most BMI_DATASZ_MAX + * Response format: + * u8 data[length] + */ + +#define BMI_WRITE_MEMORY 3 + /* + * Semantics: Host writes AR6K memory + * Request format: + * u32 command (BMI_WRITE_MEMORY) + * u32 address + * u32 length, at most BMI_DATASZ_MAX + * u8 data[length] + * Response format: none + */ + +#define BMI_EXECUTE 4 + /* + * Semantics: Causes AR6K to execute code + * Request format: + * u32 command (BMI_EXECUTE) + * u32 address + * u32 parameter + * Response format: + * u32 return value + */ + +#define BMI_SET_APP_START 5 + /* + * Semantics: Set Target application starting address + * Request format: + * u32 command (BMI_SET_APP_START) + * u32 address + * Response format: none + */ + +#define BMI_READ_SOC_REGISTER 6 + /* + * Semantics: Read a 32-bit Target SOC register. + * Request format: + * u32 command (BMI_READ_REGISTER) + * u32 address + * Response format: + * u32 value + */ + +#define BMI_WRITE_SOC_REGISTER 7 + /* + * Semantics: Write a 32-bit Target SOC register. + * Request format: + * u32 command (BMI_WRITE_REGISTER) + * u32 address + * u32 value + * + * Response format: none + */ + +#define BMI_GET_TARGET_ID 8 +#define BMI_GET_TARGET_INFO 8 + /* + * Semantics: Fetch the 4-byte Target information + * Request format: + * u32 command (BMI_GET_TARGET_ID/INFO) + * Response format1 (old firmware): + * u32 TargetVersionID + * Response format2 (newer firmware): + * u32 TARGET_VERSION_SENTINAL + * struct bmi_target_info; + */ + +PREPACK struct bmi_target_info { + u32 target_info_byte_count; /* size of this structure */ + u32 target_ver; /* Target Version ID */ + u32 target_type; /* Target type */ +} POSTPACK; +#define TARGET_VERSION_SENTINAL 0xffffffff +#define TARGET_TYPE_AR6001 1 +#define TARGET_TYPE_AR6002 2 +#define TARGET_TYPE_AR6003 3 + + +#define BMI_ROMPATCH_INSTALL 9 + /* + * Semantics: Install a ROM Patch. + * Request format: + * u32 command (BMI_ROMPATCH_INSTALL) + * u32 Target ROM Address + * u32 Target RAM Address or Value (depending on Target Type) + * u32 Size, in bytes + * u32 Activate? 1-->activate; + * 0-->install but do not activate + * Response format: + * u32 PatchID + */ + +#define BMI_ROMPATCH_UNINSTALL 10 + /* + * Semantics: Uninstall a previously-installed ROM Patch, + * automatically deactivating, if necessary. + * Request format: + * u32 command (BMI_ROMPATCH_UNINSTALL) + * u32 PatchID + * + * Response format: none + */ + +#define BMI_ROMPATCH_ACTIVATE 11 + /* + * Semantics: Activate a list of previously-installed ROM Patches. + * Request format: + * u32 command (BMI_ROMPATCH_ACTIVATE) + * u32 rompatch_count + * u32 PatchID[rompatch_count] + * + * Response format: none + */ + +#define BMI_ROMPATCH_DEACTIVATE 12 + /* + * Semantics: Deactivate a list of active ROM Patches. + * Request format: + * u32 command (BMI_ROMPATCH_DEACTIVATE) + * u32 rompatch_count + * u32 PatchID[rompatch_count] + * + * Response format: none + */ + + +#define BMI_LZ_STREAM_START 13 + /* + * Semantics: Begin an LZ-compressed stream of input + * which is to be uncompressed by the Target to an + * output buffer at address. The output buffer must + * be sufficiently large to hold the uncompressed + * output from the compressed input stream. This BMI + * command should be followed by a series of 1 or more + * BMI_LZ_DATA commands. + * u32 command (BMI_LZ_STREAM_START) + * u32 address + * Note: Not supported on all versions of ROM firmware. + */ + +#define BMI_LZ_DATA 14 + /* + * Semantics: Host writes AR6K memory with LZ-compressed + * data which is uncompressed by the Target. This command + * must be preceded by a BMI_LZ_STREAM_START command. A series + * of BMI_LZ_DATA commands are considered part of a single + * input stream until another BMI_LZ_STREAM_START is issued. + * Request format: + * u32 command (BMI_LZ_DATA) + * u32 length (of compressed data), + * at most BMI_DATASZ_MAX + * u8 CompressedData[length] + * Response format: none + * Note: Not supported on all versions of ROM firmware. + */ + +#endif /* __BMI_MSG_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/cnxmgmt.h b/trunk/drivers/staging/ath6kl/include/common/cnxmgmt.h new file mode 100644 index 000000000000..7a902cb54831 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/cnxmgmt.h @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _CNXMGMT_H_ +#define _CNXMGMT_H_ + +typedef enum { + CM_CONNECT_WITHOUT_SCAN = 0x0001, + CM_CONNECT_ASSOC_POLICY_USER = 0x0002, + CM_CONNECT_SEND_REASSOC = 0x0004, + CM_CONNECT_WITHOUT_ROAMTABLE_UPDATE = 0x0008, + CM_CONNECT_DO_WPA_OFFLOAD = 0x0010, + CM_CONNECT_DO_NOT_DEAUTH = 0x0020, +} CM_CONNECT_TYPE; + +#endif /* _CNXMGMT_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/dbglog.h b/trunk/drivers/staging/ath6kl/include/common/dbglog.h new file mode 100644 index 000000000000..5566e568b83d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/dbglog.h @@ -0,0 +1,126 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _DBGLOG_H_ +#define _DBGLOG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define DBGLOG_TIMESTAMP_OFFSET 0 +#define DBGLOG_TIMESTAMP_MASK 0x0000FFFF /* Bit 0-15. Contains bit + 8-23 of the LF0 timer */ +#define DBGLOG_DBGID_OFFSET 16 +#define DBGLOG_DBGID_MASK 0x03FF0000 /* Bit 16-25 */ +#define DBGLOG_DBGID_NUM_MAX 256 /* Upper limit is width of mask */ + +#define DBGLOG_MODULEID_OFFSET 26 +#define DBGLOG_MODULEID_MASK 0x3C000000 /* Bit 26-29 */ +#define DBGLOG_MODULEID_NUM_MAX 16 /* Upper limit is width of mask */ + +/* + * Please ensure that the definition of any new module introduced is captured + * between the DBGLOG_MODULEID_START and DBGLOG_MODULEID_END defines. The + * structure is required for the parser to correctly pick up the values for + * different modules. + */ +#define DBGLOG_MODULEID_START +#define DBGLOG_MODULEID_INF 0 +#define DBGLOG_MODULEID_WMI 1 +#define DBGLOG_MODULEID_MISC 2 +#define DBGLOG_MODULEID_PM 3 +#define DBGLOG_MODULEID_TXRX_MGMTBUF 4 +#define DBGLOG_MODULEID_TXRX_TXBUF 5 +#define DBGLOG_MODULEID_TXRX_RXBUF 6 +#define DBGLOG_MODULEID_WOW 7 +#define DBGLOG_MODULEID_WHAL 8 +#define DBGLOG_MODULEID_DC 9 +#define DBGLOG_MODULEID_CO 10 +#define DBGLOG_MODULEID_RO 11 +#define DBGLOG_MODULEID_CM 12 +#define DBGLOG_MODULEID_MGMT 13 +#define DBGLOG_MODULEID_TMR 14 +#define DBGLOG_MODULEID_BTCOEX 15 +#define DBGLOG_MODULEID_END + +#define DBGLOG_NUM_ARGS_OFFSET 30 +#define DBGLOG_NUM_ARGS_MASK 0xC0000000 /* Bit 30-31 */ +#define DBGLOG_NUM_ARGS_MAX 2 /* Upper limit is width of mask */ + +#define DBGLOG_MODULE_LOG_ENABLE_OFFSET 0 +#define DBGLOG_MODULE_LOG_ENABLE_MASK 0x0000FFFF + +#define DBGLOG_REPORTING_ENABLED_OFFSET 16 +#define DBGLOG_REPORTING_ENABLED_MASK 0x00010000 + +#define DBGLOG_TIMESTAMP_RESOLUTION_OFFSET 17 +#define DBGLOG_TIMESTAMP_RESOLUTION_MASK 0x000E0000 + +#define DBGLOG_REPORT_SIZE_OFFSET 20 +#define DBGLOG_REPORT_SIZE_MASK 0x3FF00000 + +#define DBGLOG_LOG_BUFFER_SIZE 1500 +#define DBGLOG_DBGID_DEFINITION_LEN_MAX 90 + +PREPACK struct dbglog_buf_s { + struct dbglog_buf_s *next; + u8 *buffer; + u32 bufsize; + u32 length; + u32 count; + u32 free; +} POSTPACK; + +PREPACK struct dbglog_hdr_s { + struct dbglog_buf_s *dbuf; + u32 dropped; +} POSTPACK; + +PREPACK struct dbglog_config_s { + u32 cfgvalid; /* Mask with valid config bits */ + union { + /* TODO: Take care of endianness */ + struct { + u32 mmask:16; /* Mask of modules with logging on */ + u32 rep:1; /* Reporting enabled or not */ + u32 tsr:3; /* Time stamp resolution. Def: 1 ms */ + u32 size:10; /* Report size in number of messages */ + u32 reserved:2; + } dbglog_config; + + u32 value; + } u; +} POSTPACK; + +#define cfgmmask u.dbglog_config.mmask +#define cfgrep u.dbglog_config.rep +#define cfgtsr u.dbglog_config.tsr +#define cfgsize u.dbglog_config.size +#define cfgvalue u.value + +#ifdef __cplusplus +} +#endif + +#endif /* _DBGLOG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/dbglog_id.h b/trunk/drivers/staging/ath6kl/include/common/dbglog_id.h new file mode 100644 index 000000000000..15ef829cab20 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/dbglog_id.h @@ -0,0 +1,558 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _DBGLOG_ID_H_ +#define _DBGLOG_ID_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The nomenclature for the debug identifiers is MODULE_DESCRIPTION. + * Please ensure that the definition of any new debugid introduced is captured + * between the _DBGID_DEFINITION_START and + * _DBGID_DEFINITION_END defines. The structure is required for the + * parser to correctly pick up the values for different debug identifiers. + */ + +/* INF debug identifier definitions */ +#define INF_DBGID_DEFINITION_START +#define INF_ASSERTION_FAILED 1 +#define INF_TARGET_ID 2 +#define INF_DBGID_DEFINITION_END + +/* WMI debug identifier definitions */ +#define WMI_DBGID_DEFINITION_START +#define WMI_CMD_RX_XTND_PKT_TOO_SHORT 1 +#define WMI_EXTENDED_CMD_NOT_HANDLED 2 +#define WMI_CMD_RX_PKT_TOO_SHORT 3 +#define WMI_CALLING_WMI_EXTENSION_FN 4 +#define WMI_CMD_NOT_HANDLED 5 +#define WMI_IN_SYNC 6 +#define WMI_TARGET_WMI_SYNC_CMD 7 +#define WMI_SET_SNR_THRESHOLD_PARAMS 8 +#define WMI_SET_RSSI_THRESHOLD_PARAMS 9 +#define WMI_SET_LQ_TRESHOLD_PARAMS 10 +#define WMI_TARGET_CREATE_PSTREAM_CMD 11 +#define WMI_WI_DTM_INUSE 12 +#define WMI_TARGET_DELETE_PSTREAM_CMD 13 +#define WMI_TARGET_IMPLICIT_DELETE_PSTREAM_CMD 14 +#define WMI_TARGET_GET_BIT_RATE_CMD 15 +#define WMI_GET_RATE_MASK_CMD_FIX_RATE_MASK_IS 16 +#define WMI_TARGET_GET_AVAILABLE_CHANNELS_CMD 17 +#define WMI_TARGET_GET_TX_PWR_CMD 18 +#define WMI_FREE_EVBUF_WMIBUF 19 +#define WMI_FREE_EVBUF_DATABUF 20 +#define WMI_FREE_EVBUF_BADFLAG 21 +#define WMI_HTC_RX_ERROR_DATA_PACKET 22 +#define WMI_HTC_RX_SYNC_PAUSING_FOR_MBOX 23 +#define WMI_INCORRECT_WMI_DATA_HDR_DROPPING_PKT 24 +#define WMI_SENDING_READY_EVENT 25 +#define WMI_SETPOWER_MDOE_TO_MAXPERF 26 +#define WMI_SETPOWER_MDOE_TO_REC 27 +#define WMI_BSSINFO_EVENT_FROM 28 +#define WMI_TARGET_GET_STATS_CMD 29 +#define WMI_SENDING_SCAN_COMPLETE_EVENT 30 +#define WMI_SENDING_RSSI_INDB_THRESHOLD_EVENT 31 +#define WMI_SENDING_RSSI_INDBM_THRESHOLD_EVENT 32 +#define WMI_SENDING_LINK_QUALITY_THRESHOLD_EVENT 33 +#define WMI_SENDING_ERROR_REPORT_EVENT 34 +#define WMI_SENDING_CAC_EVENT 35 +#define WMI_TARGET_GET_ROAM_TABLE_CMD 36 +#define WMI_TARGET_GET_ROAM_DATA_CMD 37 +#define WMI_SENDING_GPIO_INTR_EVENT 38 +#define WMI_SENDING_GPIO_ACK_EVENT 39 +#define WMI_SENDING_GPIO_DATA_EVENT 40 +#define WMI_CMD_RX 41 +#define WMI_CMD_RX_XTND 42 +#define WMI_EVENT_SEND 43 +#define WMI_EVENT_SEND_XTND 44 +#define WMI_CMD_PARAMS_DUMP_START 45 +#define WMI_CMD_PARAMS_DUMP_END 46 +#define WMI_CMD_PARAMS 47 +#define WMI_DBGID_DEFINITION_END + +/* MISC debug identifier definitions */ +#define MISC_DBGID_DEFINITION_START +#define MISC_WLAN_SCHEDULER_EVENT_REGISTER_ERROR 1 +#define TLPM_INIT 2 +#define TLPM_FILTER_POWER_STATE 3 +#define TLPM_NOTIFY_NOT_IDLE 4 +#define TLPM_TIMEOUT_IDLE_HANDLER 5 +#define TLPM_TIMEOUT_WAKEUP_HANDLER 6 +#define TLPM_WAKEUP_SIGNAL_HANDLER 7 +#define TLPM_UNEXPECTED_GPIO_INTR_ERROR 8 +#define TLPM_BREAK_ON_NOT_RECEIVED_ERROR 9 +#define TLPM_BREAK_OFF_NOT_RECIVED_ERROR 10 +#define TLPM_ACK_GPIO_INTR 11 +#define TLPM_ON 12 +#define TLPM_OFF 13 +#define TLPM_WAKEUP_FROM_HOST 14 +#define TLPM_WAKEUP_FROM_BT 15 +#define TLPM_TX_BREAK_RECIVED 16 +#define TLPM_IDLE_TIMER_NOT_RUNNING 17 +#define MISC_DBGID_DEFINITION_END + +/* TXRX debug identifier definitions */ +#define TXRX_TXBUF_DBGID_DEFINITION_START +#define TXRX_TXBUF_ALLOCATE_BUF 1 +#define TXRX_TXBUF_QUEUE_BUF_TO_MBOX 2 +#define TXRX_TXBUF_QUEUE_BUF_TO_TXQ 3 +#define TXRX_TXBUF_TXQ_DEPTH 4 +#define TXRX_TXBUF_IBSS_QUEUE_TO_SFQ 5 +#define TXRX_TXBUF_IBSS_QUEUE_TO_TXQ_FRM_SFQ 6 +#define TXRX_TXBUF_INITIALIZE_TIMER 7 +#define TXRX_TXBUF_ARM_TIMER 8 +#define TXRX_TXBUF_DISARM_TIMER 9 +#define TXRX_TXBUF_UNINITIALIZE_TIMER 10 +#define TXRX_TXBUF_DBGID_DEFINITION_END + +#define TXRX_RXBUF_DBGID_DEFINITION_START +#define TXRX_RXBUF_ALLOCATE_BUF 1 +#define TXRX_RXBUF_QUEUE_TO_HOST 2 +#define TXRX_RXBUF_QUEUE_TO_WLAN 3 +#define TXRX_RXBUF_ZERO_LEN_BUF 4 +#define TXRX_RXBUF_QUEUE_TO_HOST_LASTBUF_IN_RXCHAIN 5 +#define TXRX_RXBUF_LASTBUF_IN_RXCHAIN_ZEROBUF 6 +#define TXRX_RXBUF_QUEUE_EMPTY_QUEUE_TO_WLAN 7 +#define TXRX_RXBUF_SEND_TO_RECV_MGMT 8 +#define TXRX_RXBUF_SEND_TO_IEEE_LAYER 9 +#define TXRX_RXBUF_REQUEUE_ERROR 10 +#define TXRX_RXBUF_DBGID_DEFINITION_END + +#define TXRX_MGMTBUF_DBGID_DEFINITION_START +#define TXRX_MGMTBUF_ALLOCATE_BUF 1 +#define TXRX_MGMTBUF_ALLOCATE_SM_BUF 2 +#define TXRX_MGMTBUF_ALLOCATE_RMBUF 3 +#define TXRX_MGMTBUF_GET_BUF 4 +#define TXRX_MGMTBUF_GET_SM_BUF 5 +#define TXRX_MGMTBUF_QUEUE_BUF_TO_TXQ 6 +#define TXRX_MGMTBUF_REAPED_BUF 7 +#define TXRX_MGMTBUF_REAPED_SM_BUF 8 +#define TXRX_MGMTBUF_WAIT_FOR_TXQ_DRAIN 9 +#define TXRX_MGMTBUF_WAIT_FOR_TXQ_SFQ_DRAIN 10 +#define TXRX_MGMTBUF_ENQUEUE_INTO_DATA_SFQ 11 +#define TXRX_MGMTBUF_DEQUEUE_FROM_DATA_SFQ 12 +#define TXRX_MGMTBUF_PAUSE_DATA_TXQ 13 +#define TXRX_MGMTBUF_RESUME_DATA_TXQ 14 +#define TXRX_MGMTBUF_WAIT_FORTXQ_DRAIN_TIMEOUT 15 +#define TXRX_MGMTBUF_DRAINQ 16 +#define TXRX_MGMTBUF_INDICATE_Q_DRAINED 17 +#define TXRX_MGMTBUF_ENQUEUE_INTO_HW_SFQ 18 +#define TXRX_MGMTBUF_DEQUEUE_FROM_HW_SFQ 19 +#define TXRX_MGMTBUF_PAUSE_HW_TXQ 20 +#define TXRX_MGMTBUF_RESUME_HW_TXQ 21 +#define TXRX_MGMTBUF_TEAR_DOWN_BA 22 +#define TXRX_MGMTBUF_PROCESS_ADDBA_REQ 23 +#define TXRX_MGMTBUF_PROCESS_DELBA 24 +#define TXRX_MGMTBUF_PERFORM_BA 25 +#define TXRX_MGMTBUF_WLAN_RESET_ON_ERROR 26 +#define TXRX_MGMTBUF_DBGID_DEFINITION_END + +/* PM (Power Module) debug identifier definitions */ +#define PM_DBGID_DEFINITION_START +#define PM_INIT 1 +#define PM_ENABLE 2 +#define PM_SET_STATE 3 +#define PM_SET_POWERMODE 4 +#define PM_CONN_NOTIFY 5 +#define PM_REF_COUNT_NEGATIVE 6 +#define PM_INFRA_STA_APSD_ENABLE 7 +#define PM_INFRA_STA_UPDATE_APSD_STATE 8 +#define PM_CHAN_OP_REQ 9 +#define PM_SET_MY_BEACON_POLICY 10 +#define PM_SET_ALL_BEACON_POLICY 11 +#define PM_INFRA_STA_SET_PM_PARAMS1 12 +#define PM_INFRA_STA_SET_PM_PARAMS2 13 +#define PM_ADHOC_SET_PM_CAPS_FAIL 14 +#define PM_ADHOC_UNKNOWN_IBSS_ATTRIB_ID 15 +#define PM_ADHOC_SET_PM_PARAMS 16 +#define PM_ADHOC_STATE1 18 +#define PM_ADHOC_STATE2 19 +#define PM_ADHOC_CONN_MAP 20 +#define PM_FAKE_SLEEP 21 +#define PM_AP_STATE1 22 +#define PM_AP_SET_PM_PARAMS 23 +#define PM_DBGID_DEFINITION_END + +/* Wake on Wireless debug identifier definitions */ +#define WOW_DBGID_DEFINITION_START +#define WOW_INIT 1 +#define WOW_GET_CONFIG_DSET 2 +#define WOW_NO_CONFIG_DSET 3 +#define WOW_INVALID_CONFIG_DSET 4 +#define WOW_USE_DEFAULT_CONFIG 5 +#define WOW_SETUP_GPIO 6 +#define WOW_INIT_DONE 7 +#define WOW_SET_GPIO_PIN 8 +#define WOW_CLEAR_GPIO_PIN 9 +#define WOW_SET_WOW_MODE_CMD 10 +#define WOW_SET_HOST_MODE_CMD 11 +#define WOW_ADD_WOW_PATTERN_CMD 12 +#define WOW_NEW_WOW_PATTERN_AT_INDEX 13 +#define WOW_DEL_WOW_PATTERN_CMD 14 +#define WOW_LIST_CONTAINS_PATTERNS 15 +#define WOW_GET_WOW_LIST_CMD 16 +#define WOW_INVALID_FILTER_ID 17 +#define WOW_INVALID_FILTER_LISTID 18 +#define WOW_NO_VALID_FILTER_AT_ID 19 +#define WOW_NO_VALID_LIST_AT_ID 20 +#define WOW_NUM_PATTERNS_EXCEEDED 21 +#define WOW_NUM_LISTS_EXCEEDED 22 +#define WOW_GET_WOW_STATS 23 +#define WOW_CLEAR_WOW_STATS 24 +#define WOW_WAKEUP_HOST 25 +#define WOW_EVENT_WAKEUP_HOST 26 +#define WOW_EVENT_DISCARD 27 +#define WOW_PATTERN_MATCH 28 +#define WOW_PATTERN_NOT_MATCH 29 +#define WOW_PATTERN_NOT_MATCH_OFFSET 30 +#define WOW_DISABLED_HOST_ASLEEP 31 +#define WOW_ENABLED_HOST_ASLEEP_NO_PATTERNS 32 +#define WOW_ENABLED_HOST_ASLEEP_NO_MATCH_FOUND 33 +#define WOW_DBGID_DEFINITION_END + +/* WHAL debug identifier definitions */ +#define WHAL_DBGID_DEFINITION_START +#define WHAL_ERROR_ANI_CONTROL 1 +#define WHAL_ERROR_CHIP_TEST1 2 +#define WHAL_ERROR_CHIP_TEST2 3 +#define WHAL_ERROR_EEPROM_CHECKSUM 4 +#define WHAL_ERROR_EEPROM_MACADDR 5 +#define WHAL_ERROR_INTERRUPT_HIU 6 +#define WHAL_ERROR_KEYCACHE_RESET 7 +#define WHAL_ERROR_KEYCACHE_SET 8 +#define WHAL_ERROR_KEYCACHE_TYPE 9 +#define WHAL_ERROR_KEYCACHE_TKIPENTRY 10 +#define WHAL_ERROR_KEYCACHE_WEPLENGTH 11 +#define WHAL_ERROR_PHY_INVALID_CHANNEL 12 +#define WHAL_ERROR_POWER_AWAKE 13 +#define WHAL_ERROR_POWER_SET 14 +#define WHAL_ERROR_RECV_STOPDMA 15 +#define WHAL_ERROR_RECV_STOPPCU 16 +#define WHAL_ERROR_RESET_CHANNF1 17 +#define WHAL_ERROR_RESET_CHANNF2 18 +#define WHAL_ERROR_RESET_PM 19 +#define WHAL_ERROR_RESET_OFFSETCAL 20 +#define WHAL_ERROR_RESET_RFGRANT 21 +#define WHAL_ERROR_RESET_RXFRAME 22 +#define WHAL_ERROR_RESET_STOPDMA 23 +#define WHAL_ERROR_RESET_RECOVER 24 +#define WHAL_ERROR_XMIT_COMPUTE 25 +#define WHAL_ERROR_XMIT_NOQUEUE 26 +#define WHAL_ERROR_XMIT_ACTIVEQUEUE 27 +#define WHAL_ERROR_XMIT_BADTYPE 28 +#define WHAL_ERROR_XMIT_STOPDMA 29 +#define WHAL_ERROR_INTERRUPT_BB_PANIC 30 +#define WHAL_ERROR_RESET_TXIQCAL 31 +#define WHAL_ERROR_PAPRD_MAXGAIN_ABOVE_WINDOW 32 +#define WHAL_DBGID_DEFINITION_END + +/* DC debug identifier definitions */ +#define DC_DBGID_DEFINITION_START +#define DC_SCAN_CHAN_START 1 +#define DC_SCAN_CHAN_FINISH 2 +#define DC_BEACON_RECEIVE7 3 +#define DC_SSID_PROBE_CB 4 +#define DC_SEND_NEXT_SSID_PROBE 5 +#define DC_START_SEARCH 6 +#define DC_CANCEL_SEARCH_CB 7 +#define DC_STOP_SEARCH 8 +#define DC_END_SEARCH 9 +#define DC_MIN_CHDWELL_TIMEOUT 10 +#define DC_START_SEARCH_CANCELED 11 +#define DC_SET_POWER_MODE 12 +#define DC_INIT 13 +#define DC_SEARCH_OPPORTUNITY 14 +#define DC_RECEIVED_ANY_BEACON 15 +#define DC_RECEIVED_MY_BEACON 16 +#define DC_PROFILE_IS_ADHOC_BUT_BSS_IS_INFRA 17 +#define DC_PS_ENABLED_BUT_ATHEROS_IE_ABSENT 18 +#define DC_BSS_ADHOC_CHANNEL_NOT_ALLOWED 19 +#define DC_SET_BEACON_UPDATE 20 +#define DC_BEACON_UPDATE_COMPLETE 21 +#define DC_END_SEARCH_BEACON_UPDATE_COMP_CB 22 +#define DC_BSSINFO_EVENT_DROPPED 23 +#define DC_IEEEPS_ENABLED_BUT_ATIM_ABSENT 24 +#define DC_DBGID_DEFINITION_END + +/* CO debug identifier definitions */ +#define CO_DBGID_DEFINITION_START +#define CO_INIT 1 +#define CO_ACQUIRE_LOCK 2 +#define CO_START_OP1 3 +#define CO_START_OP2 4 +#define CO_DRAIN_TX_COMPLETE_CB 5 +#define CO_CHANGE_CHANNEL_CB 6 +#define CO_RETURN_TO_HOME_CHANNEL 7 +#define CO_FINISH_OP_TIMEOUT 8 +#define CO_OP_END 9 +#define CO_CANCEL_OP 10 +#define CO_CHANGE_CHANNEL 11 +#define CO_RELEASE_LOCK 12 +#define CO_CHANGE_STATE 13 +#define CO_DBGID_DEFINITION_END + +/* RO debug identifier definitions */ +#define RO_DBGID_DEFINITION_START +#define RO_REFRESH_ROAM_TABLE 1 +#define RO_UPDATE_ROAM_CANDIDATE 2 +#define RO_UPDATE_ROAM_CANDIDATE_CB 3 +#define RO_UPDATE_ROAM_CANDIDATE_FINISH 4 +#define RO_REFRESH_ROAM_TABLE_DONE 5 +#define RO_PERIODIC_SEARCH_CB 6 +#define RO_PERIODIC_SEARCH_TIMEOUT 7 +#define RO_INIT 8 +#define RO_BMISS_STATE1 9 +#define RO_BMISS_STATE2 10 +#define RO_SET_PERIODIC_SEARCH_ENABLE 11 +#define RO_SET_PERIODIC_SEARCH_DISABLE 12 +#define RO_ENABLE_SQ_THRESHOLD 13 +#define RO_DISABLE_SQ_THRESHOLD 14 +#define RO_ADD_BSS_TO_ROAM_TABLE 15 +#define RO_SET_PERIODIC_SEARCH_MODE 16 +#define RO_CONFIGURE_SQ_THRESHOLD1 17 +#define RO_CONFIGURE_SQ_THRESHOLD2 18 +#define RO_CONFIGURE_SQ_PARAMS 19 +#define RO_LOW_SIGNAL_QUALITY_EVENT 20 +#define RO_HIGH_SIGNAL_QUALITY_EVENT 21 +#define RO_REMOVE_BSS_FROM_ROAM_TABLE 22 +#define RO_UPDATE_CONNECTION_STATE_METRIC 23 +#define RO_DBGID_DEFINITION_END + +/* CM debug identifier definitions */ +#define CM_DBGID_DEFINITION_START +#define CM_INITIATE_HANDOFF 1 +#define CM_INITIATE_HANDOFF_CB 2 +#define CM_CONNECT_EVENT 3 +#define CM_DISCONNECT_EVENT 4 +#define CM_INIT 5 +#define CM_HANDOFF_SOURCE 6 +#define CM_SET_HANDOFF_TRIGGERS 7 +#define CM_CONNECT_REQUEST 8 +#define CM_CONNECT_REQUEST_CB 9 +#define CM_CONTINUE_SCAN_CB 10 +#define CM_DBGID_DEFINITION_END + + +/* mgmt debug identifier definitions */ +#define MGMT_DBGID_DEFINITION_START +#define KEYMGMT_CONNECTION_INIT 1 +#define KEYMGMT_CONNECTION_COMPLETE 2 +#define KEYMGMT_CONNECTION_CLOSE 3 +#define KEYMGMT_ADD_KEY 4 +#define MLME_NEW_STATE 5 +#define MLME_CONN_INIT 6 +#define MLME_CONN_COMPLETE 7 +#define MLME_CONN_CLOSE 8 +#define MGMT_DBGID_DEFINITION_END + +/* TMR debug identifier definitions */ +#define TMR_DBGID_DEFINITION_START +#define TMR_HANG_DETECTED 1 +#define TMR_WDT_TRIGGERED 2 +#define TMR_WDT_RESET 3 +#define TMR_HANDLER_ENTRY 4 +#define TMR_HANDLER_EXIT 5 +#define TMR_SAVED_START 6 +#define TMR_SAVED_END 7 +#define TMR_DBGID_DEFINITION_END + +/* BTCOEX debug identifier definitions */ +#define BTCOEX_DBGID_DEFINITION_START +#define BTCOEX_STATUS_CMD 1 +#define BTCOEX_PARAMS_CMD 2 +#define BTCOEX_ANT_CONFIG 3 +#define BTCOEX_COLOCATED_BT_DEVICE 4 +#define BTCOEX_CLOSE_RANGE_SCO_ON 5 +#define BTCOEX_CLOSE_RANGE_SCO_OFF 6 +#define BTCOEX_CLOSE_RANGE_A2DP_ON 7 +#define BTCOEX_CLOSE_RANGE_A2DP_OFF 8 +#define BTCOEX_A2DP_PROTECT_ON 9 +#define BTCOEX_A2DP_PROTECT_OFF 10 +#define BTCOEX_SCO_PROTECT_ON 11 +#define BTCOEX_SCO_PROTECT_OFF 12 +#define BTCOEX_CLOSE_RANGE_DETECTOR_START 13 +#define BTCOEX_CLOSE_RANGE_DETECTOR_STOP 14 +#define BTCOEX_CLOSE_RANGE_TOGGLE 15 +#define BTCOEX_CLOSE_RANGE_TOGGLE_RSSI_LRCNT 16 +#define BTCOEX_CLOSE_RANGE_RSSI_THRESH 17 +#define BTCOEX_CLOSE_RANGE_LOW_RATE_THRESH 18 +#define BTCOEX_PTA_PRI_INTR_HANDLER 19 +#define BTCOEX_PSPOLL_QUEUED 20 +#define BTCOEX_PSPOLL_COMPLETE 21 +#define BTCOEX_DBG_PM_AWAKE 22 +#define BTCOEX_DBG_PM_SLEEP 23 +#define BTCOEX_DBG_SCO_COEX_ON 24 +#define BTCOEX_SCO_DATARECEIVE 25 +#define BTCOEX_INTR_INIT 26 +#define BTCOEX_PTA_PRI_DIFF 27 +#define BTCOEX_TIM_NOTIFICATION 28 +#define BTCOEX_SCO_WAKEUP_ON_DATA 29 +#define BTCOEX_SCO_SLEEP 30 +#define BTCOEX_SET_WEIGHTS 31 +#define BTCOEX_SCO_DATARECEIVE_LATENCY_VAL 32 +#define BTCOEX_SCO_MEASURE_TIME_DIFF 33 +#define BTCOEX_SET_EOL_VAL 34 +#define BTCOEX_OPT_DETECT_HANDLER 35 +#define BTCOEX_SCO_TOGGLE_STATE 36 +#define BTCOEX_SCO_STOMP 37 +#define BTCOEX_NULL_COMP_CALLBACK 38 +#define BTCOEX_RX_INCOMING 39 +#define BTCOEX_RX_INCOMING_CTL 40 +#define BTCOEX_RX_INCOMING_MGMT 41 +#define BTCOEX_RX_INCOMING_DATA 42 +#define BTCOEX_RTS_RECEPTION 43 +#define BTCOEX_FRAME_PRI_LOW_RATE_THRES 44 +#define BTCOEX_PM_FAKE_SLEEP 45 +#define BTCOEX_ACL_COEX_STATUS 46 +#define BTCOEX_ACL_COEX_DETECTION 47 +#define BTCOEX_A2DP_COEX_STATUS 48 +#define BTCOEX_SCO_STATUS 49 +#define BTCOEX_WAKEUP_ON_DATA 50 +#define BTCOEX_DATARECEIVE 51 +#define BTCOEX_GET_MAX_AGGR_SIZE 53 +#define BTCOEX_MAX_AGGR_AVAIL_TIME 54 +#define BTCOEX_DBG_WBTIMER_INTR 55 +#define BTCOEX_DBG_SCO_SYNC 57 +#define BTCOEX_UPLINK_QUEUED_RATE 59 +#define BTCOEX_DBG_UPLINK_ENABLE_EOL 60 +#define BTCOEX_UPLINK_FRAME_DURATION 61 +#define BTCOEX_UPLINK_SET_EOL 62 +#define BTCOEX_DBG_EOL_EXPIRED 63 +#define BTCOEX_DBG_DATA_COMPLETE 64 +#define BTCOEX_UPLINK_QUEUED_TIMESTAMP 65 +#define BTCOEX_DBG_DATA_COMPLETE_TIME 66 +#define BTCOEX_DBG_A2DP_ROLE_IS_SLAVE 67 +#define BTCOEX_DBG_A2DP_ROLE_IS_MASTER 68 +#define BTCOEX_DBG_UPLINK_SEQ_NUM 69 +#define BTCOEX_UPLINK_AGGR_SEQ 70 +#define BTCOEX_DBG_TX_COMP_SEQ_NO 71 +#define BTCOEX_DBG_MAX_AGGR_PAUSE_STATE 72 +#define BTCOEX_DBG_ACL_TRAFFIC 73 +#define BTCOEX_CURR_AGGR_PROP 74 +#define BTCOEX_DBG_SCO_GET_PER_TIME_DIFF 75 +#define BTCOEX_PSPOLL_PROCESS 76 +#define BTCOEX_RETURN_FROM_MAC 77 +#define BTCOEX_FREED_REQUEUED_CNT 78 +#define BTCOEX_DBG_TOGGLE_LOW_RATES 79 +#define BTCOEX_MAC_GOES_TO_SLEEP 80 +#define BTCOEX_DBG_A2DP_NO_SYNC 81 +#define BTCOEX_RETURN_FROM_MAC_HOLD_Q_INFO 82 +#define BTCOEX_RETURN_FROM_MAC_AC 83 +#define BTCOEX_DBG_DTIM_RECV 84 +#define BTCOEX_IS_PRE_UPDATE 86 +#define BTCOEX_ENQUEUED_BIT_MAP 87 +#define BTCOEX_TX_COMPLETE_FIRST_DESC_STATS 88 +#define BTCOEX_UPLINK_DESC 89 +#define BTCOEX_SCO_GET_PER_FIRST_FRM_TIMESTAMP 90 +#define BTCOEX_DBG_RECV_ACK 94 +#define BTCOEX_DBG_ADDBA_INDICATION 95 +#define BTCOEX_TX_COMPLETE_EOL_FAILED 96 +#define BTCOEX_DBG_A2DP_USAGE_COMPLETE 97 +#define BTCOEX_DBG_A2DP_STOMP_FOR_BCN_HANDLER 98 +#define BTCOEX_DBG_A2DP_SYNC_INTR 99 +#define BTCOEX_DBG_A2DP_STOMP_FOR_BCN_RECEPTION 100 +#define BTCOEX_FORM_AGGR_CURR_AGGR 101 +#define BTCOEX_DBG_TOGGLE_A2DP_BURST_CNT 102 +#define BTCOEX_DBG_BT_TRAFFIC 103 +#define BTCOEX_DBG_STOMP_BT_TRAFFIC 104 +#define BTCOEX_RECV_NULL 105 +#define BTCOEX_DBG_A2DP_MASTER_BT_END 106 +#define BTCOEX_DBG_A2DP_BT_START 107 +#define BTCOEX_DBG_A2DP_SLAVE_BT_END 108 +#define BTCOEX_DBG_A2DP_STOMP_BT 109 +#define BTCOEX_DBG_GO_TO_SLEEP 110 +#define BTCOEX_DBG_A2DP_PKT 111 +#define BTCOEX_DBG_A2DP_PSPOLL_DATA_RECV 112 +#define BTCOEX_DBG_A2DP_NULL 113 +#define BTCOEX_DBG_UPLINK_DATA 114 +#define BTCOEX_DBG_A2DP_STOMP_LOW_PRIO_NULL 115 +#define BTCOEX_DBG_ADD_BA_RESP_TIMEOUT 116 +#define BTCOEX_DBG_TXQ_STATE 117 +#define BTCOEX_DBG_ALLOW_SCAN 118 +#define BTCOEX_DBG_SCAN_REQUEST 119 +#define BTCOEX_A2DP_SLEEP 127 +#define BTCOEX_DBG_DATA_ACTIV_TIMEOUT 128 +#define BTCOEX_DBG_SWITCH_TO_PSPOLL_ON_MODE 129 +#define BTCOEX_DBG_SWITCH_TO_PSPOLL_OFF_MODE 130 +#define BTCOEX_DATARECEIVE_AGGR 131 +#define BTCOEX_DBG_DATA_RECV_SLEEPING_PENDING 132 +#define BTCOEX_DBG_DATARESP_TIMEOUT 133 +#define BTCOEX_BDG_BMISS 134 +#define BTCOEX_DBG_DATA_RECV_WAKEUP_TIM 135 +#define BTCOEX_DBG_SECOND_BMISS 136 +#define BTCOEX_DBG_SET_WLAN_STATE 138 +#define BTCOEX_BDG_FIRST_BMISS 139 +#define BTCOEX_DBG_A2DP_CHAN_OP 140 +#define BTCOEX_DBG_A2DP_INTR 141 +#define BTCOEX_DBG_BT_INQUIRY 142 +#define BTCOEX_DBG_BT_INQUIRY_DATA_FETCH 143 +#define BTCOEX_DBG_POST_INQUIRY_FINISH 144 +#define BTCOEX_DBG_SCO_OPT_MODE_TIMER_HANDLER 145 +#define BTCOEX_DBG_NULL_FRAME_SLEEP 146 +#define BTCOEX_DBG_NULL_FRAME_AWAKE 147 +#define BTCOEX_DBG_SET_AGGR_SIZE 152 +#define BTCOEX_DBG_TEAR_BA_TIMEOUT 153 +#define BTCOEX_DBG_MGMT_FRAME_SEQ_NO 154 +#define BTCOEX_DBG_SCO_STOMP_HIGH_PRI 155 +#define BTCOEX_DBG_COLOCATED_BT_DEV 156 +#define BTCOEX_DBG_FE_ANT_TYPE 157 +#define BTCOEX_DBG_BT_INQUIRY_CMD 158 +#define BTCOEX_DBG_SCO_CONFIG 159 +#define BTCOEX_DBG_SCO_PSPOLL_CONFIG 160 +#define BTCOEX_DBG_SCO_OPTMODE_CONFIG 161 +#define BTCOEX_DBG_A2DP_CONFIG 162 +#define BTCOEX_DBG_A2DP_PSPOLL_CONFIG 163 +#define BTCOEX_DBG_A2DP_OPTMODE_CONFIG 164 +#define BTCOEX_DBG_ACLCOEX_CONFIG 165 +#define BTCOEX_DBG_ACLCOEX_PSPOLL_CONFIG 166 +#define BTCOEX_DBG_ACLCOEX_OPTMODE_CONFIG 167 +#define BTCOEX_DBG_DEBUG_CMD 168 +#define BTCOEX_DBG_SET_BT_OPERATING_STATUS 169 +#define BTCOEX_DBG_GET_CONFIG 170 +#define BTCOEX_DBG_GET_STATS 171 +#define BTCOEX_DBG_BT_OPERATING_STATUS 172 +#define BTCOEX_DBG_PERFORM_RECONNECT 173 +#define BTCOEX_DBG_ACL_WLAN_MED 175 +#define BTCOEX_DBG_ACL_BT_MED 176 +#define BTCOEX_DBG_WLAN_CONNECT 177 +#define BTCOEX_DBG_A2DP_DUAL_START 178 +#define BTCOEX_DBG_PMAWAKE_NOTIFY 179 +#define BTCOEX_DBG_BEACON_SCAN_ENABLE 180 +#define BTCOEX_DBG_BEACON_SCAN_DISABLE 181 +#define BTCOEX_DBG_RX_NOTIFY 182 +#define BTCOEX_SCO_GET_PER_SECOND_FRM_TIMESTAMP 183 +#define BTCOEX_DBG_TXQ_DETAILS 184 +#define BTCOEX_DBG_SCO_STOMP_LOW_PRI 185 +#define BTCOEX_DBG_A2DP_FORCE_SCAN 186 +#define BTCOEX_DBG_DTIM_STOMP_COMP 187 +#define BTCOEX_ACL_PRESENCE_TIMER 188 +#define BTCOEX_DBGID_DEFINITION_END + +#ifdef __cplusplus +} +#endif + +#endif /* _DBGLOG_ID_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/discovery.h b/trunk/drivers/staging/ath6kl/include/common/discovery.h new file mode 100644 index 000000000000..da1b33245069 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/discovery.h @@ -0,0 +1,75 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _DISCOVERY_H_ +#define _DISCOVERY_H_ + +/* + * DC_SCAN_PRIORITY is an 8-bit bitmap of the scan priority of a channel + */ +typedef enum { + DEFAULT_SCPRI = 0x01, + POPULAR_SCPRI = 0x02, + SSIDS_SCPRI = 0x04, + PROF_SCPRI = 0x08, +} DC_SCAN_PRIORITY; + +/* The following search type construct can be used to manipulate the behavior of the search module based on different bits set */ +typedef enum { + SCAN_RESET = 0, + SCAN_ALL = (DEFAULT_SCPRI | POPULAR_SCPRI | \ + SSIDS_SCPRI | PROF_SCPRI), + + SCAN_POPULAR = (POPULAR_SCPRI | SSIDS_SCPRI | PROF_SCPRI), + SCAN_SSIDS = (SSIDS_SCPRI | PROF_SCPRI), + SCAN_PROF_MASK = (PROF_SCPRI), + SCAN_MULTI_CHANNEL = 0x000100, + SCAN_DETERMINISTIC = 0x000200, + SCAN_PROFILE_MATCH_TERMINATED = 0x000400, + SCAN_HOME_CHANNEL_SKIP = 0x000800, + SCAN_CHANNEL_LIST_CONTINUE = 0x001000, + SCAN_CURRENT_SSID_SKIP = 0x002000, + SCAN_ACTIVE_PROBE_DISABLE = 0x004000, + SCAN_CHANNEL_HINT_ONLY = 0x008000, + SCAN_ACTIVE_CHANNELS_ONLY = 0x010000, + SCAN_UNUSED1 = 0x020000, /* unused */ + SCAN_PERIODIC = 0x040000, + SCAN_FIXED_DURATION = 0x080000, + SCAN_AP_ASSISTED = 0x100000, +} DC_SCAN_TYPE; + +typedef enum { + BSS_REPORTING_DEFAULT = 0x0, + EXCLUDE_NON_SCAN_RESULTS = 0x1, /* Exclude results outside of scan */ +} DC_BSS_REPORTING_POLICY; + +typedef enum { + DC_IGNORE_WPAx_GROUP_CIPHER = 0x01, + DC_PROFILE_MATCH_DONE = 0x02, + DC_IGNORE_AAC_BEACON = 0x04, + DC_CSA_FOLLOW_BSS = 0x08, +} DC_PROFILE_FILTER; + +#define DEFAULT_DC_PROFILE_FILTER (DC_CSA_FOLLOW_BSS) + +#endif /* _DISCOVERY_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/epping_test.h b/trunk/drivers/staging/ath6kl/include/common/epping_test.h new file mode 100644 index 000000000000..9eb5fdfa746a --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/epping_test.h @@ -0,0 +1,111 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +// + +/* This file contains shared definitions for the host/target endpoint ping test */ + +#ifndef EPPING_TEST_H_ +#define EPPING_TEST_H_ + + /* alignment to 4-bytes */ +#define EPPING_ALIGNMENT_PAD (((sizeof(struct htc_frame_hdr) + 3) & (~0x3)) - sizeof(struct htc_frame_hdr)) + +#ifndef A_OFFSETOF +#define A_OFFSETOF(type,field) (int)(&(((type *)NULL)->field)) +#endif + +#define EPPING_RSVD_FILL 0xCC + +#define HCI_RSVD_EXPECTED_PKT_TYPE_RECV_OFFSET 7 + +typedef PREPACK struct { + u8 _HCIRsvd[8]; /* reserved for HCI packet header (GMBOX) testing */ + u8 StreamEcho_h; /* stream no. to echo this packet on (filled by host) */ + u8 StreamEchoSent_t; /* stream no. packet was echoed to (filled by target) + When echoed: StreamEchoSent_t == StreamEcho_h */ + u8 StreamRecv_t; /* stream no. that target received this packet on (filled by target) */ + u8 StreamNo_h; /* stream number to send on (filled by host) */ + u8 Magic_h[4]; /* magic number to filter for this packet on the host*/ + u8 _rsvd[6]; /* reserved fields that must be set to a "reserved" value + since this packet maps to a 14-byte ethernet frame we want + to make sure ethertype field is set to something unknown */ + + u8 _pad[2]; /* padding for alignment */ + u8 TimeStamp[8]; /* timestamp of packet (host or target) */ + u32 HostContext_h; /* 4 byte host context, target echos this back */ + u32 SeqNo; /* sequence number (set by host or target) */ + u16 Cmd_h; /* ping command (filled by host) */ + u16 CmdFlags_h; /* optional flags */ + u8 CmdBuffer_h[8]; /* buffer for command (host -> target) */ + u8 CmdBuffer_t[8]; /* buffer for command (target -> host) */ + u16 DataLength; /* length of data */ + u16 DataCRC; /* 16 bit CRC of data */ + u16 HeaderCRC; /* header CRC (fields : StreamNo_h to end, minus HeaderCRC) */ +} POSTPACK EPPING_HEADER; + +#define EPPING_PING_MAGIC_0 0xAA +#define EPPING_PING_MAGIC_1 0x55 +#define EPPING_PING_MAGIC_2 0xCE +#define EPPING_PING_MAGIC_3 0xEC + + + +#define IS_EPPING_PACKET(pPkt) (((pPkt)->Magic_h[0] == EPPING_PING_MAGIC_0) && \ + ((pPkt)->Magic_h[1] == EPPING_PING_MAGIC_1) && \ + ((pPkt)->Magic_h[2] == EPPING_PING_MAGIC_2) && \ + ((pPkt)->Magic_h[3] == EPPING_PING_MAGIC_3)) + +#define SET_EPPING_PACKET_MAGIC(pPkt) { (pPkt)->Magic_h[0] = EPPING_PING_MAGIC_0; \ + (pPkt)->Magic_h[1] = EPPING_PING_MAGIC_1; \ + (pPkt)->Magic_h[2] = EPPING_PING_MAGIC_2; \ + (pPkt)->Magic_h[3] = EPPING_PING_MAGIC_3;} + +#define CMD_FLAGS_DATA_CRC (1 << 0) /* DataCRC field is valid */ +#define CMD_FLAGS_DELAY_ECHO (1 << 1) /* delay the echo of the packet */ +#define CMD_FLAGS_NO_DROP (1 << 2) /* do not drop at HTC layer no matter what the stream is */ + +#define IS_EPING_PACKET_NO_DROP(pPkt) ((pPkt)->CmdFlags_h & CMD_FLAGS_NO_DROP) + +#define EPPING_CMD_ECHO_PACKET 1 /* echo packet test */ +#define EPPING_CMD_RESET_RECV_CNT 2 /* reset recv count */ +#define EPPING_CMD_CAPTURE_RECV_CNT 3 /* fetch recv count, 4-byte count returned in CmdBuffer_t */ +#define EPPING_CMD_NO_ECHO 4 /* non-echo packet test (tx-only) */ +#define EPPING_CMD_CONT_RX_START 5 /* continuous RX packets, parameters are in CmdBuffer_h */ +#define EPPING_CMD_CONT_RX_STOP 6 /* stop continuous RX packet transmission */ + + /* test command parameters may be no more than 8 bytes */ +typedef PREPACK struct { + u16 BurstCnt; /* number of packets to burst together (for HTC 2.1 testing) */ + u16 PacketLength; /* length of packet to generate including header */ + u16 Flags; /* flags */ + +#define EPPING_CONT_RX_DATA_CRC (1 << 0) /* Add CRC to all data */ +#define EPPING_CONT_RX_RANDOM_DATA (1 << 1) /* randomize the data pattern */ +#define EPPING_CONT_RX_RANDOM_LEN (1 << 2) /* randomize the packet lengths */ +} POSTPACK EPPING_CONT_RX_PARAMS; + +#define EPPING_HDR_CRC_OFFSET A_OFFSETOF(EPPING_HEADER,StreamNo_h) +#define EPPING_HDR_BYTES_CRC (sizeof(EPPING_HEADER) - EPPING_HDR_CRC_OFFSET - (sizeof(u16))) + +#define HCI_TRANSPORT_STREAM_NUM 16 /* this number is higher than the define WMM AC classes so we + can use this to distinguish packets */ + +#endif /*EPPING_TEST_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/common/gmboxif.h b/trunk/drivers/staging/ath6kl/include/common/gmboxif.h new file mode 100644 index 000000000000..ea11c14def43 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/gmboxif.h @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __GMBOXIF_H__ +#define __GMBOXIF_H__ + +/* GMBOX interface definitions */ + +#define AR6K_GMBOX_CREDIT_COUNTER 1 /* we use credit counter 1 to track credits */ +#define AR6K_GMBOX_CREDIT_SIZE_COUNTER 2 /* credit counter 2 is used to pass the size of each credit */ + + + /* HCI UART transport definitions when used over GMBOX interface */ +#define HCI_UART_COMMAND_PKT 0x01 +#define HCI_UART_ACL_PKT 0x02 +#define HCI_UART_SCO_PKT 0x03 +#define HCI_UART_EVENT_PKT 0x04 + + /* definitions for BT HCI packets */ +typedef PREPACK struct { + u16 Flags_ConnHandle; + u16 Length; +} POSTPACK BT_HCI_ACL_HEADER; + +typedef PREPACK struct { + u16 Flags_ConnHandle; + u8 Length; +} POSTPACK BT_HCI_SCO_HEADER; + +typedef PREPACK struct { + u16 OpCode; + u8 ParamLength; +} POSTPACK BT_HCI_COMMAND_HEADER; + +typedef PREPACK struct { + u8 EventCode; + u8 ParamLength; +} POSTPACK BT_HCI_EVENT_HEADER; + +/* MBOX host interrupt signal assignments */ + +#define MBOX_SIG_HCI_BRIDGE_MAX 8 +#define MBOX_SIG_HCI_BRIDGE_BT_ON 0 +#define MBOX_SIG_HCI_BRIDGE_BT_OFF 1 +#define MBOX_SIG_HCI_BRIDGE_BAUD_SET 2 +#define MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON 3 +#define MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF 4 + + +#endif /* __GMBOXIF_H__ */ + diff --git a/trunk/drivers/staging/ath6kl/include/common/gpio_reg.h b/trunk/drivers/staging/ath6kl/include/common/gpio_reg.h new file mode 100644 index 000000000000..f9d425d48dc2 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/gpio_reg.h @@ -0,0 +1,9 @@ +#ifndef _GPIO_REG_REG_H_ +#define _GPIO_REG_REG_H_ + +#define GPIO_PIN10_ADDRESS 0x00000050 +#define GPIO_PIN11_ADDRESS 0x00000054 +#define GPIO_PIN12_ADDRESS 0x00000058 +#define GPIO_PIN13_ADDRESS 0x0000005c + +#endif /* _GPIO_REG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/htc.h b/trunk/drivers/staging/ath6kl/include/common/htc.h new file mode 100644 index 000000000000..85cbfa89d670 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/htc.h @@ -0,0 +1,227 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __HTC_H__ +#define __HTC_H__ + +#define A_OFFSETOF(type,field) (unsigned long)(&(((type *)NULL)->field)) + +#define ASSEMBLE_UNALIGNED_UINT16(p,highbyte,lowbyte) \ + (((u16)(((u8 *)(p))[(highbyte)])) << 8 | (u16)(((u8 *)(p))[(lowbyte)])) + +/* alignment independent macros (little-endian) to fetch UINT16s or UINT8s from a + * structure using only the type and field name. + * Use these macros if there is the potential for unaligned buffer accesses. */ +#define A_GET_UINT16_FIELD(p,type,field) \ + ASSEMBLE_UNALIGNED_UINT16(p,\ + A_OFFSETOF(type,field) + 1, \ + A_OFFSETOF(type,field)) + +#define A_SET_UINT16_FIELD(p,type,field,value) \ +{ \ + ((u8 *)(p))[A_OFFSETOF(type,field)] = (u8)(value); \ + ((u8 *)(p))[A_OFFSETOF(type,field) + 1] = (u8)((value) >> 8); \ +} + +#define A_GET_UINT8_FIELD(p,type,field) \ + ((u8 *)(p))[A_OFFSETOF(type,field)] + +#define A_SET_UINT8_FIELD(p,type,field,value) \ + ((u8 *)(p))[A_OFFSETOF(type,field)] = (value) + +/****** DANGER DANGER *************** + * + * The frame header length and message formats defined herein were + * selected to accommodate optimal alignment for target processing. This reduces code + * size and improves performance. + * + * Any changes to the header length may alter the alignment and cause exceptions + * on the target. When adding to the message structures insure that fields are + * properly aligned. + * + */ + +/* HTC frame header */ +PREPACK struct htc_frame_hdr { + /* do not remove or re-arrange these fields, these are minimally required + * to take advantage of 4-byte lookaheads in some hardware implementations */ + u8 EndpointID; + u8 Flags; + u16 PayloadLen; /* length of data (including trailer) that follows the header */ + + /***** end of 4-byte lookahead ****/ + + u8 ControlBytes[2]; + + /* message payload starts after the header */ + +} POSTPACK; + +/* frame header flags */ + + /* send direction */ +#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0) +#define HTC_FLAGS_SEND_BUNDLE (1 << 1) /* start or part of bundle */ + /* receive direction */ +#define HTC_FLAGS_RECV_UNUSED_0 (1 << 0) /* bit 0 unused */ +#define HTC_FLAGS_RECV_TRAILER (1 << 1) /* bit 1 trailer data present */ +#define HTC_FLAGS_RECV_UNUSED_2 (1 << 0) /* bit 2 unused */ +#define HTC_FLAGS_RECV_UNUSED_3 (1 << 0) /* bit 3 unused */ +#define HTC_FLAGS_RECV_BUNDLE_CNT_MASK (0xF0) /* bits 7..4 */ +#define HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT 4 + +#define HTC_HDR_LENGTH (sizeof(struct htc_frame_hdr)) +#define HTC_MAX_TRAILER_LENGTH 255 +#define HTC_MAX_PAYLOAD_LENGTH (4096 - sizeof(struct htc_frame_hdr)) + +/* HTC control message IDs */ + +#define HTC_MSG_READY_ID 1 +#define HTC_MSG_CONNECT_SERVICE_ID 2 +#define HTC_MSG_CONNECT_SERVICE_RESPONSE_ID 3 +#define HTC_MSG_SETUP_COMPLETE_ID 4 +#define HTC_MSG_SETUP_COMPLETE_EX_ID 5 + +#define HTC_MAX_CONTROL_MESSAGE_LENGTH 256 + +/* base message ID header */ +typedef PREPACK struct { + u16 MessageID; +} POSTPACK HTC_UNKNOWN_MSG; + +/* HTC ready message + * direction : target-to-host */ +typedef PREPACK struct { + u16 MessageID; /* ID */ + u16 CreditCount; /* number of credits the target can offer */ + u16 CreditSize; /* size of each credit */ + u8 MaxEndpoints; /* maximum number of endpoints the target has resources for */ + u8 _Pad1; +} POSTPACK HTC_READY_MSG; + + /* extended HTC ready message */ +typedef PREPACK struct { + HTC_READY_MSG Version2_0_Info; /* legacy version 2.0 information at the front... */ + /* extended information */ + u8 HTCVersion; + u8 MaxMsgsPerHTCBundle; +} POSTPACK HTC_READY_EX_MSG; + +#define HTC_VERSION_2P0 0x00 +#define HTC_VERSION_2P1 0x01 /* HTC 2.1 */ + +#define HTC_SERVICE_META_DATA_MAX_LENGTH 128 + +/* connect service + * direction : host-to-target */ +typedef PREPACK struct { + u16 MessageID; + u16 ServiceID; /* service ID of the service to connect to */ + u16 ConnectionFlags; /* connection flags */ + +#define HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE (1 << 2) /* reduce credit dribbling when + the host needs credits */ +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK (0x3) +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH 0x0 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF 0x1 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS 0x2 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_UNITY 0x3 + + u8 ServiceMetaLength; /* length of meta data that follows */ + u8 _Pad1; + + /* service-specific meta data starts after the header */ + +} POSTPACK HTC_CONNECT_SERVICE_MSG; + +/* connect response + * direction : target-to-host */ +typedef PREPACK struct { + u16 MessageID; + u16 ServiceID; /* service ID that the connection request was made */ + u8 Status; /* service connection status */ + u8 EndpointID; /* assigned endpoint ID */ + u16 MaxMsgSize; /* maximum expected message size on this endpoint */ + u8 ServiceMetaLength; /* length of meta data that follows */ + u8 _Pad1; + + /* service-specific meta data starts after the header */ + +} POSTPACK HTC_CONNECT_SERVICE_RESPONSE_MSG; + +typedef PREPACK struct { + u16 MessageID; + /* currently, no other fields */ +} POSTPACK HTC_SETUP_COMPLETE_MSG; + + /* extended setup completion message */ +typedef PREPACK struct { + u16 MessageID; + u32 SetupFlags; + u8 MaxMsgsPerBundledRecv; + u8 Rsvd[3]; +} POSTPACK HTC_SETUP_COMPLETE_EX_MSG; + +#define HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV (1 << 0) + +/* connect response status codes */ +#define HTC_SERVICE_SUCCESS 0 /* success */ +#define HTC_SERVICE_NOT_FOUND 1 /* service could not be found */ +#define HTC_SERVICE_FAILED 2 /* specific service failed the connect */ +#define HTC_SERVICE_NO_RESOURCES 3 /* no resources (i.e. no more endpoints) */ +#define HTC_SERVICE_NO_MORE_EP 4 /* specific service is not allowing any more + endpoints */ + +/* report record IDs */ + +#define HTC_RECORD_NULL 0 +#define HTC_RECORD_CREDITS 1 +#define HTC_RECORD_LOOKAHEAD 2 +#define HTC_RECORD_LOOKAHEAD_BUNDLE 3 + +typedef PREPACK struct { + u8 RecordID; /* Record ID */ + u8 Length; /* Length of record */ +} POSTPACK HTC_RECORD_HDR; + +typedef PREPACK struct { + u8 EndpointID; /* Endpoint that owns these credits */ + u8 Credits; /* credits to report since last report */ +} POSTPACK HTC_CREDIT_REPORT; + +typedef PREPACK struct { + u8 PreValid; /* pre valid guard */ + u8 LookAhead[4]; /* 4 byte lookahead */ + u8 PostValid; /* post valid guard */ + + /* NOTE: the LookAhead array is guarded by a PreValid and Post Valid guard bytes. + * The PreValid bytes must equal the inverse of the PostValid byte */ + +} POSTPACK HTC_LOOKAHEAD_REPORT; + +typedef PREPACK struct { + u8 LookAhead[4]; /* 4 byte lookahead */ +} POSTPACK HTC_BUNDLED_LOOKAHEAD_REPORT; + +#endif /* __HTC_H__ */ + diff --git a/trunk/drivers/staging/ath6kl/include/common/htc_services.h b/trunk/drivers/staging/ath6kl/include/common/htc_services.h new file mode 100644 index 000000000000..fb22268a8d84 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/htc_services.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __HTC_SERVICES_H__ +#define __HTC_SERVICES_H__ + +/* Current service IDs */ + +typedef enum { + RSVD_SERVICE_GROUP = 0, + WMI_SERVICE_GROUP = 1, + + HTC_TEST_GROUP = 254, + HTC_SERVICE_GROUP_LAST = 255 +}HTC_SERVICE_GROUP_IDS; + +#define MAKE_SERVICE_ID(group,index) \ + (int)(((int)group << 8) | (int)(index)) + +/* NOTE: service ID of 0x0000 is reserved and should never be used */ +#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP,1) +#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,0) +#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,1) +#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,2) +#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,3) +#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,4) +#define WMI_MAX_SERVICES 5 + +/* raw stream service (i.e. flash, tcmd, calibration apps) */ +#define HTC_RAW_STREAMS_SVC MAKE_SERVICE_ID(HTC_TEST_GROUP,0) + +#endif /*HTC_SERVICES_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/common/pkt_log.h b/trunk/drivers/staging/ath6kl/include/common/pkt_log.h new file mode 100644 index 000000000000..a3719adf54ca --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/pkt_log.h @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2005-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __PKT_LOG_H__ +#define __PKT_LOG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Pkt log info */ +typedef PREPACK struct pkt_log_t { + struct info_t { + u16 st; + u16 end; + u16 cur; + }info[4096]; + u16 last_idx; +}POSTPACK PACKET_LOG; + + +#ifdef __cplusplus +} +#endif +#endif /* __PKT_LOG_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/roaming.h b/trunk/drivers/staging/ath6kl/include/common/roaming.h new file mode 100644 index 000000000000..8019850a0571 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/roaming.h @@ -0,0 +1,41 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef _ROAMING_H_ +#define _ROAMING_H_ + +/* + * The signal quality could be in terms of either snr or rssi. We should + * have an enum for both of them. For the time being, we are going to move + * it to wmi.h that is shared by both host and the target, since we are + * repartitioning the code to the host + */ +#define SIGNAL_QUALITY_NOISE_FLOOR -96 +#define SIGNAL_QUALITY_METRICS_NUM_MAX 2 +typedef enum { + SIGNAL_QUALITY_METRICS_SNR = 0, + SIGNAL_QUALITY_METRICS_RSSI, + SIGNAL_QUALITY_METRICS_ALL, +} SIGNAL_QUALITY_METRICS_TYPE; + +#endif /* _ROAMING_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/targaddrs.h b/trunk/drivers/staging/ath6kl/include/common/targaddrs.h new file mode 100644 index 000000000000..c866cefbd8fd --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/targaddrs.h @@ -0,0 +1,395 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef __TARGADDRS_H__ +#define __TARGADDRS_H__ + +#if defined(AR6002) +#include "AR6002/addrs.h" +#endif + +/* + * AR6K option bits, to enable/disable various features. + * By default, all option bits are 0. + * These bits can be set in LOCAL_SCRATCH register 0. + */ +#define AR6K_OPTION_BMI_DISABLE 0x01 /* Disable BMI comm with Host */ +#define AR6K_OPTION_SERIAL_ENABLE 0x02 /* Enable serial port msgs */ +#define AR6K_OPTION_WDT_DISABLE 0x04 /* WatchDog Timer override */ +#define AR6K_OPTION_SLEEP_DISABLE 0x08 /* Disable system sleep */ +#define AR6K_OPTION_STOP_BOOT 0x10 /* Stop boot processes (for ATE) */ +#define AR6K_OPTION_ENABLE_NOANI 0x20 /* Operate without ANI */ +#define AR6K_OPTION_DSET_DISABLE 0x40 /* Ignore DataSets */ +#define AR6K_OPTION_IGNORE_FLASH 0x80 /* Ignore flash during bootup */ + +/* + * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the + * host_interest structure. It must match the address of the _host_interest + * symbol (see linker script). + * + * Host Interest is shared between Host and Target in order to coordinate + * between the two, and is intended to remain constant (with additions only + * at the end) across software releases. + * + * All addresses are available here so that it's possible to + * write a single binary that works with all Target Types. + * May be used in assembler code as well as C. + */ +#define AR6002_HOST_INTEREST_ADDRESS 0x00500400 +#define AR6003_HOST_INTEREST_ADDRESS 0x00540600 + + +#define HOST_INTEREST_MAX_SIZE 0x100 + +#if !defined(__ASSEMBLER__) +struct register_dump_s; +struct dbglog_hdr_s; + +/* + * These are items that the Host may need to access + * via BMI or via the Diagnostic Window. The position + * of items in this structure must remain constant + * across firmware revisions! + * + * Types for each item must be fixed size across + * target and host platforms. + * + * More items may be added at the end. + */ +PREPACK struct host_interest_s { + /* + * Pointer to application-defined area, if any. + * Set by Target application during startup. + */ + u32 hi_app_host_interest; /* 0x00 */ + + /* Pointer to register dump area, valid after Target crash. */ + u32 hi_failure_state; /* 0x04 */ + + /* Pointer to debug logging header */ + u32 hi_dbglog_hdr; /* 0x08 */ + + u32 hi_unused1; /* 0x0c */ + + /* + * General-purpose flag bits, similar to AR6000_OPTION_* flags. + * Can be used by application rather than by OS. + */ + u32 hi_option_flag; /* 0x10 */ + + /* + * Boolean that determines whether or not to + * display messages on the serial port. + */ + u32 hi_serial_enable; /* 0x14 */ + + /* Start address of DataSet index, if any */ + u32 hi_dset_list_head; /* 0x18 */ + + /* Override Target application start address */ + u32 hi_app_start; /* 0x1c */ + + /* Clock and voltage tuning */ + u32 hi_skip_clock_init; /* 0x20 */ + u32 hi_core_clock_setting; /* 0x24 */ + u32 hi_cpu_clock_setting; /* 0x28 */ + u32 hi_system_sleep_setting; /* 0x2c */ + u32 hi_xtal_control_setting; /* 0x30 */ + u32 hi_pll_ctrl_setting_24ghz; /* 0x34 */ + u32 hi_pll_ctrl_setting_5ghz; /* 0x38 */ + u32 hi_ref_voltage_trim_setting; /* 0x3c */ + u32 hi_clock_info; /* 0x40 */ + + /* + * Flash configuration overrides, used only + * when firmware is not executing from flash. + * (When using flash, modify the global variables + * with equivalent names.) + */ + u32 hi_bank0_addr_value; /* 0x44 */ + u32 hi_bank0_read_value; /* 0x48 */ + u32 hi_bank0_write_value; /* 0x4c */ + u32 hi_bank0_config_value; /* 0x50 */ + + /* Pointer to Board Data */ + u32 hi_board_data; /* 0x54 */ + u32 hi_board_data_initialized; /* 0x58 */ + + u32 hi_dset_RAM_index_table; /* 0x5c */ + + u32 hi_desired_baud_rate; /* 0x60 */ + u32 hi_dbglog_config; /* 0x64 */ + u32 hi_end_RAM_reserve_sz; /* 0x68 */ + u32 hi_mbox_io_block_sz; /* 0x6c */ + + u32 hi_num_bpatch_streams; /* 0x70 -- unused */ + u32 hi_mbox_isr_yield_limit; /* 0x74 */ + + u32 hi_refclk_hz; /* 0x78 */ + u32 hi_ext_clk_detected; /* 0x7c */ + u32 hi_dbg_uart_txpin; /* 0x80 */ + u32 hi_dbg_uart_rxpin; /* 0x84 */ + u32 hi_hci_uart_baud; /* 0x88 */ + u32 hi_hci_uart_pin_assignments; /* 0x8C */ + /* NOTE: byte [0] = tx pin, [1] = rx pin, [2] = rts pin, [3] = cts pin */ + u32 hi_hci_uart_baud_scale_val; /* 0x90 */ + u32 hi_hci_uart_baud_step_val; /* 0x94 */ + + u32 hi_allocram_start; /* 0x98 */ + u32 hi_allocram_sz; /* 0x9c */ + u32 hi_hci_bridge_flags; /* 0xa0 */ + u32 hi_hci_uart_support_pins; /* 0xa4 */ + /* NOTE: byte [0] = RESET pin (bit 7 is polarity), bytes[1]..bytes[3] are for future use */ + u32 hi_hci_uart_pwr_mgmt_params; /* 0xa8 */ + /* + * 0xa8 - [1]: 0 = UART FC active low, 1 = UART FC active high + * [31:16]: wakeup timeout in ms + */ + + /* Pointer to extended board data */ + u32 hi_board_ext_data; /* 0xac */ + u32 hi_board_ext_data_config; /* 0xb0 */ + + /* + * Bit [0] : valid + * Bit[31:16: size + */ + /* + * hi_reset_flag is used to do some stuff when target reset. + * such as restore app_start after warm reset or + * preserve host Interest area, or preserve ROM data, literals etc. + */ + u32 hi_reset_flag; /* 0xb4 */ + /* indicate hi_reset_flag is valid */ + u32 hi_reset_flag_valid; /* 0xb8 */ + u32 hi_hci_uart_pwr_mgmt_params_ext; /* 0xbc */ + /* + * 0xbc - [31:0]: idle timeout in ms + */ + /* ACS flags */ + u32 hi_acs_flags; /* 0xc0 */ + u32 hi_console_flags; /* 0xc4 */ + u32 hi_nvram_state; /* 0xc8 */ + u32 hi_option_flag2; /* 0xcc */ + + /* If non-zero, override values sent to Host in WMI_READY event. */ + u32 hi_sw_version_override; /* 0xd0 */ + u32 hi_abi_version_override; /* 0xd4 */ + + /* + * Percentage of high priority RX traffic to total expected RX traffic - + * applicable only to ar6004 + */ + u32 hi_hp_rx_traffic_ratio; /* 0xd8 */ + + /* test applications flags */ + u32 hi_test_apps_related ; /* 0xdc */ + /* location of test script */ + u32 hi_ota_testscript; /* 0xe0 */ + /* location of CAL data */ + u32 hi_cal_data; /* 0xe4 */ + /* Number of packet log buffers */ + u32 hi_pktlog_num_buffers; /* 0xe8 */ + +} POSTPACK; + +/* Bits defined in hi_option_flag */ +#define HI_OPTION_TIMER_WAR 0x01 /* Enable timer workaround */ +#define HI_OPTION_BMI_CRED_LIMIT 0x02 /* Limit BMI command credits */ +#define HI_OPTION_RELAY_DOT11_HDR 0x04 /* Relay Dot11 hdr to/from host */ +/* MAC addr method 0-locally administred 1-globally unique addrs */ +#define HI_OPTION_MAC_ADDR_METHOD 0x08 +#define HI_OPTION_FW_BRIDGE 0x10 /* Firmware Bridging */ +#define HI_OPTION_ENABLE_PROFILE 0x20 /* Enable CPU profiling */ +#define HI_OPTION_DISABLE_DBGLOG 0x40 /* Disable debug logging */ +#define HI_OPTION_SKIP_ERA_TRACKING 0x80 /* Skip Era Tracking */ +#define HI_OPTION_PAPRD_DISABLE 0x100 /* Disable PAPRD (debug) */ +#define HI_OPTION_NUM_DEV_LSB 0x200 +#define HI_OPTION_NUM_DEV_MSB 0x800 +#define HI_OPTION_DEV_MODE_LSB 0x1000 +#define HI_OPTION_DEV_MODE_MSB 0x8000000 +/* Disable LowFreq Timer Stabilization */ +#define HI_OPTION_NO_LFT_STBL 0x10000000 +#define HI_OPTION_SKIP_REG_SCAN 0x20000000 /* Skip regulatory scan */ +/* Do regulatory scan during init beforesending WMI ready event to host */ +#define HI_OPTION_INIT_REG_SCAN 0x40000000 +#define HI_OPTION_SKIP_MEMMAP 0x80000000 /* REV6: Do not adjust memory + map */ + +/* hi_option_flag2 options */ +#define HI_OPTION_OFFLOAD_AMSDU 0x01 +#define HI_OPTION_DFS_SUPPORT 0x02 /* Enable DFS support */ + +#define HI_OPTION_MAC_ADDR_METHOD_SHIFT 3 + +/* 2 bits of hi_option_flag are used to represent 3 modes */ +#define HI_OPTION_FW_MODE_IBSS 0x0 /* IBSS Mode */ +#define HI_OPTION_FW_MODE_BSS_STA 0x1 /* STA Mode */ +#define HI_OPTION_FW_MODE_AP 0x2 /* AP Mode */ + +/* 2 bits of hi_option flag are usedto represent 4 submodes */ +#define HI_OPTION_FW_SUBMODE_NONE 0x0 /* Normal mode */ +#define HI_OPTION_FW_SUBMODE_P2PDEV 0x1 /* p2p device mode */ +#define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2 /* p2p client mode */ +#define HI_OPTION_FW_SUBMODE_P2PGO 0x3 /* p2p go mode */ + +/* Num dev Mask */ +#define HI_OPTION_NUM_DEV_MASK 0x7 +#define HI_OPTION_NUM_DEV_SHIFT 0x9 + +/* firmware bridging */ +#define HI_OPTION_FW_BRIDGE_SHIFT 0x04 + +/* Fw Mode/SubMode Mask +|------------------------------------------------------------------------------| +| SUB | SUB | SUB | SUB | | | | +| MODE[3] | MODE[2] | MODE[1] | MODE[0] | MODE[3] | MODE[2] | MODE[1] | MODE[0| +| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) +|------------------------------------------------------------------------------| +*/ +#define HI_OPTION_FW_MODE_BITS 0x2 +#define HI_OPTION_FW_MODE_MASK 0x3 +#define HI_OPTION_FW_MODE_SHIFT 0xC +#define HI_OPTION_ALL_FW_MODE_MASK 0xFF + +#define HI_OPTION_FW_SUBMODE_BITS 0x2 +#define HI_OPTION_FW_SUBMODE_MASK 0x3 +#define HI_OPTION_FW_SUBMODE_SHIFT 0x14 +#define HI_OPTION_ALL_FW_SUBMODE_MASK 0xFF00 +#define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8 + +/* hi_reset_flag */ + +/* preserve App Start address */ +#define HI_RESET_FLAG_PRESERVE_APP_START 0x01 +/* preserve host interest */ +#define HI_RESET_FLAG_PRESERVE_HOST_INTEREST 0x02 +#define HI_RESET_FLAG_PRESERVE_ROMDATA 0x04 /* preserve ROM data */ +#define HI_RESET_FLAG_PRESERVE_NVRAM_STATE 0x08 +#define HI_RESET_FLAG_PRESERVE_BOOT_INFO 0x10 + +#define HI_RESET_FLAG_IS_VALID 0x12345678 /* indicate the reset flag is +valid */ + +#define ON_RESET_FLAGS_VALID() \ + (HOST_INTEREST->hi_reset_flag_valid == HI_RESET_FLAG_IS_VALID) + +#define RESET_FLAGS_VALIDATE() \ + (HOST_INTEREST->hi_reset_flag_valid = HI_RESET_FLAG_IS_VALID) + +#define RESET_FLAGS_INVALIDATE() \ + (HOST_INTEREST->hi_reset_flag_valid = 0) + +#define ON_RESET_PRESERVE_APP_START() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_APP_START) + +#define ON_RESET_PRESERVE_NVRAM_STATE() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_NVRAM_STATE) + +#define ON_RESET_PRESERVE_HOST_INTEREST() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_HOST_INTEREST) + +#define ON_RESET_PRESERVE_ROMDATA() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_ROMDATA) + +#define ON_RESET_PRESERVE_BOOT_INFO() \ + (HOST_INTEREST->hi_reset_flag & HI_RESET_FLAG_PRESERVE_BOOT_INFO) + +#define HI_ACS_FLAGS_ENABLED (1 << 0) /* ACS is enabled */ +#define HI_ACS_FLAGS_USE_WWAN (1 << 1) /* Use physical WWAN device */ +#define HI_ACS_FLAGS_TEST_VAP (1 << 2) /* Use test VAP */ + +/* CONSOLE FLAGS + * + * Bit Range Meaning + * --------- -------------------------------- + * 2..0 UART ID (0 = Default) + * 3 Baud Select (0 = 9600, 1 = 115200) + * 30..4 Reserved + * 31 Enable Console + * + */ + +#define HI_CONSOLE_FLAGS_ENABLE (1 << 31) +#define HI_CONSOLE_FLAGS_UART_MASK (0x7) +#define HI_CONSOLE_FLAGS_UART_SHIFT 0 +#define HI_CONSOLE_FLAGS_BAUD_SELECT (1 << 3) + +/* + * Intended for use by Host software, this macro returns the Target RAM + * address of any item in the host_interest structure. + * Example: target_addr = AR6002_HOST_INTEREST_ITEM_ADDRESS(hi_board_data); + */ +#define AR6002_HOST_INTEREST_ITEM_ADDRESS(item) \ + (u32)((unsigned long)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item))) + +#define AR6003_HOST_INTEREST_ITEM_ADDRESS(item) \ + (u32)((unsigned long)&((((struct host_interest_s *)(AR6003_HOST_INTEREST_ADDRESS))->item))) + +#define AR6004_HOST_INTEREST_ITEM_ADDRESS(item) \ + ((u32)&((((struct host_interest_s *)(AR6004_HOST_INTEREST_ADDRESS))->item))) + + +#define HOST_INTEREST_DBGLOG_IS_ENABLED() \ + (!(HOST_INTEREST->hi_option_flag & HI_OPTION_DISABLE_DBGLOG)) + +#define HOST_INTEREST_PKTLOG_IS_ENABLED() \ + ((HOST_INTEREST->hi_pktlog_num_buffers)) + + +#define HOST_INTEREST_PROFILE_IS_ENABLED() \ + (HOST_INTEREST->hi_option_flag & HI_OPTION_ENABLE_PROFILE) + +#define LF_TIMER_STABILIZATION_IS_ENABLED() \ + (!(HOST_INTEREST->hi_option_flag & HI_OPTION_NO_LFT_STBL)) + +#define IS_AMSDU_OFFLAOD_ENABLED() \ + ((HOST_INTEREST->hi_option_flag2 & HI_OPTION_OFFLOAD_AMSDU)) + +#define HOST_INTEREST_DFS_IS_ENABLED() \ + ((HOST_INTEREST->hi_option_flag2 & HI_OPTION_DFS_SUPPORT)) + +/* Convert a Target virtual address into a Target physical address */ +#define AR6002_VTOP(vaddr) ((vaddr) & 0x001fffff) +#define AR6003_VTOP(vaddr) ((vaddr) & 0x001fffff) +#define TARG_VTOP(TargetType, vaddr) \ + (((TargetType) == TARGET_TYPE_AR6002) ? AR6002_VTOP(vaddr) : AR6003_VTOP(vaddr)) + +#define AR6003_REV2_APP_START_OVERRIDE 0x944C00 +#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180 +#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500 +#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884 +#define AR6003_REV2_RAM_RESERVE_SIZE 6912 + +#define AR6003_REV3_APP_START_OVERRIDE 0x945d00 +#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000 +#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330 +#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74 +#define AR6003_REV3_RAM_RESERVE_SIZE 512 + +#define AR6003_BOARD_EXT_DATA_ADDRESS 0x57E600 + +/* # of u32 entries in targregs, used by DIAG_FETCH_TARG_REGS */ +#define AR6003_FETCH_TARG_REGS_COUNT 64 + +#endif /* !__ASSEMBLER__ */ + +#endif /* __TARGADDRS_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/testcmd.h b/trunk/drivers/staging/ath6kl/include/common/testcmd.h new file mode 100644 index 000000000000..7d94aee508b3 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/testcmd.h @@ -0,0 +1,185 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef TESTCMD_H_ +#define TESTCMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef AR6002_REV2 +#define TCMD_MAX_RATES 12 +#else +#define TCMD_MAX_RATES 28 +#endif + +typedef enum { + ZEROES_PATTERN = 0, + ONES_PATTERN, + REPEATING_10, + PN7_PATTERN, + PN9_PATTERN, + PN15_PATTERN +}TX_DATA_PATTERN; + +/* Continuous tx + mode : TCMD_CONT_TX_OFF - Disabling continuous tx + TCMD_CONT_TX_SINE - Enable continuous unmodulated tx + TCMD_CONT_TX_FRAME- Enable continuous modulated tx + freq : Channel freq in Mhz. (e.g 2412 for channel 1 in 11 g) +dataRate: 0 - 1 Mbps + 1 - 2 Mbps + 2 - 5.5 Mbps + 3 - 11 Mbps + 4 - 6 Mbps + 5 - 9 Mbps + 6 - 12 Mbps + 7 - 18 Mbps + 8 - 24 Mbps + 9 - 36 Mbps + 10 - 28 Mbps + 11 - 54 Mbps + txPwr: Tx power in dBm[5 -11] for unmod Tx, [5-14] for mod Tx +antenna: 1 - one antenna + 2 - two antenna +Note : Enable/disable continuous tx test cmd works only when target is awake. +*/ + +typedef enum { + TCMD_CONT_TX_OFF = 0, + TCMD_CONT_TX_SINE, + TCMD_CONT_TX_FRAME, + TCMD_CONT_TX_TX99, + TCMD_CONT_TX_TX100 +} TCMD_CONT_TX_MODE; + +typedef enum { + TCMD_WLAN_MODE_NOHT = 0, + TCMD_WLAN_MODE_HT20 = 1, + TCMD_WLAN_MODE_HT40PLUS = 2, + TCMD_WLAN_MODE_HT40MINUS = 3, +} TCMD_WLAN_MODE; + +typedef PREPACK struct { + u32 testCmdId; + u32 mode; + u32 freq; + u32 dataRate; + s32 txPwr; + u32 antenna; + u32 enANI; + u32 scramblerOff; + u32 aifsn; + u16 pktSz; + u16 txPattern; + u32 shortGuard; + u32 numPackets; + u32 wlanMode; +} POSTPACK TCMD_CONT_TX; + +#define TCMD_TXPATTERN_ZERONE 0x1 +#define TCMD_TXPATTERN_ZERONE_DIS_SCRAMBLE 0x2 + +/* Continuous Rx + act: TCMD_CONT_RX_PROMIS - promiscuous mode (accept all incoming frames) + TCMD_CONT_RX_FILTER - filter mode (accept only frames with dest + address equal specified + mac address (set via act =3) + TCMD_CONT_RX_REPORT off mode (disable cont rx mode and get the + report from the last cont + Rx test) + + TCMD_CONT_RX_SETMAC - set MacAddr mode (sets the MAC address for the + target. This Overrides + the default MAC address.) + +*/ +typedef enum { + TCMD_CONT_RX_PROMIS =0, + TCMD_CONT_RX_FILTER, + TCMD_CONT_RX_REPORT, + TCMD_CONT_RX_SETMAC, + TCMD_CONT_RX_SET_ANT_SWITCH_TABLE +} TCMD_CONT_RX_ACT; + +typedef PREPACK struct { + u32 testCmdId; + u32 act; + u32 enANI; + PREPACK union { + struct PREPACK TCMD_CONT_RX_PARA { + u32 freq; + u32 antenna; + u32 wlanMode; + } POSTPACK para; + struct PREPACK TCMD_CONT_RX_REPORT { + u32 totalPkt; + s32 rssiInDBm; + u32 crcErrPkt; + u32 secErrPkt; + u16 rateCnt[TCMD_MAX_RATES]; + u16 rateCntShortGuard[TCMD_MAX_RATES]; + } POSTPACK report; + struct PREPACK TCMD_CONT_RX_MAC { + u8 addr[ATH_MAC_LEN]; + } POSTPACK mac; + struct PREPACK TCMD_CONT_RX_ANT_SWITCH_TABLE { + u32 antswitch1; + u32 antswitch2; + }POSTPACK antswitchtable; + } POSTPACK u; +} POSTPACK TCMD_CONT_RX; + +/* Force sleep/wake test cmd + mode: TCMD_PM_WAKEUP - Wakeup the target + TCMD_PM_SLEEP - Force the target to sleep. + */ +typedef enum { + TCMD_PM_WAKEUP = 1, /* be consistent with target */ + TCMD_PM_SLEEP, + TCMD_PM_DEEPSLEEP +} TCMD_PM_MODE; + +typedef PREPACK struct { + u32 testCmdId; + u32 mode; +} POSTPACK TCMD_PM; + +typedef enum { + TCMD_CONT_TX_ID, + TCMD_CONT_RX_ID, + TCMD_PM_ID +} TCMD_ID; + +typedef PREPACK union { + TCMD_CONT_TX contTx; + TCMD_CONT_RX contRx; + TCMD_PM pm; +} POSTPACK TEST_CMD; + +#ifdef __cplusplus +} +#endif + +#endif /* TESTCMD_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/tlpm.h b/trunk/drivers/staging/ath6kl/include/common/tlpm.h new file mode 100644 index 000000000000..659b1c07ba90 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/tlpm.h @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#ifndef __TLPM_H__ +#define __TLPM_H__ + +/* idle timeout in 16-bit value as in HOST_INTEREST hi_hci_uart_pwr_mgmt_params */ +#define TLPM_DEFAULT_IDLE_TIMEOUT_MS 1000 +/* hex in LSB and MSB for HCI command */ +#define TLPM_DEFAULT_IDLE_TIMEOUT_LSB 0xE8 +#define TLPM_DEFAULT_IDLE_TIMEOUT_MSB 0x3 + +/* wakeup timeout in 8-bit value as in HOST_INTEREST hi_hci_uart_pwr_mgmt_params */ +#define TLPM_DEFAULT_WAKEUP_TIMEOUT_MS 10 + +/* default UART FC polarity is low */ +#define TLPM_DEFAULT_UART_FC_POLARITY 0 + +#endif diff --git a/trunk/drivers/staging/ath6kl/include/common/wlan_defs.h b/trunk/drivers/staging/ath6kl/include/common/wlan_defs.h new file mode 100644 index 000000000000..03e4d23788ce --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/wlan_defs.h @@ -0,0 +1,79 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef __WLAN_DEFS_H__ +#define __WLAN_DEFS_H__ + +/* + * This file contains WLAN definitions that may be used across both + * Host and Target software. + */ + +typedef enum { + MODE_11A = 0, /* 11a Mode */ + MODE_11G = 1, /* 11b/g Mode */ + MODE_11B = 2, /* 11b Mode */ + MODE_11GONLY = 3, /* 11g only Mode */ +#ifdef SUPPORT_11N + MODE_11NA_HT20 = 4, /* 11a HT20 mode */ + MODE_11NG_HT20 = 5, /* 11g HT20 mode */ + MODE_11NA_HT40 = 6, /* 11a HT40 mode */ + MODE_11NG_HT40 = 7, /* 11g HT40 mode */ + MODE_UNKNOWN = 8, + MODE_MAX = 8 +#else + MODE_UNKNOWN = 4, + MODE_MAX = 4 +#endif +} WLAN_PHY_MODE; + +typedef enum { + WLAN_11A_CAPABILITY = 1, + WLAN_11G_CAPABILITY = 2, + WLAN_11AG_CAPABILITY = 3, +}WLAN_CAPABILITY; + +#ifdef SUPPORT_11N +typedef unsigned long A_RATEMASK; +#else +typedef unsigned short A_RATEMASK; +#endif + +#ifdef SUPPORT_11N +#define IS_MODE_11A(mode) (((mode) == MODE_11A) || \ + ((mode) == MODE_11NA_HT20) || \ + ((mode) == MODE_11NA_HT40)) +#define IS_MODE_11B(mode) ((mode) == MODE_11B) +#define IS_MODE_11G(mode) (((mode) == MODE_11G) || \ + ((mode) == MODE_11GONLY) || \ + ((mode) == MODE_11NG_HT20) || \ + ((mode) == MODE_11NG_HT40)) +#define IS_MODE_11GONLY(mode) ((mode) == MODE_11GONLY) +#else +#define IS_MODE_11A(mode) ((mode) == MODE_11A) +#define IS_MODE_11B(mode) ((mode) == MODE_11B) +#define IS_MODE_11G(mode) (((mode) == MODE_11G) || \ + ((mode) == MODE_11GONLY)) +#define IS_MODE_11GONLY(mode) ((mode) == MODE_11GONLY) +#endif /* SUPPORT_11N */ + +#endif /* __WLANDEFS_H__ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/wmi.h b/trunk/drivers/staging/ath6kl/include/common/wmi.h new file mode 100644 index 000000000000..d9687443d32c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/wmi.h @@ -0,0 +1,3220 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +/* + * This file contains the definitions of the WMI protocol specified in the + * Wireless Module Interface (WMI). It includes definitions of all the + * commands and events. Commands are messages from the host to the WM. + * Events and Replies are messages from the WM to the host. + * + * Ownership of correctness in regards to commands + * belongs to the host driver and the WMI is not required to validate + * parameters for value, proper range, or any other checking. + * + */ + +#ifndef _WMI_H_ +#define _WMI_H_ + +#include "wmix.h" +#include "wlan_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HTC_PROTOCOL_VERSION 0x0002 +#define HTC_PROTOCOL_REVISION 0x0000 + +#define WMI_PROTOCOL_VERSION 0x0002 +#define WMI_PROTOCOL_REVISION 0x0000 + +#define ATH_MAC_LEN 6 /* length of mac in bytes */ +#define WMI_CMD_MAX_LEN 100 +#define WMI_CONTROL_MSG_MAX_LEN 256 +#define WMI_OPT_CONTROL_MSG_MAX_LEN 1536 +#define IS_ETHERTYPE(_typeOrLen) ((_typeOrLen) >= 0x0600) +#define RFC1042OUI {0x00, 0x00, 0x00} + +#define IP_ETHERTYPE 0x0800 + +#define WMI_IMPLICIT_PSTREAM 0xFF +#define WMI_MAX_THINSTREAM 15 + +#ifdef AR6002_REV2 +#define IBSS_MAX_NUM_STA 4 +#else +#define IBSS_MAX_NUM_STA 8 +#endif + +PREPACK struct host_app_area_s { + u32 wmi_protocol_ver; +} POSTPACK; + +/* + * Data Path + */ +typedef PREPACK struct { + u8 dstMac[ATH_MAC_LEN]; + u8 srcMac[ATH_MAC_LEN]; + u16 typeOrLen; +} POSTPACK ATH_MAC_HDR; + +typedef PREPACK struct { + u8 dsap; + u8 ssap; + u8 cntl; + u8 orgCode[3]; + u16 etherType; +} POSTPACK ATH_LLC_SNAP_HDR; + +typedef enum { + DATA_MSGTYPE = 0x0, + CNTL_MSGTYPE, + SYNC_MSGTYPE, + OPT_MSGTYPE, +} WMI_MSG_TYPE; + + +/* + * Macros for operating on WMI_DATA_HDR (info) field + */ + +#define WMI_DATA_HDR_MSG_TYPE_MASK 0x03 +#define WMI_DATA_HDR_MSG_TYPE_SHIFT 0 +#define WMI_DATA_HDR_UP_MASK 0x07 +#define WMI_DATA_HDR_UP_SHIFT 2 +/* In AP mode, the same bit (b5) is used to indicate Power save state in + * the Rx dir and More data bit state in the tx direction. + */ +#define WMI_DATA_HDR_PS_MASK 0x1 +#define WMI_DATA_HDR_PS_SHIFT 5 + +#define WMI_DATA_HDR_MORE_MASK 0x1 +#define WMI_DATA_HDR_MORE_SHIFT 5 + +typedef enum { + WMI_DATA_HDR_DATA_TYPE_802_3 = 0, + WMI_DATA_HDR_DATA_TYPE_802_11, + WMI_DATA_HDR_DATA_TYPE_ACL, /* used to be used for the PAL */ +} WMI_DATA_HDR_DATA_TYPE; + +#define WMI_DATA_HDR_DATA_TYPE_MASK 0x3 +#define WMI_DATA_HDR_DATA_TYPE_SHIFT 6 + +#define WMI_DATA_HDR_SET_MORE_BIT(h) ((h)->info |= (WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT)) + +#define WMI_DATA_HDR_IS_MSG_TYPE(h, t) (((h)->info & (WMI_DATA_HDR_MSG_TYPE_MASK)) == (t)) +#define WMI_DATA_HDR_SET_MSG_TYPE(h, t) (h)->info = (((h)->info & ~(WMI_DATA_HDR_MSG_TYPE_MASK << WMI_DATA_HDR_MSG_TYPE_SHIFT)) | (t << WMI_DATA_HDR_MSG_TYPE_SHIFT)) +#define WMI_DATA_HDR_GET_UP(h) (((h)->info >> WMI_DATA_HDR_UP_SHIFT) & WMI_DATA_HDR_UP_MASK) +#define WMI_DATA_HDR_SET_UP(h, p) (h)->info = (((h)->info & ~(WMI_DATA_HDR_UP_MASK << WMI_DATA_HDR_UP_SHIFT)) | (p << WMI_DATA_HDR_UP_SHIFT)) + +#define WMI_DATA_HDR_GET_DATA_TYPE(h) (((h)->info >> WMI_DATA_HDR_DATA_TYPE_SHIFT) & WMI_DATA_HDR_DATA_TYPE_MASK) +#define WMI_DATA_HDR_SET_DATA_TYPE(h, p) (h)->info = (((h)->info & ~(WMI_DATA_HDR_DATA_TYPE_MASK << WMI_DATA_HDR_DATA_TYPE_SHIFT)) | ((p) << WMI_DATA_HDR_DATA_TYPE_SHIFT)) + +#define WMI_DATA_HDR_GET_DOT11(h) (WMI_DATA_HDR_GET_DATA_TYPE((h)) == WMI_DATA_HDR_DATA_TYPE_802_11) +#define WMI_DATA_HDR_SET_DOT11(h, p) WMI_DATA_HDR_SET_DATA_TYPE((h), (p)) + +/* Macros for operating on WMI_DATA_HDR (info2) field */ +#define WMI_DATA_HDR_SEQNO_MASK 0xFFF +#define WMI_DATA_HDR_SEQNO_SHIFT 0 + +#define WMI_DATA_HDR_AMSDU_MASK 0x1 +#define WMI_DATA_HDR_AMSDU_SHIFT 12 + +#define WMI_DATA_HDR_META_MASK 0x7 +#define WMI_DATA_HDR_META_SHIFT 13 + +#define GET_SEQ_NO(_v) ((_v) & WMI_DATA_HDR_SEQNO_MASK) +#define GET_ISMSDU(_v) ((_v) & WMI_DATA_HDR_AMSDU_MASK) + +#define WMI_DATA_HDR_GET_SEQNO(h) GET_SEQ_NO((h)->info2 >> WMI_DATA_HDR_SEQNO_SHIFT) +#define WMI_DATA_HDR_SET_SEQNO(h, _v) ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_SEQNO_MASK << WMI_DATA_HDR_SEQNO_SHIFT)) | (GET_SEQ_NO(_v) << WMI_DATA_HDR_SEQNO_SHIFT)) + +#define WMI_DATA_HDR_IS_AMSDU(h) GET_ISMSDU((h)->info2 >> WMI_DATA_HDR_AMSDU_SHIFT) +#define WMI_DATA_HDR_SET_AMSDU(h, _v) ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_AMSDU_MASK << WMI_DATA_HDR_AMSDU_SHIFT)) | (GET_ISMSDU(_v) << WMI_DATA_HDR_AMSDU_SHIFT)) + +#define WMI_DATA_HDR_GET_META(h) (((h)->info2 >> WMI_DATA_HDR_META_SHIFT) & WMI_DATA_HDR_META_MASK) +#define WMI_DATA_HDR_SET_META(h, _v) ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_META_MASK << WMI_DATA_HDR_META_SHIFT)) | ((_v) << WMI_DATA_HDR_META_SHIFT)) + +/* Macros for operating on WMI_DATA_HDR (info3) field */ +#define WMI_DATA_HDR_DEVID_MASK 0xF +#define WMI_DATA_HDR_DEVID_SHIFT 0 +#define GET_DEVID(_v) ((_v) & WMI_DATA_HDR_DEVID_MASK) + +#define WMI_DATA_HDR_GET_DEVID(h) \ + (((h)->info3 >> WMI_DATA_HDR_DEVID_SHIFT) & WMI_DATA_HDR_DEVID_MASK) +#define WMI_DATA_HDR_SET_DEVID(h, _v) \ + ((h)->info3 = ((h)->info3 & ~(WMI_DATA_HDR_DEVID_MASK << WMI_DATA_HDR_DEVID_SHIFT)) | (GET_DEVID(_v) << WMI_DATA_HDR_DEVID_SHIFT)) + +typedef PREPACK struct { + s8 rssi; + u8 info; /* usage of 'info' field(8-bit): + * b1:b0 - WMI_MSG_TYPE + * b4:b3:b2 - UP(tid) + * b5 - Used in AP mode. More-data in tx dir, PS in rx. + * b7:b6 - Dot3 header(0), + * Dot11 Header(1), + * ACL data(2) + */ + + u16 info2; /* usage of 'info2' field(16-bit): + * b11:b0 - seq_no + * b12 - A-MSDU? + * b15:b13 - META_DATA_VERSION 0 - 7 + */ + u16 info3; +} POSTPACK WMI_DATA_HDR; + +/* + * TX META VERSION DEFINITIONS + */ +#define WMI_MAX_TX_META_SZ (12) +#define WMI_MAX_TX_META_VERSION (7) +#define WMI_META_VERSION_1 (0x01) +#define WMI_META_VERSION_2 (0X02) + +#define WMI_ACL_TO_DOT11_HEADROOM 36 + +#if 0 /* removed to prevent compile errors for WM.. */ +typedef PREPACK struct { +/* intentionally empty. Default version is no meta data. */ +} POSTPACK WMI_TX_META_V0; +#endif + +typedef PREPACK struct { + u8 pktID; /* The packet ID to identify the tx request */ + u8 ratePolicyID; /* The rate policy to be used for the tx of this frame */ +} POSTPACK WMI_TX_META_V1; + + +#define WMI_CSUM_DIR_TX (0x1) +#define TX_CSUM_CALC_FILL (0x1) +typedef PREPACK struct { + u8 csumStart; /*Offset from start of the WMI header for csum calculation to begin */ + u8 csumDest; /*Offset from start of WMI header where final csum goes*/ + u8 csumFlags; /*number of bytes over which csum is calculated*/ +} POSTPACK WMI_TX_META_V2; + + +/* + * RX META VERSION DEFINITIONS + */ +/* if RX meta data is present at all then the meta data field + * will consume WMI_MAX_RX_META_SZ bytes of space between the + * WMI_DATA_HDR and the payload. How much of the available + * Meta data is actually used depends on which meta data + * version is active. */ +#define WMI_MAX_RX_META_SZ (12) +#define WMI_MAX_RX_META_VERSION (7) + +#define WMI_RX_STATUS_OK 0 /* success */ +#define WMI_RX_STATUS_DECRYPT_ERR 1 /* decrypt error */ +#define WMI_RX_STATUS_MIC_ERR 2 /* tkip MIC error */ +#define WMI_RX_STATUS_ERR 3 /* undefined error */ + +#define WMI_RX_FLAGS_AGGR 0x0001 /* part of AGGR */ +#define WMI_RX_FlAGS_STBC 0x0002 /* used STBC */ +#define WMI_RX_FLAGS_SGI 0x0004 /* used SGI */ +#define WMI_RX_FLAGS_HT 0x0008 /* is HT packet */ +/* the flags field is also used to store the CRYPTO_TYPE of the frame + * that value is shifted by WMI_RX_FLAGS_CRYPTO_SHIFT */ +#define WMI_RX_FLAGS_CRYPTO_SHIFT 4 +#define WMI_RX_FLAGS_CRYPTO_MASK 0x1f +#define WMI_RX_META_GET_CRYPTO(flags) (((flags) >> WMI_RX_FLAGS_CRYPTO_SHIFT) & WMI_RX_FLAGS_CRYPTO_MASK) + +#if 0 /* removed to prevent compile errors for WM.. */ +typedef PREPACK struct { +/* intentionally empty. Default version is no meta data. */ +} POSTPACK WMI_RX_META_VERSION_0; +#endif + +typedef PREPACK struct { + u8 status; /* one of WMI_RX_STATUS_... */ + u8 rix; /* rate index mapped to rate at which this packet was received. */ + u8 rssi; /* rssi of packet */ + u8 channel;/* rf channel during packet reception */ + u16 flags; /* a combination of WMI_RX_FLAGS_... */ +} POSTPACK WMI_RX_META_V1; + +#define RX_CSUM_VALID_FLAG (0x1) +typedef PREPACK struct { + u16 csum; + u8 csumFlags;/* bit 0 set -partial csum valid + bit 1 set -test mode */ +} POSTPACK WMI_RX_META_V2; + + + +#define WMI_GET_DEVICE_ID(info1) ((info1) & 0xF) +/* Macros for operating on WMI_CMD_HDR (info1) field */ +#define WMI_CMD_HDR_DEVID_MASK 0xF +#define WMI_CMD_HDR_DEVID_SHIFT 0 +#define GET_CMD_DEVID(_v) ((_v) & WMI_CMD_HDR_DEVID_MASK) + +#define WMI_CMD_HDR_GET_DEVID(h) \ + (((h)->info1 >> WMI_CMD_HDR_DEVID_SHIFT) & WMI_CMD_HDR_DEVID_MASK) +#define WMI_CMD_HDR_SET_DEVID(h, _v) \ + ((h)->info1 = ((h)->info1 & \ + ~(WMI_CMD_HDR_DEVID_MASK << WMI_CMD_HDR_DEVID_SHIFT)) | \ + (GET_CMD_DEVID(_v) << WMI_CMD_HDR_DEVID_SHIFT)) + +/* + * Control Path + */ +typedef PREPACK struct { + u16 commandId; +/* + * info1 - 16 bits + * b03:b00 - id + * b15:b04 - unused + */ + u16 info1; + + u16 reserved; /* For alignment */ +} POSTPACK WMI_CMD_HDR; /* used for commands and events */ + +/* + * List of Commnands + */ +typedef enum { + WMI_CONNECT_CMDID = 0x0001, + WMI_RECONNECT_CMDID, + WMI_DISCONNECT_CMDID, + WMI_SYNCHRONIZE_CMDID, + WMI_CREATE_PSTREAM_CMDID, + WMI_DELETE_PSTREAM_CMDID, + WMI_START_SCAN_CMDID, + WMI_SET_SCAN_PARAMS_CMDID, + WMI_SET_BSS_FILTER_CMDID, + WMI_SET_PROBED_SSID_CMDID, /* 10 */ + WMI_SET_LISTEN_INT_CMDID, + WMI_SET_BMISS_TIME_CMDID, + WMI_SET_DISC_TIMEOUT_CMDID, + WMI_GET_CHANNEL_LIST_CMDID, + WMI_SET_BEACON_INT_CMDID, + WMI_GET_STATISTICS_CMDID, + WMI_SET_CHANNEL_PARAMS_CMDID, + WMI_SET_POWER_MODE_CMDID, + WMI_SET_IBSS_PM_CAPS_CMDID, + WMI_SET_POWER_PARAMS_CMDID, /* 20 */ + WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID, + WMI_ADD_CIPHER_KEY_CMDID, + WMI_DELETE_CIPHER_KEY_CMDID, + WMI_ADD_KRK_CMDID, + WMI_DELETE_KRK_CMDID, + WMI_SET_PMKID_CMDID, + WMI_SET_TX_PWR_CMDID, + WMI_GET_TX_PWR_CMDID, + WMI_SET_ASSOC_INFO_CMDID, + WMI_ADD_BAD_AP_CMDID, /* 30 */ + WMI_DELETE_BAD_AP_CMDID, + WMI_SET_TKIP_COUNTERMEASURES_CMDID, + WMI_RSSI_THRESHOLD_PARAMS_CMDID, + WMI_TARGET_ERROR_REPORT_BITMASK_CMDID, + WMI_SET_ACCESS_PARAMS_CMDID, + WMI_SET_RETRY_LIMITS_CMDID, + WMI_SET_OPT_MODE_CMDID, + WMI_OPT_TX_FRAME_CMDID, + WMI_SET_VOICE_PKT_SIZE_CMDID, + WMI_SET_MAX_SP_LEN_CMDID, /* 40 */ + WMI_SET_ROAM_CTRL_CMDID, + WMI_GET_ROAM_TBL_CMDID, + WMI_GET_ROAM_DATA_CMDID, + WMI_ENABLE_RM_CMDID, + WMI_SET_MAX_OFFHOME_DURATION_CMDID, + WMI_EXTENSION_CMDID, /* Non-wireless extensions */ + WMI_SNR_THRESHOLD_PARAMS_CMDID, + WMI_LQ_THRESHOLD_PARAMS_CMDID, + WMI_SET_LPREAMBLE_CMDID, + WMI_SET_RTS_CMDID, /* 50 */ + WMI_CLR_RSSI_SNR_CMDID, + WMI_SET_FIXRATES_CMDID, + WMI_GET_FIXRATES_CMDID, + WMI_SET_AUTH_MODE_CMDID, + WMI_SET_REASSOC_MODE_CMDID, + WMI_SET_WMM_CMDID, + WMI_SET_WMM_TXOP_CMDID, + WMI_TEST_CMDID, + /* COEX AR6002 only*/ + WMI_SET_BT_STATUS_CMDID, + WMI_SET_BT_PARAMS_CMDID, /* 60 */ + + WMI_SET_KEEPALIVE_CMDID, + WMI_GET_KEEPALIVE_CMDID, + WMI_SET_APPIE_CMDID, + WMI_GET_APPIE_CMDID, + WMI_SET_WSC_STATUS_CMDID, + + /* Wake on Wireless */ + WMI_SET_HOST_SLEEP_MODE_CMDID, + WMI_SET_WOW_MODE_CMDID, + WMI_GET_WOW_LIST_CMDID, + WMI_ADD_WOW_PATTERN_CMDID, + WMI_DEL_WOW_PATTERN_CMDID, /* 70 */ + + WMI_SET_FRAMERATES_CMDID, + WMI_SET_AP_PS_CMDID, + WMI_SET_QOS_SUPP_CMDID, + /* WMI_THIN_RESERVED_... mark the start and end + * values for WMI_THIN_RESERVED command IDs. These + * command IDs can be found in wmi_thin.h */ + WMI_THIN_RESERVED_START = 0x8000, + WMI_THIN_RESERVED_END = 0x8fff, + /* + * Developer commands starts at 0xF000 + */ + WMI_SET_BITRATE_CMDID = 0xF000, + WMI_GET_BITRATE_CMDID, + WMI_SET_WHALPARAM_CMDID, + + + /*Should add the new command to the tail for compatible with + * etna. + */ + WMI_SET_MAC_ADDRESS_CMDID, + WMI_SET_AKMP_PARAMS_CMDID, + WMI_SET_PMKID_LIST_CMDID, + WMI_GET_PMKID_LIST_CMDID, + WMI_ABORT_SCAN_CMDID, + WMI_SET_TARGET_EVENT_REPORT_CMDID, + + // Unused + WMI_UNUSED1, + WMI_UNUSED2, + + /* + * AP mode commands + */ + WMI_AP_HIDDEN_SSID_CMDID, + WMI_AP_SET_NUM_STA_CMDID, + WMI_AP_ACL_POLICY_CMDID, + WMI_AP_ACL_MAC_LIST_CMDID, + WMI_AP_CONFIG_COMMIT_CMDID, + WMI_AP_SET_MLME_CMDID, + WMI_AP_SET_PVB_CMDID, + WMI_AP_CONN_INACT_CMDID, + WMI_AP_PROT_SCAN_TIME_CMDID, + WMI_AP_SET_COUNTRY_CMDID, + WMI_AP_SET_DTIM_CMDID, + WMI_AP_MODE_STAT_CMDID, + + WMI_SET_IP_CMDID, + WMI_SET_PARAMS_CMDID, + WMI_SET_MCAST_FILTER_CMDID, + WMI_DEL_MCAST_FILTER_CMDID, + + WMI_ALLOW_AGGR_CMDID, + WMI_ADDBA_REQ_CMDID, + WMI_DELBA_REQ_CMDID, + WMI_SET_HT_CAP_CMDID, + WMI_SET_HT_OP_CMDID, + WMI_SET_TX_SELECT_RATES_CMDID, + WMI_SET_TX_SGI_PARAM_CMDID, + WMI_SET_RATE_POLICY_CMDID, + + WMI_HCI_CMD_CMDID, + WMI_RX_FRAME_FORMAT_CMDID, + WMI_SET_THIN_MODE_CMDID, + WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID, + + WMI_AP_SET_11BG_RATESET_CMDID, + WMI_SET_PMK_CMDID, + WMI_MCAST_FILTER_CMDID, + /* COEX CMDID AR6003*/ + WMI_SET_BTCOEX_FE_ANT_CMDID, + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID, + WMI_SET_BTCOEX_SCO_CONFIG_CMDID, + WMI_SET_BTCOEX_A2DP_CONFIG_CMDID, + WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID, + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID, + WMI_SET_BTCOEX_DEBUG_CMDID, + WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID, + WMI_GET_BTCOEX_STATS_CMDID, + WMI_GET_BTCOEX_CONFIG_CMDID, + + WMI_SET_DFS_ENABLE_CMDID, /* F034 */ + WMI_SET_DFS_MINRSSITHRESH_CMDID, + WMI_SET_DFS_MAXPULSEDUR_CMDID, + WMI_DFS_RADAR_DETECTED_CMDID, + + /* P2P CMDS */ + WMI_P2P_SET_CONFIG_CMDID, /* F038 */ + WMI_WPS_SET_CONFIG_CMDID, + WMI_SET_REQ_DEV_ATTR_CMDID, + WMI_P2P_FIND_CMDID, + WMI_P2P_STOP_FIND_CMDID, + WMI_P2P_GO_NEG_START_CMDID, + WMI_P2P_LISTEN_CMDID, + + WMI_CONFIG_TX_MAC_RULES_CMDID, /* F040 */ + WMI_SET_PROMISCUOUS_MODE_CMDID, + WMI_RX_FRAME_FILTER_CMDID, + WMI_SET_CHANNEL_CMDID, + + /* WAC commands */ + WMI_ENABLE_WAC_CMDID, + WMI_WAC_SCAN_REPLY_CMDID, + WMI_WAC_CTRL_REQ_CMDID, + WMI_SET_DIV_PARAMS_CMDID, + + WMI_GET_PMK_CMDID, + WMI_SET_PASSPHRASE_CMDID, + WMI_SEND_ASSOC_RES_CMDID, + WMI_SET_ASSOC_REQ_RELAY_CMDID, + WMI_GET_RFKILL_MODE_CMDID, + + /* ACS command, consists of sub-commands */ + WMI_ACS_CTRL_CMDID, + + /* Ultra low power store / recall commands */ + WMI_STORERECALL_CONFIGURE_CMDID, + WMI_STORERECALL_RECALL_CMDID, + WMI_STORERECALL_HOST_READY_CMDID, + WMI_FORCE_TARGET_ASSERT_CMDID, + WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, +} WMI_COMMAND_ID; + +/* + * Frame Types + */ +typedef enum { + WMI_FRAME_BEACON = 0, + WMI_FRAME_PROBE_REQ, + WMI_FRAME_PROBE_RESP, + WMI_FRAME_ASSOC_REQ, + WMI_FRAME_ASSOC_RESP, + WMI_NUM_MGMT_FRAME +} WMI_MGMT_FRAME_TYPE; + +/* + * Connect Command + */ +typedef enum { + INFRA_NETWORK = 0x01, + ADHOC_NETWORK = 0x02, + ADHOC_CREATOR = 0x04, + AP_NETWORK = 0x10, +} NETWORK_TYPE; + +typedef enum { + OPEN_AUTH = 0x01, + SHARED_AUTH = 0x02, + LEAP_AUTH = 0x04, /* different from IEEE_AUTH_MODE definitions */ +} DOT11_AUTH_MODE; + +enum { + AUTH_IDLE, + AUTH_OPEN_IN_PROGRESS, +}; + +typedef enum { + NONE_AUTH = 0x01, + WPA_AUTH = 0x02, + WPA2_AUTH = 0x04, + WPA_PSK_AUTH = 0x08, + WPA2_PSK_AUTH = 0x10, + WPA_AUTH_CCKM = 0x20, + WPA2_AUTH_CCKM = 0x40, +} AUTH_MODE; + +typedef enum { + NONE_CRYPT = 0x01, + WEP_CRYPT = 0x02, + TKIP_CRYPT = 0x04, + AES_CRYPT = 0x08, +#ifdef WAPI_ENABLE + WAPI_CRYPT = 0x10, +#endif /*WAPI_ENABLE*/ +} CRYPTO_TYPE; + +#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT +#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1) + +#ifdef WAPI_ENABLE +#undef WMI_MAX_CRYPTO_TYPE +#define WMI_MAX_CRYPTO_TYPE (WAPI_CRYPT + 1) +#endif /* WAPI_ENABLE */ + +#ifdef WAPI_ENABLE +#define IW_ENCODE_ALG_SM4 0x20 +#define IW_AUTH_WAPI_ENABLED 0x20 +#endif + +#define WMI_MIN_KEY_INDEX 0 +#define WMI_MAX_KEY_INDEX 3 + +#ifdef WAPI_ENABLE +#undef WMI_MAX_KEY_INDEX +#define WMI_MAX_KEY_INDEX 7 /* wapi grpKey 0-3, prwKey 4-7 */ +#endif /* WAPI_ENABLE */ + +#define WMI_MAX_KEY_LEN 32 + +#define WMI_MAX_SSID_LEN 32 + +typedef enum { + CONNECT_ASSOC_POLICY_USER = 0x0001, + CONNECT_SEND_REASSOC = 0x0002, + CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, + CONNECT_PROFILE_MATCH_DONE = 0x0008, + CONNECT_IGNORE_AAC_BEACON = 0x0010, + CONNECT_CSA_FOLLOW_BSS = 0x0020, + CONNECT_DO_WPA_OFFLOAD = 0x0040, + CONNECT_DO_NOT_DEAUTH = 0x0080, +} WMI_CONNECT_CTRL_FLAGS_BITS; + +#define DEFAULT_CONNECT_CTRL_FLAGS (CONNECT_CSA_FOLLOW_BSS) + +typedef PREPACK struct { + u8 networkType; + u8 dot11AuthMode; + u8 authMode; + u8 pairwiseCryptoType; + u8 pairwiseCryptoLen; + u8 groupCryptoType; + u8 groupCryptoLen; + u8 ssidLength; + u8 ssid[WMI_MAX_SSID_LEN]; + u16 channel; + u8 bssid[ATH_MAC_LEN]; + u32 ctrl_flags; +} POSTPACK WMI_CONNECT_CMD; + +/* + * WMI_RECONNECT_CMDID + */ +typedef PREPACK struct { + u16 channel; /* hint */ + u8 bssid[ATH_MAC_LEN]; /* mandatory if set */ +} POSTPACK WMI_RECONNECT_CMD; + +#define WMI_PMK_LEN 32 +typedef PREPACK struct { + u8 pmk[WMI_PMK_LEN]; +} POSTPACK WMI_SET_PMK_CMD; + +/* + * WMI_SET_EXCESS_TX_RETRY_THRES_CMDID + */ +typedef PREPACK struct { + u32 threshold; +} POSTPACK WMI_SET_EXCESS_TX_RETRY_THRES_CMD; + +/* + * WMI_ADD_CIPHER_KEY_CMDID + */ +typedef enum { + PAIRWISE_USAGE = 0x00, + GROUP_USAGE = 0x01, + TX_USAGE = 0x02, /* default Tx Key - Static WEP only */ +} KEY_USAGE; + +/* + * Bit Flag + * Bit 0 - Initialise TSC - default is Initialize + */ +#define KEY_OP_INIT_TSC 0x01 +#define KEY_OP_INIT_RSC 0x02 +#ifdef WAPI_ENABLE +#define KEY_OP_INIT_WAPIPN 0x10 +#endif /* WAPI_ENABLE */ + +#define KEY_OP_INIT_VAL 0x03 /* Default Initialise the TSC & RSC */ +#define KEY_OP_VALID_MASK 0x03 + +typedef PREPACK struct { + u8 keyIndex; + u8 keyType; + u8 keyUsage; /* KEY_USAGE */ + u8 keyLength; + u8 keyRSC[8]; /* key replay sequence counter */ + u8 key[WMI_MAX_KEY_LEN]; + u8 key_op_ctrl; /* Additional Key Control information */ + u8 key_macaddr[ATH_MAC_LEN]; +} POSTPACK WMI_ADD_CIPHER_KEY_CMD; + +/* + * WMI_DELETE_CIPHER_KEY_CMDID + */ +typedef PREPACK struct { + u8 keyIndex; +} POSTPACK WMI_DELETE_CIPHER_KEY_CMD; + +#define WMI_KRK_LEN 16 +/* + * WMI_ADD_KRK_CMDID + */ +typedef PREPACK struct { + u8 krk[WMI_KRK_LEN]; +} POSTPACK WMI_ADD_KRK_CMD; + +/* + * WMI_SET_TKIP_COUNTERMEASURES_CMDID + */ +typedef enum { + WMI_TKIP_CM_DISABLE = 0x0, + WMI_TKIP_CM_ENABLE = 0x1, +} WMI_TKIP_CM_CONTROL; + +typedef PREPACK struct { + u8 cm_en; /* WMI_TKIP_CM_CONTROL */ +} POSTPACK WMI_SET_TKIP_COUNTERMEASURES_CMD; + +/* + * WMI_SET_PMKID_CMDID + */ + +#define WMI_PMKID_LEN 16 + +typedef enum { + PMKID_DISABLE = 0, + PMKID_ENABLE = 1, +} PMKID_ENABLE_FLG; + +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; + u8 enable; /* PMKID_ENABLE_FLG */ + u8 pmkid[WMI_PMKID_LEN]; +} POSTPACK WMI_SET_PMKID_CMD; + +/* + * WMI_START_SCAN_CMD + */ +typedef enum { + WMI_LONG_SCAN = 0, + WMI_SHORT_SCAN = 1, +} WMI_SCAN_TYPE; + +typedef PREPACK struct { + u32 forceFgScan; + u32 isLegacy; /* For Legacy Cisco AP compatibility */ + u32 homeDwellTime; /* Maximum duration in the home channel(milliseconds) */ + u32 forceScanInterval; /* Time interval between scans (milliseconds)*/ + u8 scanType; /* WMI_SCAN_TYPE */ + u8 numChannels; /* how many channels follow */ + u16 channelList[1]; /* channels in Mhz */ +} POSTPACK WMI_START_SCAN_CMD; + +/* + * WMI_SET_SCAN_PARAMS_CMDID + */ +#define WMI_SHORTSCANRATIO_DEFAULT 3 +/* + * Warning: ScanCtrlFlag value of 0xFF is used to disable all flags in WMI_SCAN_PARAMS_CMD + * Do not add any more flags to WMI_SCAN_CTRL_FLAG_BITS + */ +typedef enum { + CONNECT_SCAN_CTRL_FLAGS = 0x01, /* set if can scan in the Connect cmd */ + SCAN_CONNECTED_CTRL_FLAGS = 0x02, /* set if scan for the SSID it is */ + /* already connected to */ + ACTIVE_SCAN_CTRL_FLAGS = 0x04, /* set if enable active scan */ + ROAM_SCAN_CTRL_FLAGS = 0x08, /* set if enable roam scan when bmiss and lowrssi */ + REPORT_BSSINFO_CTRL_FLAGS = 0x10, /* set if follows customer BSSINFO reporting rule */ + ENABLE_AUTO_CTRL_FLAGS = 0x20, /* if disabled, target doesn't + scan after a disconnect event */ + ENABLE_SCAN_ABORT_EVENT = 0x40 /* Scan complete event with canceled status will be generated when a scan is prempted before it gets completed */ +} WMI_SCAN_CTRL_FLAGS_BITS; + +#define CAN_SCAN_IN_CONNECT(flags) (flags & CONNECT_SCAN_CTRL_FLAGS) +#define CAN_SCAN_CONNECTED(flags) (flags & SCAN_CONNECTED_CTRL_FLAGS) +#define ENABLE_ACTIVE_SCAN(flags) (flags & ACTIVE_SCAN_CTRL_FLAGS) +#define ENABLE_ROAM_SCAN(flags) (flags & ROAM_SCAN_CTRL_FLAGS) +#define CONFIG_REPORT_BSSINFO(flags) (flags & REPORT_BSSINFO_CTRL_FLAGS) +#define IS_AUTO_SCAN_ENABLED(flags) (flags & ENABLE_AUTO_CTRL_FLAGS) +#define SCAN_ABORT_EVENT_ENABLED(flags) (flags & ENABLE_SCAN_ABORT_EVENT) + +#define DEFAULT_SCAN_CTRL_FLAGS (CONNECT_SCAN_CTRL_FLAGS| SCAN_CONNECTED_CTRL_FLAGS| ACTIVE_SCAN_CTRL_FLAGS| ROAM_SCAN_CTRL_FLAGS | ENABLE_AUTO_CTRL_FLAGS) + + +typedef PREPACK struct { + u16 fg_start_period; /* seconds */ + u16 fg_end_period; /* seconds */ + u16 bg_period; /* seconds */ + u16 maxact_chdwell_time; /* msec */ + u16 pas_chdwell_time; /* msec */ + u8 shortScanRatio; /* how many shorts scan for one long */ + u8 scanCtrlFlags; + u16 minact_chdwell_time; /* msec */ + u16 maxact_scan_per_ssid; /* max active scans per ssid */ + u32 max_dfsch_act_time; /* msecs */ +} POSTPACK WMI_SCAN_PARAMS_CMD; + +/* + * WMI_SET_BSS_FILTER_CMDID + */ +typedef enum { + NONE_BSS_FILTER = 0x0, /* no beacons forwarded */ + ALL_BSS_FILTER, /* all beacons forwarded */ + PROFILE_FILTER, /* only beacons matching profile */ + ALL_BUT_PROFILE_FILTER, /* all but beacons matching profile */ + CURRENT_BSS_FILTER, /* only beacons matching current BSS */ + ALL_BUT_BSS_FILTER, /* all but beacons matching BSS */ + PROBED_SSID_FILTER, /* beacons matching probed ssid */ + LAST_BSS_FILTER, /* marker only */ +} WMI_BSS_FILTER; + +typedef PREPACK struct { + u8 bssFilter; /* see WMI_BSS_FILTER */ + u8 reserved1; /* For alignment */ + u16 reserved2; /* For alignment */ + u32 ieMask; +} POSTPACK WMI_BSS_FILTER_CMD; + +/* + * WMI_SET_PROBED_SSID_CMDID + */ +#define MAX_PROBED_SSID_INDEX 9 + +typedef enum { + DISABLE_SSID_FLAG = 0, /* disables entry */ + SPECIFIC_SSID_FLAG = 0x01, /* probes specified ssid */ + ANY_SSID_FLAG = 0x02, /* probes for any ssid */ +} WMI_SSID_FLAG; + +typedef PREPACK struct { + u8 entryIndex; /* 0 to MAX_PROBED_SSID_INDEX */ + u8 flag; /* WMI_SSID_FLG */ + u8 ssidLength; + u8 ssid[32]; +} POSTPACK WMI_PROBED_SSID_CMD; + +/* + * WMI_SET_LISTEN_INT_CMDID + * The Listen interval is between 15 and 3000 TUs + */ +#define MIN_LISTEN_INTERVAL 15 +#define MAX_LISTEN_INTERVAL 5000 +#define MIN_LISTEN_BEACONS 1 +#define MAX_LISTEN_BEACONS 50 + +typedef PREPACK struct { + u16 listenInterval; + u16 numBeacons; +} POSTPACK WMI_LISTEN_INT_CMD; + +/* + * WMI_SET_BEACON_INT_CMDID + */ +typedef PREPACK struct { + u16 beaconInterval; +} POSTPACK WMI_BEACON_INT_CMD; + +/* + * WMI_SET_BMISS_TIME_CMDID + * valid values are between 1000 and 5000 TUs + */ + +#define MIN_BMISS_TIME 1000 +#define MAX_BMISS_TIME 5000 +#define MIN_BMISS_BEACONS 1 +#define MAX_BMISS_BEACONS 50 + +typedef PREPACK struct { + u16 bmissTime; + u16 numBeacons; +} POSTPACK WMI_BMISS_TIME_CMD; + +/* + * WMI_SET_POWER_MODE_CMDID + */ +typedef enum { + REC_POWER = 0x01, + MAX_PERF_POWER, +} WMI_POWER_MODE; + +typedef PREPACK struct { + u8 powerMode; /* WMI_POWER_MODE */ +} POSTPACK WMI_POWER_MODE_CMD; + +typedef PREPACK struct { + s8 status; /* WMI_SET_PARAMS_REPLY */ +} POSTPACK WMI_SET_PARAMS_REPLY; + +typedef PREPACK struct { + u32 opcode; + u32 length; + char buffer[1]; /* WMI_SET_PARAMS */ +} POSTPACK WMI_SET_PARAMS_CMD; + +typedef PREPACK struct { + u8 multicast_mac[ATH_MAC_LEN]; /* WMI_SET_MCAST_FILTER */ +} POSTPACK WMI_SET_MCAST_FILTER_CMD; + +typedef PREPACK struct { + u8 enable; /* WMI_MCAST_FILTER */ +} POSTPACK WMI_MCAST_FILTER_CMD; + +/* + * WMI_SET_POWER_PARAMS_CMDID + */ +typedef enum { + IGNORE_DTIM = 0x01, + NORMAL_DTIM = 0x02, + STICK_DTIM = 0x03, + AUTO_DTIM = 0x04, +} WMI_DTIM_POLICY; + +/* Policy to determnine whether TX should wakeup WLAN if sleeping */ +typedef enum { + TX_WAKEUP_UPON_SLEEP = 1, + TX_DONT_WAKEUP_UPON_SLEEP = 2 +} WMI_TX_WAKEUP_POLICY_UPON_SLEEP; + +/* + * Policy to determnine whether power save failure event should be sent to + * host during scanning + */ +typedef enum { + SEND_POWER_SAVE_FAIL_EVENT_ALWAYS = 1, + IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN = 2, +} POWER_SAVE_FAIL_EVENT_POLICY; + +typedef PREPACK struct { + u16 idle_period; /* msec */ + u16 pspoll_number; + u16 dtim_policy; + u16 tx_wakeup_policy; + u16 num_tx_to_wakeup; + u16 ps_fail_event_policy; +} POSTPACK WMI_POWER_PARAMS_CMD; + +/* Adhoc power save types */ +typedef enum { + ADHOC_PS_DISABLE=1, + ADHOC_PS_ATH=2, + ADHOC_PS_IEEE=3, + ADHOC_PS_OTHER=4, +} WMI_ADHOC_PS_TYPE; + +typedef PREPACK struct { + u8 power_saving; + u8 ttl; /* number of beacon periods */ + u16 atim_windows; /* msec */ + u16 timeout_value; /* msec */ +} POSTPACK WMI_IBSS_PM_CAPS_CMD; + +/* AP power save types */ +typedef enum { + AP_PS_DISABLE=1, + AP_PS_ATH=2, +} WMI_AP_PS_TYPE; + +typedef PREPACK struct { + u32 idle_time; /* in msec */ + u32 ps_period; /* in usec */ + u8 sleep_period; /* in ps periods */ + u8 psType; +} POSTPACK WMI_AP_PS_CMD; + +/* + * WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID + */ +typedef enum { + IGNORE_TIM_ALL_QUEUES_APSD = 0, + PROCESS_TIM_ALL_QUEUES_APSD = 1, + IGNORE_TIM_SIMULATED_APSD = 2, + PROCESS_TIM_SIMULATED_APSD = 3, +} APSD_TIM_POLICY; + +typedef PREPACK struct { + u16 psPollTimeout; /* msec */ + u16 triggerTimeout; /* msec */ + u32 apsdTimPolicy; /* TIM behavior with ques APSD enabled. Default is IGNORE_TIM_ALL_QUEUES_APSD */ + u32 simulatedAPSDTimPolicy; /* TIM behavior with simulated APSD enabled. Default is PROCESS_TIM_SIMULATED_APSD */ +} POSTPACK WMI_POWERSAVE_TIMERS_POLICY_CMD; + +/* + * WMI_SET_VOICE_PKT_SIZE_CMDID + */ +typedef PREPACK struct { + u16 voicePktSize; +} POSTPACK WMI_SET_VOICE_PKT_SIZE_CMD; + +/* + * WMI_SET_MAX_SP_LEN_CMDID + */ +typedef enum { + DELIVER_ALL_PKT = 0x0, + DELIVER_2_PKT = 0x1, + DELIVER_4_PKT = 0x2, + DELIVER_6_PKT = 0x3, +} APSD_SP_LEN_TYPE; + +typedef PREPACK struct { + u8 maxSPLen; +} POSTPACK WMI_SET_MAX_SP_LEN_CMD; + +/* + * WMI_SET_DISC_TIMEOUT_CMDID + */ +typedef PREPACK struct { + u8 disconnectTimeout; /* seconds */ +} POSTPACK WMI_DISC_TIMEOUT_CMD; + +typedef enum { + UPLINK_TRAFFIC = 0, + DNLINK_TRAFFIC = 1, + BIDIR_TRAFFIC = 2, +} DIR_TYPE; + +typedef enum { + DISABLE_FOR_THIS_AC = 0, + ENABLE_FOR_THIS_AC = 1, + ENABLE_FOR_ALL_AC = 2, +} VOICEPS_CAP_TYPE; + +typedef enum { + TRAFFIC_TYPE_APERIODIC = 0, + TRAFFIC_TYPE_PERIODIC = 1, +}TRAFFIC_TYPE; + +/* + * WMI_SYNCHRONIZE_CMDID + */ +typedef PREPACK struct { + u8 dataSyncMap; +} POSTPACK WMI_SYNC_CMD; + +/* + * WMI_CREATE_PSTREAM_CMDID + */ +typedef PREPACK struct { + u32 minServiceInt; /* in milli-sec */ + u32 maxServiceInt; /* in milli-sec */ + u32 inactivityInt; /* in milli-sec */ + u32 suspensionInt; /* in milli-sec */ + u32 serviceStartTime; + u32 minDataRate; /* in bps */ + u32 meanDataRate; /* in bps */ + u32 peakDataRate; /* in bps */ + u32 maxBurstSize; + u32 delayBound; + u32 minPhyRate; /* in bps */ + u32 sba; + u32 mediumTime; + u16 nominalMSDU; /* in octects */ + u16 maxMSDU; /* in octects */ + u8 trafficClass; + u8 trafficDirection; /* DIR_TYPE */ + u8 rxQueueNum; + u8 trafficType; /* TRAFFIC_TYPE */ + u8 voicePSCapability; /* VOICEPS_CAP_TYPE */ + u8 tsid; + u8 userPriority; /* 802.1D user priority */ + u8 nominalPHY; /* nominal phy rate */ +} POSTPACK WMI_CREATE_PSTREAM_CMD; + +/* + * WMI_DELETE_PSTREAM_CMDID + */ +typedef PREPACK struct { + u8 txQueueNumber; + u8 rxQueueNumber; + u8 trafficDirection; + u8 trafficClass; + u8 tsid; +} POSTPACK WMI_DELETE_PSTREAM_CMD; + +/* + * WMI_SET_CHANNEL_PARAMS_CMDID + */ +typedef enum { + WMI_11A_MODE = 0x1, + WMI_11G_MODE = 0x2, + WMI_11AG_MODE = 0x3, + WMI_11B_MODE = 0x4, + WMI_11GONLY_MODE = 0x5, +} WMI_PHY_MODE; + +#define WMI_MAX_CHANNELS 32 + +typedef PREPACK struct { + u8 reserved1; + u8 scanParam; /* set if enable scan */ + u8 phyMode; /* see WMI_PHY_MODE */ + u8 numChannels; /* how many channels follow */ + u16 channelList[1]; /* channels in Mhz */ +} POSTPACK WMI_CHANNEL_PARAMS_CMD; + + +/* + * WMI_RSSI_THRESHOLD_PARAMS_CMDID + * Setting the polltime to 0 would disable polling. + * Threshold values are in the ascending order, and should agree to: + * (lowThreshold_lowerVal < lowThreshold_upperVal < highThreshold_lowerVal + * < highThreshold_upperVal) + */ + +typedef PREPACK struct WMI_RSSI_THRESHOLD_PARAMS{ + u32 pollTime; /* Polling time as a factor of LI */ + s16 thresholdAbove1_Val; /* lowest of upper */ + s16 thresholdAbove2_Val; + s16 thresholdAbove3_Val; + s16 thresholdAbove4_Val; + s16 thresholdAbove5_Val; + s16 thresholdAbove6_Val; /* highest of upper */ + s16 thresholdBelow1_Val; /* lowest of bellow */ + s16 thresholdBelow2_Val; + s16 thresholdBelow3_Val; + s16 thresholdBelow4_Val; + s16 thresholdBelow5_Val; + s16 thresholdBelow6_Val; /* highest of bellow */ + u8 weight; /* "alpha" */ + u8 reserved[3]; +} POSTPACK WMI_RSSI_THRESHOLD_PARAMS_CMD; + +/* + * WMI_SNR_THRESHOLD_PARAMS_CMDID + * Setting the polltime to 0 would disable polling. + */ + +typedef PREPACK struct WMI_SNR_THRESHOLD_PARAMS{ + u32 pollTime; /* Polling time as a factor of LI */ + u8 weight; /* "alpha" */ + u8 thresholdAbove1_Val; /* lowest of uppper*/ + u8 thresholdAbove2_Val; + u8 thresholdAbove3_Val; + u8 thresholdAbove4_Val; /* highest of upper */ + u8 thresholdBelow1_Val; /* lowest of bellow */ + u8 thresholdBelow2_Val; + u8 thresholdBelow3_Val; + u8 thresholdBelow4_Val; /* highest of bellow */ + u8 reserved[3]; +} POSTPACK WMI_SNR_THRESHOLD_PARAMS_CMD; + +/* + * WMI_LQ_THRESHOLD_PARAMS_CMDID + */ +typedef PREPACK struct WMI_LQ_THRESHOLD_PARAMS { + u8 enable; + u8 thresholdAbove1_Val; + u8 thresholdAbove2_Val; + u8 thresholdAbove3_Val; + u8 thresholdAbove4_Val; + u8 thresholdBelow1_Val; + u8 thresholdBelow2_Val; + u8 thresholdBelow3_Val; + u8 thresholdBelow4_Val; + u8 reserved[3]; +} POSTPACK WMI_LQ_THRESHOLD_PARAMS_CMD; + +typedef enum { + WMI_LPREAMBLE_DISABLED = 0, + WMI_LPREAMBLE_ENABLED +} WMI_LPREAMBLE_STATUS; + +typedef enum { + WMI_IGNORE_BARKER_IN_ERP = 0, + WMI_DONOT_IGNORE_BARKER_IN_ERP +} WMI_PREAMBLE_POLICY; + +typedef PREPACK struct { + u8 status; + u8 preamblePolicy; +}POSTPACK WMI_SET_LPREAMBLE_CMD; + +typedef PREPACK struct { + u16 threshold; +}POSTPACK WMI_SET_RTS_CMD; + +/* + * WMI_TARGET_ERROR_REPORT_BITMASK_CMDID + * Sets the error reporting event bitmask in target. Target clears it + * upon an error. Subsequent errors are counted, but not reported + * via event, unless the bitmask is set again. + */ +typedef PREPACK struct { + u32 bitmask; +} POSTPACK WMI_TARGET_ERROR_REPORT_BITMASK; + +/* + * WMI_SET_TX_PWR_CMDID + */ +typedef PREPACK struct { + u8 dbM; /* in dbM units */ +} POSTPACK WMI_SET_TX_PWR_CMD, WMI_TX_PWR_REPLY; + +/* + * WMI_SET_ASSOC_INFO_CMDID + * + * A maximum of 2 private IEs can be sent in the [Re]Assoc request. + * A 3rd one, the CCX version IE can also be set from the host. + */ +#define WMI_MAX_ASSOC_INFO_TYPE 2 +#define WMI_CCX_VER_IE 2 /* ieType to set CCX Version IE */ + +#define WMI_MAX_ASSOC_INFO_LEN 240 + +typedef PREPACK struct { + u8 ieType; + u8 bufferSize; + u8 assocInfo[1]; /* up to WMI_MAX_ASSOC_INFO_LEN */ +} POSTPACK WMI_SET_ASSOC_INFO_CMD; + + +/* + * WMI_GET_TX_PWR_CMDID does not take any parameters + */ + +/* + * WMI_ADD_BAD_AP_CMDID + */ +#define WMI_MAX_BAD_AP_INDEX 1 + +typedef PREPACK struct { + u8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */ + u8 bssid[ATH_MAC_LEN]; +} POSTPACK WMI_ADD_BAD_AP_CMD; + +/* + * WMI_DELETE_BAD_AP_CMDID + */ +typedef PREPACK struct { + u8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */ +} POSTPACK WMI_DELETE_BAD_AP_CMD; + +/* + * WMI_SET_ACCESS_PARAMS_CMDID + */ +#define WMI_DEFAULT_TXOP_ACPARAM 0 /* implies one MSDU */ +#define WMI_DEFAULT_ECWMIN_ACPARAM 4 /* corresponds to CWmin of 15 */ +#define WMI_DEFAULT_ECWMAX_ACPARAM 10 /* corresponds to CWmax of 1023 */ +#define WMI_MAX_CW_ACPARAM 15 /* maximum eCWmin or eCWmax */ +#define WMI_DEFAULT_AIFSN_ACPARAM 2 +#define WMI_MAX_AIFSN_ACPARAM 15 +typedef PREPACK struct { + u16 txop; /* in units of 32 usec */ + u8 eCWmin; + u8 eCWmax; + u8 aifsn; + u8 ac; +} POSTPACK WMI_SET_ACCESS_PARAMS_CMD; + + +/* + * WMI_SET_RETRY_LIMITS_CMDID + * + * This command is used to customize the number of retries the + * wlan device will perform on a given frame. + */ +#define WMI_MIN_RETRIES 2 +#define WMI_MAX_RETRIES 13 +typedef enum { + MGMT_FRAMETYPE = 0, + CONTROL_FRAMETYPE = 1, + DATA_FRAMETYPE = 2 +} WMI_FRAMETYPE; + +typedef PREPACK struct { + u8 frameType; /* WMI_FRAMETYPE */ + u8 trafficClass; /* applies only to DATA_FRAMETYPE */ + u8 maxRetries; + u8 enableNotify; +} POSTPACK WMI_SET_RETRY_LIMITS_CMD; + +/* + * WMI_SET_ROAM_CTRL_CMDID + * + * This command is used to influence the Roaming behaviour + * Set the host biases of the BSSs before setting the roam mode as bias + * based. + */ + +/* + * Different types of Roam Control + */ + +typedef enum { + WMI_FORCE_ROAM = 1, /* Roam to the specified BSSID */ + WMI_SET_ROAM_MODE = 2, /* default ,progd bias, no roam */ + WMI_SET_HOST_BIAS = 3, /* Set the Host Bias */ + WMI_SET_LOWRSSI_SCAN_PARAMS = 4, /* Set lowrssi Scan parameters */ +} WMI_ROAM_CTRL_TYPE; + +#define WMI_MIN_ROAM_CTRL_TYPE WMI_FORCE_ROAM +#define WMI_MAX_ROAM_CTRL_TYPE WMI_SET_LOWRSSI_SCAN_PARAMS + +/* + * ROAM MODES + */ + +typedef enum { + WMI_DEFAULT_ROAM_MODE = 1, /* RSSI based ROAM */ + WMI_HOST_BIAS_ROAM_MODE = 2, /* HOST BIAS based ROAM */ + WMI_LOCK_BSS_MODE = 3 /* Lock to the Current BSS - no Roam */ +} WMI_ROAM_MODE; + +/* + * BSS HOST BIAS INFO + */ + +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; + s8 bias; +} POSTPACK WMI_BSS_BIAS; + +typedef PREPACK struct { + u8 numBss; + WMI_BSS_BIAS bssBias[1]; +} POSTPACK WMI_BSS_BIAS_INFO; + +typedef PREPACK struct WMI_LOWRSSI_SCAN_PARAMS { + u16 lowrssi_scan_period; + s16 lowrssi_scan_threshold; + s16 lowrssi_roam_threshold; + u8 roam_rssi_floor; + u8 reserved[1]; /* For alignment */ +} POSTPACK WMI_LOWRSSI_SCAN_PARAMS; + +typedef PREPACK struct { + PREPACK union { + u8 bssid[ATH_MAC_LEN]; /* WMI_FORCE_ROAM */ + u8 roamMode; /* WMI_SET_ROAM_MODE */ + WMI_BSS_BIAS_INFO bssBiasInfo; /* WMI_SET_HOST_BIAS */ + WMI_LOWRSSI_SCAN_PARAMS lrScanParams; + } POSTPACK info; + u8 roamCtrlType ; +} POSTPACK WMI_SET_ROAM_CTRL_CMD; + +/* + * WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID + */ +typedef enum { + BT_WLAN_CONN_PRECDENCE_WLAN=0, /* Default */ + BT_WLAN_CONN_PRECDENCE_PAL, +} BT_WLAN_CONN_PRECEDENCE; + +typedef PREPACK struct { + u8 precedence; +} POSTPACK WMI_SET_BT_WLAN_CONN_PRECEDENCE; + +/* + * WMI_ENABLE_RM_CMDID + */ +typedef PREPACK struct { + u32 enable_radio_measurements; +} POSTPACK WMI_ENABLE_RM_CMD; + +/* + * WMI_SET_MAX_OFFHOME_DURATION_CMDID + */ +typedef PREPACK struct { + u8 max_offhome_duration; +} POSTPACK WMI_SET_MAX_OFFHOME_DURATION_CMD; + +typedef PREPACK struct { + u32 frequency; + u8 threshold; +} POSTPACK WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD; +/*---------------------- BTCOEX RELATED -------------------------------------*/ +/*----------------------COMMON to AR6002 and AR6003 -------------------------*/ +typedef enum { + BT_STREAM_UNDEF = 0, + BT_STREAM_SCO, /* SCO stream */ + BT_STREAM_A2DP, /* A2DP stream */ + BT_STREAM_SCAN, /* BT Discovery or Page */ + BT_STREAM_ESCO, + BT_STREAM_MAX +} BT_STREAM_TYPE; + +typedef enum { + BT_PARAM_SCO_PSPOLL_LATENCY_ONE_FOURTH =1, + BT_PARAM_SCO_PSPOLL_LATENCY_HALF, + BT_PARAM_SCO_PSPOLL_LATENCY_THREE_FOURTH, +} BT_PARAMS_SCO_PSPOLL_LATENCY; + +typedef enum { + BT_PARAMS_SCO_STOMP_SCO_NEVER =1, + BT_PARAMS_SCO_STOMP_SCO_ALWAYS, + BT_PARAMS_SCO_STOMP_SCO_IN_LOWRSSI, +} BT_PARAMS_SCO_STOMP_RULES; + +typedef enum { + BT_STATUS_UNDEF = 0, + BT_STATUS_ON, + BT_STATUS_OFF, + BT_STATUS_MAX +} BT_STREAM_STATUS; + +typedef PREPACK struct { + u8 streamType; + u8 status; +} POSTPACK WMI_SET_BT_STATUS_CMD; + +typedef enum { + BT_ANT_TYPE_UNDEF=0, + BT_ANT_TYPE_DUAL, + BT_ANT_TYPE_SPLITTER, + BT_ANT_TYPE_SWITCH, + BT_ANT_TYPE_HIGH_ISO_DUAL +} BT_ANT_FRONTEND_CONFIG; + +typedef enum { + BT_COLOCATED_DEV_BTS4020=0, + BT_COLCATED_DEV_CSR , + BT_COLOCATED_DEV_VALKYRIE +} BT_COLOCATED_DEV_TYPE; + +/*********************** Applicable to AR6002 ONLY ******************************/ + +typedef enum { + BT_PARAM_SCO = 1, /* SCO stream parameters */ + BT_PARAM_A2DP , + BT_PARAM_ANTENNA_CONFIG, + BT_PARAM_COLOCATED_BT_DEVICE, + BT_PARAM_ACLCOEX, + BT_PARAM_11A_SEPARATE_ANT, + BT_PARAM_MAX +} BT_PARAM_TYPE; + + +#define BT_SCO_ALLOW_CLOSE_RANGE_OPT (1 << 0) +#define BT_SCO_FORCE_AWAKE_OPT (1 << 1) +#define BT_SCO_SET_RSSI_OVERRIDE(flags) ((flags) |= (1 << 2)) +#define BT_SCO_GET_RSSI_OVERRIDE(flags) (((flags) >> 2) & 0x1) +#define BT_SCO_SET_RTS_OVERRIDE(flags) ((flags) |= (1 << 3)) +#define BT_SCO_GET_RTS_OVERRIDE(flags) (((flags) >> 3) & 0x1) +#define BT_SCO_GET_MIN_LOW_RATE_CNT(flags) (((flags) >> 8) & 0xFF) +#define BT_SCO_GET_MAX_LOW_RATE_CNT(flags) (((flags) >> 16) & 0xFF) +#define BT_SCO_SET_MIN_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 8) +#define BT_SCO_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16) + +typedef PREPACK struct { + u32 numScoCyclesForceTrigger; /* Number SCO cycles after which + force a pspoll. default = 10 */ + u32 dataResponseTimeout; /* Timeout Waiting for Downlink pkt + in response for ps-poll, + default = 10 msecs */ + u32 stompScoRules; + u32 scoOptFlags; /* SCO Options Flags : + bits: meaning: + 0 Allow Close Range Optimization + 1 Force awake during close range + 2 If set use host supplied RSSI for OPT + 3 If set use host supplied RTS COUNT for OPT + 4..7 Unused + 8..15 Low Data Rate Min Cnt + 16..23 Low Data Rate Max Cnt + */ + + u8 stompDutyCyleVal; /* Sco cycles to limit ps-poll queuing + if stomped */ + u8 stompDutyCyleMaxVal; /*firm ware increases stomp duty cycle + gradually uptill this value on need basis*/ + u8 psPollLatencyFraction; /* Fraction of idle + period, within which + additional ps-polls + can be queued */ + u8 noSCOSlots; /* Number of SCO Tx/Rx slots. + HVx, EV3, 2EV3 = 2 */ + u8 noIdleSlots; /* Number of Bluetooth idle slots between + consecutive SCO Tx/Rx slots + HVx, EV3 = 4 + 2EV3 = 10 */ + u8 scoOptOffRssi;/*RSSI value below which we go to ps poll*/ + u8 scoOptOnRssi; /*RSSI value above which we reenter opt mode*/ + u8 scoOptRtsCount; +} POSTPACK BT_PARAMS_SCO; + +#define BT_A2DP_ALLOW_CLOSE_RANGE_OPT (1 << 0) +#define BT_A2DP_FORCE_AWAKE_OPT (1 << 1) +#define BT_A2DP_SET_RSSI_OVERRIDE(flags) ((flags) |= (1 << 2)) +#define BT_A2DP_GET_RSSI_OVERRIDE(flags) (((flags) >> 2) & 0x1) +#define BT_A2DP_SET_RTS_OVERRIDE(flags) ((flags) |= (1 << 3)) +#define BT_A2DP_GET_RTS_OVERRIDE(flags) (((flags) >> 3) & 0x1) +#define BT_A2DP_GET_MIN_LOW_RATE_CNT(flags) (((flags) >> 8) & 0xFF) +#define BT_A2DP_GET_MAX_LOW_RATE_CNT(flags) (((flags) >> 16) & 0xFF) +#define BT_A2DP_SET_MIN_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 8) +#define BT_A2DP_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16) + +typedef PREPACK struct { + u32 a2dpWlanUsageLimit; /* MAX time firmware uses the medium for + wlan, after it identifies the idle time + default (30 msecs) */ + u32 a2dpBurstCntMin; /* Minimum number of bluetooth data frames + to replenish Wlan Usage limit (default 3) */ + u32 a2dpDataRespTimeout; + u32 a2dpOptFlags; /* A2DP Option flags: + bits: meaning: + 0 Allow Close Range Optimization + 1 Force awake during close range + 2 If set use host supplied RSSI for OPT + 3 If set use host supplied RTS COUNT for OPT + 4..7 Unused + 8..15 Low Data Rate Min Cnt + 16..23 Low Data Rate Max Cnt + */ + u8 isCoLocatedBtRoleMaster; + u8 a2dpOptOffRssi;/*RSSI value below which we go to ps poll*/ + u8 a2dpOptOnRssi; /*RSSI value above which we reenter opt mode*/ + u8 a2dpOptRtsCount; +}POSTPACK BT_PARAMS_A2DP; + +/* During BT ftp/ BT OPP or any another data based acl profile on bluetooth + (non a2dp).*/ +typedef PREPACK struct { + u32 aclWlanMediumUsageTime; /* Wlan usage time during Acl (non-a2dp) + coexistence (default 30 msecs) */ + u32 aclBtMediumUsageTime; /* Bt usage time during acl coexistence + (default 30 msecs)*/ + u32 aclDataRespTimeout; + u32 aclDetectTimeout; /* ACL coexistence enabled if we get + 10 Pkts in X msec(default 100 msecs) */ + u32 aclmaxPktCnt; /* No of ACL pkts to receive before + enabling ACL coex */ + +}POSTPACK BT_PARAMS_ACLCOEX; + +typedef PREPACK struct { + PREPACK union { + BT_PARAMS_SCO scoParams; + BT_PARAMS_A2DP a2dpParams; + BT_PARAMS_ACLCOEX aclCoexParams; + u8 antType; /* 0 -Disabled (default) + 1 - BT_ANT_TYPE_DUAL + 2 - BT_ANT_TYPE_SPLITTER + 3 - BT_ANT_TYPE_SWITCH */ + u8 coLocatedBtDev; /* 0 - BT_COLOCATED_DEV_BTS4020 (default) + 1 - BT_COLCATED_DEV_CSR + 2 - BT_COLOCATED_DEV_VALKYRIe + */ + } POSTPACK info; + u8 paramType ; +} POSTPACK WMI_SET_BT_PARAMS_CMD; + +/************************ END AR6002 BTCOEX *******************************/ +/*-----------------------AR6003 BTCOEX -----------------------------------*/ + +/* ---------------WMI_SET_BTCOEX_FE_ANT_CMDID --------------------------*/ +/* Indicates front end antenna configuration. This command needs to be issued + * right after initialization and after WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID. + * AR6003 enables coexistence and antenna switching based on the configuration. + */ +typedef enum { + WMI_BTCOEX_NOT_ENABLED = 0, + WMI_BTCOEX_FE_ANT_SINGLE =1, + WMI_BTCOEX_FE_ANT_DUAL=2, + WMI_BTCOEX_FE_ANT_DUAL_HIGH_ISO=3, + WMI_BTCOEX_FE_ANT_TYPE_MAX +}WMI_BTCOEX_FE_ANT_TYPE; + +typedef PREPACK struct { + u8 btcoexFeAntType; /* 1 - WMI_BTCOEX_FE_ANT_SINGLE for single antenna front end + 2 - WMI_BTCOEX_FE_ANT_DUAL for dual antenna front end + (for isolations less 35dB, for higher isolation there + is not need to pass this command). + (not implemented) + */ +}POSTPACK WMI_SET_BTCOEX_FE_ANT_CMD; + +/* -------------WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID ----------------*/ +/* Indicate the bluetooth chip to the firmware. Firmware can have different algorithm based + * bluetooth chip type.Based on bluetooth device, different coexistence protocol would be used. + */ +typedef PREPACK struct { + u8 btcoexCoLocatedBTdev; /*1 - Qcom BT (3 -wire PTA) + 2 - CSR BT (3 wire PTA) + 3 - Atheros 3001 BT (3 wire PTA) + 4 - STE bluetooth (4-wire ePTA) + 5 - Atheros 3002 BT (4-wire MCI) + defaults= 3 (Atheros 3001 BT ) + */ +}POSTPACK WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD; + +/* -------------WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID ------------*/ +/* Configuration parameters during bluetooth inquiry and page. Page configuration + * is applicable only on interfaces which can distinguish page (applicable only for ePTA - + * STE bluetooth). + * Bluetooth inquiry start and end is indicated via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID. + * During this the station will be power-save mode. + */ +typedef PREPACK struct { + u32 btInquiryDataFetchFrequency;/* The frequency of querying the AP for data + (via pspoll) is configured by this parameter. + "default = 10 ms" */ + + u32 protectBmissDurPostBtInquiry;/* The firmware will continue to be in inquiry state + for configured duration, after inquiry completion + . This is to ensure other bluetooth transactions + (RDP, SDP profiles, link key exchange ...etc) + goes through smoothly without wifi stomping. + default = 10 secs*/ + + u32 maxpageStomp; /*Applicable only for STE-BT interface. Currently not + used */ + u32 btInquiryPageFlag; /* Not used */ +}POSTPACK WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD; + +/*---------------------WMI_SET_BTCOEX_SCO_CONFIG_CMDID ---------------*/ +/* Configure SCO parameters. These parameters would be used whenever firmware is indicated + * of (e)SCO profile on bluetooth ( via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID). + * Configration of BTCOEX_SCO_CONFIG data structure are common configuration and applies + * ps-poll mode and opt mode. + * Ps-poll Mode - Station is in power-save and retrieves downlink data between sco gaps. + * Opt Mode - station is in awake state and access point can send data to station any time. + * BTCOEX_PSPOLLMODE_SCO_CONFIG - Configuration applied only during ps-poll mode. + * BTCOEX_OPTMODE_SCO_CONFIG - Configuration applied only during opt mode. + */ +#define WMI_SCO_CONFIG_FLAG_ALLOW_OPTIMIZATION (1 << 0) +#define WMI_SCO_CONFIG_FLAG_IS_EDR_CAPABLE (1 << 1) +#define WMI_SCO_CONFIG_FLAG_IS_BT_MASTER (1 << 2) +#define WMI_SCO_CONFIG_FLAG_FW_DETECT_OF_PER (1 << 3) +typedef PREPACK struct { + u32 scoSlots; /* Number of SCO Tx/Rx slots. + HVx, EV3, 2EV3 = 2 */ + u32 scoIdleSlots; /* Number of Bluetooth idle slots between + consecutive SCO Tx/Rx slots + HVx, EV3 = 4 + 2EV3 = 10 + */ + u32 scoFlags; /* SCO Options Flags : + bits: meaning: + 0 Allow Close Range Optimization + 1 Is EDR capable or Not + 2 IS Co-located Bt role Master + 3 Firmware determines the periodicity of SCO. + */ + + u32 linkId; /* applicable to STE-BT - not used */ +}POSTPACK BTCOEX_SCO_CONFIG; + +typedef PREPACK struct { + u32 scoCyclesForceTrigger; /* Number SCO cycles after which + force a pspoll. default = 10 */ + u32 scoDataResponseTimeout; /* Timeout Waiting for Downlink pkt + in response for ps-poll, + default = 20 msecs */ + + u32 scoStompDutyCyleVal; /* not implemented */ + + u32 scoStompDutyCyleMaxVal; /*Not implemented */ + + u32 scoPsPollLatencyFraction; /* Fraction of idle + period, within which + additional ps-polls can be queued + 1 - 1/4 of idle duration + 2 - 1/2 of idle duration + 3 - 3/4 of idle duration + default =2 (1/2) + */ +}POSTPACK BTCOEX_PSPOLLMODE_SCO_CONFIG; + +typedef PREPACK struct { + u32 scoStompCntIn100ms;/*max number of SCO stomp in 100ms allowed in + opt mode. If exceeds the configured value, + switch to ps-poll mode + default = 3 */ + + u32 scoContStompMax; /* max number of continuous stomp allowed in opt mode. + if exceeded switch to pspoll mode + default = 3 */ + + u32 scoMinlowRateMbps; /* Low rate threshold */ + + u32 scoLowRateCnt; /* number of low rate pkts (< scoMinlowRateMbps) allowed in 100 ms. + If exceeded switch/stay to ps-poll mode, lower stay in opt mode. + default = 36 + */ + + u32 scoHighPktRatio; /*(Total Rx pkts in 100 ms + 1)/ + ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms, + if exceeded switch/stay in opt mode and if lower switch/stay in pspoll mode. + default = 5 (80% of high rates) + */ + + u32 scoMaxAggrSize; /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates + max number of aggregates if it was negogiated to higher value + default = 1 + Recommended value Basic rate headsets = 1, EDR (2-EV3) =4. + */ +}POSTPACK BTCOEX_OPTMODE_SCO_CONFIG; + +typedef PREPACK struct { + u32 scanInterval; + u32 maxScanStompCnt; +}POSTPACK BTCOEX_WLANSCAN_SCO_CONFIG; + +typedef PREPACK struct { + BTCOEX_SCO_CONFIG scoConfig; + BTCOEX_PSPOLLMODE_SCO_CONFIG scoPspollConfig; + BTCOEX_OPTMODE_SCO_CONFIG scoOptModeConfig; + BTCOEX_WLANSCAN_SCO_CONFIG scoWlanScanConfig; +}POSTPACK WMI_SET_BTCOEX_SCO_CONFIG_CMD; + +/* ------------------WMI_SET_BTCOEX_A2DP_CONFIG_CMDID -------------------*/ +/* Configure A2DP profile parameters. These parameters would be used whenver firmware is indicated + * of A2DP profile on bluetooth ( via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID). + * Configuration of BTCOEX_A2DP_CONFIG data structure are common configuration and applies to + * ps-poll mode and opt mode. + * Ps-poll Mode - Station is in power-save and retrieves downlink data between a2dp data bursts. + * Opt Mode - station is in power save during a2dp bursts and awake in the gaps. + * BTCOEX_PSPOLLMODE_A2DP_CONFIG - Configuration applied only during ps-poll mode. + * BTCOEX_OPTMODE_A2DP_CONFIG - Configuration applied only during opt mode. + */ + +#define WMI_A2DP_CONFIG_FLAG_ALLOW_OPTIMIZATION (1 << 0) +#define WMI_A2DP_CONFIG_FLAG_IS_EDR_CAPABLE (1 << 1) +#define WMI_A2DP_CONFIG_FLAG_IS_BT_ROLE_MASTER (1 << 2) +#define WMI_A2DP_CONFIG_FLAG_IS_A2DP_HIGH_PRI (1 << 3) +#define WMI_A2DP_CONFIG_FLAG_FIND_BT_ROLE (1 << 4) + +typedef PREPACK struct { + u32 a2dpFlags; /* A2DP Option flags: + bits: meaning: + 0 Allow Close Range Optimization + 1 IS EDR capable + 2 IS Co-located Bt role Master + 3 a2dp traffic is high priority + 4 Fw detect the role of bluetooth. + */ + u32 linkId; /* Applicable only to STE-BT - not used */ + +}POSTPACK BTCOEX_A2DP_CONFIG; + +typedef PREPACK struct { + u32 a2dpWlanMaxDur; /* MAX time firmware uses the medium for + wlan, after it identifies the idle time + default (30 msecs) */ + + u32 a2dpMinBurstCnt; /* Minimum number of bluetooth data frames + to replenish Wlan Usage limit (default 3) */ + + u32 a2dpDataRespTimeout; /* Max duration firmware waits for downlink + by stomping on bluetooth + after ps-poll is acknowledged. + default = 20 ms + */ +}POSTPACK BTCOEX_PSPOLLMODE_A2DP_CONFIG; + +typedef PREPACK struct { + u32 a2dpMinlowRateMbps; /* Low rate threshold */ + + u32 a2dpLowRateCnt; /* number of low rate pkts (< a2dpMinlowRateMbps) allowed in 100 ms. + If exceeded switch/stay to ps-poll mode, lower stay in opt mode. + default = 36 + */ + + u32 a2dpHighPktRatio; /*(Total Rx pkts in 100 ms + 1)/ + ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms, + if exceeded switch/stay in opt mode and if lower switch/stay in pspoll mode. + default = 5 (80% of high rates) + */ + + u32 a2dpMaxAggrSize; /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates + max number of aggregates if it was negogiated to higher value + default = 1 + Recommended value Basic rate headsets = 1, EDR (2-EV3) =8. + */ + u32 a2dpPktStompCnt; /*number of a2dp pkts that can be stomped per burst. + default = 6*/ + +}POSTPACK BTCOEX_OPTMODE_A2DP_CONFIG; + +typedef PREPACK struct { + BTCOEX_A2DP_CONFIG a2dpConfig; + BTCOEX_PSPOLLMODE_A2DP_CONFIG a2dppspollConfig; + BTCOEX_OPTMODE_A2DP_CONFIG a2dpOptConfig; +}POSTPACK WMI_SET_BTCOEX_A2DP_CONFIG_CMD; + +/*------------ WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID---------------------*/ +/* Configure non-A2dp ACL profile parameters.The starts of ACL profile can either be + * indicated via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID orenabled via firmware detection + * which is configured via "aclCoexFlags". + * Configration of BTCOEX_ACLCOEX_CONFIG data structure are common configuration and applies + * ps-poll mode and opt mode. + * Ps-poll Mode - Station is in power-save and retrieves downlink data during wlan medium. + * Opt Mode - station is in power save during bluetooth medium time and awake during wlan duration. + * (Not implemented yet) + * + * BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG - Configuration applied only during ps-poll mode. + * BTCOEX_OPTMODE_ACLCOEX_CONFIG - Configuration applied only during opt mode. + */ + +#define WMI_ACLCOEX_FLAGS_ALLOW_OPTIMIZATION (1 << 0) +#define WMI_ACLCOEX_FLAGS_DISABLE_FW_DETECTION (1 << 1) + +typedef PREPACK struct { + u32 aclWlanMediumDur; /* Wlan usage time during Acl (non-a2dp) + coexistence (default 30 msecs) + */ + + u32 aclBtMediumDur; /* Bt usage time during acl coexistence + (default 30 msecs) + */ + + u32 aclDetectTimeout; /* BT activity observation time limit. + In this time duration, number of bt pkts are counted. + If the Cnt reaches "aclPktCntLowerLimit" value + for "aclIterToEnableCoex" iteration continuously, + firmware gets into ACL coexistence mode. + Similarly, if bt traffic count during ACL coexistence + has not reached "aclPktCntLowerLimit" continuously + for "aclIterToEnableCoex", then ACL coexistence is + disabled. + -default 100 msecs + */ + + u32 aclPktCntLowerLimit; /* Acl Pkt Cnt to be received in duration of + "aclDetectTimeout" for + "aclIterForEnDis" times to enabling ACL coex. + Similar logic is used to disable acl coexistence. + (If "aclPktCntLowerLimit" cnt of acl pkts + are not seen by the for "aclIterForEnDis" + then acl coexistence is disabled). + default = 10 + */ + + u32 aclIterForEnDis; /* number of Iteration of "aclPktCntLowerLimit" for Enabling and + Disabling Acl Coexistence. + default = 3 + */ + + u32 aclPktCntUpperLimit; /* This is upperBound limit, if there is more than + "aclPktCntUpperLimit" seen in "aclDetectTimeout", + ACL coexistence is enabled right away. + - default 15*/ + + u32 aclCoexFlags; /* A2DP Option flags: + bits: meaning: + 0 Allow Close Range Optimization + 1 disable Firmware detection + (Currently supported configuration is aclCoexFlags =0) + */ + u32 linkId; /* Applicable only for STE-BT - not used */ + +}POSTPACK BTCOEX_ACLCOEX_CONFIG; + +typedef PREPACK struct { + u32 aclDataRespTimeout; /* Max duration firmware waits for downlink + by stomping on bluetooth + after ps-poll is acknowledged. + default = 20 ms */ + +}POSTPACK BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG; + + +/* Not implemented yet*/ +typedef PREPACK struct { + u32 aclCoexMinlowRateMbps; + u32 aclCoexLowRateCnt; + u32 aclCoexHighPktRatio; + u32 aclCoexMaxAggrSize; + u32 aclPktStompCnt; +}POSTPACK BTCOEX_OPTMODE_ACLCOEX_CONFIG; + +typedef PREPACK struct { + BTCOEX_ACLCOEX_CONFIG aclCoexConfig; + BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG aclCoexPspollConfig; + BTCOEX_OPTMODE_ACLCOEX_CONFIG aclCoexOptConfig; +}POSTPACK WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD; + +/* -----------WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ------------------*/ +typedef enum { + WMI_BTCOEX_BT_PROFILE_SCO =1, + WMI_BTCOEX_BT_PROFILE_A2DP, + WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE, + WMI_BTCOEX_BT_PROFILE_ACLCOEX, +}WMI_BTCOEX_BT_PROFILE; + +typedef PREPACK struct { + u32 btProfileType; + u32 btOperatingStatus; + u32 btLinkId; +}WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD; + +/*--------------------- WMI_SET_BTCOEX_DEBUG_CMDID ---------------------*/ +/* Used for firmware development and debugging */ +typedef PREPACK struct { + u32 btcoexDbgParam1; + u32 btcoexDbgParam2; + u32 btcoexDbgParam3; + u32 btcoexDbgParam4; + u32 btcoexDbgParam5; +}WMI_SET_BTCOEX_DEBUG_CMD; + +/*---------------------WMI_GET_BTCOEX_CONFIG_CMDID --------------------- */ +/* Command to firmware to get configuration parameters of the bt profile + * reported via WMI_BTCOEX_CONFIG_EVENTID */ +typedef PREPACK struct { + u32 btProfileType; /* 1 - SCO + 2 - A2DP + 3 - INQUIRY_PAGE + 4 - ACLCOEX + */ + u32 linkId; /* not used */ +}WMI_GET_BTCOEX_CONFIG_CMD; + +/*------------------WMI_REPORT_BTCOEX_CONFIG_EVENTID------------------- */ +/* Event from firmware to host, sent in response to WMI_GET_BTCOEX_CONFIG_CMDID + * */ +typedef PREPACK struct { + u32 btProfileType; + u32 linkId; /* not used */ + PREPACK union { + WMI_SET_BTCOEX_SCO_CONFIG_CMD scoConfigCmd; + WMI_SET_BTCOEX_A2DP_CONFIG_CMD a2dpConfigCmd; + WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD aclcoexConfig; + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD btinquiryPageConfigCmd; + } POSTPACK info; +} POSTPACK WMI_BTCOEX_CONFIG_EVENT; + +/*------------- WMI_REPORT_BTCOEX_BTCOEX_STATS_EVENTID--------------------*/ +/* Used for firmware development and debugging*/ +typedef PREPACK struct { + u32 highRatePktCnt; + u32 firstBmissCnt; + u32 psPollFailureCnt; + u32 nullFrameFailureCnt; + u32 optModeTransitionCnt; +}BTCOEX_GENERAL_STATS; + +typedef PREPACK struct { + u32 scoStompCntAvg; + u32 scoStompIn100ms; + u32 scoMaxContStomp; + u32 scoAvgNoRetries; + u32 scoMaxNoRetriesIn100ms; +}BTCOEX_SCO_STATS; + +typedef PREPACK struct { + u32 a2dpBurstCnt; + u32 a2dpMaxBurstCnt; + u32 a2dpAvgIdletimeIn100ms; + u32 a2dpAvgStompCnt; +}BTCOEX_A2DP_STATS; + +typedef PREPACK struct { + u32 aclPktCntInBtTime; + u32 aclStompCntInWlanTime; + u32 aclPktCntIn100ms; +}BTCOEX_ACLCOEX_STATS; + +typedef PREPACK struct { + BTCOEX_GENERAL_STATS coexStats; + BTCOEX_SCO_STATS scoStats; + BTCOEX_A2DP_STATS a2dpStats; + BTCOEX_ACLCOEX_STATS aclCoexStats; +}WMI_BTCOEX_STATS_EVENT; + + +/*--------------------------END OF BTCOEX -------------------------------------*/ +typedef PREPACK struct { + u32 sleepState; +}WMI_REPORT_SLEEP_STATE_EVENT; + +typedef enum { + WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP =0, + WMI_REPORT_SLEEP_STATUS_IS_AWAKE +} WMI_REPORT_SLEEP_STATUS; +typedef enum { + DISCONN_EVT_IN_RECONN = 0, /* default */ + NO_DISCONN_EVT_IN_RECONN +} TARGET_EVENT_REPORT_CONFIG; + +typedef PREPACK struct { + u32 evtConfig; +} POSTPACK WMI_SET_TARGET_EVENT_REPORT_CMD; + + +typedef PREPACK struct { + u16 cmd_buf_sz; /* HCI cmd buffer size */ + u8 buf[1]; /* Absolute HCI cmd */ +} POSTPACK WMI_HCI_CMD; + +/* + * Command Replies + */ + +/* + * WMI_GET_CHANNEL_LIST_CMDID reply + */ +typedef PREPACK struct { + u8 reserved1; + u8 numChannels; /* number of channels in reply */ + u16 channelList[1]; /* channel in Mhz */ +} POSTPACK WMI_CHANNEL_LIST_REPLY; + +typedef enum { + A_SUCCEEDED = 0, + A_FAILED_DELETE_STREAM_DOESNOT_EXIST=250, + A_SUCCEEDED_MODIFY_STREAM=251, + A_FAILED_INVALID_STREAM = 252, + A_FAILED_MAX_THINSTREAMS = 253, + A_FAILED_CREATE_REMOVE_PSTREAM_FIRST = 254, +} PSTREAM_REPLY_STATUS; + +typedef PREPACK struct { + u8 status; /* PSTREAM_REPLY_STATUS */ + u8 txQueueNumber; + u8 rxQueueNumber; + u8 trafficClass; + u8 trafficDirection; /* DIR_TYPE */ +} POSTPACK WMI_CRE_PRIORITY_STREAM_REPLY; + +typedef PREPACK struct { + u8 status; /* PSTREAM_REPLY_STATUS */ + u8 txQueueNumber; + u8 rxQueueNumber; + u8 trafficDirection; /* DIR_TYPE */ + u8 trafficClass; +} POSTPACK WMI_DEL_PRIORITY_STREAM_REPLY; + +/* + * List of Events (target to host) + */ +typedef enum { + WMI_READY_EVENTID = 0x1001, + WMI_CONNECT_EVENTID, + WMI_DISCONNECT_EVENTID, + WMI_BSSINFO_EVENTID, + WMI_CMDERROR_EVENTID, + WMI_REGDOMAIN_EVENTID, + WMI_PSTREAM_TIMEOUT_EVENTID, + WMI_NEIGHBOR_REPORT_EVENTID, + WMI_TKIP_MICERR_EVENTID, + WMI_SCAN_COMPLETE_EVENTID, /* 0x100a */ + WMI_REPORT_STATISTICS_EVENTID, + WMI_RSSI_THRESHOLD_EVENTID, + WMI_ERROR_REPORT_EVENTID, + WMI_OPT_RX_FRAME_EVENTID, + WMI_REPORT_ROAM_TBL_EVENTID, + WMI_EXTENSION_EVENTID, + WMI_CAC_EVENTID, + WMI_SNR_THRESHOLD_EVENTID, + WMI_LQ_THRESHOLD_EVENTID, + WMI_TX_RETRY_ERR_EVENTID, /* 0x1014 */ + WMI_REPORT_ROAM_DATA_EVENTID, + WMI_TEST_EVENTID, + WMI_APLIST_EVENTID, + WMI_GET_WOW_LIST_EVENTID, + WMI_GET_PMKID_LIST_EVENTID, + WMI_CHANNEL_CHANGE_EVENTID, + WMI_PEER_NODE_EVENTID, + WMI_PSPOLL_EVENTID, + WMI_DTIMEXPIRY_EVENTID, + WMI_WLAN_VERSION_EVENTID, + WMI_SET_PARAMS_REPLY_EVENTID, + WMI_ADDBA_REQ_EVENTID, /*0x1020 */ + WMI_ADDBA_RESP_EVENTID, + WMI_DELBA_REQ_EVENTID, + WMI_TX_COMPLETE_EVENTID, + WMI_HCI_EVENT_EVENTID, + WMI_ACL_DATA_EVENTID, + WMI_REPORT_SLEEP_STATE_EVENTID, +#ifdef WAPI_ENABLE + WMI_WAPI_REKEY_EVENTID, +#endif + WMI_REPORT_BTCOEX_STATS_EVENTID, + WMI_REPORT_BTCOEX_CONFIG_EVENTID, + WMI_GET_PMK_EVENTID, + + /* DFS Events */ + WMI_DFS_HOST_ATTACH_EVENTID, + WMI_DFS_HOST_INIT_EVENTID, + WMI_DFS_RESET_DELAYLINES_EVENTID, + WMI_DFS_RESET_RADARQ_EVENTID, + WMI_DFS_RESET_AR_EVENTID, + WMI_DFS_RESET_ARQ_EVENTID, + WMI_DFS_SET_DUR_MULTIPLIER_EVENTID, + WMI_DFS_SET_BANGRADAR_EVENTID, + WMI_DFS_SET_DEBUGLEVEL_EVENTID, + WMI_DFS_PHYERR_EVENTID, + /* CCX Evants */ + WMI_CCX_RM_STATUS_EVENTID, + + /* P2P Events */ + WMI_P2P_GO_NEG_RESULT_EVENTID, + + WMI_WAC_SCAN_DONE_EVENTID, + WMI_WAC_REPORT_BSS_EVENTID, + WMI_WAC_START_WPS_EVENTID, + WMI_WAC_CTRL_REQ_REPLY_EVENTID, + + /* RFKILL Events */ + WMI_RFKILL_STATE_CHANGE_EVENTID, + WMI_RFKILL_GET_MODE_CMD_EVENTID, + WMI_THIN_RESERVED_START_EVENTID = 0x8000, + + /* + * Events in this range are reserved for thinmode + * See wmi_thin.h for actual definitions + */ + WMI_THIN_RESERVED_END_EVENTID = 0x8fff, + + WMI_SET_CHANNEL_EVENTID, + WMI_ASSOC_REQ_EVENTID, + + /* generic ACS event */ + WMI_ACS_EVENTID, + WMI_REPORT_WMM_PARAMS_EVENTID +} WMI_EVENT_ID; + + +typedef enum { + WMI_11A_CAPABILITY = 1, + WMI_11G_CAPABILITY = 2, + WMI_11AG_CAPABILITY = 3, + WMI_11NA_CAPABILITY = 4, + WMI_11NG_CAPABILITY = 5, + WMI_11NAG_CAPABILITY = 6, + // END CAPABILITY + WMI_11N_CAPABILITY_OFFSET = (WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY), +} WMI_PHY_CAPABILITY; + +typedef PREPACK struct { + u8 macaddr[ATH_MAC_LEN]; + u8 phyCapability; /* WMI_PHY_CAPABILITY */ +} POSTPACK WMI_READY_EVENT_1; + +typedef PREPACK struct { + u32 sw_version; + u32 abi_version; + u8 macaddr[ATH_MAC_LEN]; + u8 phyCapability; /* WMI_PHY_CAPABILITY */ +} POSTPACK WMI_READY_EVENT_2; + +#if defined(ATH_TARGET) +#ifdef AR6002_REV2 +#define WMI_READY_EVENT WMI_READY_EVENT_1 /* AR6002_REV2 target code */ +#else +#define WMI_READY_EVENT WMI_READY_EVENT_2 /* AR6001, AR6002_REV4, AR6002_REV5 */ +#endif +#else +#define WMI_READY_EVENT WMI_READY_EVENT_2 /* host code */ +#endif + + +/* + * Connect Event + */ +typedef PREPACK struct { + u16 channel; + u8 bssid[ATH_MAC_LEN]; + u16 listenInterval; + u16 beaconInterval; + u32 networkType; + u8 beaconIeLen; + u8 assocReqLen; + u8 assocRespLen; + u8 assocInfo[1]; +} POSTPACK WMI_CONNECT_EVENT; + +/* + * Disconnect Event + */ +typedef enum { + NO_NETWORK_AVAIL = 0x01, + LOST_LINK = 0x02, /* bmiss */ + DISCONNECT_CMD = 0x03, + BSS_DISCONNECTED = 0x04, + AUTH_FAILED = 0x05, + ASSOC_FAILED = 0x06, + NO_RESOURCES_AVAIL = 0x07, + CSERV_DISCONNECT = 0x08, + INVALID_PROFILE = 0x0a, + DOT11H_CHANNEL_SWITCH = 0x0b, + PROFILE_MISMATCH = 0x0c, + CONNECTION_EVICTED = 0x0d, + IBSS_MERGE = 0xe, +} WMI_DISCONNECT_REASON; + +typedef PREPACK struct { + u16 protocolReasonStatus; /* reason code, see 802.11 spec. */ + u8 bssid[ATH_MAC_LEN]; /* set if known */ + u8 disconnectReason ; /* see WMI_DISCONNECT_REASON */ + u8 assocRespLen; + u8 assocInfo[1]; +} POSTPACK WMI_DISCONNECT_EVENT; + +/* + * BSS Info Event. + * Mechanism used to inform host of the presence and characteristic of + * wireless networks present. Consists of bss info header followed by + * the beacon or probe-response frame body. The 802.11 header is not included. + */ +typedef enum { + BEACON_FTYPE = 0x1, + PROBERESP_FTYPE, + ACTION_MGMT_FTYPE, + PROBEREQ_FTYPE, +} WMI_BI_FTYPE; + +enum { + BSS_ELEMID_CHANSWITCH = 0x01, + BSS_ELEMID_ATHEROS = 0x02, +}; + +typedef PREPACK struct { + u16 channel; + u8 frameType; /* see WMI_BI_FTYPE */ + u8 snr; + s16 rssi; + u8 bssid[ATH_MAC_LEN]; + u32 ieMask; +} POSTPACK WMI_BSS_INFO_HDR; + +/* + * BSS INFO HDR version 2.0 + * With 6 bytes HTC header and 6 bytes of WMI header + * WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management + * header space. + * - Reduce the ieMask to 2 bytes as only two bit flags are used + * - Remove rssi and compute it on the host. rssi = snr - 95 + */ +typedef PREPACK struct { + u16 channel; + u8 frameType; /* see WMI_BI_FTYPE */ + u8 snr; + u8 bssid[ATH_MAC_LEN]; + u16 ieMask; +} POSTPACK WMI_BSS_INFO_HDR2; + +/* + * Command Error Event + */ +typedef enum { + INVALID_PARAM = 0x01, + ILLEGAL_STATE = 0x02, + INTERNAL_ERROR = 0x03, +} WMI_ERROR_CODE; + +typedef PREPACK struct { + u16 commandId; + u8 errorCode; +} POSTPACK WMI_CMD_ERROR_EVENT; + +/* + * New Regulatory Domain Event + */ +typedef PREPACK struct { + u32 regDomain; +} POSTPACK WMI_REG_DOMAIN_EVENT; + +typedef PREPACK struct { + u8 txQueueNumber; + u8 rxQueueNumber; + u8 trafficDirection; + u8 trafficClass; +} POSTPACK WMI_PSTREAM_TIMEOUT_EVENT; + +typedef PREPACK struct { + u8 reserve1; + u8 reserve2; + u8 reserve3; + u8 trafficClass; +} POSTPACK WMI_ACM_REJECT_EVENT; + +/* + * The WMI_NEIGHBOR_REPORT Event is generated by the target to inform + * the host of BSS's it has found that matches the current profile. + * It can be used by the host to cache PMKs and/to initiate pre-authentication + * if the BSS supports it. The first bssid is always the current associated + * BSS. + * The bssid and bssFlags information repeats according to the number + * or APs reported. + */ +typedef enum { + WMI_DEFAULT_BSS_FLAGS = 0x00, + WMI_PREAUTH_CAPABLE_BSS = 0x01, + WMI_PMKID_VALID_BSS = 0x02, +} WMI_BSS_FLAGS; + +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; + u8 bssFlags; /* see WMI_BSS_FLAGS */ +} POSTPACK WMI_NEIGHBOR_INFO; + +typedef PREPACK struct { + s8 numberOfAps; + WMI_NEIGHBOR_INFO neighbor[1]; +} POSTPACK WMI_NEIGHBOR_REPORT_EVENT; + +/* + * TKIP MIC Error Event + */ +typedef PREPACK struct { + u8 keyid; + u8 ismcast; +} POSTPACK WMI_TKIP_MICERR_EVENT; + +/* + * WMI_SCAN_COMPLETE_EVENTID - no parameters (old), staus parameter (new) + */ +typedef PREPACK struct { + s32 status; +} POSTPACK WMI_SCAN_COMPLETE_EVENT; + +#define MAX_OPT_DATA_LEN 1400 + +/* + * WMI_SET_ADHOC_BSSID_CMDID + */ +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; +} POSTPACK WMI_SET_ADHOC_BSSID_CMD; + +/* + * WMI_SET_OPT_MODE_CMDID + */ +typedef enum { + SPECIAL_OFF, + SPECIAL_ON, +} OPT_MODE_TYPE; + +typedef PREPACK struct { + u8 optMode; +} POSTPACK WMI_SET_OPT_MODE_CMD; + +/* + * WMI_TX_OPT_FRAME_CMDID + */ +typedef enum { + OPT_PROBE_REQ = 0x01, + OPT_PROBE_RESP = 0x02, + OPT_CPPP_START = 0x03, + OPT_CPPP_STOP = 0x04, +} WMI_OPT_FTYPE; + +typedef PREPACK struct { + u16 optIEDataLen; + u8 frmType; + u8 dstAddr[ATH_MAC_LEN]; + u8 bssid[ATH_MAC_LEN]; + u8 reserved; /* For alignment */ + u8 optIEData[1]; +} POSTPACK WMI_OPT_TX_FRAME_CMD; + +/* + * Special frame receive Event. + * Mechanism used to inform host of the receiption of the special frames. + * Consists of special frame info header followed by special frame body. + * The 802.11 header is not included. + */ +typedef PREPACK struct { + u16 channel; + u8 frameType; /* see WMI_OPT_FTYPE */ + s8 snr; + u8 srcAddr[ATH_MAC_LEN]; + u8 bssid[ATH_MAC_LEN]; +} POSTPACK WMI_OPT_RX_INFO_HDR; + +/* + * Reporting statistics. + */ +typedef PREPACK struct { + u32 tx_packets; + u32 tx_bytes; + u32 tx_unicast_pkts; + u32 tx_unicast_bytes; + u32 tx_multicast_pkts; + u32 tx_multicast_bytes; + u32 tx_broadcast_pkts; + u32 tx_broadcast_bytes; + u32 tx_rts_success_cnt; + u32 tx_packet_per_ac[4]; + u32 tx_errors_per_ac[4]; + + u32 tx_errors; + u32 tx_failed_cnt; + u32 tx_retry_cnt; + u32 tx_mult_retry_cnt; + u32 tx_rts_fail_cnt; + s32 tx_unicast_rate; +}POSTPACK tx_stats_t; + +typedef PREPACK struct { + u32 rx_packets; + u32 rx_bytes; + u32 rx_unicast_pkts; + u32 rx_unicast_bytes; + u32 rx_multicast_pkts; + u32 rx_multicast_bytes; + u32 rx_broadcast_pkts; + u32 rx_broadcast_bytes; + u32 rx_fragment_pkt; + + u32 rx_errors; + u32 rx_crcerr; + u32 rx_key_cache_miss; + u32 rx_decrypt_err; + u32 rx_duplicate_frames; + s32 rx_unicast_rate; +}POSTPACK rx_stats_t; + +typedef PREPACK struct { + u32 tkip_local_mic_failure; + u32 tkip_counter_measures_invoked; + u32 tkip_replays; + u32 tkip_format_errors; + u32 ccmp_format_errors; + u32 ccmp_replays; +}POSTPACK tkip_ccmp_stats_t; + +typedef PREPACK struct { + u32 power_save_failure_cnt; + u16 stop_tx_failure_cnt; + u16 atim_tx_failure_cnt; + u16 atim_rx_failure_cnt; + u16 bcn_rx_failure_cnt; +}POSTPACK pm_stats_t; + +typedef PREPACK struct { + u32 cs_bmiss_cnt; + u32 cs_lowRssi_cnt; + u16 cs_connect_cnt; + u16 cs_disconnect_cnt; + s16 cs_aveBeacon_rssi; + u16 cs_roam_count; + s16 cs_rssi; + u8 cs_snr; + u8 cs_aveBeacon_snr; + u8 cs_lastRoam_msec; +} POSTPACK cserv_stats_t; + +typedef PREPACK struct { + tx_stats_t tx_stats; + rx_stats_t rx_stats; + tkip_ccmp_stats_t tkipCcmpStats; +}POSTPACK wlan_net_stats_t; + +typedef PREPACK struct { + u32 arp_received; + u32 arp_matched; + u32 arp_replied; +} POSTPACK arp_stats_t; + +typedef PREPACK struct { + u32 wow_num_pkts_dropped; + u16 wow_num_events_discarded; + u8 wow_num_host_pkt_wakeups; + u8 wow_num_host_event_wakeups; +} POSTPACK wlan_wow_stats_t; + +typedef PREPACK struct { + u32 lqVal; + s32 noise_floor_calibation; + pm_stats_t pmStats; + wlan_net_stats_t txrxStats; + wlan_wow_stats_t wowStats; + arp_stats_t arpStats; + cserv_stats_t cservStats; +} POSTPACK WMI_TARGET_STATS; + +/* + * WMI_RSSI_THRESHOLD_EVENTID. + * Indicate the RSSI events to host. Events are indicated when we breach a + * thresold value. + */ +typedef enum{ + WMI_RSSI_THRESHOLD1_ABOVE = 0, + WMI_RSSI_THRESHOLD2_ABOVE, + WMI_RSSI_THRESHOLD3_ABOVE, + WMI_RSSI_THRESHOLD4_ABOVE, + WMI_RSSI_THRESHOLD5_ABOVE, + WMI_RSSI_THRESHOLD6_ABOVE, + WMI_RSSI_THRESHOLD1_BELOW, + WMI_RSSI_THRESHOLD2_BELOW, + WMI_RSSI_THRESHOLD3_BELOW, + WMI_RSSI_THRESHOLD4_BELOW, + WMI_RSSI_THRESHOLD5_BELOW, + WMI_RSSI_THRESHOLD6_BELOW +}WMI_RSSI_THRESHOLD_VAL; + +typedef PREPACK struct { + s16 rssi; + u8 range; +}POSTPACK WMI_RSSI_THRESHOLD_EVENT; + +/* + * WMI_ERROR_REPORT_EVENTID + */ +typedef enum{ + WMI_TARGET_PM_ERR_FAIL = 0x00000001, + WMI_TARGET_KEY_NOT_FOUND = 0x00000002, + WMI_TARGET_DECRYPTION_ERR = 0x00000004, + WMI_TARGET_BMISS = 0x00000008, + WMI_PSDISABLE_NODE_JOIN = 0x00000010, + WMI_TARGET_COM_ERR = 0x00000020, + WMI_TARGET_FATAL_ERR = 0x00000040 +} WMI_TARGET_ERROR_VAL; + +typedef PREPACK struct { + u32 errorVal; +}POSTPACK WMI_TARGET_ERROR_REPORT_EVENT; + +typedef PREPACK struct { + u8 retrys; +}POSTPACK WMI_TX_RETRY_ERR_EVENT; + +typedef enum{ + WMI_SNR_THRESHOLD1_ABOVE = 1, + WMI_SNR_THRESHOLD1_BELOW, + WMI_SNR_THRESHOLD2_ABOVE, + WMI_SNR_THRESHOLD2_BELOW, + WMI_SNR_THRESHOLD3_ABOVE, + WMI_SNR_THRESHOLD3_BELOW, + WMI_SNR_THRESHOLD4_ABOVE, + WMI_SNR_THRESHOLD4_BELOW +} WMI_SNR_THRESHOLD_VAL; + +typedef PREPACK struct { + u8 range; /* WMI_SNR_THRESHOLD_VAL */ + u8 snr; +}POSTPACK WMI_SNR_THRESHOLD_EVENT; + +typedef enum{ + WMI_LQ_THRESHOLD1_ABOVE = 1, + WMI_LQ_THRESHOLD1_BELOW, + WMI_LQ_THRESHOLD2_ABOVE, + WMI_LQ_THRESHOLD2_BELOW, + WMI_LQ_THRESHOLD3_ABOVE, + WMI_LQ_THRESHOLD3_BELOW, + WMI_LQ_THRESHOLD4_ABOVE, + WMI_LQ_THRESHOLD4_BELOW +} WMI_LQ_THRESHOLD_VAL; + +typedef PREPACK struct { + s32 lq; + u8 range; /* WMI_LQ_THRESHOLD_VAL */ +}POSTPACK WMI_LQ_THRESHOLD_EVENT; +/* + * WMI_REPORT_ROAM_TBL_EVENTID + */ +#define MAX_ROAM_TBL_CAND 5 + +typedef PREPACK struct { + s32 roam_util; + u8 bssid[ATH_MAC_LEN]; + s8 rssi; + s8 rssidt; + s8 last_rssi; + s8 util; + s8 bias; + u8 reserved; /* For alignment */ +} POSTPACK WMI_BSS_ROAM_INFO; + + +typedef PREPACK struct { + u16 roamMode; + u16 numEntries; + WMI_BSS_ROAM_INFO bssRoamInfo[1]; +} POSTPACK WMI_TARGET_ROAM_TBL; + +/* + * WMI_HCI_EVENT_EVENTID + */ +typedef PREPACK struct { + u16 evt_buf_sz; /* HCI event buffer size */ + u8 buf[1]; /* HCI event */ +} POSTPACK WMI_HCI_EVENT; + +/* + * WMI_CAC_EVENTID + */ +typedef enum { + CAC_INDICATION_ADMISSION = 0x00, + CAC_INDICATION_ADMISSION_RESP = 0x01, + CAC_INDICATION_DELETE = 0x02, + CAC_INDICATION_NO_RESP = 0x03, +}CAC_INDICATION; + +#define WMM_TSPEC_IE_LEN 63 + +typedef PREPACK struct { + u8 ac; + u8 cac_indication; + u8 statusCode; + u8 tspecSuggestion[WMM_TSPEC_IE_LEN]; +}POSTPACK WMI_CAC_EVENT; + +/* + * WMI_APLIST_EVENTID + */ + +typedef enum { + APLIST_VER1 = 1, +} APLIST_VER; + +typedef PREPACK struct { + u8 bssid[ATH_MAC_LEN]; + u16 channel; +} POSTPACK WMI_AP_INFO_V1; + +typedef PREPACK union { + WMI_AP_INFO_V1 apInfoV1; +} POSTPACK WMI_AP_INFO; + +typedef PREPACK struct { + u8 apListVer; + u8 numAP; + WMI_AP_INFO apList[1]; +} POSTPACK WMI_APLIST_EVENT; + +/* + * developer commands + */ + +/* + * WMI_SET_BITRATE_CMDID + * + * Get bit rate cmd uses same definition as set bit rate cmd + */ +typedef enum { + RATE_AUTO = -1, + RATE_1Mb = 0, + RATE_2Mb = 1, + RATE_5_5Mb = 2, + RATE_11Mb = 3, + RATE_6Mb = 4, + RATE_9Mb = 5, + RATE_12Mb = 6, + RATE_18Mb = 7, + RATE_24Mb = 8, + RATE_36Mb = 9, + RATE_48Mb = 10, + RATE_54Mb = 11, + RATE_MCS_0_20 = 12, + RATE_MCS_1_20 = 13, + RATE_MCS_2_20 = 14, + RATE_MCS_3_20 = 15, + RATE_MCS_4_20 = 16, + RATE_MCS_5_20 = 17, + RATE_MCS_6_20 = 18, + RATE_MCS_7_20 = 19, + RATE_MCS_0_40 = 20, + RATE_MCS_1_40 = 21, + RATE_MCS_2_40 = 22, + RATE_MCS_3_40 = 23, + RATE_MCS_4_40 = 24, + RATE_MCS_5_40 = 25, + RATE_MCS_6_40 = 26, + RATE_MCS_7_40 = 27, +} WMI_BIT_RATE; + +typedef PREPACK struct { + s8 rateIndex; /* see WMI_BIT_RATE */ + s8 mgmtRateIndex; + s8 ctlRateIndex; +} POSTPACK WMI_BIT_RATE_CMD; + + +typedef PREPACK struct { + s8 rateIndex; /* see WMI_BIT_RATE */ +} POSTPACK WMI_BIT_RATE_REPLY; + + +/* + * WMI_SET_FIXRATES_CMDID + * + * Get fix rates cmd uses same definition as set fix rates cmd + */ +#define FIX_RATE_1Mb ((u32)0x1) +#define FIX_RATE_2Mb ((u32)0x2) +#define FIX_RATE_5_5Mb ((u32)0x4) +#define FIX_RATE_11Mb ((u32)0x8) +#define FIX_RATE_6Mb ((u32)0x10) +#define FIX_RATE_9Mb ((u32)0x20) +#define FIX_RATE_12Mb ((u32)0x40) +#define FIX_RATE_18Mb ((u32)0x80) +#define FIX_RATE_24Mb ((u32)0x100) +#define FIX_RATE_36Mb ((u32)0x200) +#define FIX_RATE_48Mb ((u32)0x400) +#define FIX_RATE_54Mb ((u32)0x800) +#define FIX_RATE_MCS_0_20 ((u32)0x1000) +#define FIX_RATE_MCS_1_20 ((u32)0x2000) +#define FIX_RATE_MCS_2_20 ((u32)0x4000) +#define FIX_RATE_MCS_3_20 ((u32)0x8000) +#define FIX_RATE_MCS_4_20 ((u32)0x10000) +#define FIX_RATE_MCS_5_20 ((u32)0x20000) +#define FIX_RATE_MCS_6_20 ((u32)0x40000) +#define FIX_RATE_MCS_7_20 ((u32)0x80000) +#define FIX_RATE_MCS_0_40 ((u32)0x100000) +#define FIX_RATE_MCS_1_40 ((u32)0x200000) +#define FIX_RATE_MCS_2_40 ((u32)0x400000) +#define FIX_RATE_MCS_3_40 ((u32)0x800000) +#define FIX_RATE_MCS_4_40 ((u32)0x1000000) +#define FIX_RATE_MCS_5_40 ((u32)0x2000000) +#define FIX_RATE_MCS_6_40 ((u32)0x4000000) +#define FIX_RATE_MCS_7_40 ((u32)0x8000000) + +typedef PREPACK struct { + u32 fixRateMask; /* see WMI_BIT_RATE */ +} POSTPACK WMI_FIX_RATES_CMD, WMI_FIX_RATES_REPLY; + +typedef PREPACK struct { + u8 bEnableMask; + u8 frameType; /*type and subtype*/ + u32 frameRateMask; /* see WMI_BIT_RATE */ +} POSTPACK WMI_FRAME_RATES_CMD, WMI_FRAME_RATES_REPLY; + +/* + * WMI_SET_RECONNECT_AUTH_MODE_CMDID + * + * Set authentication mode + */ +typedef enum { + RECONN_DO_AUTH = 0x00, + RECONN_NOT_AUTH = 0x01 +} WMI_AUTH_MODE; + +typedef PREPACK struct { + u8 mode; +} POSTPACK WMI_SET_AUTH_MODE_CMD; + +/* + * WMI_SET_REASSOC_MODE_CMDID + * + * Set authentication mode + */ +typedef enum { + REASSOC_DO_DISASSOC = 0x00, + REASSOC_DONOT_DISASSOC = 0x01 +} WMI_REASSOC_MODE; + +typedef PREPACK struct { + u8 mode; +}POSTPACK WMI_SET_REASSOC_MODE_CMD; + +typedef enum { + ROAM_DATA_TIME = 1, /* Get The Roam Time Data */ +} ROAM_DATA_TYPE; + +typedef PREPACK struct { + u32 disassoc_time; + u32 no_txrx_time; + u32 assoc_time; + u32 allow_txrx_time; + u8 disassoc_bssid[ATH_MAC_LEN]; + s8 disassoc_bss_rssi; + u8 assoc_bssid[ATH_MAC_LEN]; + s8 assoc_bss_rssi; +} POSTPACK WMI_TARGET_ROAM_TIME; + +typedef PREPACK struct { + PREPACK union { + WMI_TARGET_ROAM_TIME roamTime; + } POSTPACK u; + u8 roamDataType ; +} POSTPACK WMI_TARGET_ROAM_DATA; + +typedef enum { + WMI_WMM_DISABLED = 0, + WMI_WMM_ENABLED +} WMI_WMM_STATUS; + +typedef PREPACK struct { + u8 status; +}POSTPACK WMI_SET_WMM_CMD; + +typedef PREPACK struct { + u8 status; +}POSTPACK WMI_SET_QOS_SUPP_CMD; + +typedef enum { + WMI_TXOP_DISABLED = 0, + WMI_TXOP_ENABLED +} WMI_TXOP_CFG; + +typedef PREPACK struct { + u8 txopEnable; +}POSTPACK WMI_SET_WMM_TXOP_CMD; + +typedef PREPACK struct { + u8 keepaliveInterval; +} POSTPACK WMI_SET_KEEPALIVE_CMD; + +typedef PREPACK struct { + u32 configured; + u8 keepaliveInterval; +} POSTPACK WMI_GET_KEEPALIVE_CMD; + +/* + * Add Application specified IE to a management frame + */ +#define WMI_MAX_IE_LEN 255 + +typedef PREPACK struct { + u8 mgmtFrmType; /* one of WMI_MGMT_FRAME_TYPE */ + u8 ieLen; /* Length of the IE that should be added to the MGMT frame */ + u8 ieInfo[1]; +} POSTPACK WMI_SET_APPIE_CMD; + +/* + * Notify the WSC registration status to the target + */ +#define WSC_REG_ACTIVE 1 +#define WSC_REG_INACTIVE 0 +/* Generic Hal Interface for setting hal paramters. */ +/* Add new Set HAL Param cmdIds here for newer params */ +typedef enum { + WHAL_SETCABTO_CMDID = 1, +}WHAL_CMDID; + +typedef PREPACK struct { + u8 cabTimeOut; +} POSTPACK WHAL_SETCABTO_PARAM; + +typedef PREPACK struct { + u8 whalCmdId; + u8 data[1]; +} POSTPACK WHAL_PARAMCMD; + + +#define WOW_MAX_FILTER_LISTS 1 /*4*/ +#define WOW_MAX_FILTERS_PER_LIST 4 +#define WOW_PATTERN_SIZE 64 +#define WOW_MASK_SIZE 64 + +#define MAC_MAX_FILTERS_PER_LIST 4 + +typedef PREPACK struct { + u8 wow_valid_filter; + u8 wow_filter_id; + u8 wow_filter_size; + u8 wow_filter_offset; + u8 wow_filter_mask[WOW_MASK_SIZE]; + u8 wow_filter_pattern[WOW_PATTERN_SIZE]; +} POSTPACK WOW_FILTER; + + +typedef PREPACK struct { + u8 wow_valid_list; + u8 wow_list_id; + u8 wow_num_filters; + u8 wow_total_list_size; + WOW_FILTER list[WOW_MAX_FILTERS_PER_LIST]; +} POSTPACK WOW_FILTER_LIST; + +typedef PREPACK struct { + u8 valid_filter; + u8 mac_addr[ATH_MAC_LEN]; +} POSTPACK MAC_FILTER; + + +typedef PREPACK struct { + u8 total_list_size; + u8 enable; + MAC_FILTER list[MAC_MAX_FILTERS_PER_LIST]; +} POSTPACK MAC_FILTER_LIST; + +#define MAX_IP_ADDRS 2 +typedef PREPACK struct { + u32 ips[MAX_IP_ADDRS]; /* IP in Network Byte Order */ +} POSTPACK WMI_SET_IP_CMD; + +typedef PREPACK struct { + u32 awake; + u32 asleep; +} POSTPACK WMI_SET_HOST_SLEEP_MODE_CMD; + +typedef enum { + WOW_FILTER_SSID = 0x1 +} WMI_WOW_FILTER; + +typedef PREPACK struct { + u32 enable_wow; + WMI_WOW_FILTER filter; + u16 hostReqDelay; +} POSTPACK WMI_SET_WOW_MODE_CMD; + +typedef PREPACK struct { + u8 filter_list_id; +} POSTPACK WMI_GET_WOW_LIST_CMD; + +/* + * WMI_GET_WOW_LIST_CMD reply + */ +typedef PREPACK struct { + u8 num_filters; /* number of patterns in reply */ + u8 this_filter_num; /* this is filter # x of total num_filters */ + u8 wow_mode; + u8 host_mode; + WOW_FILTER wow_filters[1]; +} POSTPACK WMI_GET_WOW_LIST_REPLY; + +typedef PREPACK struct { + u8 filter_list_id; + u8 filter_size; + u8 filter_offset; + u8 filter[1]; +} POSTPACK WMI_ADD_WOW_PATTERN_CMD; + +typedef PREPACK struct { + u16 filter_list_id; + u16 filter_id; +} POSTPACK WMI_DEL_WOW_PATTERN_CMD; + +typedef PREPACK struct { + u8 macaddr[ATH_MAC_LEN]; +} POSTPACK WMI_SET_MAC_ADDRESS_CMD; + +/* + * WMI_SET_AKMP_PARAMS_CMD + */ + +#define WMI_AKMP_MULTI_PMKID_EN 0x000001 + +typedef PREPACK struct { + u32 akmpInfo; +} POSTPACK WMI_SET_AKMP_PARAMS_CMD; + +typedef PREPACK struct { + u8 pmkid[WMI_PMKID_LEN]; +} POSTPACK WMI_PMKID; + +/* + * WMI_SET_PMKID_LIST_CMD + */ +#define WMI_MAX_PMKID_CACHE 8 + +typedef PREPACK struct { + u32 numPMKID; + WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE]; +} POSTPACK WMI_SET_PMKID_LIST_CMD; + +/* + * WMI_GET_PMKID_LIST_CMD Reply + * Following the Number of PMKIDs is the list of PMKIDs + */ +typedef PREPACK struct { + u32 numPMKID; + u8 bssidList[ATH_MAC_LEN][1]; + WMI_PMKID pmkidList[1]; +} POSTPACK WMI_PMKID_LIST_REPLY; + +typedef PREPACK struct { + u16 oldChannel; + u32 newChannel; +} POSTPACK WMI_CHANNEL_CHANGE_EVENT; + +typedef PREPACK struct { + u32 version; +} POSTPACK WMI_WLAN_VERSION_EVENT; + + +/* WMI_ADDBA_REQ_EVENTID */ +typedef PREPACK struct { + u8 tid; + u8 win_sz; + u16 st_seq_no; + u8 status; /* f/w response for ADDBA Req; OK(0) or failure(!=0) */ +} POSTPACK WMI_ADDBA_REQ_EVENT; + +/* WMI_ADDBA_RESP_EVENTID */ +typedef PREPACK struct { + u8 tid; + u8 status; /* OK(0), failure (!=0) */ + u16 amsdu_sz; /* Three values: Not supported(0), 3839, 8k */ +} POSTPACK WMI_ADDBA_RESP_EVENT; + +/* WMI_DELBA_EVENTID + * f/w received a DELBA for peer and processed it. + * Host is notified of this + */ +typedef PREPACK struct { + u8 tid; + u8 is_peer_initiator; + u16 reason_code; +} POSTPACK WMI_DELBA_EVENT; + + +#ifdef WAPI_ENABLE +#define WAPI_REKEY_UCAST 1 +#define WAPI_REKEY_MCAST 2 +typedef PREPACK struct { + u8 type; + u8 macAddr[ATH_MAC_LEN]; +} POSTPACK WMI_WAPIREKEY_EVENT; +#endif + + +/* WMI_ALLOW_AGGR_CMDID + * Configures tid's to allow ADDBA negotiations + * on each tid, in each direction + */ +typedef PREPACK struct { + u16 tx_allow_aggr; /* 16-bit mask to allow uplink ADDBA negotiation - bit position indicates tid*/ + u16 rx_allow_aggr; /* 16-bit mask to allow donwlink ADDBA negotiation - bit position indicates tid*/ +} POSTPACK WMI_ALLOW_AGGR_CMD; + +/* WMI_ADDBA_REQ_CMDID + * f/w starts performing ADDBA negotiations with peer + * on the given tid + */ +typedef PREPACK struct { + u8 tid; +} POSTPACK WMI_ADDBA_REQ_CMD; + +/* WMI_DELBA_REQ_CMDID + * f/w would teardown BA with peer. + * is_send_initiator indicates if it's or tx or rx side + */ +typedef PREPACK struct { + u8 tid; + u8 is_sender_initiator; + +} POSTPACK WMI_DELBA_REQ_CMD; + +#define PEER_NODE_JOIN_EVENT 0x00 +#define PEER_NODE_LEAVE_EVENT 0x01 +#define PEER_FIRST_NODE_JOIN_EVENT 0x10 +#define PEER_LAST_NODE_LEAVE_EVENT 0x11 +typedef PREPACK struct { + u8 eventCode; + u8 peerMacAddr[ATH_MAC_LEN]; +} POSTPACK WMI_PEER_NODE_EVENT; + +#define IEEE80211_FRAME_TYPE_MGT 0x00 +#define IEEE80211_FRAME_TYPE_CTL 0x04 + +/* + * Transmit complete event data structure(s) + */ + + +typedef PREPACK struct { +#define TX_COMPLETE_STATUS_SUCCESS 0 +#define TX_COMPLETE_STATUS_RETRIES 1 +#define TX_COMPLETE_STATUS_NOLINK 2 +#define TX_COMPLETE_STATUS_TIMEOUT 3 +#define TX_COMPLETE_STATUS_OTHER 4 + + u8 status; /* one of TX_COMPLETE_STATUS_... */ + u8 pktID; /* packet ID to identify parent packet */ + u8 rateIdx; /* rate index on successful transmission */ + u8 ackFailures; /* number of ACK failures in tx attempt */ +#if 0 /* optional params currently omitted. */ + u32 queueDelay; // usec delay measured Tx Start time - host delivery time + u32 mediaDelay; // usec delay measured ACK rx time - host delivery time +#endif +} POSTPACK TX_COMPLETE_MSG_V1; /* version 1 of tx complete msg */ + +typedef PREPACK struct { + u8 numMessages; /* number of tx comp msgs following this struct */ + u8 msgLen; /* length in bytes for each individual msg following this struct */ + u8 msgType; /* version of tx complete msg data following this struct */ + u8 reserved; /* individual messages follow this header */ +} POSTPACK WMI_TX_COMPLETE_EVENT; + +#define WMI_TXCOMPLETE_VERSION_1 (0x01) + + +/* + * ------- AP Mode definitions -------------- + */ + +/* + * !!! Warning !!! + * -Changing the following values needs compilation of both driver and firmware + */ +#ifdef AR6002_REV2 +#define AP_MAX_NUM_STA 4 +#else +#define AP_MAX_NUM_STA 8 +#endif +#define AP_ACL_SIZE 10 +#define IEEE80211_MAX_IE 256 +#define MCAST_AID 0xFF /* Spl. AID used to set DTIM flag in the beacons */ +#define DEF_AP_COUNTRY_CODE "US " +#define DEF_AP_WMODE_G WMI_11G_MODE +#define DEF_AP_WMODE_AG WMI_11AG_MODE +#define DEF_AP_DTIM 5 +#define DEF_BEACON_INTERVAL 100 + +/* AP mode disconnect reasons */ +#define AP_DISCONNECT_STA_LEFT 101 +#define AP_DISCONNECT_FROM_HOST 102 +#define AP_DISCONNECT_COMM_TIMEOUT 103 + +/* + * Used with WMI_AP_HIDDEN_SSID_CMDID + */ +#define HIDDEN_SSID_FALSE 0 +#define HIDDEN_SSID_TRUE 1 +typedef PREPACK struct { + u8 hidden_ssid; +} POSTPACK WMI_AP_HIDDEN_SSID_CMD; + +/* + * Used with WMI_AP_ACL_POLICY_CMDID + */ +#define AP_ACL_DISABLE 0x00 +#define AP_ACL_ALLOW_MAC 0x01 +#define AP_ACL_DENY_MAC 0x02 +#define AP_ACL_RETAIN_LIST_MASK 0x80 +typedef PREPACK struct { + u8 policy; +} POSTPACK WMI_AP_ACL_POLICY_CMD; + +/* + * Used with WMI_AP_ACL_MAC_LIST_CMDID + */ +#define ADD_MAC_ADDR 1 +#define DEL_MAC_ADDR 2 +typedef PREPACK struct { + u8 action; + u8 index; + u8 mac[ATH_MAC_LEN]; + u8 wildcard; +} POSTPACK WMI_AP_ACL_MAC_CMD; + +typedef PREPACK struct { + u16 index; + u8 acl_mac[AP_ACL_SIZE][ATH_MAC_LEN]; + u8 wildcard[AP_ACL_SIZE]; + u8 policy; +} POSTPACK WMI_AP_ACL; + +/* + * Used with WMI_AP_SET_NUM_STA_CMDID + */ +typedef PREPACK struct { + u8 num_sta; +} POSTPACK WMI_AP_SET_NUM_STA_CMD; + +/* + * Used with WMI_AP_SET_MLME_CMDID + */ +typedef PREPACK struct { + u8 mac[ATH_MAC_LEN]; + u16 reason; /* 802.11 reason code */ + u8 cmd; /* operation to perform */ +#define WMI_AP_MLME_ASSOC 1 /* associate station */ +#define WMI_AP_DISASSOC 2 /* disassociate station */ +#define WMI_AP_DEAUTH 3 /* deauthenticate station */ +#define WMI_AP_MLME_AUTHORIZE 4 /* authorize station */ +#define WMI_AP_MLME_UNAUTHORIZE 5 /* unauthorize station */ +} POSTPACK WMI_AP_SET_MLME_CMD; + +typedef PREPACK struct { + u32 period; +} POSTPACK WMI_AP_CONN_INACT_CMD; + +typedef PREPACK struct { + u32 period_min; + u32 dwell_ms; +} POSTPACK WMI_AP_PROT_SCAN_TIME_CMD; + +typedef PREPACK struct { + u32 flag; + u16 aid; +} POSTPACK WMI_AP_SET_PVB_CMD; + +#define WMI_DISABLE_REGULATORY_CODE "FF" + +typedef PREPACK struct { + u8 countryCode[3]; +} POSTPACK WMI_AP_SET_COUNTRY_CMD; + +typedef PREPACK struct { + u8 dtim; +} POSTPACK WMI_AP_SET_DTIM_CMD; + +typedef PREPACK struct { + u8 band; /* specifies which band to apply these values */ + u8 enable; /* allows 11n to be disabled on a per band basis */ + u8 chan_width_40M_supported; + u8 short_GI_20MHz; + u8 short_GI_40MHz; + u8 intolerance_40MHz; + u8 max_ampdu_len_exp; +} POSTPACK WMI_SET_HT_CAP_CMD; + +typedef PREPACK struct { + u8 sta_chan_width; +} POSTPACK WMI_SET_HT_OP_CMD; + +typedef PREPACK struct { + u32 rateMasks[8]; +} POSTPACK WMI_SET_TX_SELECT_RATES_CMD; + +typedef PREPACK struct { + u32 sgiMask; + u8 sgiPERThreshold; +} POSTPACK WMI_SET_TX_SGI_PARAM_CMD; + +#define DEFAULT_SGI_MASK 0x08080000 +#define DEFAULT_SGI_PER 10 + +typedef PREPACK struct { + u32 rateField; /* 1 bit per rate corresponding to index */ + u8 id; + u8 shortTrys; + u8 longTrys; + u8 reserved; /* padding */ +} POSTPACK WMI_SET_RATE_POLICY_CMD; + +typedef PREPACK struct { + u8 metaVersion; /* version of meta data for rx packets <0 = default> (0-7 = valid) */ + u8 dot11Hdr; /* 1 == leave .11 header intact , 0 == replace .11 header with .3 */ + u8 defragOnHost; /* 1 == defragmentation is performed by host, 0 == performed by target */ + u8 reserved[1]; /* alignment */ +} POSTPACK WMI_RX_FRAME_FORMAT_CMD; + + +typedef PREPACK struct { + u8 enable; /* 1 == device operates in thin mode , 0 == normal mode */ + u8 reserved[3]; +} POSTPACK WMI_SET_THIN_MODE_CMD; + +/* AP mode events */ +/* WMI_PS_POLL_EVENT */ +typedef PREPACK struct { + u16 aid; +} POSTPACK WMI_PSPOLL_EVENT; + +typedef PREPACK struct { + u32 tx_bytes; + u32 tx_pkts; + u32 tx_error; + u32 tx_discard; + u32 rx_bytes; + u32 rx_pkts; + u32 rx_error; + u32 rx_discard; + u32 aid; +} POSTPACK WMI_PER_STA_STAT; + +#define AP_GET_STATS 0 +#define AP_CLEAR_STATS 1 + +typedef PREPACK struct { + u32 action; + WMI_PER_STA_STAT sta[AP_MAX_NUM_STA+1]; +} POSTPACK WMI_AP_MODE_STAT; +#define WMI_AP_MODE_STAT_SIZE(numSta) (sizeof(u32) + ((numSta + 1) * sizeof(WMI_PER_STA_STAT))) + +#define AP_11BG_RATESET1 1 +#define AP_11BG_RATESET2 2 +#define DEF_AP_11BG_RATESET AP_11BG_RATESET1 +typedef PREPACK struct { + u8 rateset; +} POSTPACK WMI_AP_SET_11BG_RATESET_CMD; +/* + * End of AP mode definitions + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _WMI_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common/wmix.h b/trunk/drivers/staging/ath6kl/include/common/wmix.h new file mode 100644 index 000000000000..9435eab1b7f5 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common/wmix.h @@ -0,0 +1,271 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +/* + * This file contains extensions of the WMI protocol specified in the + * Wireless Module Interface (WMI). It includes definitions of all + * extended commands and events. Extensions include useful commands + * that are not directly related to wireless activities. They may + * be hardware-specific, and they might not be supported on all + * implementations. + * + * Extended WMIX commands are encapsulated in a WMI message with + * cmd=WMI_EXTENSION_CMD. + */ + +#ifndef _WMIX_H_ +#define _WMIX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "dbglog.h" + +/* + * Extended WMI commands are those that are needed during wireless + * operation, but which are not really wireless commands. This allows, + * for instance, platform-specific commands. Extended WMI commands are + * embedded in a WMI command message with WMI_COMMAND_ID=WMI_EXTENSION_CMDID. + * Extended WMI events are similarly embedded in a WMI event message with + * WMI_EVENT_ID=WMI_EXTENSION_EVENTID. + */ +typedef PREPACK struct { + u32 commandId; +} POSTPACK WMIX_CMD_HDR; + +typedef enum { + WMIX_DSETOPEN_REPLY_CMDID = 0x2001, + WMIX_DSETDATA_REPLY_CMDID, + WMIX_GPIO_OUTPUT_SET_CMDID, + WMIX_GPIO_INPUT_GET_CMDID, + WMIX_GPIO_REGISTER_SET_CMDID, + WMIX_GPIO_REGISTER_GET_CMDID, + WMIX_GPIO_INTR_ACK_CMDID, + WMIX_HB_CHALLENGE_RESP_CMDID, + WMIX_DBGLOG_CFG_MODULE_CMDID, + WMIX_PROF_CFG_CMDID, /* 0x200a */ + WMIX_PROF_ADDR_SET_CMDID, + WMIX_PROF_START_CMDID, + WMIX_PROF_STOP_CMDID, + WMIX_PROF_COUNT_GET_CMDID, +} WMIX_COMMAND_ID; + +typedef enum { + WMIX_DSETOPENREQ_EVENTID = 0x3001, + WMIX_DSETCLOSE_EVENTID, + WMIX_DSETDATAREQ_EVENTID, + WMIX_GPIO_INTR_EVENTID, + WMIX_GPIO_DATA_EVENTID, + WMIX_GPIO_ACK_EVENTID, + WMIX_HB_CHALLENGE_RESP_EVENTID, + WMIX_DBGLOG_EVENTID, + WMIX_PROF_COUNT_EVENTID, +} WMIX_EVENT_ID; + +/* + * =============DataSet support================= + */ + +/* + * WMIX_DSETOPENREQ_EVENTID + * DataSet Open Request Event + */ +typedef PREPACK struct { + u32 dset_id; + u32 targ_dset_handle; /* echo'ed, not used by Host, */ + u32 targ_reply_fn; /* echo'ed, not used by Host, */ + u32 targ_reply_arg; /* echo'ed, not used by Host, */ +} POSTPACK WMIX_DSETOPENREQ_EVENT; + +/* + * WMIX_DSETCLOSE_EVENTID + * DataSet Close Event + */ +typedef PREPACK struct { + u32 access_cookie; +} POSTPACK WMIX_DSETCLOSE_EVENT; + +/* + * WMIX_DSETDATAREQ_EVENTID + * DataSet Data Request Event + */ +typedef PREPACK struct { + u32 access_cookie; + u32 offset; + u32 length; + u32 targ_buf; /* echo'ed, not used by Host, */ + u32 targ_reply_fn; /* echo'ed, not used by Host, */ + u32 targ_reply_arg; /* echo'ed, not used by Host, */ +} POSTPACK WMIX_DSETDATAREQ_EVENT; + +typedef PREPACK struct { + u32 status; + u32 targ_dset_handle; + u32 targ_reply_fn; + u32 targ_reply_arg; + u32 access_cookie; + u32 size; + u32 version; +} POSTPACK WMIX_DSETOPEN_REPLY_CMD; + +typedef PREPACK struct { + u32 status; + u32 targ_buf; + u32 targ_reply_fn; + u32 targ_reply_arg; + u32 length; + u8 buf[1]; +} POSTPACK WMIX_DSETDATA_REPLY_CMD; + + +/* + * =============GPIO support================= + * All masks are 18-bit masks with bit N operating on GPIO pin N. + */ + + +/* + * Set GPIO pin output state. + * In order for output to be driven, a pin must be enabled for output. + * This can be done during initialization through the GPIO Configuration + * DataSet, or during operation with the enable_mask. + * + * If a request is made to simultaneously set/clear or set/disable or + * clear/disable or disable/enable, results are undefined. + */ +typedef PREPACK struct { + u32 set_mask; /* pins to set */ + u32 clear_mask; /* pins to clear */ + u32 enable_mask; /* pins to enable for output */ + u32 disable_mask; /* pins to disable/tristate */ +} POSTPACK WMIX_GPIO_OUTPUT_SET_CMD; + +/* + * Set a GPIO register. For debug/exceptional cases. + * Values for gpioreg_id are GPIO_REGISTER_IDs, defined in a + * platform-dependent header. + */ +typedef PREPACK struct { + u32 gpioreg_id; /* GPIO register ID */ + u32 value; /* value to write */ +} POSTPACK WMIX_GPIO_REGISTER_SET_CMD; + +/* Get a GPIO register. For debug/exceptional cases. */ +typedef PREPACK struct { + u32 gpioreg_id; /* GPIO register to read */ +} POSTPACK WMIX_GPIO_REGISTER_GET_CMD; + +/* + * Host acknowledges and re-arms GPIO interrupts. A single + * message should be used to acknowledge all interrupts that + * were delivered in an earlier WMIX_GPIO_INTR_EVENT message. + */ +typedef PREPACK struct { + u32 ack_mask; /* interrupts to acknowledge */ +} POSTPACK WMIX_GPIO_INTR_ACK_CMD; + +/* + * Target informs Host of GPIO interrupts that have occurred since the + * last WMIX_GIPO_INTR_ACK_CMD was received. Additional information -- + * the current GPIO input values is provided -- in order to support + * use of a GPIO interrupt as a Data Valid signal for other GPIO pins. + */ +typedef PREPACK struct { + u32 intr_mask; /* pending GPIO interrupts */ + u32 input_values; /* recent GPIO input values */ +} POSTPACK WMIX_GPIO_INTR_EVENT; + +/* + * Target responds to Host's earlier WMIX_GPIO_INPUT_GET_CMDID request + * using a GPIO_DATA_EVENT with + * value set to the mask of GPIO pin inputs and + * reg_id set to GPIO_ID_NONE + * + * + * Target responds to Hosts's earlier WMIX_GPIO_REGISTER_GET_CMDID request + * using a GPIO_DATA_EVENT with + * value set to the value of the requested register and + * reg_id identifying the register (reflects the original request) + * NB: reg_id supports the future possibility of unsolicited + * WMIX_GPIO_DATA_EVENTs (for polling GPIO input), and it may + * simplify Host GPIO support. + */ +typedef PREPACK struct { + u32 value; + u32 reg_id; +} POSTPACK WMIX_GPIO_DATA_EVENT; + +/* + * =============Error Detection support================= + */ + +/* + * WMIX_HB_CHALLENGE_RESP_CMDID + * Heartbeat Challenge Response command + */ +typedef PREPACK struct { + u32 cookie; + u32 source; +} POSTPACK WMIX_HB_CHALLENGE_RESP_CMD; + +/* + * WMIX_HB_CHALLENGE_RESP_EVENTID + * Heartbeat Challenge Response Event + */ +#define WMIX_HB_CHALLENGE_RESP_EVENT WMIX_HB_CHALLENGE_RESP_CMD + +typedef PREPACK struct { + struct dbglog_config_s config; +} POSTPACK WMIX_DBGLOG_CFG_MODULE_CMD; + +/* + * =============Target Profiling support================= + */ + +typedef PREPACK struct { + u32 period; /* Time (in 30.5us ticks) between samples */ + u32 nbins; +} POSTPACK WMIX_PROF_CFG_CMD; + +typedef PREPACK struct { + u32 addr; +} POSTPACK WMIX_PROF_ADDR_SET_CMD; + +/* + * Target responds to Hosts's earlier WMIX_PROF_COUNT_GET_CMDID request + * using a WMIX_PROF_COUNT_EVENT with + * addr set to the next address + * count set to the corresponding count + */ +typedef PREPACK struct { + u32 addr; + u32 count; +} POSTPACK WMIX_PROF_COUNT_EVENT; + + +#ifdef __cplusplus +} +#endif + +#endif /* _WMIX_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/common_drv.h b/trunk/drivers/staging/ath6kl/include/common_drv.h new file mode 100644 index 000000000000..34db29958bcb --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/common_drv.h @@ -0,0 +1,104 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef COMMON_DRV_H_ +#define COMMON_DRV_H_ + +#include "hif.h" +#include "htc_packet.h" +#include "htc_api.h" + +/* structure that is the state information for the default credit distribution callback + * drivers should instantiate (zero-init as well) this structure in their driver instance + * and pass it as a context to the HTC credit distribution functions */ +struct common_credit_state_info { + int TotalAvailableCredits; /* total credits in the system at startup */ + int CurrentFreeCredits; /* credits available in the pool that have not been + given out to endpoints */ + struct htc_endpoint_credit_dist *pLowestPriEpDist; /* pointer to the lowest priority endpoint dist struct */ +}; + +struct hci_transport_callbacks { + s32 (*setupTransport)(void *ar); + void (*cleanupTransport)(void *ar); +}; + +struct hci_transport_misc_handles { + void *netDevice; + void *hifDevice; + void *htcHandle; +}; + +/* HTC TX packet tagging definitions */ +#define AR6K_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED +#define AR6K_DATA_PKT_TAG (AR6K_CONTROL_PKT_TAG + 1) + +#define AR6002_VERSION_REV1 0x20000086 +#define AR6002_VERSION_REV2 0x20000188 +#define AR6003_VERSION_REV1 0x300002ba +#define AR6003_VERSION_REV2 0x30000384 + +#define AR6002_CUST_DATA_SIZE 112 +#define AR6003_CUST_DATA_SIZE 16 + +#ifdef __cplusplus +extern "C" { +#endif + +/* OS-independent APIs */ +int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo); + +int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +int ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address, u8 *data, u32 length); + +int ar6000_reset_device(struct hif_device *hifDevice, u32 TargetType, bool waitForCompletion, bool coldReset); + +void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType); + +int ar6000_set_htc_params(struct hif_device *hifDevice, + u32 TargetType, + u32 MboxIsrYieldValue, + u8 HtcControlBuffers); + +int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice, + u32 TargetType, + u32 Flags); + +void ar6000_copy_cust_data_from_target(struct hif_device *hifDevice, u32 TargetType); + +u8 *ar6000_get_cust_data_buffer(u32 TargetType); + +int ar6000_setBTState(void *context, u8 *pInBuf, u32 InBufSize); + +int ar6000_setDevicePowerState(void *context, u8 *pInBuf, u32 InBufSize); + +int ar6000_setWowMode(void *context, u8 *pInBuf, u32 InBufSize); + +int ar6000_setHostMode(void *context, u8 *pInBuf, u32 InBufSize); + +#ifdef __cplusplus +} +#endif + +#endif /*COMMON_DRV_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/dbglog_api.h b/trunk/drivers/staging/ath6kl/include/dbglog_api.h new file mode 100644 index 000000000000..a53aed316e3b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/dbglog_api.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains host side debug primitives. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _DBGLOG_API_H_ +#define _DBGLOG_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "dbglog.h" + +#define DBGLOG_HOST_LOG_BUFFER_SIZE DBGLOG_LOG_BUFFER_SIZE + +#define DBGLOG_GET_DBGID(arg) \ + ((arg & DBGLOG_DBGID_MASK) >> DBGLOG_DBGID_OFFSET) + +#define DBGLOG_GET_MODULEID(arg) \ + ((arg & DBGLOG_MODULEID_MASK) >> DBGLOG_MODULEID_OFFSET) + +#define DBGLOG_GET_NUMARGS(arg) \ + ((arg & DBGLOG_NUM_ARGS_MASK) >> DBGLOG_NUM_ARGS_OFFSET) + +#define DBGLOG_GET_TIMESTAMP(arg) \ + ((arg & DBGLOG_TIMESTAMP_MASK) >> DBGLOG_TIMESTAMP_OFFSET) + +#ifdef __cplusplus +} +#endif + +#endif /* _DBGLOG_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/dl_list.h b/trunk/drivers/staging/ath6kl/include/dl_list.h new file mode 100644 index 000000000000..13b1e6956c22 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/dl_list.h @@ -0,0 +1,153 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Double-link list definitions (adapted from Atheros SDIO stack) +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef __DL_LIST_H___ +#define __DL_LIST_H___ + +#include "a_osapi.h" + +#define A_CONTAINING_STRUCT(address, struct_type, field_name)\ + ((struct_type *)((unsigned long)(address) - (unsigned long)(&((struct_type *)0)->field_name))) + +/* list functions */ +/* pointers for the list */ +struct dl_list { + struct dl_list *pPrev; + struct dl_list *pNext; +}; +/* + * DL_LIST_INIT , initialize doubly linked list +*/ +#define DL_LIST_INIT(pList)\ + {(pList)->pPrev = pList; (pList)->pNext = pList;} + +/* faster macro to init list and add a single item */ +#define DL_LIST_INIT_AND_ADD(pList,pItem) \ +{ (pList)->pPrev = (pItem); \ + (pList)->pNext = (pItem); \ + (pItem)->pNext = (pList); \ + (pItem)->pPrev = (pList); \ +} + +#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList))) +#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext +#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev +/* + * ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member + * NOT: do not use this function if the items in the list are deleted inside the + * iteration loop +*/ +#define ITERATE_OVER_LIST(pStart, pTemp) \ + for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext) + + +/* safe iterate macro that allows the item to be removed from the list + * the iteration continues to the next item in the list + */ +#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \ +{ \ + struct dl_list * pTemp; \ + pTemp = (pStart)->pNext; \ + while (pTemp != (pStart)) { \ + (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset); \ + pTemp = pTemp->pNext; \ + +#define ITERATE_END }} + +/* + * DL_ListInsertTail - insert pAdd to the end of the list +*/ +static INLINE struct dl_list *DL_ListInsertTail(struct dl_list *pList, struct dl_list *pAdd) { + /* insert at tail */ + pAdd->pPrev = pList->pPrev; + pAdd->pNext = pList; + pList->pPrev->pNext = pAdd; + pList->pPrev = pAdd; + return pAdd; +} + +/* + * DL_ListInsertHead - insert pAdd into the head of the list +*/ +static INLINE struct dl_list * DL_ListInsertHead(struct dl_list * pList, struct dl_list * pAdd) { + /* insert at head */ + pAdd->pPrev = pList; + pAdd->pNext = pList->pNext; + pList->pNext->pPrev = pAdd; + pList->pNext = pAdd; + return pAdd; +} + +#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem)) +/* + * DL_ListRemove - remove pDel from list +*/ +static INLINE struct dl_list * DL_ListRemove(struct dl_list * pDel) { + pDel->pNext->pPrev = pDel->pPrev; + pDel->pPrev->pNext = pDel->pNext; + /* point back to itself just to be safe, incase remove is called again */ + pDel->pNext = pDel; + pDel->pPrev = pDel; + return pDel; +} + +/* + * DL_ListRemoveItemFromHead - get a list item from the head +*/ +static INLINE struct dl_list * DL_ListRemoveItemFromHead(struct dl_list * pList) { + struct dl_list * pItem = NULL; + if (pList->pNext != pList) { + pItem = pList->pNext; + /* remove the first item from head */ + DL_ListRemove(pItem); + } + return pItem; +} + +static INLINE struct dl_list * DL_ListRemoveItemFromTail(struct dl_list * pList) { + struct dl_list * pItem = NULL; + if (pList->pPrev != pList) { + pItem = pList->pPrev; + /* remove the item from tail */ + DL_ListRemove(pItem); + } + return pItem; +} + +/* transfer src list items to the tail of the destination list */ +static INLINE void DL_ListTransferItemsToTail(struct dl_list * pDest, struct dl_list * pSrc) { + /* only concatenate if src is not empty */ + if (!DL_LIST_IS_EMPTY(pSrc)) { + /* cut out circular list in src and re-attach to end of dest */ + pSrc->pPrev->pNext = pDest; + pSrc->pNext->pPrev = pDest->pPrev; + pDest->pPrev->pNext = pSrc->pNext; + pDest->pPrev = pSrc->pPrev; + /* terminate src list, it is now empty */ + pSrc->pPrev = pSrc; + pSrc->pNext = pSrc; + } +} + +#endif /* __DL_LIST_H___ */ diff --git a/trunk/drivers/staging/ath6kl/include/dset_api.h b/trunk/drivers/staging/ath6kl/include/dset_api.h new file mode 100644 index 000000000000..fe901ba40ec6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/dset_api.h @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Host-side DataSet API. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _DSET_API_H_ +#define _DSET_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Host-side DataSet support is optional, and is not + * currently required for correct operation. To disable + * Host-side DataSet support, set this to 0. + */ +#ifndef CONFIG_HOST_DSET_SUPPORT +#define CONFIG_HOST_DSET_SUPPORT 1 +#endif + +/* Called to send a DataSet Open Reply back to the Target. */ +int wmi_dset_open_reply(struct wmi_t *wmip, + u32 status, + u32 access_cookie, + u32 size, + u32 version, + u32 targ_handle, + u32 targ_reply_fn, + u32 targ_reply_arg); + +/* Called to send a DataSet Data Reply back to the Target. */ +int wmi_dset_data_reply(struct wmi_t *wmip, + u32 status, + u8 *host_buf, + u32 length, + u32 targ_buf, + u32 targ_reply_fn, + u32 targ_reply_arg); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* _DSET_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/hci_transport_api.h b/trunk/drivers/staging/ath6kl/include/hci_transport_api.h new file mode 100644 index 000000000000..5e903fad23fc --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/hci_transport_api.h @@ -0,0 +1,259 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HCI_TRANSPORT_API_H_ +#define _HCI_TRANSPORT_API_H_ + + /* Bluetooth HCI packets are stored in HTC packet containers */ +#include "htc_packet.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef void *HCI_TRANSPORT_HANDLE; + +typedef HTC_ENDPOINT_ID HCI_TRANSPORT_PACKET_TYPE; + + /* we map each HCI packet class to a static Endpoint ID */ +#define HCI_COMMAND_TYPE ENDPOINT_1 +#define HCI_EVENT_TYPE ENDPOINT_2 +#define HCI_ACL_TYPE ENDPOINT_3 +#define HCI_PACKET_INVALID ENDPOINT_MAX + +#define HCI_GET_PACKET_TYPE(pP) (pP)->Endpoint +#define HCI_SET_PACKET_TYPE(pP,s) (pP)->Endpoint = (s) + +/* callback when an HCI packet was completely sent */ +typedef void (*HCI_TRANSPORT_SEND_PKT_COMPLETE)(void *, struct htc_packet *); +/* callback when an HCI packet is received */ +typedef void (*HCI_TRANSPORT_RECV_PKT)(void *, struct htc_packet *); +/* Optional receive buffer re-fill callback, + * On some OSes (like Linux) packets are allocated from a global pool and indicated up + * to the network stack. The driver never gets the packets back from the OS. For these OSes + * a refill callback can be used to allocate and re-queue buffers into HTC. + * A refill callback is used for the reception of ACL and EVENT packets. The caller must + * set the watermark trigger point to cause a refill. + */ +typedef void (*HCI_TRANSPORT_RECV_REFILL)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable); +/* Optional receive packet refill + * On some systems packet buffers are an extremely limited resource. Rather than + * queue largest-possible-sized buffers to the HCI bridge, some systems would rather + * allocate a specific size as the packet is received. The trade off is + * slightly more processing (callback invoked for each RX packet) + * for the benefit of committing fewer buffer resources into the bridge. + * + * The callback is provided the length of the pending packet to fetch. This includes the + * full transport header, HCI header, plus the length of payload. The callback can return a pointer to + * the allocated HTC packet for immediate use. + * + * NOTE*** This callback is mutually exclusive with the the refill callback above. + * + * */ +typedef struct htc_packet *(*HCI_TRANSPORT_RECV_ALLOC)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int Length); + +typedef enum _HCI_SEND_FULL_ACTION { + HCI_SEND_FULL_KEEP = 0, /* packet that overflowed should be kept in the queue */ + HCI_SEND_FULL_DROP = 1, /* packet that overflowed should be dropped */ +} HCI_SEND_FULL_ACTION; + +/* callback when an HCI send queue exceeds the caller's MaxSendQueueDepth threshold, + * the callback must return the send full action to take (either DROP or KEEP) */ +typedef HCI_SEND_FULL_ACTION (*HCI_TRANSPORT_SEND_FULL)(void *, struct htc_packet *); + +struct hci_transport_properties { + int HeadRoom; /* number of bytes in front of HCI packet for header space */ + int TailRoom; /* number of bytes at the end of the HCI packet for tail space */ + int IOBlockPad; /* I/O block padding required (always a power of 2) */ +}; + +struct hci_transport_config_info { + int ACLRecvBufferWaterMark; /* low watermark to trigger recv refill */ + int EventRecvBufferWaterMark; /* low watermark to trigger recv refill */ + int MaxSendQueueDepth; /* max number of packets in the single send queue */ + void *pContext; /* context for all callbacks */ + void (*TransportFailure)(void *pContext, int Status); /* transport failure callback */ + int (*TransportReady)(HCI_TRANSPORT_HANDLE, struct hci_transport_properties *,void *pContext); /* transport is ready */ + void (*TransportRemoved)(void *pContext); /* transport was removed */ + /* packet processing callbacks */ + HCI_TRANSPORT_SEND_PKT_COMPLETE pHCISendComplete; + HCI_TRANSPORT_RECV_PKT pHCIPktRecv; + HCI_TRANSPORT_RECV_REFILL pHCIPktRecvRefill; + HCI_TRANSPORT_RECV_ALLOC pHCIPktRecvAlloc; + HCI_TRANSPORT_SEND_FULL pHCISendFull; +}; + +/* ------ Function Prototypes ------ */ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Attach to the HCI transport module + @function name: HCI_TransportAttach + @input: HTCHandle - HTC handle (see HTC apis) + pInfo - initialization information + @output: + @return: HCI_TRANSPORT_HANDLE on success, NULL on failure + @notes: The HTC module provides HCI transport services. + @example: + @see also: HCI_TransportDetach ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Detach from the HCI transport module + @function name: HCI_TransportDetach + @input: HciTrans - HCI transport handle + pInfo - initialization information + @output: + @return: + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add receive packets to the HCI transport + @function name: HCI_TransportAddReceivePkts + @input: HciTrans - HCI transport handle + pQueue - a queue holding one or more packets + @output: + @return: 0 on success + @notes: user must supply HTC packets for capturing incomming HCI packets. The caller + must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL() + macro. Each packet in the queue must be of the same type and length + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Send an HCI packet packet + @function name: HCI_TransportSendPkt + @input: HciTrans - HCI transport handle + pPacket - packet to send + Synchronous - send the packet synchronously (blocking) + @output: + @return: 0 + @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() and + HCI_SET_PACKET_TYPE() macros to prepare the packet. + If Synchronous is set to false the call is fully asynchronous. On error or completion, + the registered send complete callback will be called. + If Synchronous is set to true, the call will block until the packet is sent, if the + interface cannot send the packet within a 2 second timeout, the function will return + the failure code : A_EBUSY. + + Synchronous Mode should only be used at start-up to initialize the HCI device using + custom HCI commands. It should NOT be mixed with Asynchronous operations. Mixed synchronous + and asynchronous operation behavior is undefined. + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous); + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Stop HCI transport + @function name: HCI_TransportStop + @input: HciTrans - hci transport handle + @output: + @return: + @notes: HCI transport communication will be halted. All receive and pending TX packets will + be flushed. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Start the HCI transport + @function name: HCI_TransportStart + @input: HciTrans - hci transport handle + @output: + @return: 0 on success + @notes: HCI transport communication will begin, the caller can expect the arrival + of HCI recv packets as soon as this call returns. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Enable or Disable Asynchronous Recv + @function name: HCI_TransportEnableDisableAsyncRecv + @input: HciTrans - hci transport handle + Enable - enable or disable asynchronous recv + @output: + @return: 0 on success + @notes: This API must be called when HCI recv is handled synchronously + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Receive an event packet from the HCI transport synchronously using polling + @function name: HCI_TransportRecvHCIEventSync + @input: HciTrans - hci transport handle + pPacket - HTC packet to hold the recv data + MaxPollMS - maximum polling duration in Milliseconds; + @output: + @return: 0 on success + @notes: This API should be used only during HCI device initialization, the caller must call + HCI_TransportEnableDisableAsyncRecv with Enable=false prior to using this API. + This API will only capture HCI Event packets. + @example: + @see also: HCI_TransportEnableDisableAsyncRecv ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans, + struct htc_packet *pPacket, + int MaxPollMS); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Set the desired baud rate for the underlying transport layer + @function name: HCI_TransportSetBaudRate + @input: HciTrans - hci transport handle + Baud - baud rate in bps + @output: + @return: 0 on success + @notes: This API should be used only after HCI device initialization + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Enable/Disable HCI Transport Power Management + @function name: HCI_TransportEnablePowerMgmt + @input: HciTrans - hci transport handle + Enable - 1 = Enable, 0 = Disable + @output: + @return: 0 on success + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); + +#ifdef __cplusplus +} +#endif + +#endif /* _HCI_TRANSPORT_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/hif.h b/trunk/drivers/staging/ath6kl/include/hif.h new file mode 100644 index 000000000000..24200e778c3b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/hif.h @@ -0,0 +1,456 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HIF specific declarations and prototypes +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HIF_H_ +#define _HIF_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include "dl_list.h" + + +typedef struct htc_callbacks HTC_CALLBACKS; +struct hif_device; + +/* + * direction - Direction of transfer (HIF_READ/HIF_WRITE). + */ +#define HIF_READ 0x00000001 +#define HIF_WRITE 0x00000002 +#define HIF_DIR_MASK (HIF_READ | HIF_WRITE) + +/* + * type - An interface may support different kind of read/write commands. + * For example: SDIO supports CMD52/CMD53s. In case of MSIO it + * translates to using different kinds of TPCs. The command type + * is thus divided into a basic and an extended command and can + * be specified using HIF_BASIC_IO/HIF_EXTENDED_IO. + */ +#define HIF_BASIC_IO 0x00000004 +#define HIF_EXTENDED_IO 0x00000008 +#define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO) + +/* + * emode - This indicates the whether the command is to be executed in a + * blocking or non-blocking fashion (HIF_SYNCHRONOUS/ + * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been + * implemented using the asynchronous mode allowing the the bus + * driver to indicate the completion of operation through the + * registered callback routine. The requirement primarily comes + * from the contexts these operations get called from (a driver's + * transmit context or the ISR context in case of receive). + * Support for both of these modes is essential. + */ +#define HIF_SYNCHRONOUS 0x00000010 +#define HIF_ASYNCHRONOUS 0x00000020 +#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS) + +/* + * dmode - An interface may support different kinds of commands based on + * the tradeoff between the amount of data it can carry and the + * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/ + * HIF_BLOCK_BASIS). In case of latter, the data is rounded off + * to the nearest block size by padding. The size of the block is + * configurable at compile time using the HIF_BLOCK_SIZE and is + * negotiated with the target during initialization after the + * AR6000 interrupts are enabled. + */ +#define HIF_BYTE_BASIS 0x00000040 +#define HIF_BLOCK_BASIS 0x00000080 +#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS) + +/* + * amode - This indicates if the address has to be incremented on AR6000 + * after every read/write operation (HIF?FIXED_ADDRESS/ + * HIF_INCREMENTAL_ADDRESS). + */ +#define HIF_FIXED_ADDRESS 0x00000100 +#define HIF_INCREMENTAL_ADDRESS 0x00000200 +#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS) + +#define HIF_WR_ASYNC_BYTE_FIX \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_WR_ASYNC_BYTE_INC \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_ASYNC_BLOCK_INC \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_SYNC_BYTE_FIX \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_WR_SYNC_BYTE_INC \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_SYNC_BLOCK_INC \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_WR_ASYNC_BLOCK_FIX \ + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) +#define HIF_WR_SYNC_BLOCK_FIX \ + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_SYNC_BYTE_INC \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_SYNC_BYTE_FIX \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_ASYNC_BYTE_FIX \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_ASYNC_BLOCK_FIX \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) +#define HIF_RD_ASYNC_BYTE_INC \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_ASYNC_BLOCK_INC \ + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_SYNC_BLOCK_INC \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) +#define HIF_RD_SYNC_BLOCK_FIX \ + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) + +typedef enum { + HIF_DEVICE_POWER_STATE = 0, + HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + HIF_DEVICE_GET_MBOX_ADDR, + HIF_DEVICE_GET_PENDING_EVENTS_FUNC, + HIF_DEVICE_GET_IRQ_PROC_MODE, + HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, + HIF_DEVICE_POWER_STATE_CHANGE, + HIF_DEVICE_GET_IRQ_YIELD_PARAMS, + HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT, + HIF_DEVICE_GET_OS_DEVICE, + HIF_DEVICE_DEBUG_BUS_STATE, +} HIF_DEVICE_CONFIG_OPCODE; + +/* + * HIF CONFIGURE definitions: + * + * HIF_DEVICE_GET_MBOX_BLOCK_SIZE + * input : none + * output : array of 4 u32s + * notes: block size is returned for each mailbox (4) + * + * HIF_DEVICE_GET_MBOX_ADDR + * input : none + * output : struct hif_device_mbox_info + * notes: + * + * HIF_DEVICE_GET_PENDING_EVENTS_FUNC + * input : none + * output: HIF_PENDING_EVENTS_FUNC function pointer + * notes: this is optional for the HIF layer, if the request is + * not handled then it indicates that the upper layer can use + * the standard device methods to get pending events (IRQs, mailbox messages etc..) + * otherwise it can call the function pointer to check pending events. + * + * HIF_DEVICE_GET_IRQ_PROC_MODE + * input : none + * output : HIF_DEVICE_IRQ_PROCESSING_MODE (interrupt processing mode) + * note: the hif layer interfaces with the underlying OS-specific bus driver. The HIF + * layer can report whether IRQ processing is requires synchronous behavior or + * can be processed using asynchronous bus requests (typically faster). + * + * HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC + * input : + * output : HIF_MASK_UNMASK_RECV_EVENT function pointer + * notes: this is optional for the HIF layer. The HIF layer may require a special mechanism + * to mask receive message events. The upper layer can call this pointer when it needs + * to mask/unmask receive events (in case it runs out of buffers). + * + * HIF_DEVICE_POWER_STATE_CHANGE + * + * input : HIF_DEVICE_POWER_CHANGE_TYPE + * output : none + * note: this is optional for the HIF layer. The HIF layer can handle power on/off state change + * requests in an interconnect specific way. This is highly OS and bus driver dependent. + * The caller must guarantee that no HIF read/write requests will be made after the device + * is powered down. + * + * HIF_DEVICE_GET_IRQ_YIELD_PARAMS + * + * input : none + * output : struct hif_device_irq_yield_params + * note: This query checks if the HIF layer wishes to impose a processing yield count for the DSR handler. + * The DSR callback handler will exit after a fixed number of RX packets or events are processed. + * This query is only made if the device reports an IRQ processing mode of HIF_DEVICE_IRQ_SYNC_ONLY. + * The HIF implementation can ignore this command if it does not desire the DSR callback to yield. + * The HIF layer can indicate the maximum number of IRQ processing units (RX packets) before the + * DSR handler callback must yield and return control back to the HIF layer. When a yield limit is + * used the DSR callback will not call HIFAckInterrupts() as it would normally do before returning. + * The HIF implementation that requires a yield count must call HIFAckInterrupt() when it is prepared + * to process interrupts again. + * + * HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT + * input : none + * output : struct hif_device_scatter_support_info + * note: This query checks if the HIF layer implements the SCATTER request interface. Scatter requests + * allows upper layers to submit mailbox I/O operations using a list of buffers. This is useful for + * multi-message transfers that can better utilize the bus interconnect. + * + * + * HIF_DEVICE_GET_OS_DEVICE + * intput : none + * output : struct hif_device_os_device_info; + * note: On some operating systems, the HIF layer has a parent device object for the bus. This object + * may be required to register certain types of logical devices. + * + * HIF_DEVICE_DEBUG_BUS_STATE + * input : none + * output : none + * note: This configure option triggers the HIF interface to dump as much bus interface state. This + * configuration request is optional (No-OP on some HIF implementations) + * + */ + +struct hif_mbox_properties { + u32 ExtendedAddress; /* extended address for larger writes */ + u32 ExtendedSize; +}; + +#define HIF_MBOX_FLAG_NO_BUNDLING (1 << 0) /* do not allow bundling over the mailbox */ + +typedef enum _MBOX_BUF_IF_TYPE { + MBOX_BUS_IF_SDIO = 0, + MBOX_BUS_IF_SPI = 1, +} MBOX_BUF_IF_TYPE; + +struct hif_device_mbox_info { + u32 MboxAddresses[4]; /* must be first element for legacy HIFs that return the address in + and ARRAY of 32-bit words */ + + /* the following describe extended mailbox properties */ + struct hif_mbox_properties MboxProp[4]; + /* if the HIF supports the GMbox extended address region it can report it + * here, some interfaces cannot support the GMBOX address range and not set this */ + u32 GMboxAddress; + u32 GMboxSize; + u32 Flags; /* flags to describe mbox behavior or usage */ + MBOX_BUF_IF_TYPE MboxBusIFType; /* mailbox bus interface type */ +}; + +typedef enum { + HIF_DEVICE_IRQ_SYNC_ONLY, /* for HIF implementations that require the DSR to process all + interrupts before returning */ + HIF_DEVICE_IRQ_ASYNC_SYNC, /* for HIF implementations that allow DSR to process interrupts + using ASYNC I/O (that is HIFAckInterrupt can be called at a + later time */ +} HIF_DEVICE_IRQ_PROCESSING_MODE; + +typedef enum { + HIF_DEVICE_POWER_UP, /* HIF layer should power up interface and/or module */ + HIF_DEVICE_POWER_DOWN, /* HIF layer should initiate bus-specific measures to minimize power */ + HIF_DEVICE_POWER_CUT /* HIF layer should initiate bus-specific AND/OR platform-specific measures + to completely power-off the module and associated hardware (i.e. cut power supplies) + */ +} HIF_DEVICE_POWER_CHANGE_TYPE; + +struct hif_device_irq_yield_params { + int RecvPacketYieldCount; /* max number of packets to force DSR to return */ +}; + + +struct hif_scatter_item { + u8 *pBuffer; /* CPU accessible address of buffer */ + int Length; /* length of transfer to/from this buffer */ + void *pCallerContexts[2]; /* space for caller to insert a context associated with this item */ +}; + +struct hif_scatter_req; +typedef void ( *HIF_SCATTER_COMP_CB)(struct hif_scatter_req *); + +typedef enum _HIF_SCATTER_METHOD { + HIF_SCATTER_NONE = 0, + HIF_SCATTER_DMA_REAL, /* Real SG support no restrictions */ + HIF_SCATTER_DMA_BOUNCE, /* Uses SG DMA but HIF layer uses an internal bounce buffer */ +} HIF_SCATTER_METHOD; + +struct hif_scatter_req { + struct dl_list ListLink; /* link management */ + u32 Address; /* address for the read/write operation */ + u32 Request; /* request flags */ + u32 TotalLength; /* total length of entire transfer */ + u32 CallerFlags; /* caller specific flags can be stored here */ + HIF_SCATTER_COMP_CB CompletionRoutine; /* completion routine set by caller */ + int CompletionStatus; /* status of completion */ + void *Context; /* caller context for this request */ + int ValidScatterEntries; /* number of valid entries set by caller */ + HIF_SCATTER_METHOD ScatterMethod; /* scatter method handled by HIF */ + void *HIFPrivate[4]; /* HIF private area */ + u8 *pScatterBounceBuffer; /* bounce buffer for upper layers to copy to/from */ + struct hif_scatter_item ScatterList[1]; /* start of scatter list */ +}; + +typedef struct hif_scatter_req * ( *HIF_ALLOCATE_SCATTER_REQUEST)(struct hif_device *device); +typedef void ( *HIF_FREE_SCATTER_REQUEST)(struct hif_device *device, struct hif_scatter_req *request); +typedef int ( *HIF_READWRITE_SCATTER)(struct hif_device *device, struct hif_scatter_req *request); + +struct hif_device_scatter_support_info { + /* information returned from HIF layer */ + HIF_ALLOCATE_SCATTER_REQUEST pAllocateReqFunc; + HIF_FREE_SCATTER_REQUEST pFreeReqFunc; + HIF_READWRITE_SCATTER pReadWriteScatterFunc; + int MaxScatterEntries; + int MaxTransferSizePerScatterReq; +}; + +struct hif_device_os_device_info { + void *pOSDevice; +}; + +#define HIF_MAX_DEVICES 1 + +struct htc_callbacks { + void *context; /* context to pass to the dsrhandler + note : rwCompletionHandler is provided the context passed to HIFReadWrite */ + int (* rwCompletionHandler)(void *rwContext, int status); + int (* dsrHandler)(void *context); +}; + +typedef struct osdrv_callbacks { + void *context; /* context to pass for all callbacks except deviceRemovedHandler + the deviceRemovedHandler is only called if the device is claimed */ + int (* deviceInsertedHandler)(void *context, void *hif_handle); + int (* deviceRemovedHandler)(void *claimedContext, void *hif_handle); + int (* deviceSuspendHandler)(void *context); + int (* deviceResumeHandler)(void *context); + int (* deviceWakeupHandler)(void *context); + int (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config); +} OSDRV_CALLBACKS; + +#define HIF_OTHER_EVENTS (1 << 0) /* other interrupts (non-Recv) are pending, host + needs to read the register table to figure out what */ +#define HIF_RECV_MSG_AVAIL (1 << 1) /* pending recv packet */ + +struct hif_pending_events_info { + u32 Events; + u32 LookAhead; + u32 AvailableRecvBytes; +#ifdef THREAD_X + u32 Polling; + u32 INT_CAUSE_REG; +#endif +}; + + /* function to get pending events , some HIF modules use special mechanisms + * to detect packet available and other interrupts */ +typedef int ( *HIF_PENDING_EVENTS_FUNC)(struct hif_device *device, + struct hif_pending_events_info *pEvents, + void *AsyncContext); + +#define HIF_MASK_RECV true +#define HIF_UNMASK_RECV false + /* function to mask recv events */ +typedef int ( *HIF_MASK_UNMASK_RECV_EVENT)(struct hif_device *device, + bool Mask, + void *AsyncContext); + + +/* + * This API is used to perform any global initialization of the HIF layer + * and to set OS driver callbacks (i.e. insertion/removal) to the HIF layer + * + */ +int HIFInit(OSDRV_CALLBACKS *callbacks); + +/* This API claims the HIF device and provides a context for handling removal. + * The device removal callback is only called when the OSDRV layer claims + * a device. The claimed context must be non-NULL */ +void HIFClaimDevice(struct hif_device *device, void *claimedContext); +/* release the claimed device */ +void HIFReleaseDevice(struct hif_device *device); + +/* This API allows the HTC layer to attach to the HIF device */ +int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks); +/* This API detaches the HTC layer from the HIF device */ +void HIFDetachHTC(struct hif_device *device); + +/* + * This API is used to provide the read/write interface over the specific bus + * interface. + * address - Starting address in the AR6000's address space. For mailbox + * writes, it refers to the start of the mbox boundary. It should + * be ensured that the last byte falls on the mailbox's EOM. For + * mailbox reads, it refers to the end of the mbox boundary. + * buffer - Pointer to the buffer containg the data to be transmitted or + * received. + * length - Amount of data to be transmitted or received. + * request - Characterizes the attributes of the command. + */ +int +HIFReadWrite(struct hif_device *device, + u32 address, + u8 *buffer, + u32 length, + u32 request, + void *context); + +/* + * This can be initiated from the unload driver context when the OSDRV layer has no more use for + * the device. + */ +void HIFShutDownDevice(struct hif_device *device); + +/* + * This should translate to an acknowledgment to the bus driver indicating that + * the previous interrupt request has been serviced and the all the relevant + * sources have been cleared. HTC is ready to process more interrupts. + * This should prevent the bus driver from raising an interrupt unless the + * previous one has been serviced and acknowledged using the previous API. + */ +void HIFAckInterrupt(struct hif_device *device); + +void HIFMaskInterrupt(struct hif_device *device); + +void HIFUnMaskInterrupt(struct hif_device *device); + +#ifdef THREAD_X +/* + * This set of functions are to be used by the bus driver to notify + * the HIF module about various events. + * These are not implemented if the bus driver provides an alternative + * way for this notification though callbacks for instance. + */ +int HIFInsertEventNotify(void); + +int HIFRemoveEventNotify(void); + +int HIFIRQEventNotify(void); + +int HIFRWCompleteEventNotify(void); +#endif + +int +HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode, + void *config, u32 configLen); + +/* + * This API wait for the remaining MBOX messages to be drained + * This should be moved to HTC AR6K layer + */ +int hifWaitForPendingRecv(struct hif_device *device); + +#ifdef __cplusplus +} +#endif + +#endif /* _HIF_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/host_version.h b/trunk/drivers/staging/ath6kl/include/host_version.h new file mode 100644 index 000000000000..74f1982c681b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/host_version.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains version information for the sample host driver for the +// AR6000 chip +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HOST_VERSION_H_ +#define _HOST_VERSION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * The version number is made up of major, minor, patch and build + * numbers. These are 16 bit numbers. The build and release script will + * set the build number using a Perforce counter. Here the build number is + * set to 9999 so that builds done without the build-release script are easily + * identifiable. + */ + +#define ATH_SW_VER_MAJOR __VER_MAJOR_ +#define ATH_SW_VER_MINOR __VER_MINOR_ +#define ATH_SW_VER_PATCH __VER_PATCH_ +#define ATH_SW_VER_BUILD __BUILD_NUMBER_ + +#ifdef __cplusplus +} +#endif + +#endif /* _HOST_VERSION_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/htc_api.h b/trunk/drivers/staging/ath6kl/include/htc_api.h new file mode 100644 index 000000000000..4fb767559f82 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/htc_api.h @@ -0,0 +1,575 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HTC_API_H_ +#define _HTC_API_H_ + +#include "htc_packet.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* TODO.. for BMI */ +#define ENDPOINT1 0 +// TODO -remove me, but we have to fix BMI first +#define HTC_MAILBOX_NUM_MAX 4 + +/* this is the amount of header room required by users of HTC */ +#define HTC_HEADER_LEN HTC_HDR_LENGTH + +typedef void *HTC_HANDLE; + +typedef u16 HTC_SERVICE_ID; + +struct htc_init_info { + void *pContext; /* context for target failure notification */ + void (*TargetFailure)(void *Instance, int Status); +}; + +/* per service connection send completion */ +typedef void (*HTC_EP_SEND_PKT_COMPLETE)(void *,struct htc_packet *); +/* per service connection callback when a plurality of packets have been sent + * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback) + * to hold a list of completed send packets. + * If the handler cannot fully traverse the packet queue before returning, it should + * transfer the items of the queue into the caller's private queue using: + * HTC_PACKET_ENQUEUE() */ +typedef void (*HTC_EP_SEND_PKT_COMP_MULTIPLE)(void *,struct htc_packet_queue *); +/* per service connection pkt received */ +typedef void (*HTC_EP_RECV_PKT)(void *,struct htc_packet *); +/* per service connection callback when a plurality of packets are received + * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback) + * to hold a list of recv packets. + * If the handler cannot fully traverse the packet queue before returning, it should + * transfer the items of the queue into the caller's private queue using: + * HTC_PACKET_ENQUEUE() */ +typedef void (*HTC_EP_RECV_PKT_MULTIPLE)(void *,struct htc_packet_queue *); + +/* Optional per service connection receive buffer re-fill callback, + * On some OSes (like Linux) packets are allocated from a global pool and indicated up + * to the network stack. The driver never gets the packets back from the OS. For these OSes + * a refill callback can be used to allocate and re-queue buffers into HTC. + * + * On other OSes, the network stack can call into the driver's OS-specifc "return_packet" handler and + * the driver can re-queue these buffers into HTC. In this regard a refill callback is + * unnecessary */ +typedef void (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint); + +/* Optional per service connection receive buffer allocation callback. + * On some systems packet buffers are an extremely limited resource. Rather than + * queue largest-possible-sized buffers to HTC, some systems would rather + * allocate a specific size as the packet is received. The trade off is + * slightly more processing (callback invoked for each RX packet) + * for the benefit of committing fewer buffer resources into HTC. + * + * The callback is provided the length of the pending packet to fetch. This includes the + * HTC header length plus the length of payload. The callback can return a pointer to + * the allocated HTC packet for immediate use. + * + * Alternatively a variant of this handler can be used to allocate large receive packets as needed. + * For example an application can use the refill mechanism for normal packets and the recv-alloc mechanism to + * handle the case where a large packet buffer is required. This can significantly reduce the + * amount of "committed" memory used to receive packets. + * + * */ +typedef struct htc_packet *(*HTC_EP_RECV_ALLOC)(void *, HTC_ENDPOINT_ID Endpoint, int Length); + +typedef enum _HTC_SEND_FULL_ACTION { + HTC_SEND_FULL_KEEP = 0, /* packet that overflowed should be kept in the queue */ + HTC_SEND_FULL_DROP = 1, /* packet that overflowed should be dropped */ +} HTC_SEND_FULL_ACTION; + +/* Optional per service connection callback when a send queue is full. This can occur if the + * host continues queueing up TX packets faster than credits can arrive + * To prevent the host (on some Oses like Linux) from continuously queueing packets + * and consuming resources, this callback is provided so that that the host + * can disable TX in the subsystem (i.e. network stack). + * This callback is invoked for each packet that "overflows" the HTC queue. The callback can + * determine whether the new packet that overflowed the queue can be kept (HTC_SEND_FULL_KEEP) or + * dropped (HTC_SEND_FULL_DROP). If a packet is dropped, the EpTxComplete handler will be called + * and the packet's status field will be set to A_NO_RESOURCE. + * Other OSes require a "per-packet" indication for each completed TX packet, this + * closed loop mechanism will prevent the network stack from overunning the NIC + * The packet to keep or drop is passed for inspection to the registered handler the handler + * must ONLY inspect the packet, it may not free or reclaim the packet. */ +typedef HTC_SEND_FULL_ACTION (*HTC_EP_SEND_QUEUE_FULL)(void *, struct htc_packet *pPacket); + +struct htc_ep_callbacks { + void *pContext; /* context for each callback */ + HTC_EP_SEND_PKT_COMPLETE EpTxComplete; /* tx completion callback for connected endpoint */ + HTC_EP_RECV_PKT EpRecv; /* receive callback for connected endpoint */ + HTC_EP_RECV_REFILL EpRecvRefill; /* OPTIONAL receive re-fill callback for connected endpoint */ + HTC_EP_SEND_QUEUE_FULL EpSendFull; /* OPTIONAL send full callback */ + HTC_EP_RECV_ALLOC EpRecvAlloc; /* OPTIONAL recv allocation callback */ + HTC_EP_RECV_ALLOC EpRecvAllocThresh; /* OPTIONAL recv allocation callback based on a threshold */ + HTC_EP_SEND_PKT_COMP_MULTIPLE EpTxCompleteMultiple; /* OPTIONAL completion handler for multiple complete + indications (EpTxComplete must be NULL) */ + HTC_EP_RECV_PKT_MULTIPLE EpRecvPktMultiple; /* OPTIONAL completion handler for multiple + recv packet indications (EpRecv must be NULL) */ + int RecvAllocThreshold; /* if EpRecvAllocThresh is non-NULL, HTC will compare the + threshold value to the current recv packet length and invoke + the EpRecvAllocThresh callback to acquire a packet buffer */ + int RecvRefillWaterMark; /* if a EpRecvRefill handler is provided, this value + can be used to set a trigger refill callback + when the recv queue drops below this value + if set to 0, the refill is only called when packets + are empty */ +}; + +/* service connection information */ +struct htc_service_connect_req { + HTC_SERVICE_ID ServiceID; /* service ID to connect to */ + u16 ConnectionFlags; /* connection flags, see htc protocol definition */ + u8 *pMetaData; /* ptr to optional service-specific meta-data */ + u8 MetaDataLength; /* optional meta data length */ + struct htc_ep_callbacks EpCallbacks; /* endpoint callbacks */ + int MaxSendQueueDepth; /* maximum depth of any send queue */ + u32 LocalConnectionFlags; /* HTC flags for the host-side (local) connection */ + unsigned int MaxSendMsgSize; /* override max message size in send direction */ +}; + +#define HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING (1 << 0) /* enable send bundle padding for this endpoint */ + +/* service connection response information */ +struct htc_service_connect_resp { + u8 *pMetaData; /* caller supplied buffer to optional meta-data */ + u8 BufferLength; /* length of caller supplied buffer */ + u8 ActualLength; /* actual length of meta data */ + HTC_ENDPOINT_ID Endpoint; /* endpoint to communicate over */ + unsigned int MaxMsgLength; /* max length of all messages over this endpoint */ + u8 ConnectRespCode; /* connect response code from target */ +}; + +/* endpoint distribution structure */ +struct htc_endpoint_credit_dist { + struct htc_endpoint_credit_dist *pNext; + struct htc_endpoint_credit_dist *pPrev; + HTC_SERVICE_ID ServiceID; /* Service ID (set by HTC) */ + HTC_ENDPOINT_ID Endpoint; /* endpoint for this distribution struct (set by HTC) */ + u32 DistFlags; /* distribution flags, distribution function can + set default activity using SET_EP_ACTIVE() macro */ + int TxCreditsNorm; /* credits for normal operation, anything above this + indicates the endpoint is over-subscribed, this field + is only relevant to the credit distribution function */ + int TxCreditsMin; /* floor for credit distribution, this field is + only relevant to the credit distribution function */ + int TxCreditsAssigned; /* number of credits assigned to this EP, this field + is only relevant to the credit dist function */ + int TxCredits; /* current credits available, this field is used by + HTC to determine whether a message can be sent or + must be queued */ + int TxCreditsToDist; /* pending credits to distribute on this endpoint, this + is set by HTC when credit reports arrive. + The credit distribution functions sets this to zero + when it distributes the credits */ + int TxCreditsSeek; /* this is the number of credits that the current pending TX + packet needs to transmit. This is set by HTC when + and endpoint needs credits in order to transmit */ + int TxCreditSize; /* size in bytes of each credit (set by HTC) */ + int TxCreditsPerMaxMsg; /* credits required for a maximum sized messages (set by HTC) */ + void *pHTCReserved; /* reserved for HTC use */ + int TxQueueDepth; /* current depth of TX queue , i.e. messages waiting for credits + This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE + or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint + that has non-zero credits to recover + */ +}; + +#define HTC_EP_ACTIVE ((u32) (1u << 31)) + +/* macro to check if an endpoint has gone active, useful for credit + * distributions */ +#define IS_EP_ACTIVE(epDist) ((epDist)->DistFlags & HTC_EP_ACTIVE) +#define SET_EP_ACTIVE(epDist) (epDist)->DistFlags |= HTC_EP_ACTIVE + + /* credit distibution code that is passed into the distrbution function, + * there are mandatory and optional codes that must be handled */ +typedef enum _HTC_CREDIT_DIST_REASON { + HTC_CREDIT_DIST_SEND_COMPLETE = 0, /* credits available as a result of completed + send operations (MANDATORY) resulting in credit reports */ + HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, /* a change in endpoint activity occurred (OPTIONAL) */ + HTC_CREDIT_DIST_SEEK_CREDITS, /* an endpoint needs to "seek" credits (OPTIONAL) */ + HTC_DUMP_CREDIT_STATE /* for debugging, dump any state information that is kept by + the distribution function */ +} HTC_CREDIT_DIST_REASON; + +typedef void (*HTC_CREDIT_DIST_CALLBACK)(void *Context, + struct htc_endpoint_credit_dist *pEPList, + HTC_CREDIT_DIST_REASON Reason); + +typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context, + struct htc_endpoint_credit_dist *pEPList, + int TotalCredits); + + /* endpoint statistics action */ +typedef enum _HTC_ENDPOINT_STAT_ACTION { + HTC_EP_STAT_SAMPLE = 0, /* only read statistics */ + HTC_EP_STAT_SAMPLE_AND_CLEAR = 1, /* sample and immediately clear statistics */ + HTC_EP_STAT_CLEAR /* clear only */ +} HTC_ENDPOINT_STAT_ACTION; + + /* endpoint statistics */ +struct htc_endpoint_stats { + u32 TxCreditLowIndications; /* number of times the host set the credit-low flag in a send message on + this endpoint */ + u32 TxIssued; /* running count of total TX packets issued */ + u32 TxPacketsBundled; /* running count of TX packets that were issued in bundles */ + u32 TxBundles; /* running count of TX bundles that were issued */ + u32 TxDropped; /* tx packets that were dropped */ + u32 TxCreditRpts; /* running count of total credit reports received for this endpoint */ + u32 TxCreditRptsFromRx; /* credit reports received from this endpoint's RX packets */ + u32 TxCreditRptsFromOther; /* credit reports received from RX packets of other endpoints */ + u32 TxCreditRptsFromEp0; /* credit reports received from endpoint 0 RX packets */ + u32 TxCreditsFromRx; /* count of credits received via Rx packets on this endpoint */ + u32 TxCreditsFromOther; /* count of credits received via another endpoint */ + u32 TxCreditsFromEp0; /* count of credits received via another endpoint */ + u32 TxCreditsConsummed; /* count of consummed credits */ + u32 TxCreditsReturned; /* count of credits returned */ + u32 RxReceived; /* count of RX packets received */ + u32 RxLookAheads; /* count of lookahead records + found in messages received on this endpoint */ + u32 RxPacketsBundled; /* count of recv packets received in a bundle */ + u32 RxBundleLookAheads; /* count of number of bundled lookaheads */ + u32 RxBundleIndFromHdr; /* count of the number of bundle indications from the HTC header */ + u32 RxAllocThreshHit; /* count of the number of times the recv allocation threshold was hit */ + u32 RxAllocThreshBytes; /* total number of bytes */ +}; + +/* ------ Function Prototypes ------ */ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Create an instance of HTC over the underlying HIF device + @function name: HTCCreate + @input: HifDevice - hif device handle, + pInfo - initialization information + @output: + @return: HTC_HANDLE on success, NULL on failure + @notes: + @example: + @see also: HTCDestroy ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +HTC_HANDLE HTCCreate(void *HifDevice, struct htc_init_info *pInfo); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get the underlying HIF device handle + @function name: HTCGetHifDevice + @input: HTCHandle - handle passed into the AddInstance callback + @output: + @return: opaque HIF device handle usable in HIF API calls. + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void *HTCGetHifDevice(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Set credit distribution parameters + @function name: HTCSetCreditDistribution + @input: HTCHandle - HTC handle + pCreditDistCont - caller supplied context to pass into distribution functions + CreditDistFunc - Distribution function callback + CreditDistInit - Credit Distribution initialization callback + ServicePriorityOrder - Array containing list of service IDs, lowest index is highest + priority + ListLength - number of elements in ServicePriorityOrder + @output: + @return: + @notes: The user can set a custom credit distribution function to handle special requirements + for each endpoint. A default credit distribution routine can be used by setting + CreditInitFunc to NULL. The default credit distribution is only provided for simple + "fair" credit distribution without regard to any prioritization. + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, + void *pCreditDistContext, + HTC_CREDIT_DIST_CALLBACK CreditDistFunc, + HTC_CREDIT_INIT_CALLBACK CreditInitFunc, + HTC_SERVICE_ID ServicePriorityOrder[], + int ListLength); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Wait for the target to indicate the HTC layer is ready + @function name: HTCWaitTarget + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This API blocks until the target responds with an HTC ready message. + The caller should not connect services until the target has indicated it is + ready. + @example: + @see also: HTCConnectService ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCWaitTarget(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Start target service communications + @function name: HTCStart + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This API indicates to the target that the service connection phase is complete + and the target can freely start all connected services. This API should only be + called AFTER all service connections have been made. TCStart will issue a + SETUP_COMPLETE message to the target to indicate that all service connections + have been made and the target can start communicating over the endpoints. + @example: + @see also: HTCConnectService ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCStart(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add receive packet to HTC + @function name: HTCAddReceivePkt + @input: HTCHandle - HTC handle + pPacket - HTC receive packet to add + @output: + @return: 0 on success + @notes: user must supply HTC packets for capturing incomming HTC frames. The caller + must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL() + macro. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Connect to an HTC service + @function name: HTCConnectService + @input: HTCHandle - HTC handle + pReq - connection details + @output: pResp - connection response + @return: + @notes: Service connections must be performed before HTCStart. User provides callback handlers + for various endpoint events. + @example: + @see also: HTCStart ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCConnectService(HTC_HANDLE HTCHandle, + struct htc_service_connect_req *pReq, + struct htc_service_connect_resp *pResp); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Send an HTC packet + @function name: HTCSendPkt + @input: HTCHandle - HTC handle + pPacket - packet to send + @output: + @return: 0 + @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro. + This interface is fully asynchronous. On error, HTC SendPkt will + call the registered Endpoint callback to cleanup the packet. + @example: + @see also: HTCFlushEndpoint ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Stop HTC service communications + @function name: HTCStop + @input: HTCHandle - HTC handle + @output: + @return: + @notes: HTC communications is halted. All receive and pending TX packets will + be flushed. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCStop(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Destroy HTC service + @function name: HTCDestroy + @input: HTCHandle + @output: + @return: + @notes: This cleans up all resources allocated by HTCCreate(). + @example: + @see also: HTCCreate ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCDestroy(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Flush pending TX packets + @function name: HTCFlushEndpoint + @input: HTCHandle - HTC handle + Endpoint - Endpoint to flush + Tag - flush tag + @output: + @return: + @notes: The Tag parameter is used to selectively flush packets with matching tags. + The value of 0 forces all packets to be flush regardless of tag. + @example: + @see also: HTCSendPkt ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Dump credit distribution state + @function name: HTCDumpCreditStates + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This dumps all credit distribution information to the debugger + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCDumpCreditStates(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Indicate a traffic activity change on an endpoint + @function name: HTCIndicateActivityChange + @input: HTCHandle - HTC handle + Endpoint - endpoint in which activity has changed + Active - true if active, false if it has become inactive + @output: + @return: + @notes: This triggers the registered credit distribution function to + re-adjust credits for active/inactive endpoints. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + bool Active); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get endpoint statistics + @function name: HTCGetEndpointStatistics + @input: HTCHandle - HTC handle + Endpoint - Endpoint identifier + Action - action to take with statistics + @output: + pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR) + + @return: true if statistics profiling is enabled, otherwise false. + + @notes: Statistics is a compile-time option and this function may return false + if HTC is not compiled with profiling. + + The caller can specify the statistic "action" to take when sampling + the statistics. This includes: + + HTC_EP_STAT_SAMPLE: The pStats structure is filled with the current values. + HTC_EP_STAT_SAMPLE_AND_CLEAR: The structure is filled and the current statistics + are cleared. + HTC_EP_STAT_CLEA : the statistics are cleared, the called can pass a NULL value for + pStats + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +bool HTCGetEndpointStatistics(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + HTC_ENDPOINT_STAT_ACTION Action, + struct htc_endpoint_stats *pStats); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Unblock HTC message reception + @function name: HTCUnblockRecv + @input: HTCHandle - HTC handle + @output: + @return: + @notes: + HTC will block the receiver if the EpRecvAlloc callback fails to provide a packet. + The caller can use this API to indicate to HTC when resources (buffers) are available + such that the receiver can be unblocked and HTC may re-attempt fetching the pending message. + + This API is not required if the user uses the EpRecvRefill callback or uses the HTCAddReceivePacket() + API to recycle or provide receive packets to HTC. + + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void HTCUnblockRecv(HTC_HANDLE HTCHandle); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: send a series of HTC packets + @function name: HTCSendPktsMultiple + @input: HTCHandle - HTC handle + pPktQueue - local queue holding packets to send + @output: + @return: 0 + @notes: Caller must initialize each packet using SET_HTC_PACKET_INFO_TX() macro. + The queue must only contain packets directed at the same endpoint. + Caller supplies a pointer to an struct htc_packet_queue structure holding the TX packets in FIFO order. + This API will remove the packets from the pkt queue and place them into the HTC Tx Queue + and bundle messages where possible. + The caller may allocate the pkt queue on the stack to hold the packets. + This interface is fully asynchronous. On error, HTCSendPkts will + call the registered Endpoint callback to cleanup the packet. + @example: + @see also: HTCFlushEndpoint ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add multiple receive packets to HTC + @function name: HTCAddReceivePktMultiple + @input: HTCHandle - HTC handle + pPktQueue - HTC receive packet queue holding packets to add + @output: + @return: 0 on success + @notes: user must supply HTC packets for capturing incomming HTC frames. The caller + must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL() + macro. The queue must only contain recv packets for the same endpoint. + Caller supplies a pointer to an struct htc_packet_queue structure holding the recv packet. + This API will remove the packets from the pkt queue and place them into internal + recv packet list. + The caller may allocate the pkt queue on the stack to hold the packets. + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Check if an endpoint is marked active + @function name: HTCIsEndpointActive + @input: HTCHandle - HTC handle + Endpoint - endpoint to check for active state + @output: + @return: returns true if Endpoint is Active + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +bool HTCIsEndpointActive(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint); + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get the number of recv buffers currently queued into an HTC endpoint + @function name: HTCGetNumRecvBuffers + @input: HTCHandle - HTC handle + Endpoint - endpoint to check + @output: + @return: returns number of buffers in queue + @notes: + @example: + @see also: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint); + +/* internally used functions for testing... */ +void HTCEnableRecv(HTC_HANDLE HTCHandle); +void HTCDisableRecv(HTC_HANDLE HTCHandle); +int HTCWaitForPendingRecv(HTC_HANDLE HTCHandle, + u32 TimeoutInMs, + bool *pbIsRecvPending); + +#ifdef __cplusplus +} +#endif + +#endif /* _HTC_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/htc_packet.h b/trunk/drivers/staging/ath6kl/include/htc_packet.h new file mode 100644 index 000000000000..ba65c34ebc9c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/htc_packet.h @@ -0,0 +1,227 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef HTC_PACKET_H_ +#define HTC_PACKET_H_ + + +#include "dl_list.h" + +/* ------ Endpoint IDS ------ */ +typedef enum +{ + ENDPOINT_UNUSED = -1, + ENDPOINT_0 = 0, + ENDPOINT_1 = 1, + ENDPOINT_2 = 2, + ENDPOINT_3, + ENDPOINT_4, + ENDPOINT_5, + ENDPOINT_6, + ENDPOINT_7, + ENDPOINT_8, + ENDPOINT_MAX, +} HTC_ENDPOINT_ID; + +struct htc_packet; + +typedef void (* HTC_PACKET_COMPLETION)(void *,struct htc_packet *); + +typedef u16 HTC_TX_TAG; + +struct htc_tx_packet_info { + HTC_TX_TAG Tag; /* tag used to selective flush packets */ + int CreditsUsed; /* number of credits used for this TX packet (HTC internal) */ + u8 SendFlags; /* send flags (HTC internal) */ + int SeqNo; /* internal seq no for debugging (HTC internal) */ +}; + +#define HTC_TX_PACKET_TAG_ALL 0 /* a tag of zero is reserved and used to flush ALL packets */ +#define HTC_TX_PACKET_TAG_INTERNAL 1 /* internal tags start here */ +#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */ + +struct htc_rx_packet_info { + u32 ExpectedHdr; /* HTC internal use */ + u32 HTCRxFlags; /* HTC internal use */ + u32 IndicationFlags; /* indication flags set on each RX packet indication */ +}; + +#define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0) /* more packets on this endpoint are being fetched */ + +/* wrapper around endpoint-specific packets */ +struct htc_packet { + struct dl_list ListLink; /* double link */ + void *pPktContext; /* caller's per packet specific context */ + + u8 *pBufferStart; /* the true buffer start , the caller can + store the real buffer start here. In + receive callbacks, the HTC layer sets pBuffer + to the start of the payload past the header. This + field allows the caller to reset pBuffer when it + recycles receive packets back to HTC */ + /* + * Pointer to the start of the buffer. In the transmit + * direction this points to the start of the payload. In the + * receive direction, however, the buffer when queued up + * points to the start of the HTC header but when returned + * to the caller points to the start of the payload + */ + u8 *pBuffer; /* payload start (RX/TX) */ + u32 BufferLength; /* length of buffer */ + u32 ActualLength; /* actual length of payload */ + HTC_ENDPOINT_ID Endpoint; /* endpoint that this packet was sent/recv'd from */ + int Status; /* completion status */ + union { + struct htc_tx_packet_info AsTx; /* Tx Packet specific info */ + struct htc_rx_packet_info AsRx; /* Rx Packet specific info */ + } PktInfo; + + /* the following fields are for internal HTC use */ + HTC_PACKET_COMPLETION Completion; /* completion */ + void *pContext; /* HTC private completion context */ +}; + + + +#define COMPLETE_HTC_PACKET(p,status) \ +{ \ + (p)->Status = (status); \ + (p)->Completion((p)->pContext,(p)); \ +} + +#define INIT_HTC_PACKET_INFO(p,b,len) \ +{ \ + (p)->pBufferStart = (b); \ + (p)->BufferLength = (len); \ +} + +/* macro to set an initial RX packet for refilling HTC */ +#define SET_HTC_PACKET_INFO_RX_REFILL(p,c,b,len,ep) \ +{ \ + (p)->pPktContext = (c); \ + (p)->pBuffer = (b); \ + (p)->pBufferStart = (b); \ + (p)->BufferLength = (len); \ + (p)->Endpoint = (ep); \ +} + +/* fast macro to recycle an RX packet that will be re-queued to HTC */ +#define HTC_PACKET_RESET_RX(p) \ + { (p)->pBuffer = (p)->pBufferStart; (p)->ActualLength = 0; } + +/* macro to set packet parameters for TX */ +#define SET_HTC_PACKET_INFO_TX(p,c,b,len,ep,tag) \ +{ \ + (p)->pPktContext = (c); \ + (p)->pBuffer = (b); \ + (p)->ActualLength = (len); \ + (p)->Endpoint = (ep); \ + (p)->PktInfo.AsTx.Tag = (tag); \ +} + +/* HTC Packet Queueing Macros */ +struct htc_packet_queue { + struct dl_list QueueHead; + int Depth; +}; + +/* initialize queue */ +#define INIT_HTC_PACKET_QUEUE(pQ) \ +{ \ + DL_LIST_INIT(&(pQ)->QueueHead); \ + (pQ)->Depth = 0; \ +} + +/* enqueue HTC packet to the tail of the queue */ +#define HTC_PACKET_ENQUEUE(pQ,p) \ +{ DL_ListInsertTail(&(pQ)->QueueHead,&(p)->ListLink); \ + (pQ)->Depth++; \ +} + +/* enqueue HTC packet to the tail of the queue */ +#define HTC_PACKET_ENQUEUE_TO_HEAD(pQ,p) \ +{ DL_ListInsertHead(&(pQ)->QueueHead,&(p)->ListLink); \ + (pQ)->Depth++; \ +} +/* test if a queue is empty */ +#define HTC_QUEUE_EMPTY(pQ) ((pQ)->Depth == 0) +/* get packet at head without removing it */ +static INLINE struct htc_packet *HTC_GET_PKT_AT_HEAD(struct htc_packet_queue *queue) { + if (queue->Depth == 0) { + return NULL; + } + return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(&queue->QueueHead)),struct htc_packet,ListLink); +} +/* remove a packet from a queue, where-ever it is in the queue */ +#define HTC_PACKET_REMOVE(pQ,p) \ +{ \ + DL_ListRemove(&(p)->ListLink); \ + (pQ)->Depth--; \ +} + +/* dequeue an HTC packet from the head of the queue */ +static INLINE struct htc_packet *HTC_PACKET_DEQUEUE(struct htc_packet_queue *queue) { + struct dl_list *pItem = DL_ListRemoveItemFromHead(&queue->QueueHead); + if (pItem != NULL) { + queue->Depth--; + return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink); + } + return NULL; +} + +/* dequeue an HTC packet from the tail of the queue */ +static INLINE struct htc_packet *HTC_PACKET_DEQUEUE_TAIL(struct htc_packet_queue *queue) { + struct dl_list *pItem = DL_ListRemoveItemFromTail(&queue->QueueHead); + if (pItem != NULL) { + queue->Depth--; + return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink); + } + return NULL; +} + +#define HTC_PACKET_QUEUE_DEPTH(pQ) (pQ)->Depth + + +#define HTC_GET_ENDPOINT_FROM_PKT(p) (p)->Endpoint +#define HTC_GET_TAG_FROM_PKT(p) (p)->PktInfo.AsTx.Tag + + /* transfer the packets from one queue to the tail of another queue */ +#define HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(pQDest,pQSrc) \ +{ \ + DL_ListTransferItemsToTail(&(pQDest)->QueueHead,&(pQSrc)->QueueHead); \ + (pQDest)->Depth += (pQSrc)->Depth; \ + (pQSrc)->Depth = 0; \ +} + + /* fast version to init and add a single packet to a queue */ +#define INIT_HTC_PACKET_QUEUE_AND_ADD(pQ,pP) \ +{ \ + DL_LIST_INIT_AND_ADD(&(pQ)->QueueHead,&(pP)->ListLink) \ + (pQ)->Depth = 1; \ +} + +#define HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQ, pPTemp) \ + ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead,(pPTemp), struct htc_packet, ListLink) + +#define HTC_PACKET_QUEUE_ITERATE_END ITERATE_END + +#endif /*HTC_PACKET_H_*/ diff --git a/trunk/drivers/staging/ath6kl/include/wlan_api.h b/trunk/drivers/staging/ath6kl/include/wlan_api.h new file mode 100644 index 000000000000..9eea5875dd38 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/wlan_api.h @@ -0,0 +1,128 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the API for the host wlan module +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HOST_WLAN_API_H_ +#define _HOST_WLAN_API_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct ieee80211_node_table; +struct ieee80211_frame; + +struct ieee80211_common_ie { + u16 ie_chan; + u8 *ie_tstamp; + u8 *ie_ssid; + u8 *ie_rates; + u8 *ie_xrates; + u8 *ie_country; + u8 *ie_wpa; + u8 *ie_rsn; + u8 *ie_wmm; + u8 *ie_ath; + u16 ie_capInfo; + u16 ie_beaconInt; + u8 *ie_tim; + u8 *ie_chswitch; + u8 ie_erp; + u8 *ie_wsc; + u8 *ie_htcap; + u8 *ie_htop; +#ifdef WAPI_ENABLE + u8 *ie_wapi; +#endif +}; + +typedef struct bss { + u8 ni_macaddr[6]; + u8 ni_snr; + s16 ni_rssi; + struct bss *ni_list_next; + struct bss *ni_list_prev; + struct bss *ni_hash_next; + struct bss *ni_hash_prev; + struct ieee80211_common_ie ni_cie; + u8 *ni_buf; + u16 ni_framelen; + struct ieee80211_node_table *ni_table; + u32 ni_refcnt; + int ni_scangen; + + u32 ni_tstamp; + u32 ni_actcnt; +#ifdef OS_ROAM_MANAGEMENT + u32 ni_si_gen; +#endif +} bss_t; + +typedef void wlan_node_iter_func(void *arg, bss_t *); + +bss_t *wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size); +void wlan_node_free(bss_t *ni); +void wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni, + const u8 *macaddr); +bss_t *wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr); +void wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni); +void wlan_free_allnodes(struct ieee80211_node_table *nt); +void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f, + void *arg); + +void wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt); +void wlan_node_table_reset(struct ieee80211_node_table *nt); +void wlan_node_table_cleanup(struct ieee80211_node_table *nt); + +int wlan_parse_beacon(u8 *buf, int framelen, + struct ieee80211_common_ie *cie); + +u16 wlan_ieee2freq(int chan); +u32 wlan_freq2ieee(u16 freq); + +void wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge); + +void +wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt); + +bss_t * +wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid, + u32 ssidLength, bool bIsWPA2, bool bMatchSSID); + +void +wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni); + +bss_t *wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid); + +bss_t * +wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid, + u32 ssidLength, u32 dot11AuthMode, u32 authMode, + u32 pairwiseCryptoType, u32 grpwiseCryptoTyp); + +#ifdef __cplusplus +} +#endif + +#endif /* _HOST_WLAN_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/include/wmi_api.h b/trunk/drivers/staging/ath6kl/include/wmi_api.h new file mode 100644 index 000000000000..c8583e0c4a96 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/include/wmi_api.h @@ -0,0 +1,441 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the definitions for the Wireless Module Interface (WMI). +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _WMI_API_H_ +#define _WMI_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + /* WMI converts a dix frame with an ethernet payload (up to 1500 bytes) + * to an 802.3 frame (adds SNAP header) and adds on a WMI data header */ +#define WMI_MAX_TX_DATA_FRAME_LENGTH (1500 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR)) + + /* A normal WMI data frame */ +#define WMI_MAX_NORMAL_RX_DATA_FRAME_LENGTH (1500 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR)) + + /* An AMSDU frame */ /* The MAX AMSDU length of AR6003 is 3839 */ +#define WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH (3840 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR)) + +/* + * IP QoS Field definitions according to 802.1p + */ +#define BEST_EFFORT_PRI 0 +#define BACKGROUND_PRI 1 +#define EXCELLENT_EFFORT_PRI 3 +#define CONTROLLED_LOAD_PRI 4 +#define VIDEO_PRI 5 +#define VOICE_PRI 6 +#define NETWORK_CONTROL_PRI 7 +#define MAX_NUM_PRI 8 + +#define UNDEFINED_PRI (0xff) + +#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000 /* 5 seconds */ + +#define A_ROUND_UP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) + +typedef enum { + ATHEROS_COMPLIANCE = 0x1, +}TSPEC_PARAM_COMPLIANCE; + +struct wmi_t; + +void *wmi_init(void *devt); + +void wmi_qos_state_init(struct wmi_t *wmip); +void wmi_shutdown(struct wmi_t *wmip); +HTC_ENDPOINT_ID wmi_get_control_ep(struct wmi_t * wmip); +void wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid); +u16 wmi_get_mapped_qos_queue(struct wmi_t *, u8 ); +int wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf); +int wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData, WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS); +int wmi_dot3_2_dix(void *osbuf); + +int wmi_dot11_hdr_remove (struct wmi_t *wmip, void *osbuf); +int wmi_dot11_hdr_add(struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode); + +int wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf); +int wmi_syncpoint(struct wmi_t *wmip); +int wmi_syncpoint_reset(struct wmi_t *wmip); +u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled); + +u8 wmi_determine_userPriority (u8 *pkt, u32 layer2Pri); + +int wmi_control_rx(struct wmi_t *wmip, void *osbuf); +void wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg); +void wmi_free_allnodes(struct wmi_t *wmip); +bss_t *wmi_find_node(struct wmi_t *wmip, const u8 *macaddr); +void wmi_free_node(struct wmi_t *wmip, const u8 *macaddr); + + +typedef enum { + NO_SYNC_WMIFLAG = 0, + SYNC_BEFORE_WMIFLAG, /* transmit all queued data before cmd */ + SYNC_AFTER_WMIFLAG, /* any new data waits until cmd execs */ + SYNC_BOTH_WMIFLAG, + END_WMIFLAG /* end marker */ +} WMI_SYNC_FLAG; + +int wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, + WMI_SYNC_FLAG flag); + +int wmi_connect_cmd(struct wmi_t *wmip, + NETWORK_TYPE netType, + DOT11_AUTH_MODE dot11AuthMode, + AUTH_MODE authMode, + CRYPTO_TYPE pairwiseCrypto, + u8 pairwiseCryptoLen, + CRYPTO_TYPE groupCrypto, + u8 groupCryptoLen, + int ssidLength, + u8 *ssid, + u8 *bssid, + u16 channel, + u32 ctrl_flags); + +int wmi_reconnect_cmd(struct wmi_t *wmip, + u8 *bssid, + u16 channel); +int wmi_disconnect_cmd(struct wmi_t *wmip); +int wmi_getrev_cmd(struct wmi_t *wmip); +int wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType, + u32 forceFgScan, u32 isLegacy, + u32 homeDwellTime, u32 forceScanInterval, + s8 numChan, u16 *channelList); +int wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec, + u16 fg_end_sec, u16 bg_sec, + u16 minact_chdw_msec, + u16 maxact_chdw_msec, u16 pas_chdw_msec, + u8 shScanRatio, u8 scanCtrlFlags, + u32 max_dfsch_act_time, + u16 maxact_scan_per_ssid); +int wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask); +int wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag, + u8 ssidLength, u8 *ssid); +int wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons); +int wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmisstime, u16 bmissbeacons); +int wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType, + u8 ieLen, u8 *ieInfo); +int wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode); +int wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl, + u16 atim_windows, u16 timeout_value); +int wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time, + u32 ps_period, u8 sleep_period); +int wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod, + u16 psPollNum, u16 dtimPolicy, + u16 wakup_tx_policy, u16 num_tx_to_wakeup, + u16 ps_fail_event_policy); +int wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout); +int wmi_sync_cmd(struct wmi_t *wmip, u8 syncNumber); +int wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream); +int wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 streamID); +int wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask); +int wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate); +int wmi_get_bitrate_cmd(struct wmi_t *wmip); +s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx); +int wmi_get_regDomain_cmd(struct wmi_t *wmip); +int wmi_get_channelList_cmd(struct wmi_t *wmip); +int wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam, + WMI_PHY_MODE mode, s8 numChan, + u16 *channelList); + +int wmi_set_snr_threshold_params(struct wmi_t *wmip, + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); +int wmi_set_rssi_threshold_params(struct wmi_t *wmip, + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); +int wmi_clr_rssi_snr(struct wmi_t *wmip); +int wmi_set_lq_threshold_params(struct wmi_t *wmip, + WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd); +int wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold); +int wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy); + +int wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 bitmask); + +int wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, + u32 source); + +int wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask, + u16 tsr, bool rep, u16 size, + u32 valid); + +int wmi_get_stats_cmd(struct wmi_t *wmip); + +int wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, + CRYPTO_TYPE keyType, u8 keyUsage, + u8 keyLength,u8 *keyRSC, + u8 *keyMaterial, u8 key_op_ctrl, u8 *mac, + WMI_SYNC_FLAG sync_flag); +int wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk); +int wmi_delete_krk_cmd(struct wmi_t *wmip); +int wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex); +int wmi_set_akmp_params_cmd(struct wmi_t *wmip, + WMI_SET_AKMP_PARAMS_CMD *akmpParams); +int wmi_get_pmkid_list_cmd(struct wmi_t *wmip); +int wmi_set_pmkid_list_cmd(struct wmi_t *wmip, + WMI_SET_PMKID_LIST_CMD *pmkInfo); +int wmi_abort_scan_cmd(struct wmi_t *wmip); +int wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM); +int wmi_get_txPwr_cmd(struct wmi_t *wmip); +int wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid); +int wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex); +int wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en); +int wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId, + bool set); +int wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, + u8 eCWmin, u8 eCWmax, + u8 aifsn); +int wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType, + u8 trafficClass, u8 maxRetries, + u8 enableNotify); + +void wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid); + +int wmi_get_roam_tbl_cmd(struct wmi_t *wmip); +int wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType); +int wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p, + u8 size); +int wmi_set_powersave_timers_cmd(struct wmi_t *wmip, + WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd, + u8 size); + +int wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode); +int wmi_opt_tx_frame_cmd(struct wmi_t *wmip, + u8 frmType, + u8 *dstMacAddr, + u8 *bssid, + u16 optIEDataLen, + u8 *optIEData); + +int wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl); +int wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize); +int wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSpLen); +u8 convert_userPriority_to_trafficClass(u8 userPriority); +u8 wmi_get_power_mode_cmd(struct wmi_t *wmip); +int wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance); + +#ifdef CONFIG_HOST_TCMD_SUPPORT +int wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len); +#endif + +int wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status); +int wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd); + +int wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd); + +int wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd); + +int wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *cmd); + +int wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd); + +int wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_A2DP_CONFIG_CMD* cmd); + + +int wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD* cmd); + +int wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd); + +int wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip, + WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd); + +int wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd); + +int wmi_get_btcoex_stats_cmd(struct wmi_t * wmip); + +int wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold); + +/* + * This function is used to configure the fix rates mask to the target. + */ +int wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask); +int wmi_get_ratemask_cmd(struct wmi_t *wmip); + +int wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode); + +int wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode); + +int wmi_set_qos_supp_cmd(struct wmi_t *wmip,u8 status); +int wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status); +int wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable); +int wmi_set_country(struct wmi_t *wmip, u8 *countryCode); + +int wmi_get_keepalive_configured(struct wmi_t *wmip); +u8 wmi_get_keepalive_cmd(struct wmi_t *wmip); +int wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval); + +int wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, + u8 ieLen,u8 *ieInfo); + +int wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen); + +s32 wmi_get_rate(s8 rateindex); + +int wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *cmd); + +/*Wake on Wireless WMI commands*/ +int wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd); +int wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd); +int wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd); +int wmi_add_wow_pattern_cmd(struct wmi_t *wmip, + WMI_ADD_WOW_PATTERN_CMD *cmd, u8 *pattern, u8 *mask, u8 pattern_size); +int wmi_del_wow_pattern_cmd(struct wmi_t *wmip, + WMI_DEL_WOW_PATTERN_CMD *cmd); +int wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status); + +int +wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer); + +int +wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4); + +int +wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4); + +int +wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable); + +bss_t * +wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid, + u32 ssidLength, bool bIsWPA2, bool bMatchSSID); + + +void +wmi_node_return (struct wmi_t *wmip, bss_t *bss); + +void +wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge); + +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +int wmi_prof_cfg_cmd(struct wmi_t *wmip, u32 period, u32 nbins); +int wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr); +int wmi_prof_start_cmd(struct wmi_t *wmip); +int wmi_prof_stop_cmd(struct wmi_t *wmip); +int wmi_prof_count_get_cmd(struct wmi_t *wmip); +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ +#ifdef OS_ROAM_MANAGEMENT +void wmi_scan_indication (struct wmi_t *wmip); +#endif + +int +wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd); + +bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id); +int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss); + + +/* + * AP mode + */ +int +wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p); + +int +wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid); + +int +wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta); + +int +wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy); + +int +wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *a); + +u8 acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl); + +int +wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason); + +int +wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag); + +int +wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period); + +int +wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell); + +int +wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim); + +int +wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset); + +int +wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd); + +int +wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width); + +int +wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz); + +int +wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray); + +int +wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid); + +int +wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink); + +int +wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask); + +int +wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion, bool rxDot11Hdr, bool defragOnHost); + +int +wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode); + +int +wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence); + +int +wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk); + +int +wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd); + +u16 wmi_ieee2freq (int chan); + +u32 wmi_freq2ieee (u16 freq); + +bss_t * +wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid, + u32 ssidLength, + u32 dot11AuthMode, u32 authMode, + u32 pairwiseCryptoType, u32 grpwiseCryptoTyp); + +#ifdef __cplusplus +} +#endif + +#endif /* _WMI_API_H_ */ diff --git a/trunk/drivers/staging/ath6kl/miscdrv/ar3kconfig.c b/trunk/drivers/staging/ath6kl/miscdrv/ar3kconfig.c new file mode 100644 index 000000000000..e0ea2183019d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/ar3kconfig.c @@ -0,0 +1,565 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// AR3K configuration implementation +// +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME misc +#include "a_debug.h" +#include "common_drv.h" +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +#include "export_hci_transport.h" +#else +#include "hci_transport_api.h" +#endif +#include "ar3kconfig.h" +#include "tlpm.h" + +#define BAUD_CHANGE_COMMAND_STATUS_OFFSET 5 +#define HCI_EVENT_RESP_TIMEOUTMS 3000 +#define HCI_CMD_OPCODE_BYTE_LOW_OFFSET 0 +#define HCI_CMD_OPCODE_BYTE_HI_OFFSET 1 +#define HCI_EVENT_OPCODE_BYTE_LOW 3 +#define HCI_EVENT_OPCODE_BYTE_HI 4 +#define HCI_CMD_COMPLETE_EVENT_CODE 0xE +#define HCI_MAX_EVT_RECV_LENGTH 257 +#define EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET 5 + +int AthPSInitialize(struct ar3k_config_info *hdev); + +static int SendHCICommand(struct ar3k_config_info *pConfig, + u8 *pBuffer, + int Length) +{ + struct htc_packet *pPacket = NULL; + int status = 0; + + do { + + pPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet)); + if (NULL == pPacket) { + status = A_NO_MEMORY; + break; + } + + A_MEMZERO(pPacket,sizeof(struct htc_packet)); + SET_HTC_PACKET_INFO_TX(pPacket, + NULL, + pBuffer, + Length, + HCI_COMMAND_TYPE, + AR6K_CONTROL_PKT_TAG); + + /* issue synchronously */ + status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,true); + + } while (false); + + if (pPacket != NULL) { + kfree(pPacket); + } + + return status; +} + +static int RecvHCIEvent(struct ar3k_config_info *pConfig, + u8 *pBuffer, + int *pLength) +{ + int status = 0; + struct htc_packet *pRecvPacket = NULL; + + do { + + pRecvPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet)); + if (NULL == pRecvPacket) { + status = A_NO_MEMORY; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); + break; + } + + A_MEMZERO(pRecvPacket,sizeof(struct htc_packet)); + + SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE); + + status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev, + pRecvPacket, + HCI_EVENT_RESP_TIMEOUTMS); + if (status) { + break; + } + + *pLength = pRecvPacket->ActualLength; + + } while (false); + + if (pRecvPacket != NULL) { + kfree(pRecvPacket); + } + + return status; +} + +int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig, + u8 *pHCICommand, + int CmdLength, + u8 **ppEventBuffer, + u8 **ppBufferToFree) +{ + int status = 0; + u8 *pBuffer = NULL; + u8 *pTemp; + int length; + bool commandComplete = false; + u8 opCodeBytes[2]; + + do { + + length = max(HCI_MAX_EVT_RECV_LENGTH,CmdLength); + length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom; + length += pConfig->pHCIProps->IOBlockPad; + + pBuffer = (u8 *)A_MALLOC(length); + if (NULL == pBuffer) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n")); + status = A_NO_MEMORY; + break; + } + + /* get the opcodes to check the command complete event */ + opCodeBytes[0] = pHCICommand[HCI_CMD_OPCODE_BYTE_LOW_OFFSET]; + opCodeBytes[1] = pHCICommand[HCI_CMD_OPCODE_BYTE_HI_OFFSET]; + + /* copy HCI command */ + memcpy(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength); + /* send command */ + status = SendHCICommand(pConfig, + pBuffer + pConfig->pHCIProps->HeadRoom, + CmdLength); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to send HCI Command (%d) \n", status)); + AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command"); + break; + } + + /* reuse buffer to capture command complete event */ + A_MEMZERO(pBuffer,length); + status = RecvHCIEvent(pConfig,pBuffer,&length); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI event recv failed \n")); + AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command"); + break; + } + + pTemp = pBuffer + pConfig->pHCIProps->HeadRoom; + if (pTemp[0] == HCI_CMD_COMPLETE_EVENT_CODE) { + if ((pTemp[HCI_EVENT_OPCODE_BYTE_LOW] == opCodeBytes[0]) && + (pTemp[HCI_EVENT_OPCODE_BYTE_HI] == opCodeBytes[1])) { + commandComplete = true; + } + } + + if (!commandComplete) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Unexpected HCI event : %d \n",pTemp[0])); + AR_DEBUG_PRINTBUF(pTemp,pTemp[1],"Unexpected HCI event"); + status = A_ECOMM; + break; + } + + if (ppEventBuffer != NULL) { + /* caller wants to look at the event */ + *ppEventBuffer = pTemp; + if (ppBufferToFree == NULL) { + status = A_EINVAL; + break; + } + /* caller must free the buffer */ + *ppBufferToFree = pBuffer; + pBuffer = NULL; + } + + } while (false); + + if (pBuffer != NULL) { + kfree(pBuffer); + } + + return status; +} + +static int AR3KConfigureHCIBaud(struct ar3k_config_info *pConfig) +{ + int status = 0; + u8 hciBaudChangeCommand[] = {0x0c,0xfc,0x2,0,0}; + u16 baudVal; + u8 *pEvent = NULL; + u8 *pBufferToFree = NULL; + + do { + + if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) { + baudVal = (u16)(pConfig->AR3KBaudRate / 100); + hciBaudChangeCommand[3] = (u8)baudVal; + hciBaudChangeCommand[4] = (u8)(baudVal >> 8); + + status = SendHCICommandWaitCommandComplete(pConfig, + hciBaudChangeCommand, + sizeof(hciBaudChangeCommand), + &pEvent, + &pBufferToFree); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n")); + break; + } + + if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("AR3K Config: Baud change command event status failed: %d \n", + pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET])); + status = A_ECOMM; + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate)); + } + + if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) { + /* some versions of AR3K do not switch baud immediately, up to 300MS */ + A_MDELAY(325); + } + + if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) { + /* Tell target to change UART baud rate for AR6K */ + status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("AR3K Config: failed to set scale and step values: %d \n", status)); + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, + ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate)); + } + + } while (false); + + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + + return status; +} + +static int AR3KExitMinBoot(struct ar3k_config_info *pConfig) +{ + int status; + char exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00}; + u8 *pEvent = NULL; + u8 *pBufferToFree = NULL; + + status = SendHCICommandWaitCommandComplete(pConfig, + exitMinBootCmd, + sizeof(exitMinBootCmd), + &pEvent, + &pBufferToFree); + + if (!status) { + if (pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET] != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("AR3K Config: MinBoot exit command event status failed: %d \n", + pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET])); + status = A_ECOMM; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("AR3K Config: MinBoot Exit Command Complete (Success) \n")); + A_MDELAY(1); + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: MinBoot Exit Failed! \n")); + } + + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + + return status; +} + +static int AR3KConfigureSendHCIReset(struct ar3k_config_info *pConfig) +{ + int status = 0; + u8 hciResetCommand[] = {0x03,0x0c,0x0}; + u8 *pEvent = NULL; + u8 *pBufferToFree = NULL; + + status = SendHCICommandWaitCommandComplete( pConfig, + hciResetCommand, + sizeof(hciResetCommand), + &pEvent, + &pBufferToFree ); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n")); + } + + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + + return status; +} + +static int AR3KEnableTLPM(struct ar3k_config_info *pConfig) +{ + int status; + /* AR3K vendor specific command for Host Wakeup Config */ + char hostWakeupConfig[] = {0x31,0xFC,0x18, + 0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms + 0x00,0x00,0x00,0x00, + TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms + 0x00,0x00,0x00,0x00}; + /* AR3K vendor specific command for Target Wakeup Config */ + char targetWakeupConfig[] = {0x31,0xFC,0x18, + 0x04,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms + 0x00,0x00,0x00,0x00, + TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms + 0x00,0x00,0x00,0x00}; + /* AR3K vendor specific command for Host Wakeup Enable */ + char hostWakeupEnable[] = {0x31,0xFC,0x4, + 0x01,0x00,0x00,0x00}; + /* AR3K vendor specific command for Target Wakeup Enable */ + char targetWakeupEnable[] = {0x31,0xFC,0x4, + 0x06,0x00,0x00,0x00}; + /* AR3K vendor specific command for Sleep Enable */ + char sleepEnable[] = {0x4,0xFC,0x1, + 0x1}; + u8 *pEvent = NULL; + u8 *pBufferToFree = NULL; + + if (0 != pConfig->IdleTimeout) { + u8 idle_lsb = pConfig->IdleTimeout & 0xFF; + u8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8; + hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb; + hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb; + } + + if (0 != pConfig->WakeupTimeout) { + hostWakeupConfig[19] = targetWakeupConfig[19] = (pConfig->WakeupTimeout & 0xFF); + } + + status = SendHCICommandWaitCommandComplete(pConfig, + hostWakeupConfig, + sizeof(hostWakeupConfig), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n")); + return status; + } + + pEvent = NULL; + pBufferToFree = NULL; + status = SendHCICommandWaitCommandComplete(pConfig, + targetWakeupConfig, + sizeof(targetWakeupConfig), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n")); + return status; + } + + pEvent = NULL; + pBufferToFree = NULL; + status = SendHCICommandWaitCommandComplete(pConfig, + hostWakeupEnable, + sizeof(hostWakeupEnable), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n")); + return status; + } + + pEvent = NULL; + pBufferToFree = NULL; + status = SendHCICommandWaitCommandComplete(pConfig, + targetWakeupEnable, + sizeof(targetWakeupEnable), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n")); + return status; + } + + pEvent = NULL; + pBufferToFree = NULL; + status = SendHCICommandWaitCommandComplete(pConfig, + sleepEnable, + sizeof(sleepEnable), + &pEvent, + &pBufferToFree); + if (pBufferToFree != NULL) { + kfree(pBufferToFree); + } + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n")); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Enable TLPM Completed (status = %d) \n",status)); + + return status; +} + +int AR3KConfigure(struct ar3k_config_info *pConfig) +{ + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n")); + + do { + + if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) { + status = A_EINVAL; + break; + } + + /* disable asynchronous recv while we issue commands and receive events synchronously */ + status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false); + if (status) { + break; + } + + if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) { + status = AR3KExitMinBoot(pConfig); + if (status) { + break; + } + } + + + /* Load patching and PST file if available*/ + if (0 != AthPSInitialize(pConfig)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n")); + } + + /* Send HCI reset to make PS tags take effect*/ + AR3KConfigureSendHCIReset(pConfig); + + if (pConfig->Flags & + (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) { + status = AR3KConfigureHCIBaud(pConfig); + if (status) { + break; + } + } + + + + if (pConfig->PwrMgmtEnabled) { + /* the delay is required after the previous HCI reset before further + * HCI commands can be issued + */ + A_MDELAY(200); + AR3KEnableTLPM(pConfig); + } + + /* re-enable asynchronous recv */ + status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true); + if (status) { + break; + } + + + } while (false); + + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status)); + + return status; +} + +int AR3KConfigureExit(void *config) +{ + int status = 0; + struct ar3k_config_info *pConfig = (struct ar3k_config_info *)config; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n")); + + do { + + if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) { + status = A_EINVAL; + break; + } + + /* disable asynchronous recv while we issue commands and receive events synchronously */ + status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false); + if (status) { + break; + } + + if (pConfig->Flags & + (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) { + status = AR3KConfigureHCIBaud(pConfig); + if (status) { + break; + } + } + + /* re-enable asynchronous recv */ + status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true); + if (status) { + break; + } + + + } while (false); + + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status)); + + return status; +} + diff --git a/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c new file mode 100644 index 000000000000..282ceac597b8 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * This file implements the Atheros PS and patch downloaded for HCI UART Transport driver. + * This file can be used for HCI SDIO transport implementation for AR6002 with HCI_TRANSPORT_SDIO + * defined. + * + * + * ar3kcpsconfig.c + * + * + * + * The software source and binaries included in this development package are + * licensed, not sold. You, or your company, received the package under one + * or more license agreements. The rights granted to you are specifically + * listed in these license agreement(s). All other rights remain with Atheros + * Communications, Inc., its subsidiaries, or the respective owner including + * those listed on the included copyright notices.. Distribution of any + * portion of this package must be in strict compliance with the license + * agreement(s) terms. + * + * + * + */ + + + +#include "ar3kpsconfig.h" +#ifndef HCI_TRANSPORT_SDIO +#include "hci_ath.h" +#include "hci_uart.h" +#endif /* #ifndef HCI_TRANSPORT_SDIO */ + +#define MAX_FW_PATH_LEN 50 +#define MAX_BDADDR_FORMAT_LENGTH 30 + +/* + * Structure used to send HCI packet, hci packet length and device info + * together as parameter to PSThread. + */ +typedef struct { + + struct ps_cmd_packet *HciCmdList; + u32 num_packets; + struct ar3k_config_info *dev; +}HciCommandListParam; + +int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig, + u8 *pHCICommand, + int CmdLength, + u8 **ppEventBuffer, + u8 **ppBufferToFree); + +u32 Rom_Version; +u32 Build_Version; +extern bool BDADDR; + +int getDeviceType(struct ar3k_config_info *pConfig, u32 *code); +int ReadVersionInfo(struct ar3k_config_info *pConfig); +#ifndef HCI_TRANSPORT_SDIO + +DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent); +DECLARE_WAIT_QUEUE_HEAD(HciEvent); +u8 *HciEventpacket; +rwlock_t syncLock; +wait_queue_t Eventwait; + +int PSHciWritepacket(struct hci_dev*,u8* Data, u32 len); +extern char *bdaddr; +#endif /* HCI_TRANSPORT_SDIO */ + +int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type); + +int PSSendOps(void *arg); + +#ifdef BT_PS_DEBUG +void Hci_log(u8 * log_string,u8 *data,u32 len) +{ + int i; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s : ",log_string)); + for (i = 0; i < len; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("0x%02x ", data[i])); + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n...................................\n")); +} +#else +#define Hci_log(string,data,len) +#endif /* BT_PS_DEBUG */ + + + + +int AthPSInitialize(struct ar3k_config_info *hdev) +{ + int status = 0; + if(hdev == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Device handle received\n")); + return A_ERROR; + } + +#ifndef HCI_TRANSPORT_SDIO + DECLARE_WAITQUEUE(wait, current); +#endif /* HCI_TRANSPORT_SDIO */ + + +#ifdef HCI_TRANSPORT_SDIO + status = PSSendOps((void*)hdev); +#else + if(InitPSState(hdev) == -1) { + return A_ERROR; + } + allow_signal(SIGKILL); + add_wait_queue(&PsCompleteEvent,&wait); + set_current_state(TASK_INTERRUPTIBLE); + if(!kernel_thread(PSSendOps,(void*)hdev,CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Kthread Failed\n")); + remove_wait_queue(&PsCompleteEvent,&wait); + return A_ERROR; + } + wait_event_interruptible(PsCompleteEvent,(PSTagMode == false)); + set_current_state(TASK_RUNNING); + remove_wait_queue(&PsCompleteEvent,&wait); + +#endif /* HCI_TRANSPORT_SDIO */ + + + return status; + +} + +int PSSendOps(void *arg) +{ + int i; + int status = 0; + struct ps_cmd_packet *HciCmdList; /* List storing the commands */ + const struct firmware* firmware; + u32 numCmds; + u8 *event; + u8 *bufferToFree; + struct hci_dev *device; + u8 *buffer; + u32 len; + u32 DevType; + u8 *PsFileName; + u8 *patchFileName; + u8 *path = NULL; + u8 *config_path = NULL; + u8 config_bdaddr[MAX_BDADDR_FORMAT_LENGTH]; + struct ar3k_config_info *hdev = (struct ar3k_config_info*)arg; + struct device *firmwareDev = NULL; + status = 0; + HciCmdList = NULL; +#ifdef HCI_TRANSPORT_SDIO + device = hdev->pBtStackHCIDev; + firmwareDev = device->parent; +#else + device = hdev; + firmwareDev = &device->dev; + AthEnableSyncCommandOp(true); +#endif /* HCI_TRANSPORT_SDIO */ + /* First verify if the controller is an FPGA or ASIC, so depending on the device type the PS file to be written will be different. + */ + + path =(u8 *)A_MALLOC(MAX_FW_PATH_LEN); + if(path == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN)); + goto complete; + } + config_path = (u8 *) A_MALLOC(MAX_FW_PATH_LEN); + if(config_path == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for config_path\n", MAX_FW_PATH_LEN)); + goto complete; + } + + if(A_ERROR == getDeviceType(hdev,&DevType)) { + status = 1; + goto complete; + } + if(A_ERROR == ReadVersionInfo(hdev)) { + status = 1; + goto complete; + } + + patchFileName = PATCH_FILE; + snprintf(path, MAX_FW_PATH_LEN, "%s/%xcoex/",CONFIG_PATH,Rom_Version); + if(DevType){ + if(DevType == 0xdeadc0de){ + PsFileName = PS_ASIC_FILE; + } else{ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" FPGA Test Image : %x %x \n",Rom_Version,Build_Version)); + if((Rom_Version == 0x99999999) && (Build_Version == 1)){ + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("FPGA Test Image : Skipping Patch File load\n")); + patchFileName = NULL; + } + PsFileName = PS_FPGA_FILE; + } + } + else{ + PsFileName = PS_ASIC_FILE; + } + + snprintf(config_path, MAX_FW_PATH_LEN, "%s%s",path,PsFileName); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%x: FPGA/ASIC PS File Name %s\n", DevType,config_path)); + /* Read the PS file to a dynamically allocated buffer */ + if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); + status = 1; + goto complete; + + } + if(NULL == firmware || firmware->size == 0) { + status = 1; + goto complete; + } + buffer = (u8 *)A_MALLOC(firmware->size); + if(buffer != NULL) { + /* Copy the read file to a local Dynamic buffer */ + memcpy(buffer,firmware->data,firmware->size); + len = firmware->size; + A_RELEASE_FIRMWARE(firmware); + /* Parse the PS buffer to a global variable */ + status = AthDoParsePS(buffer,len); + kfree(buffer); + } else { + A_RELEASE_FIRMWARE(firmware); + } + + + /* Read the patch file to a dynamically allocated buffer */ + if(patchFileName != NULL) + snprintf(config_path, + MAX_FW_PATH_LEN, "%s%s",path,patchFileName); + else { + status = 0; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path)); + if((patchFileName == NULL) || (A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); + /* + * It is not necessary that Patch file be available, continue with PS Operations if. + * failed. + */ + status = 0; + + } else { + if(NULL == firmware || firmware->size == 0) { + status = 0; + } else { + buffer = (u8 *)A_MALLOC(firmware->size); + if(buffer != NULL) { + /* Copy the read file to a local Dynamic buffer */ + memcpy(buffer,firmware->data,firmware->size); + len = firmware->size; + A_RELEASE_FIRMWARE(firmware); + /* parse and store the Patch file contents to a global variables */ + status = AthDoParsePatch(buffer,len); + kfree(buffer); + } else { + A_RELEASE_FIRMWARE(firmware); + } + } + } + + /* Create an HCI command list from the parsed PS and patch information */ + AthCreateCommandList(&HciCmdList,&numCmds); + + /* Form the parameter for PSSendOps() API */ + + + /* + * First Send the CRC packet, + * We have to continue with the PS operations only if the CRC packet has been replied with + * a Command complete event with status Error. + */ + + if(SendHCICommandWaitCommandComplete + (hdev, + HciCmdList[0].Hcipacket, + HciCmdList[0].packetLen, + &event, + &bufferToFree) == 0) { + if(ReadPSEvent(event) == 0) { /* Exit if the status is success */ + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + +#ifndef HCI_TRANSPORT_SDIO + if(bdaddr && bdaddr[0] !='\0') { + write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING); + } +#endif + status = 1; + goto complete; + } + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + } else { + status = 0; + goto complete; + } + + for(i = 1; i bdaddr[0] !=0x00 || + hdev->bdaddr[1] !=0x00 || + hdev->bdaddr[2] !=0x00 || + hdev->bdaddr[3] !=0x00 || + hdev->bdaddr[4] !=0x00 || + hdev->bdaddr[5] !=0x00) + write_bdaddr(hdev,hdev->bdaddr,BDADDR_TYPE_HEX); + +#ifndef HCI_TRANSPORT_SDIO + + if(bdaddr && bdaddr[0] != '\0') { + write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING); + } else +#endif /* HCI_TRANSPORT_SDIO */ + /* Write BDADDR Read from OTP here */ + + + +#endif + + { + /* Read Contents of BDADDR file if user has not provided any option */ + snprintf(config_path,MAX_FW_PATH_LEN, "%s%s",path,BDADDR_FILE); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path)); + if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); + status = 1; + goto complete; + } + if(NULL == firmware || firmware->size == 0) { + status = 1; + goto complete; + } + len = min_t(size_t, firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1); + memcpy(config_bdaddr, firmware->data, len); + config_bdaddr[len] = '\0'; + write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING); + A_RELEASE_FIRMWARE(firmware); + } +complete: +#ifndef HCI_TRANSPORT_SDIO + AthEnableSyncCommandOp(false); + PSTagMode = false; + wake_up_interruptible(&PsCompleteEvent); +#endif /* HCI_TRANSPORT_SDIO */ + if(NULL != HciCmdList) { + AthFreeCommandList(&HciCmdList,numCmds); + } + if(path) { + kfree(path); + } + if(config_path) { + kfree(config_path); + } + return status; +} +#ifndef HCI_TRANSPORT_SDIO +/* + * This API is used to send the HCI command to controller and return + * with a HCI Command Complete event. + * For HCI SDIO transport, this will be internally defined. + */ +int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig, + u8 *pHCICommand, + int CmdLength, + u8 **ppEventBuffer, + u8 **ppBufferToFree) +{ + if(CmdLength == 0) { + return A_ERROR; + } + Hci_log("COM Write -->",pHCICommand,CmdLength); + PSAcked = false; + if(PSHciWritepacket(pConfig,pHCICommand,CmdLength) == 0) { + /* If the controller is not available, return Error */ + return A_ERROR; + } + //add_timer(&psCmdTimer); + wait_event_interruptible(HciEvent,(PSAcked == true)); + if(NULL != HciEventpacket) { + *ppEventBuffer = HciEventpacket; + *ppBufferToFree = HciEventpacket; + } else { + /* Did not get an event from controller. return error */ + *ppBufferToFree = NULL; + return A_ERROR; + } + + return 0; +} +#endif /* HCI_TRANSPORT_SDIO */ + +int ReadPSEvent(u8* Data){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" PS Event %x %x %x\n",Data[4],Data[5],Data[3])); + + if(Data[4] == 0xFC && Data[5] == 0x00) + { + switch(Data[3]){ + case 0x0B: + return 0; + break; + case 0x0C: + /* Change Baudrate */ + return 0; + break; + case 0x04: + return 0; + break; + case 0x1E: + Rom_Version = Data[9]; + Rom_Version = ((Rom_Version << 8) |Data[8]); + Rom_Version = ((Rom_Version << 8) |Data[7]); + Rom_Version = ((Rom_Version << 8) |Data[6]); + + Build_Version = Data[13]; + Build_Version = ((Build_Version << 8) |Data[12]); + Build_Version = ((Build_Version << 8) |Data[11]); + Build_Version = ((Build_Version << 8) |Data[10]); + return 0; + break; + + + } + } + + return A_ERROR; +} +int str2ba(unsigned char *str_bdaddr,unsigned char *bdaddr) +{ + unsigned char bdbyte[3]; + unsigned char *str_byte = str_bdaddr; + int i,j; + unsigned char colon_present = 0; + + if(NULL != strstr(str_bdaddr,":")) { + colon_present = 1; + } + + + bdbyte[2] = '\0'; + + for( i = 0,j = 5; i < 6; i++, j--) { + bdbyte[0] = str_byte[0]; + bdbyte[1] = str_byte[1]; + bdaddr[j] = A_STRTOL(bdbyte,NULL,16); + if(colon_present == 1) { + str_byte+=3; + } else { + str_byte+=2; + } + } + return 0; +} + +int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type) +{ + u8 bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + u8 *event; + u8 *bufferToFree = NULL; + int result = A_ERROR; + int inc,outc; + + if (type == BDADDR_TYPE_STRING) + str2ba(bdaddr,&bdaddr_cmd[7]); + else { + /* Bdaddr has to be sent as LAP first */ + for(inc = 5 ,outc = 7; inc >=0; inc--, outc++) + bdaddr_cmd[outc] = bdaddr[inc]; + } + + if(0 == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd, + sizeof(bdaddr_cmd), + &event,&bufferToFree)) { + + if(event[4] == 0xFC && event[5] == 0x00){ + if(event[3] == 0x0B){ + result = 0; + } + } + + } + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + return result; + +} +int ReadVersionInfo(struct ar3k_config_info *pConfig) +{ + u8 hciCommand[] = {0x1E,0xfc,0x00}; + u8 *event; + u8 *bufferToFree = NULL; + int result = A_ERROR; + if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { + result = ReadPSEvent(event); + + } + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + return result; +} +int getDeviceType(struct ar3k_config_info *pConfig, u32 *code) +{ + u8 hciCommand[] = {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04}; + u8 *event; + u8 *bufferToFree = NULL; + u32 reg; + int result = A_ERROR; + *code = 0; + hciCommand[3] = (u8)(FPGA_REGISTER & 0xFF); + hciCommand[4] = (u8)((FPGA_REGISTER >> 8) & 0xFF); + hciCommand[5] = (u8)((FPGA_REGISTER >> 16) & 0xFF); + hciCommand[6] = (u8)((FPGA_REGISTER >> 24) & 0xFF); + if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { + + if(event[4] == 0xFC && event[5] == 0x00){ + switch(event[3]){ + case 0x05: + reg = event[9]; + reg = ((reg << 8) |event[8]); + reg = ((reg << 8) |event[7]); + reg = ((reg << 8) |event[6]); + *code = reg; + result = 0; + + break; + case 0x06: + //Sleep(500); + break; + } + } + + } + if(bufferToFree != NULL) { + kfree(bufferToFree); + } + return result; +} + + diff --git a/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h new file mode 100644 index 000000000000..d44351307807 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * This file defines the symbols exported by Atheros PS and patch download module. + * define the constant HCI_TRANSPORT_SDIO if the module is being used for HCI SDIO transport. + * defined. + * + * + * ar3kcpsconfig.h + * + * + * + * The software source and binaries included in this development package are + * licensed, not sold. You, or your company, received the package under one + * or more license agreements. The rights granted to you are specifically + * listed in these license agreement(s). All other rights remain with Atheros + * Communications, Inc., its subsidiaries, or the respective owner including + * those listed on the included copyright notices.. Distribution of any + * portion of this package must be in strict compliance with the license + * agreement(s) terms. + * + * + * + */ + + + +#ifndef __AR3KPSCONFIG_H +#define __AR3KPSCONFIG_H + +/* + * Define the flag HCI_TRANSPORT_SDIO and undefine HCI_TRANSPORT_UART if the transport being used is SDIO. + */ +#undef HCI_TRANSPORT_UART + +#include +#include +#include + + +#include +#include + + +#include +#include + +#include "ar3kpsparser.h" + +#define FPGA_REGISTER 0x4FFC +#define BDADDR_TYPE_STRING 0 +#define BDADDR_TYPE_HEX 1 +#define CONFIG_PATH "ar3k" + +#define PS_ASIC_FILE "PS_ASIC.pst" +#define PS_FPGA_FILE "PS_FPGA.pst" + +#define PATCH_FILE "RamPatch.txt" +#define BDADDR_FILE "ar3kbdaddr.pst" + +#define ROM_VER_AR3001_3_1_0 30000 +#define ROM_VER_AR3001_3_1_1 30101 + + +#ifndef HCI_TRANSPORT_SDIO +#define struct ar3k_config_info struct hci_dev +extern wait_queue_head_t HciEvent; +extern wait_queue_t Eventwait; +extern u8 *HciEventpacket; +#endif /* #ifndef HCI_TRANSPORT_SDIO */ + +int AthPSInitialize(struct ar3k_config_info *hdev); +int ReadPSEvent(u8* Data); +#endif /* __AR3KPSCONFIG_H */ diff --git a/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c new file mode 100644 index 000000000000..b99a11a9dd69 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * This file implements the Atheros PS and patch parser. + * It implements APIs to parse data buffer with patch and PS information and convert it to HCI commands. + * + * + * + * ar3kpsparser.c + * + * + * + * The software source and binaries included in this development package are + * licensed, not sold. You, or your company, received the package under one + * or more license agreements. The rights granted to you are specifically + * listed in these license agreement(s). All other rights remain with Atheros + * Communications, Inc., its subsidiaries, or the respective owner including + * those listed on the included copyright notices.. Distribution of any + * portion of this package must be in strict compliance with the license + * agreement(s) terms. + * + * + * + */ + + +#include "ar3kpsparser.h" + +#include +#include + +#define BD_ADDR_SIZE 6 +#define WRITE_PATCH 8 +#define ENABLE_PATCH 11 +#define PS_RESET 2 +#define PS_WRITE 1 +#define PS_VERIFY_CRC 9 +#define CHANGE_BDADDR 15 + +#define HCI_COMMAND_HEADER 7 + +#define HCI_EVENT_SIZE 7 + +#define WRITE_PATCH_COMMAND_STATUS_OFFSET 5 + +#define PS_RAM_SIZE 2048 + +#define RAM_PS_REGION (1<<0) +#define RAM_PATCH_REGION (1<<1) +#define RAMPS_MAX_PS_DATA_PER_TAG 20000 +#define MAX_RADIO_CFG_TABLE_SIZE 244 +#define RAMPS_MAX_PS_TAGS_PER_FILE 50 + +#define PS_MAX_LEN 500 +#define LINE_SIZE_MAX (PS_MAX_LEN *2) + +/* Constant values used by parser */ +#define BYTES_OF_PS_DATA_PER_LINE 16 +#define RAMPS_MAX_PS_DATA_PER_TAG 20000 + + +/* Number pf PS/Patch entries in an HCI packet */ +#define MAX_BYTE_LENGTH 244 + +#define SKIP_BLANKS(str) while (*str == ' ') str++ + +enum MinBootFileFormatE +{ + MB_FILEFORMAT_RADIOTBL, + MB_FILEFORMAT_PATCH, + MB_FILEFORMAT_COEXCONFIG +}; + +enum RamPsSection +{ + RAM_PS_SECTION, + RAM_PATCH_SECTION, + RAM_DYN_MEM_SECTION +}; + +enum eType { + eHex, + edecimal +}; + + +typedef struct tPsTagEntry +{ + u32 TagId; + u32 TagLen; + u8 *TagData; +} tPsTagEntry, *tpPsTagEntry; + +typedef struct tRamPatch +{ + u16 Len; + u8 *Data; +} tRamPatch, *ptRamPatch; + + + +struct st_ps_data_format { + enum eType eDataType; + bool bIsArray; +}; + +struct st_read_status { + unsigned uTagID; + unsigned uSection; + unsigned uLineCount; + unsigned uCharCount; + unsigned uByteCount; +}; + + +/* Stores the number of PS Tags */ +static u32 Tag_Count = 0; + +/* Stores the number of patch commands */ +static u32 Patch_Count = 0; +static u32 Total_tag_lenght = 0; +bool BDADDR = false; +u32 StartTagId; + +tPsTagEntry PsTagEntry[RAMPS_MAX_PS_TAGS_PER_FILE]; +tRamPatch RamPatch[MAX_NUM_PATCH_ENTRY]; + + +int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat); +char AthReadChar(u8 *buffer, u32 len,u32 *pos); +char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos); +static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index); + +/* Function to reads the next character from the input buffer */ +char AthReadChar(u8 *buffer, u32 len,u32 *pos) +{ + char Ch; + if(buffer == NULL || *pos >=len ) + { + return '\0'; + } else { + Ch = buffer[*pos]; + (*pos)++; + return Ch; + } +} +/* PS parser helper function */ +unsigned int uGetInputDataFormat(char *pCharLine, struct st_ps_data_format *pstFormat) +{ + if(pCharLine[0] != '[') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + return 0; + } + switch(pCharLine[1]) { + case 'H': + case 'h': + if(pCharLine[2]==':') { + if((pCharLine[3]== 'a') || (pCharLine[3]== 'A')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 5; + return 0; + } + else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A + return 1; + } + } + if((pCharLine[3]== 'S') || (pCharLine[3]== 's')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = false; + pCharLine += 5; + return 0; + } + else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A + return 1; + } + } + else if(pCharLine[3] == ']') { //[H:] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 4; + return 0; + } + else { //[H: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); + return 1; + } + } + else if(pCharLine[2]==']') { //[H] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 3; + return 0; + } + else { //[H + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); + return 1; + } + break; + + case 'A': + case 'a': + if(pCharLine[2]==':') { + if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 5; + return 0; + } + else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 1\n")); //[A:H + return 1; + } + } + else if(pCharLine[3]== ']') { //[A:] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 4; + return 0; + } + else { //[A: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 2\n")); + return 1; + } + } + else if(pCharLine[2]==']') { //[H] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 3; + return 0; + } + else { //[H + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 3\n")); + return 1; + } + break; + + case 'S': + case 's': + if(pCharLine[2]==':') { + if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 5; + return 0; + } + else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 5\n")); //[A:H + return 1; + } + } + else if(pCharLine[3]== ']') { //[A:] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 4; + return 0; + } + else { //[A: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 6\n")); + return 1; + } + } + else if(pCharLine[2]==']') { //[H] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = true; + pCharLine += 3; + return 0; + } + else { //[H + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 7\n")); + return 1; + } + break; + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 8\n")); + return 1; + } +} + +unsigned int uReadDataInSection(char *pCharLine, struct st_ps_data_format stPS_DataFormat) +{ + char *pTokenPtr = pCharLine; + + if(pTokenPtr[0] == '[') { + while(pTokenPtr[0] != ']' && pTokenPtr[0] != '\0') { + pTokenPtr++; + } + if(pTokenPtr[0] == '\0') { + return (0x0FFF); + } + pTokenPtr++; + + + } + if(stPS_DataFormat.eDataType == eHex) { + if(stPS_DataFormat.bIsArray == true) { + //Not implemented + return (0x0FFF); + } + else { + return (A_STRTOL(pTokenPtr, NULL, 16)); + } + } + else { + //Not implemented + return (0x0FFF); + } +} +int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat) +{ + char *Buffer; + char *pCharLine; + u8 TagCount; + u16 ByteCount; + u8 ParseSection=RAM_PS_SECTION; + u32 pos; + + + + int uReadCount; + struct st_ps_data_format stPS_DataFormat; + struct st_read_status stReadStatus = {0, 0, 0,0}; + pos = 0; + Buffer = NULL; + + if (srcbuffer == NULL || srclen == 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Could not open .\n")); + return A_ERROR; + } + TagCount = 0; + ByteCount = 0; + Buffer = A_MALLOC(LINE_SIZE_MAX + 1); + if(NULL == Buffer) { + return A_ERROR; + } + if (FileFormat == MB_FILEFORMAT_PATCH) + { + int LineRead = 0; + while((pCharLine = AthGetLine(Buffer, LINE_SIZE_MAX, srcbuffer,srclen,&pos)) != NULL) + { + + SKIP_BLANKS(pCharLine); + + // Comment line or empty line + if ((pCharLine[0] == '/') && (pCharLine[1] == '/')) + { + continue; + } + + if ((pCharLine[0] == '#')) { + if (stReadStatus.uSection != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("error\n")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + else { + stReadStatus.uSection = 1; + continue; + } + } + if ((pCharLine[0] == '/') && (pCharLine[1] == '*')) + { + pCharLine+=2; + SKIP_BLANKS(pCharLine); + + if(!strncmp(pCharLine,"PA",2)||!strncmp(pCharLine,"Pa",2)||!strncmp(pCharLine,"pa",2)) + ParseSection=RAM_PATCH_SECTION; + + if(!strncmp(pCharLine,"DY",2)||!strncmp(pCharLine,"Dy",2)||!strncmp(pCharLine,"dy",2)) + ParseSection=RAM_DYN_MEM_SECTION; + + if(!strncmp(pCharLine,"PS",2)||!strncmp(pCharLine,"Ps",2)||!strncmp(pCharLine,"ps",2)) + ParseSection=RAM_PS_SECTION; + + LineRead = 0; + stReadStatus.uSection = 0; + + continue; + } + + switch(ParseSection) + { + case RAM_PS_SECTION: + { + if (stReadStatus.uSection == 1) //TagID + { + SKIP_BLANKS(pCharLine); + if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail\n")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + //pCharLine +=5; + PsTagEntry[TagCount].TagId = uReadDataInSection(pCharLine, stPS_DataFormat); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG ID %d \n",PsTagEntry[TagCount].TagId)); + + //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag # %x\n", PsTagEntry[TagCount].TagId); + if (TagCount == 0) + { + StartTagId = PsTagEntry[TagCount].TagId; + } + stReadStatus.uSection = 2; + } + else if (stReadStatus.uSection == 2) //TagLength + { + + if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail \n")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + //pCharLine +=5; + ByteCount = uReadDataInSection(pCharLine, stPS_DataFormat); + + //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag length %x\n", ByteCount)); + if (ByteCount > LINE_SIZE_MAX/2) + { + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + PsTagEntry[TagCount].TagLen = ByteCount; + PsTagEntry[TagCount].TagData = (u8 *)A_MALLOC(ByteCount); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG Length %d Tag Index %d \n",PsTagEntry[TagCount].TagLen,TagCount)); + stReadStatus.uSection = 3; + stReadStatus.uLineCount = 0; + } + else if( stReadStatus.uSection == 3) { //Data + + if(stReadStatus.uLineCount == 0) { + if(uGetInputDataFormat(pCharLine,&stPS_DataFormat)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat Fail\n")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + //pCharLine +=5; + } + SKIP_BLANKS(pCharLine); + stReadStatus.uCharCount = 0; + if(pCharLine[stReadStatus.uCharCount] == '[') { + while(pCharLine[stReadStatus.uCharCount] != ']' && pCharLine[stReadStatus.uCharCount] != '\0' ) { + stReadStatus.uCharCount++; + } + if(pCharLine[stReadStatus.uCharCount] == ']' ) { + stReadStatus.uCharCount++; + } else { + stReadStatus.uCharCount = 0; + } + } + uReadCount = (ByteCount > BYTES_OF_PS_DATA_PER_LINE)? BYTES_OF_PS_DATA_PER_LINE: ByteCount; + //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ")); + if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == true) { + while(uReadCount > 0) { + PsTagEntry[TagCount].TagData[stReadStatus.uByteCount] = + (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount]) << 4) + | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 1])); + + PsTagEntry[TagCount].TagData[stReadStatus.uByteCount+1] = + (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 3]) << 4) + | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 4])); + + stReadStatus.uCharCount += 6; // read two bytes, plus a space; + stReadStatus.uByteCount += 2; + uReadCount -= 2; + } + if(ByteCount > BYTES_OF_PS_DATA_PER_LINE) { + ByteCount -= BYTES_OF_PS_DATA_PER_LINE; + } + else { + ByteCount = 0; + } + } + else { + //to be implemented + } + + stReadStatus.uLineCount++; + + if(ByteCount == 0) { + stReadStatus.uSection = 0; + stReadStatus.uCharCount = 0; + stReadStatus.uLineCount = 0; + stReadStatus.uByteCount = 0; + } + else { + stReadStatus.uCharCount = 0; + } + + if((stReadStatus.uSection == 0)&&(++TagCount == RAMPS_MAX_PS_TAGS_PER_FILE)) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n Buffer over flow PS File too big!!!")); + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + //Sleep (3000); + //exit(1); + } + + } + } + + break; + default: + { + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + break; + } + LineRead++; + } + Tag_Count = TagCount; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Number of Tags %d\n", Tag_Count)); + } + + + if (TagCount > RAMPS_MAX_PS_TAGS_PER_FILE) + { + + if(Buffer != NULL) { + kfree(Buffer); + } + return A_ERROR; + } + + if(Buffer != NULL) { + kfree(Buffer); + } + return 0; + +} + + + +/********************/ + + +int GetNextTwoChar(u8 *srcbuffer,u32 len, u32 *pos, char *buffer) +{ + unsigned char ch; + + ch = AthReadChar(srcbuffer,len,pos); + if(ch != '\0' && isxdigit(ch)) { + buffer[0] = ch; + } else + { + return A_ERROR; + } + ch = AthReadChar(srcbuffer,len,pos); + if(ch != '\0' && isxdigit(ch)) { + buffer[1] = ch; + } else + { + return A_ERROR; + } + return 0; +} + +int AthDoParsePatch(u8 *patchbuffer, u32 patchlen) +{ + + char Byte[3]; + char Line[MAX_BYTE_LENGTH + 1]; + int ByteCount,ByteCount_Org; + int count; + int i,j,k; + int data; + u32 filepos; + Byte[2] = '\0'; + j = 0; + filepos = 0; + Patch_Count = 0; + + while(NULL != AthGetLine(Line,MAX_BYTE_LENGTH,patchbuffer,patchlen,&filepos)) { + if(strlen(Line) <= 1 || !isxdigit(Line[0])) { + continue; + } else { + break; + } + } + ByteCount = A_STRTOL(Line, NULL, 16); + ByteCount_Org = ByteCount; + + while(ByteCount > MAX_BYTE_LENGTH){ + + /* Handle case when the number of patch buffer is more than the 20K */ + if(MAX_NUM_PATCH_ENTRY == Patch_Count) { + for(i = 0; i < Patch_Count; i++) { + kfree(RamPatch[i].Data); + } + return A_ERROR; + } + RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH; + RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(MAX_BYTE_LENGTH); + Patch_Count ++; + + + ByteCount= ByteCount - MAX_BYTE_LENGTH; + } + + RamPatch[Patch_Count].Len= (ByteCount & 0xFF); + if(ByteCount != 0) { + RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(ByteCount); + Patch_Count ++; + } + count = 0; + while(ByteCount_Org > MAX_BYTE_LENGTH){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j)); + for (i = 0,k=0; i < MAX_BYTE_LENGTH*2; i += 2,k++,count +=2) { + if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) { + return A_ERROR; + } + data = A_STRTOUL(&Byte[0], NULL, 16); + RamPatch[j].Data[k] = (data & 0xFF); + + + } + j++; + ByteCount_Org = ByteCount_Org - MAX_BYTE_LENGTH; + } + if(j == 0){ + j++; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j)); + for (k=0; k < ByteCount_Org; i += 2,k++,count+=2) { + if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) { + return A_ERROR; + } + data = A_STRTOUL(Byte, NULL, 16); + RamPatch[j].Data[k] = (data & 0xFF); + + + } + return 0; +} + + +/********************/ +int AthDoParsePS(u8 *srcbuffer, u32 srclen) +{ + int status; + int i; + bool BDADDR_Present = false; + + Tag_Count = 0; + + Total_tag_lenght = 0; + BDADDR = false; + + + status = A_ERROR; + + if(NULL != srcbuffer && srclen != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("File Open Operation Successful\n")); + + status = AthParseFilesUnified(srcbuffer,srclen,MB_FILEFORMAT_PATCH); + } + + + + if(Tag_Count == 0){ + Total_tag_lenght = 10; + + } + else{ + for(i=0; i 0 && !BDADDR_Present){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is not present adding 10 extra bytes \r\n")); + Total_tag_lenght=Total_tag_lenght + 10; + } + Total_tag_lenght = Total_tag_lenght+ 10 + (Tag_Count*4); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Total Length %d\n",Total_tag_lenght)); + + + return status; +} +char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos) +{ + + int count; + static short flag; + char CharRead; + count = 0; + flag = A_ERROR; + + do + { + CharRead = AthReadChar(srcbuffer,len,pos); + if( CharRead == '\0' ) { + buffer[count+1] = '\0'; + if(count == 0) { + return NULL; + } + else { + return buffer; + } + } + + if(CharRead == 13) { + } else if(CharRead == 10) { + buffer[count] ='\0'; + flag = A_ERROR; + return buffer; + }else { + buffer[count++] = CharRead; + } + + } + while(count < maxlen-1 && CharRead != '\0'); + buffer[count] = '\0'; + + return buffer; +} + +static void LoadHeader(u8 *HCI_PS_Command,u8 opcode,int length,int index){ + + HCI_PS_Command[0]= 0x0B; + HCI_PS_Command[1]= 0xFC; + HCI_PS_Command[2]= length + 4; + HCI_PS_Command[3]= opcode; + HCI_PS_Command[4]= (index & 0xFF); + HCI_PS_Command[5]= ((index>>8) & 0xFF); + HCI_PS_Command[6]= length; +} + +///////////////////////// +// +int AthCreateCommandList(struct ps_cmd_packet **HciPacketList, u32 *numPackets) +{ + + u8 count; + u32 NumcmdEntry = 0; + + u32 Crc = 0; + *numPackets = 0; + + + if(Patch_Count > 0) + Crc |= RAM_PATCH_REGION; + if(Tag_Count > 0) + Crc |= RAM_PS_REGION; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("PS Thread Started CRC %x Patch Count %d Tag Count %d \n",Crc,Patch_Count,Tag_Count)); + + if(Patch_Count || Tag_Count ){ + NumcmdEntry+=(2 + Patch_Count + Tag_Count); /* CRC Packet + PS Reset Packet + Patch List + PS List*/ + if(Patch_Count > 0) { + NumcmdEntry++; /* Patch Enable Command */ + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size %d \r\n",NumcmdEntry,(u32)sizeof(struct ps_cmd_packet) * NumcmdEntry)); + (*HciPacketList) = A_MALLOC(sizeof(struct ps_cmd_packet) * NumcmdEntry); + if(NULL == *HciPacketList) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("memory allocation failed \r\n")); + } + AthPSCreateHCICommand(PS_VERIFY_CRC,Crc,*HciPacketList,numPackets); + if(Patch_Count > 0){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Write Patch**** \r\n")); + AthPSCreateHCICommand(WRITE_PATCH,Patch_Count,*HciPacketList,numPackets); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Enable Patch**** \r\n")); + AthPSCreateHCICommand(ENABLE_PATCH,0,*HciPacketList,numPackets); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Reset**** %d[0x%x] \r\n",PS_RAM_SIZE,PS_RAM_SIZE)); + AthPSCreateHCICommand(PS_RESET,PS_RAM_SIZE,*HciPacketList,numPackets); + if(Tag_Count > 0){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Write**** \r\n")); + AthPSCreateHCICommand(PS_WRITE,Tag_Count,*HciPacketList,numPackets); + } + } + if(!BDADDR){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR not present \r\n")); + + } + for(count = 0; count < Patch_Count; count++) { + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing Patch Buffer %d \r\n",count)); + kfree(RamPatch[count].Data); + } + + for(count = 0; count < Tag_Count; count++) { + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing PS Buffer %d \r\n",count)); + kfree(PsTagEntry[count].TagData); + } + +/* + * SDIO Transport uses synchronous mode of data transfer + * So, AthPSOperations() call returns only after receiving the + * command complete event. + */ + return *numPackets; +} + + +//////////////////////// + +///////////// +static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index) +{ + u8 *HCI_PS_Command; + u32 Length; + int i,j; + + switch(Opcode) + { + case WRITE_PATCH: + + + for(i=0;i< Param1;i++){ + + HCI_PS_Command = (u8 *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Allocated Buffer Size %d\n",RamPatch[i].Len+HCI_COMMAND_HEADER)); + if(HCI_PS_Command == NULL){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n")); + return A_ERROR; + } + memset (HCI_PS_Command, 0, RamPatch[i].Len+HCI_COMMAND_HEADER); + LoadHeader(HCI_PS_Command,Opcode,RamPatch[i].Len,i); + for(j=0;j> 8) & 0xFF); + PSPatchPacket[*index].Hcipacket = HCI_PS_Command; + PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER; + (*index)++; + + break; + + case PS_WRITE: + for(i=0;i< Param1;i++){ + if(PsTagEntry[i].TagId ==1) + BDADDR = true; + + HCI_PS_Command = (u8 *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER); + if(HCI_PS_Command == NULL){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n")); + return A_ERROR; + } + + memset (HCI_PS_Command, 0, PsTagEntry[i].TagLen+HCI_COMMAND_HEADER); + LoadHeader(HCI_PS_Command,Opcode,PsTagEntry[i].TagLen,PsTagEntry[i].TagId); + + for(j=0;j +#include +#include "athdefs.h" +#ifdef HCI_TRANSPORT_SDIO +#include "a_config.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME misc +#include "a_debug.h" +#include "common_drv.h" +#include "hci_transport_api.h" +#include "ar3kconfig.h" +#else +#ifndef A_PRINTF +#define A_PRINTF(args...) printk(KERN_ALERT args) +#endif /* A_PRINTF */ +#include "debug_linux.h" + +/* Helper data type declaration */ + +#define ATH_DEBUG_ERR (1 << 0) +#define ATH_DEBUG_WARN (1 << 1) +#define ATH_DEBUG_INFO (1 << 2) + + + +#define false 0 +#define true 1 + +#ifndef A_MALLOC +#define A_MALLOC(size) kmalloc((size),GFP_KERNEL) +#endif /* A_MALLOC */ +#endif /* HCI_TRANSPORT_UART */ + +/* String manipulation APIs */ +#ifndef A_STRTOUL +#define A_STRTOUL simple_strtoul +#endif /* A_STRTOL */ + +#ifndef A_STRTOL +#define A_STRTOL simple_strtol +#endif /* A_STRTOL */ + + +/* The maximum number of bytes possible in a patch entry */ +#define MAX_PATCH_SIZE 20000 + +/* Maximum HCI packets that will be formed from the Patch file */ +#define MAX_NUM_PATCH_ENTRY (MAX_PATCH_SIZE/MAX_BYTE_LENGTH) + 1 + + + + + + + +struct ps_cmd_packet +{ + u8 *Hcipacket; + int packetLen; +}; + +/* Parses a Patch information buffer and store it in global structure */ +int AthDoParsePatch(u8 *, u32 ); + +/* parses a PS information buffer and stores it in a global structure */ +int AthDoParsePS(u8 *, u32 ); + +/* + * Uses the output of Both AthDoParsePS and AthDoParsePatch APIs to form HCI command array with + * all the PS and patch commands. + * The list will have the below mentioned commands in order. + * CRC command packet + * Download patch command(s) + * Enable patch Command + * PS Reset Command + * PS Tag Command(s) + * + */ +int AthCreateCommandList(struct ps_cmd_packet **, u32 *); + +/* Cleanup the dynamically allicated HCI command list */ +int AthFreeCommandList(struct ps_cmd_packet **HciPacketList, u32 numPackets); +#endif /* __AR3KPSPARSER_H */ diff --git a/trunk/drivers/staging/ath6kl/miscdrv/common_drv.c b/trunk/drivers/staging/ath6kl/miscdrv/common_drv.c new file mode 100644 index 000000000000..1ce539aa019b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/common_drv.c @@ -0,0 +1,910 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" + +#include "hw/mbox_host_reg.h" +#include "gpio_reg.h" +#include "hw/rtc_reg.h" +#include "hw/mbox_reg.h" +#include "hw/apb_map.h" + +#include "a_osapi.h" +#include "targaddrs.h" +#include "hif.h" +#include "htc_api.h" +#include "wmi.h" +#include "bmi.h" +#include "bmi_msg.h" +#include "common_drv.h" +#define ATH_MODULE_NAME misc +#include "a_debug.h" +#include "ar6000_diag.h" + +static ATH_DEBUG_MODULE_DBG_INFO *g_pModuleInfoHead = NULL; +static A_MUTEX_T g_ModuleListLock; +static bool g_ModuleDebugInit = false; + +#ifdef ATH_DEBUG_MODULE + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(misc, + "misc", + "Common and misc APIs", + ATH_DEBUG_MASK_DEFAULTS, + 0, + NULL); + +#endif + +#define HOST_INTEREST_ITEM_ADDRESS(target, item) \ + ((((target) == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((target) == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0))) + + +#define AR6001_LOCAL_COUNT_ADDRESS 0x0c014080 +#define AR6002_LOCAL_COUNT_ADDRESS 0x00018080 +#define AR6003_LOCAL_COUNT_ADDRESS 0x00018080 +#define CPU_DBG_SEL_ADDRESS 0x00000483 +#define CPU_DBG_ADDRESS 0x00000484 + +static u8 custDataAR6002[AR6002_CUST_DATA_SIZE]; +static u8 custDataAR6003[AR6003_CUST_DATA_SIZE]; + +/* Compile the 4BYTE version of the window register setup routine, + * This mitigates host interconnect issues with non-4byte aligned bus requests, some + * interconnects use bus adapters that impose strict limitations. + * Since diag window access is not intended for performance critical operations, the 4byte mode should + * be satisfactory even though it generates 4X the bus activity. */ + +#ifdef USE_4BYTE_REGISTER_ACCESS + + /* set the window address register (using 4-byte register access ). */ +int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address) +{ + int status; + u8 addrValue[4]; + s32 i; + + /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written + * last to initiate the access cycle */ + + for (i = 1; i <= 3; i++) { + /* fill the buffer with the address byte value we want to hit 4 times*/ + addrValue[0] = ((u8 *)&Address)[i]; + addrValue[1] = addrValue[0]; + addrValue[2] = addrValue[0]; + addrValue[3] = addrValue[0]; + + /* hit each byte of the register address with a 4-byte write operation to the same address, + * this is a harmless operation */ + status = HIFReadWrite(hifDevice, + RegisterAddr+i, + addrValue, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + if (status) { + break; + } + } + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n", + Address, RegisterAddr)); + return status; + } + + /* write the address register again, this time write the whole 4-byte value. + * The effect here is that the LSB write causes the cycle to start, the extra + * 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */ + status = HIFReadWrite(hifDevice, + RegisterAddr, + (u8 *)(&Address), + 4, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n", + Address, RegisterAddr)); + return status; + } + + return 0; + + + +} + + +#else + + /* set the window address register */ +int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address) +{ + int status; + + /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written + * last to initiate the access cycle */ + status = HIFReadWrite(hifDevice, + RegisterAddr+1, /* write upper 3 bytes */ + ((u8 *)(&Address))+1, + sizeof(u32)-1, + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n", + RegisterAddr, Address)); + return status; + } + + /* write the LSB of the register, this initiates the operation */ + status = HIFReadWrite(hifDevice, + RegisterAddr, + (u8 *)(&Address), + sizeof(u8), + HIF_WR_SYNC_BYTE_INC, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n", + RegisterAddr, Address)); + return status; + } + + return 0; +} + +#endif + +/* + * Read from the AR6000 through its diagnostic window. + * No cooperation from the Target is required for this. + */ +int +ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data) +{ + int status; + + /* set window register to start read cycle */ + status = ar6000_SetAddressWindowRegister(hifDevice, + WINDOW_READ_ADDR_ADDRESS, + *address); + + if (status) { + return status; + } + + /* read the data */ + status = HIFReadWrite(hifDevice, + WINDOW_DATA_ADDRESS, + (u8 *)data, + sizeof(u32), + HIF_RD_SYNC_BYTE_INC, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n")); + return status; + } + + return status; +} + + +/* + * Write to the AR6000 through its diagnostic window. + * No cooperation from the Target is required for this. + */ +int +ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data) +{ + int status; + + /* set write data */ + status = HIFReadWrite(hifDevice, + WINDOW_DATA_ADDRESS, + (u8 *)data, + sizeof(u32), + HIF_WR_SYNC_BYTE_INC, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data)); + return status; + } + + /* set window register, which starts the write cycle */ + return ar6000_SetAddressWindowRegister(hifDevice, + WINDOW_WRITE_ADDR_ADDRESS, + *address); + } + +int +ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address, + u8 *data, u32 length) +{ + u32 count; + int status = 0; + + for (count = 0; count < length; count += 4, address += 4) { + if ((status = ar6000_ReadRegDiag(hifDevice, &address, + (u32 *)&data[count])) != 0) + { + break; + } + } + + return status; +} + +int +ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address, + u8 *data, u32 length) +{ + u32 count; + int status = 0; + + for (count = 0; count < length; count += 4, address += 4) { + if ((status = ar6000_WriteRegDiag(hifDevice, &address, + (u32 *)&data[count])) != 0) + { + break; + } + } + + return status; +} + +int +ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval) +{ + int status; + u8 vals[4]; + u8 register_selection[4]; + + register_selection[0] = register_selection[1] = register_selection[2] = register_selection[3] = (regsel & 0xff); + status = HIFReadWrite(hifDevice, + CPU_DBG_SEL_ADDRESS, + register_selection, + 4, + HIF_WR_SYNC_BYTE_FIX, + NULL); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write CPU_DBG_SEL (%d)\n", regsel)); + return status; + } + + status = HIFReadWrite(hifDevice, + CPU_DBG_ADDRESS, + (u8 *)vals, + sizeof(vals), + HIF_RD_SYNC_BYTE_INC, + NULL); + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from CPU_DBG_ADDRESS\n")); + return status; + } + + *regval = vals[0]<<0 | vals[1]<<8 | vals[2]<<16 | vals[3]<<24; + + return status; +} + +void +ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs) +{ + int i; + u32 val; + + for (i=0; i REGISTER_DUMP_LEN_MAX +#error "REG_DUMP_COUNT_AR6001 too large" +#endif +#if REG_DUMP_COUNT_AR6002 > REGISTER_DUMP_LEN_MAX +#error "REG_DUMP_COUNT_AR6002 too large" +#endif +#if REG_DUMP_COUNT_AR6003 > REGISTER_DUMP_LEN_MAX +#error "REG_DUMP_COUNT_AR6003 too large" +#endif + + +void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType) +{ + u32 address; + u32 regDumpArea = 0; + int status; + u32 regDumpValues[REGISTER_DUMP_LEN_MAX]; + u32 regDumpCount = 0; + u32 i; + + do { + + /* the reg dump pointer is copied to the host interest area */ + address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state); + address = TARG_VTOP(TargetType, address); + + if (TargetType == TARGET_TYPE_AR6002) { + regDumpCount = REG_DUMP_COUNT_AR6002; + } else if (TargetType == TARGET_TYPE_AR6003) { + regDumpCount = REG_DUMP_COUNT_AR6003; + } else { + A_ASSERT(0); + } + + /* read RAM location through diagnostic window */ + status = ar6000_ReadRegDiag(hifDevice, &address, ®DumpArea); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea)); + + if (regDumpArea == 0) { + /* no reg dump */ + break; + } + + regDumpArea = TARG_VTOP(TargetType, regDumpArea); + + /* fetch register dump data */ + status = ar6000_ReadDataDiag(hifDevice, + regDumpArea, + (u8 *)®DumpValues[0], + regDumpCount * (sizeof(u32))); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n")); + break; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n")); + + for (i = 0; i < regDumpCount; i++) { + //ATHR_DISPLAY_MSG (_T(" %d : 0x%8.8X \n"), i, regDumpValues[i]); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[i])); + +#ifdef UNDER_CE + /* + * For Every logPrintf() Open the File so that in case of Crashes + * We will have until the Last Message Flushed on to the File + * So use logPrintf Sparingly..!! + */ + tgtassertPrintf (ATH_DEBUG_TRC," %d: 0x%8.8X \n",i, regDumpValues[i]); +#endif + } + + } while (false); + +} + +/* set HTC/Mbox operational parameters, this can only be called when the target is in the + * BMI phase */ +int ar6000_set_htc_params(struct hif_device *hifDevice, + u32 TargetType, + u32 MboxIsrYieldValue, + u8 HtcControlBuffers) +{ + int status; + u32 blocksizes[HTC_MAILBOX_NUM_MAX]; + + do { + /* get the block sizes */ + status = HIFConfigureDevice(hifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + blocksizes, sizeof(blocksizes)); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR,("Failed to get block size info from HIF layer...\n")); + break; + } + /* note: we actually get the block size for mailbox 1, for SDIO the block + * size on mailbox 0 is artificially set to 1 */ + /* must be a power of 2 */ + A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0); + + if (HtcControlBuffers != 0) { + /* set override for number of control buffers to use */ + blocksizes[1] |= ((u32)HtcControlBuffers) << 16; + } + + /* set the host interest area for the block size */ + status = BMIWriteMemory(hifDevice, + HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz), + (u8 *)&blocksizes[1], + 4); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for IO block size failed \n")); + break; + } + + AR_DEBUG_PRINTF(ATH_LOG_INF,("Block Size Set: %d (target address:0x%X)\n", + blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz))); + + if (MboxIsrYieldValue != 0) { + /* set the host interest area for the mbox ISR yield limit */ + status = BMIWriteMemory(hifDevice, + HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_isr_yield_limit), + (u8 *)&MboxIsrYieldValue, + 4); + + if (status) { + AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for yield limit failed \n")); + break; + } + } + + } while (false); + + return status; +} + +void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription) +{ + char stream[60]; + char byteOffsetStr[10]; + u32 i; + u16 offset, count, byteOffset; + + A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length, pDescription); + + count = 0; + offset = 0; + byteOffset = 0; + for(i = 0; i < length; i++) { + A_SPRINTF(stream + offset, "%2.2X ", buffer[i]); + count ++; + offset += 3; + + if(count == 16) { + count = 0; + offset = 0; + A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset); + A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); + A_MEMZERO(stream, 60); + byteOffset += 16; + } + } + + if(offset != 0) { + A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset); + A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); + } + + A_PRINTF("<------------------------------------------------->\n"); +} + +void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo) +{ + int i; + struct ath_debug_mask_description *pDesc; + + if (pInfo == NULL) { + return; + } + + pDesc = pInfo->pMaskDescriptions; + + A_PRINTF("========================================================\n\n"); + A_PRINTF("Module Debug Info => Name : %s \n", pInfo->ModuleName); + A_PRINTF(" => Descr. : %s \n", pInfo->ModuleDescription); + A_PRINTF("\n Current mask => 0x%8.8X \n", pInfo->CurrentMask); + A_PRINTF("\n Avail. Debug Masks :\n\n"); + + for (i = 0; i < pInfo->MaxDescriptions; i++,pDesc++) { + A_PRINTF(" => 0x%8.8X -- %s \n", pDesc->Mask, pDesc->Description); + } + + if (0 == i) { + A_PRINTF(" => * none defined * \n"); + } + + A_PRINTF("\n Standard Debug Masks :\n\n"); + /* print standard masks */ + A_PRINTF(" => 0x%8.8X -- Errors \n", ATH_DEBUG_ERR); + A_PRINTF(" => 0x%8.8X -- Warnings \n", ATH_DEBUG_WARN); + A_PRINTF(" => 0x%8.8X -- Informational \n", ATH_DEBUG_INFO); + A_PRINTF(" => 0x%8.8X -- Tracing \n", ATH_DEBUG_TRC); + A_PRINTF("\n========================================================\n"); + +} + + +static ATH_DEBUG_MODULE_DBG_INFO *FindModule(char *module_name) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; + + if (!g_ModuleDebugInit) { + return NULL; + } + + while (pInfo != NULL) { + /* TODO: need to use something other than strlen */ + if (memcmp(pInfo->ModuleName,module_name,strlen(module_name)) == 0) { + break; + } + pInfo = pInfo->pNext; + } + + return pInfo; +} + + +void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo) +{ + if (!g_ModuleDebugInit) { + return; + } + + A_MUTEX_LOCK(&g_ModuleListLock); + + if (!(pInfo->Flags & ATH_DEBUG_INFO_FLAGS_REGISTERED)) { + if (g_pModuleInfoHead == NULL) { + g_pModuleInfoHead = pInfo; + } else { + pInfo->pNext = g_pModuleInfoHead; + g_pModuleInfoHead = pInfo; + } + pInfo->Flags |= ATH_DEBUG_INFO_FLAGS_REGISTERED; + } + + A_MUTEX_UNLOCK(&g_ModuleListLock); +} + +void a_dump_module_debug_info_by_name(char *module_name) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; + + if (!g_ModuleDebugInit) { + return; + } + + if (memcmp(module_name,"all",3) == 0) { + /* dump all */ + while (pInfo != NULL) { + a_dump_module_debug_info(pInfo); + pInfo = pInfo->pNext; + } + return; + } + + pInfo = FindModule(module_name); + + if (pInfo != NULL) { + a_dump_module_debug_info(pInfo); + } + +} + +int a_get_module_mask(char *module_name, u32 *pMask) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name); + + if (NULL == pInfo) { + return A_ERROR; + } + + *pMask = pInfo->CurrentMask; + return 0; +} + +int a_set_module_mask(char *module_name, u32 Mask) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name); + + if (NULL == pInfo) { + return A_ERROR; + } + + pInfo->CurrentMask = Mask; + A_PRINTF("Module %s, new mask: 0x%8.8X \n",module_name,pInfo->CurrentMask); + return 0; +} + + +void a_module_debug_support_init(void) +{ + if (g_ModuleDebugInit) { + return; + } + A_MUTEX_INIT(&g_ModuleListLock); + g_pModuleInfoHead = NULL; + g_ModuleDebugInit = true; + A_REGISTER_MODULE_DEBUG_INFO(misc); +} + +void a_module_debug_support_cleanup(void) +{ + ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; + ATH_DEBUG_MODULE_DBG_INFO *pCur; + + if (!g_ModuleDebugInit) { + return; + } + + g_ModuleDebugInit = false; + + A_MUTEX_LOCK(&g_ModuleListLock); + + while (pInfo != NULL) { + pCur = pInfo; + pInfo = pInfo->pNext; + pCur->pNext = NULL; + /* clear registered flag */ + pCur->Flags &= ~ATH_DEBUG_INFO_FLAGS_REGISTERED; + } + + A_MUTEX_UNLOCK(&g_ModuleListLock); + + A_MUTEX_DELETE(&g_ModuleListLock); + g_pModuleInfoHead = NULL; +} + + /* can only be called during bmi init stage */ +int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice, + u32 TargetType, + u32 Flags) +{ + int status = 0; + + do { + + if (TargetType != TARGET_TYPE_AR6003) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Target Type:%d, does not support HCI bridging! \n", + TargetType)); + break; + } + + /* set hci bridge flags */ + status = BMIWriteMemory(hifDevice, + HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_hci_bridge_flags), + (u8 *)&Flags, + 4); + + + } while (false); + + return status; +} + diff --git a/trunk/drivers/staging/ath6kl/miscdrv/credit_dist.c b/trunk/drivers/staging/ath6kl/miscdrv/credit_dist.c new file mode 100644 index 000000000000..c777e98a756e --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/credit_dist.c @@ -0,0 +1,417 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#define ATH_MODULE_NAME misc +#include "a_debug.h" +#include "htc_api.h" +#include "common_drv.h" + +/********* CREDIT DISTRIBUTION FUNCTIONS ******************************************/ + +#define NO_VO_SERVICE 1 /* currently WMI only uses 3 data streams, so we leave VO service inactive */ +#define CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS 1 + +#ifdef NO_VO_SERVICE +#define DATA_SVCS_USED 3 +#else +#define DATA_SVCS_USED 4 +#endif + +static void RedistributeCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEPDistList); + +static void SeekCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEPDistList); + +/* reduce an ep's credits back to a set limit */ +static INLINE void ReduceCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEpDist, + int Limit) +{ + int credits; + + /* set the new limit */ + pEpDist->TxCreditsAssigned = Limit; + + if (pEpDist->TxCredits <= Limit) { + return; + } + + /* figure out how much to take away */ + credits = pEpDist->TxCredits - Limit; + /* take them away */ + pEpDist->TxCredits -= credits; + pCredInfo->CurrentFreeCredits += credits; +} + +/* give an endpoint some credits from the free credit pool */ +#define GiveCredits(pCredInfo,pEpDist,credits) \ +{ \ + (pEpDist)->TxCredits += (credits); \ + (pEpDist)->TxCreditsAssigned += (credits); \ + (pCredInfo)->CurrentFreeCredits -= (credits); \ +} + + +/* default credit init callback. + * This function is called in the context of HTCStart() to setup initial (application-specific) + * credit distributions */ +static void ar6000_credit_init(void *Context, + struct htc_endpoint_credit_dist *pEPList, + int TotalCredits) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + int count; + struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context; + + pCredInfo->CurrentFreeCredits = TotalCredits; + pCredInfo->TotalAvailableCredits = TotalCredits; + + pCurEpDist = pEPList; + + /* run through the list and initialize */ + while (pCurEpDist != NULL) { + + /* set minimums for each endpoint */ + pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg; + +#ifdef CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS + + if (TotalCredits > 4) + { + if ((pCurEpDist->ServiceID == WMI_DATA_BK_SVC) || (pCurEpDist->ServiceID == WMI_DATA_BE_SVC)){ + /* assign at least min credits to lower than VO priority services */ + GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin); + /* force active */ + SET_EP_ACTIVE(pCurEpDist); + } + } + +#endif + + if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) { + /* give control service some credits */ + GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin); + /* control service is always marked active, it never goes inactive EVER */ + SET_EP_ACTIVE(pCurEpDist); + } else if (pCurEpDist->ServiceID == WMI_DATA_BK_SVC) { + /* this is the lowest priority data endpoint, save this off for easy access */ + pCredInfo->pLowestPriEpDist = pCurEpDist; + } + + /* Streams have to be created (explicit | implicit)for all kinds + * of traffic. BE endpoints are also inactive in the beginning. + * When BE traffic starts it creates implicit streams that + * redistributes credits. + */ + + /* note, all other endpoints have minimums set but are initially given NO credits. + * Credits will be distributed as traffic activity demands */ + pCurEpDist = pCurEpDist->pNext; + } + + if (pCredInfo->CurrentFreeCredits <= 0) { + AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit distributions \n", TotalCredits)); + A_ASSERT(false); + return; + } + + /* reset list */ + pCurEpDist = pEPList; + /* now run through the list and set max operating credit limits for everyone */ + while (pCurEpDist != NULL) { + if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) { + /* control service max is just 1 max message */ + pCurEpDist->TxCreditsNorm = pCurEpDist->TxCreditsPerMaxMsg; + } else { + /* for the remaining data endpoints, we assume that each TxCreditsPerMaxMsg are + * the same. + * We use a simple calculation here, we take the remaining credits and + * determine how many max messages this can cover and then set each endpoint's + * normal value equal to 3/4 this amount. + * */ + count = (pCredInfo->CurrentFreeCredits/pCurEpDist->TxCreditsPerMaxMsg) * pCurEpDist->TxCreditsPerMaxMsg; + count = (count * 3) >> 2; + count = max(count,pCurEpDist->TxCreditsPerMaxMsg); + /* set normal */ + pCurEpDist->TxCreditsNorm = count; + + } + pCurEpDist = pCurEpDist->pNext; + } + +} + + +/* default credit distribution callback + * This callback is invoked whenever endpoints require credit distributions. + * A lock is held while this function is invoked, this function shall NOT block. + * The pEPDistList is a list of distribution structures in prioritized order as + * defined by the call to the HTCSetCreditDistribution() api. + * + */ +static void ar6000_credit_distribute(void *Context, + struct htc_endpoint_credit_dist *pEPDistList, + HTC_CREDIT_DIST_REASON Reason) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context; + + switch (Reason) { + case HTC_CREDIT_DIST_SEND_COMPLETE : + pCurEpDist = pEPDistList; + /* we are given the start of the endpoint distribution list. + * There may be one or more endpoints to service. + * Run through the list and distribute credits */ + while (pCurEpDist != NULL) { + + if (pCurEpDist->TxCreditsToDist > 0) { + /* return the credits back to the endpoint */ + pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist; + /* always zero out when we are done */ + pCurEpDist->TxCreditsToDist = 0; + + if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsAssigned) { + /* reduce to the assigned limit, previous credit reductions + * could have caused the limit to change */ + ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsAssigned); + } + + if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsNorm) { + /* oversubscribed endpoints need to reduce back to normal */ + ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsNorm); + } + + if (!IS_EP_ACTIVE(pCurEpDist)) { + /* endpoint is inactive, now check for messages waiting for credits */ + if (pCurEpDist->TxQueueDepth == 0) { + /* EP is inactive and there are no pending messages, + * reduce credits back to zero to recover credits */ + ReduceCredits(pCredInfo, pCurEpDist, 0); + } + } + } + + pCurEpDist = pCurEpDist->pNext; + } + + break; + + case HTC_CREDIT_DIST_ACTIVITY_CHANGE : + RedistributeCredits(pCredInfo,pEPDistList); + break; + case HTC_CREDIT_DIST_SEEK_CREDITS : + SeekCredits(pCredInfo,pEPDistList); + break; + case HTC_DUMP_CREDIT_STATE : + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Credit Distribution, total : %d, free : %d\n", + pCredInfo->TotalAvailableCredits, pCredInfo->CurrentFreeCredits)); + break; + default: + break; + + } + + /* sanity checks done after each distribution action */ + A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits); + A_ASSERT(pCredInfo->CurrentFreeCredits >= 0); + +} + +/* redistribute credits based on activity change */ +static void RedistributeCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEPDistList) +{ + struct htc_endpoint_credit_dist *pCurEpDist = pEPDistList; + + /* walk through the list and remove credits from inactive endpoints */ + while (pCurEpDist != NULL) { + +#ifdef CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS + + if ((pCurEpDist->ServiceID == WMI_DATA_BK_SVC) || (pCurEpDist->ServiceID == WMI_DATA_BE_SVC)) { + /* force low priority streams to always be active to retain their minimum credit distribution */ + SET_EP_ACTIVE(pCurEpDist); + } +#endif + + if (pCurEpDist->ServiceID != WMI_CONTROL_SVC) { + if (!IS_EP_ACTIVE(pCurEpDist)) { + if (pCurEpDist->TxQueueDepth == 0) { + /* EP is inactive and there are no pending messages, reduce credits back to zero */ + ReduceCredits(pCredInfo, pCurEpDist, 0); + } else { + /* we cannot zero the credits assigned to this EP, but to keep + * the credits available for these leftover packets, reduce to + * a minimum */ + ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsMin); + } + } + } + + /* NOTE in the active case, we do not need to do anything further, + * when an EP goes active and needs credits, HTC will call into + * our distribution function using a reason code of HTC_CREDIT_DIST_SEEK_CREDITS */ + + pCurEpDist = pCurEpDist->pNext; + } + +} + +/* HTC has an endpoint that needs credits, pEPDist is the endpoint in question */ +static void SeekCredits(struct common_credit_state_info *pCredInfo, + struct htc_endpoint_credit_dist *pEPDist) +{ + struct htc_endpoint_credit_dist *pCurEpDist; + int credits = 0; + int need; + + do { + + if (pEPDist->ServiceID == WMI_CONTROL_SVC) { + /* we never oversubscribe on the control service, this is not + * a high performance path and the target never holds onto control + * credits for too long */ + break; + } + +#ifdef CONFIG_GIVE_LOW_PRIORITY_STREAMS_MIN_CREDITS + if (pEPDist->ServiceID == WMI_DATA_VI_SVC) { + if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm)) { + /* limit VI service from oversubscribing */ + break; + } + } + + if (pEPDist->ServiceID == WMI_DATA_VO_SVC) { + if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm)) { + /* limit VO service from oversubscribing */ + break; + } + } +#else + if (pEPDist->ServiceID == WMI_DATA_VI_SVC) { + if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm) || + (pCredInfo->CurrentFreeCredits <= pEPDist->TxCreditsPerMaxMsg)) { + /* limit VI service from oversubscribing */ + /* at least one free credit will not be used by VI */ + break; + } + } + + if (pEPDist->ServiceID == WMI_DATA_VO_SVC) { + if ((pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm) || + (pCredInfo->CurrentFreeCredits <= pEPDist->TxCreditsPerMaxMsg)) { + /* limit VO service from oversubscribing */ + /* at least one free credit will not be used by VO */ + break; + } + } +#endif + + /* for all other services, we follow a simple algorithm of + * 1. checking the free pool for credits + * 2. checking lower priority endpoints for credits to take */ + + /* give what we can */ + credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek); + + if (credits >= pEPDist->TxCreditsSeek) { + /* we found some to fulfill the seek request */ + break; + } + + /* we don't have enough in the free pool, try taking away from lower priority services + * + * The rule for taking away credits: + * 1. Only take from lower priority endpoints + * 2. Only take what is allocated above the minimum (never starve an endpoint completely) + * 3. Only take what you need. + * + * */ + + /* starting at the lowest priority */ + pCurEpDist = pCredInfo->pLowestPriEpDist; + + /* work backwards until we hit the endpoint again */ + while (pCurEpDist != pEPDist) { + /* calculate how many we need so far */ + need = pEPDist->TxCreditsSeek - pCredInfo->CurrentFreeCredits; + + if ((pCurEpDist->TxCreditsAssigned - need) >= pCurEpDist->TxCreditsMin) { + /* the current one has been allocated more than it's minimum and it + * has enough credits assigned above it's minimum to fulfill our need + * try to take away just enough to fulfill our need */ + ReduceCredits(pCredInfo, + pCurEpDist, + pCurEpDist->TxCreditsAssigned - need); + + if (pCredInfo->CurrentFreeCredits >= pEPDist->TxCreditsSeek) { + /* we have enough */ + break; + } + } + + pCurEpDist = pCurEpDist->pPrev; + } + + /* return what we can get */ + credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek); + + } while (false); + + /* did we find some credits? */ + if (credits) { + /* give what we can */ + GiveCredits(pCredInfo, pEPDist, credits); + } + +} + +/* initialize and setup credit distribution */ +int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo) +{ + HTC_SERVICE_ID servicepriority[5]; + + A_MEMZERO(pCredInfo,sizeof(struct common_credit_state_info)); + + servicepriority[0] = WMI_CONTROL_SVC; /* highest */ + servicepriority[1] = WMI_DATA_VO_SVC; + servicepriority[2] = WMI_DATA_VI_SVC; + servicepriority[3] = WMI_DATA_BE_SVC; + servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */ + + /* set callbacks and priority list */ + HTCSetCreditDistribution(HTCHandle, + pCredInfo, + ar6000_credit_distribute, + ar6000_credit_init, + servicepriority, + 5); + + return 0; +} + diff --git a/trunk/drivers/staging/ath6kl/miscdrv/miscdrv.h b/trunk/drivers/staging/ath6kl/miscdrv/miscdrv.h new file mode 100644 index 000000000000..41be5670db42 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/miscdrv/miscdrv.h @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _MISCDRV_H +#define _MISCDRV_H + + +#define HOST_INTEREST_ITEM_ADDRESS(target, item) \ + AR6002_HOST_INTEREST_ITEM_ADDRESS(item) + +u32 ar6kRev2Array[][128] = { + {0xFFFF, 0xFFFF}, // No Patches + }; + +#define CFG_REV2_ITEMS 0 // no patches so far +#define AR6K_RESET_ADDR 0x4000 +#define AR6K_RESET_VAL 0x100 + +#define EEPROM_SZ 768 +#define EEPROM_WAIT_LIMIT 4 + +#endif + diff --git a/trunk/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/trunk/drivers/staging/ath6kl/os/linux/ar6000_drv.c new file mode 100644 index 000000000000..32ee39ad00df --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/ar6000_drv.c @@ -0,0 +1,6267 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +/* + * This driver is a pseudo ethernet driver to access the Atheros AR6000 + * WLAN Device + */ + +#include "ar6000_drv.h" +#include "cfg80211.h" +#include "htc.h" +#include "wmi_filter_linux.h" +#include "epping_test.h" +#include "wlan_config.h" +#include "ar3kconfig.h" +#include "ar6k_pal.h" +#include "AR6002/addrs.h" + + +/* LINUX_HACK_FUDGE_FACTOR -- this is used to provide a workaround for linux behavior. When + * the meta data was added to the header it was found that linux did not correctly provide + * enough headroom. However when more headroom was requested beyond what was truly needed + * Linux gave the requested headroom. Therefore to get the necessary headroom from Linux + * the driver requests more than is needed by the amount = LINUX_HACK_FUDGE_FACTOR */ +#define LINUX_HACK_FUDGE_FACTOR 16 +#define BDATA_BDADDR_OFFSET 28 + +u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +u8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + +#ifdef DEBUG + +#define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0) +#define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1) +#define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2) +#define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3) +#define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4) +#define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5) +#define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) + +static struct ath_debug_mask_description driver_debug_desc[] = { + { ATH_DEBUG_DBG_LOG , "Target Debug Logs"}, + { ATH_DEBUG_WLAN_CONNECT , "WLAN connect"}, + { ATH_DEBUG_WLAN_SCAN , "WLAN scan"}, + { ATH_DEBUG_WLAN_TX , "WLAN Tx"}, + { ATH_DEBUG_WLAN_RX , "WLAN Rx"}, + { ATH_DEBUG_HTC_RAW , "HTC Raw IF tracing"}, + { ATH_DEBUG_HCI_BRIDGE , "HCI Bridge Setup"}, + { ATH_DEBUG_HCI_RECV , "HCI Recv tracing"}, + { ATH_DEBUG_HCI_DUMP , "HCI Packet dumps"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(driver, + "driver", + "Linux Driver Interface", + ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_WLAN_SCAN | + ATH_DEBUG_HCI_BRIDGE, + ATH_DEBUG_DESCRIPTION_COUNT(driver_debug_desc), + driver_debug_desc); + +#endif + + +#define IS_MAC_NULL(mac) (mac[0]==0 && mac[1]==0 && mac[2]==0 && mac[3]==0 && mac[4]==0 && mac[5]==0) +#define IS_MAC_BCAST(mac) (*mac==0xff) + +#define DESCRIPTION "Driver to access the Atheros AR600x Device, version " __stringify(__VER_MAJOR_) "." __stringify(__VER_MINOR_) "." __stringify(__VER_PATCH_) "." __stringify(__BUILD_NUMBER_) + +MODULE_AUTHOR("Atheros Communications, Inc."); +MODULE_DESCRIPTION(DESCRIPTION); +MODULE_LICENSE("Dual BSD/GPL"); + +#ifndef REORG_APTC_HEURISTICS +#undef ADAPTIVE_POWER_THROUGHPUT_CONTROL +#endif /* REORG_APTC_HEURISTICS */ + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +#define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */ +#define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */ +#define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */ + +typedef struct aptc_traffic_record { + bool timerScheduled; + struct timeval samplingTS; + unsigned long bytesReceived; + unsigned long bytesTransmitted; +} APTC_TRAFFIC_RECORD; + +A_TIMER aptcTimer; +APTC_TRAFFIC_RECORD aptcTR; +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +// callbacks registered by HCI transport driver +struct hci_transport_callbacks ar6kHciTransCallbacks = { NULL }; +#endif + +unsigned int processDot11Hdr = 0; + +char ifname[IFNAMSIZ] = {0,}; + +int wlaninitmode = WLAN_INIT_MODE_DEFAULT; +static bool bypasswmi; +unsigned int debuglevel = 0; +int tspecCompliance = ATHEROS_COMPLIANCE; +unsigned int busspeedlow = 0; +unsigned int onebitmode = 0; +unsigned int skipflash = 0; +unsigned int wmitimeout = 2; +unsigned int wlanNodeCaching = 1; +unsigned int enableuartprint = ENABLEUARTPRINT_DEFAULT; +unsigned int logWmiRawMsgs = 0; +unsigned int enabletimerwar = 0; +unsigned int num_device = 1; +unsigned int regscanmode; +unsigned int fwmode = 1; +unsigned int mbox_yield_limit = 99; +unsigned int enablerssicompensation = 0; +int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF; +int allow_trace_signal = 0; +#ifdef CONFIG_HOST_TCMD_SUPPORT +unsigned int testmode =0; +#endif + +unsigned int irqprocmode = HIF_DEVICE_IRQ_SYNC_ONLY;//HIF_DEVICE_IRQ_ASYNC_SYNC; +unsigned int panic_on_assert = 1; +unsigned int nohifscattersupport = NOHIFSCATTERSUPPORT_DEFAULT; + +unsigned int setuphci = SETUPHCI_DEFAULT; +unsigned int loghci = 0; +unsigned int setupbtdev = SETUPBTDEV_DEFAULT; +#ifndef EXPORT_HCI_BRIDGE_INTERFACE +unsigned int ar3khcibaud = AR3KHCIBAUD_DEFAULT; +unsigned int hciuartscale = HCIUARTSCALE_DEFAULT; +unsigned int hciuartstep = HCIUARTSTEP_DEFAULT; +#endif +unsigned int csumOffload=0; +unsigned int csumOffloadTest=0; +unsigned int eppingtest=0; +unsigned int mac_addr_method; +unsigned int firmware_bridge; + +module_param_string(ifname, ifname, sizeof(ifname), 0644); +module_param(wlaninitmode, int, 0644); +module_param(bypasswmi, bool, 0644); +module_param(debuglevel, uint, 0644); +module_param(tspecCompliance, int, 0644); +module_param(onebitmode, uint, 0644); +module_param(busspeedlow, uint, 0644); +module_param(skipflash, uint, 0644); +module_param(wmitimeout, uint, 0644); +module_param(wlanNodeCaching, uint, 0644); +module_param(logWmiRawMsgs, uint, 0644); +module_param(enableuartprint, uint, 0644); +module_param(enabletimerwar, uint, 0644); +module_param(fwmode, uint, 0644); +module_param(mbox_yield_limit, uint, 0644); +module_param(reduce_credit_dribble, int, 0644); +module_param(allow_trace_signal, int, 0644); +module_param(enablerssicompensation, uint, 0644); +module_param(processDot11Hdr, uint, 0644); +module_param(csumOffload, uint, 0644); +#ifdef CONFIG_HOST_TCMD_SUPPORT +module_param(testmode, uint, 0644); +#endif +module_param(irqprocmode, uint, 0644); +module_param(nohifscattersupport, uint, 0644); +module_param(panic_on_assert, uint, 0644); +module_param(setuphci, uint, 0644); +module_param(loghci, uint, 0644); +module_param(setupbtdev, uint, 0644); +#ifndef EXPORT_HCI_BRIDGE_INTERFACE +module_param(ar3khcibaud, uint, 0644); +module_param(hciuartscale, uint, 0644); +module_param(hciuartstep, uint, 0644); +#endif +module_param(eppingtest, uint, 0644); + +/* in 2.6.10 and later this is now a pointer to a uint */ +unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX; +#define mboxnum &_mboxnum + +#ifdef DEBUG +u32 g_dbg_flags = DBG_DEFAULTS; +unsigned int debugflags = 0; +int debugdriver = 0; +unsigned int debughtc = 0; +unsigned int debugbmi = 0; +unsigned int debughif = 0; +unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0}; +module_param(debugflags, uint, 0644); +module_param(debugdriver, int, 0644); +module_param(debughtc, uint, 0644); +module_param(debugbmi, uint, 0644); +module_param(debughif, uint, 0644); +module_param_array(txcreditsavailable, uint, mboxnum, 0644); +module_param_array(txcreditsconsumed, uint, mboxnum, 0644); +module_param_array(txcreditintrenable, uint, mboxnum, 0644); +module_param_array(txcreditintrenableaggregate, uint, mboxnum, 0644); + +#endif /* DEBUG */ + +unsigned int resetok = 1; +unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0}; +unsigned int hifBusRequestNumMax = 40; +unsigned int war23838_disabled = 0; +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +unsigned int enableAPTCHeuristics = 1; +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ +module_param_array(tx_attempt, uint, mboxnum, 0644); +module_param_array(tx_post, uint, mboxnum, 0644); +module_param_array(tx_complete, uint, mboxnum, 0644); +module_param(hifBusRequestNumMax, uint, 0644); +module_param(war23838_disabled, uint, 0644); +module_param(resetok, uint, 0644); +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +module_param(enableAPTCHeuristics, uint, 0644); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + +#ifdef BLOCK_TX_PATH_FLAG +int blocktx = 0; +module_param(blocktx, int, 0644); +#endif /* BLOCK_TX_PATH_FLAG */ + +typedef struct user_rssi_compensation_t { + u16 customerID; + union { + u16 a_enable; + u16 bg_enable; + u16 enable; + }; + s16 bg_param_a; + s16 bg_param_b; + s16 a_param_a; + s16 a_param_b; + u32 reserved; +} USER_RSSI_CPENSATION; + +static USER_RSSI_CPENSATION rssi_compensation_param; + +static s16 rssi_compensation_table[96]; + +int reconnect_flag = 0; +static ar6k_pal_config_t ar6k_pal_config_g; + +/* Function declarations */ +static int ar6000_init_module(void); +static void ar6000_cleanup_module(void); + +int ar6000_init(struct net_device *dev); +static int ar6000_open(struct net_device *dev); +static int ar6000_close(struct net_device *dev); +static void ar6000_init_control_info(struct ar6_softc *ar); +static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev); + +void ar6000_destroy(struct net_device *dev, unsigned int unregister); +static void ar6000_detect_error(unsigned long ptr); +static void ar6000_set_multicast_list(struct net_device *dev); +static struct net_device_stats *ar6000_get_stats(struct net_device *dev); + +static void disconnect_timer_handler(unsigned long ptr); + +void read_rssi_compensation_param(struct ar6_softc *ar); + +/* + * HTC service connection handlers + */ +static int ar6000_avail_ev(void *context, void *hif_handle); + +static int ar6000_unavail_ev(void *context, void *hif_handle); + +int ar6000_configure_target(struct ar6_softc *ar); + +static void ar6000_target_failure(void *Instance, int Status); + +static void ar6000_rx(void *Context, struct htc_packet *pPacket); + +static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint); + +static void ar6000_tx_complete(void *Context, struct htc_packet_queue *pPackets); + +static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket); + +static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num); +static void ar6000_deliver_frames_to_nw_stack(void * dev, void *osbuf); +//static void ar6000_deliver_frames_to_bt_stack(void * dev, void *osbuf); + +static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length); + +static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count); + +static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar); + +static ssize_t +ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count); + +static ssize_t +ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count); + +static int +ar6000_sysfs_bmi_init(struct ar6_softc *ar); + +void ar6k_cleanup_hci_pal(struct ar6_softc *ar); + +static void +ar6000_sysfs_bmi_deinit(struct ar6_softc *ar); + +int +ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode); + +/* + * Static variables + */ + +struct net_device *ar6000_devices[MAX_AR6000]; +static int is_netdev_registered; +DECLARE_WAIT_QUEUE_HEAD(arEvent); +static void ar6000_cookie_init(struct ar6_softc *ar); +static void ar6000_cookie_cleanup(struct ar6_softc *ar); +static void ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie); +static struct ar_cookie *ar6000_alloc_cookie(struct ar6_softc *ar); + +static int ar6000_reinstall_keys(struct ar6_softc *ar,u8 key_op_ctrl); + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT +struct net_device *arApNetDev; +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + +static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM]; + +#define HOST_INTEREST_ITEM_ADDRESS(ar, item) \ + (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0)) + + +static struct net_device_ops ar6000_netdev_ops = { + .ndo_init = NULL, + .ndo_open = ar6000_open, + .ndo_stop = ar6000_close, + .ndo_get_stats = ar6000_get_stats, + .ndo_start_xmit = ar6000_data_tx, + .ndo_set_multicast_list = ar6000_set_multicast_list, +}; + +/* Debug log support */ + +/* + * Flag to govern whether the debug logs should be parsed in the kernel + * or reported to the application. + */ +#define REPORT_DEBUG_LOGS_TO_APP + +int +ar6000_set_host_app_area(struct ar6_softc *ar) +{ + u32 address, data; + struct host_app_area_s host_app_area; + + /* Fetch the address of the host_app_area_s instance in the host interest area */ + address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest)); + if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != 0) { + return A_ERROR; + } + address = TARG_VTOP(ar->arTargetType, data); + host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION; + if (ar6000_WriteDataDiag(ar->arHifDevice, address, + (u8 *)&host_app_area, + sizeof(struct host_app_area_s)) != 0) + { + return A_ERROR; + } + + return 0; +} + +u32 dbglog_get_debug_hdr_ptr(struct ar6_softc *ar) +{ + u32 param; + u32 address; + int status; + + address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr)); + if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address, + (u8 *)¶m, 4)) != 0) + { + param = 0; + } + + return param; +} + +/* + * The dbglog module has been initialized. Its ok to access the relevant + * data stuctures over the diagnostic window. + */ +void +ar6000_dbglog_init_done(struct ar6_softc *ar) +{ + ar->dbglog_init_done = true; +} + +u32 dbglog_get_debug_fragment(s8 *datap, u32 len, u32 limit) +{ + s32 *buffer; + u32 count; + u32 numargs; + u32 length; + u32 fraglen; + + count = fraglen = 0; + buffer = (s32 *)datap; + length = (limit >> 2); + + if (len <= limit) { + fraglen = len; + } else { + while (count < length) { + numargs = DBGLOG_GET_NUMARGS(buffer[count]); + fraglen = (count << 2); + count += numargs + 1; + } + } + + return fraglen; +} + +void +dbglog_parse_debug_logs(s8 *datap, u32 len) +{ + s32 *buffer; + u32 count; + u32 timestamp; + u32 debugid; + u32 moduleid; + u32 numargs; + u32 length; + + count = 0; + buffer = (s32 *)datap; + length = (len >> 2); + while (count < length) { + debugid = DBGLOG_GET_DBGID(buffer[count]); + moduleid = DBGLOG_GET_MODULEID(buffer[count]); + numargs = DBGLOG_GET_NUMARGS(buffer[count]); + timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]); + switch (numargs) { + case 0: + AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d)\n", moduleid, debugid, timestamp)); + break; + + case 1: + AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x\n", moduleid, debugid, + timestamp, buffer[count+1])); + break; + + case 2: + AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid, + timestamp, buffer[count+1], buffer[count+2])); + break; + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid args: %d\n", numargs)); + } + count += numargs + 1; + } +} + +int +ar6000_dbglog_get_debug_logs(struct ar6_softc *ar) +{ + u32 data[8]; /* Should be able to accommodate struct dbglog_buf_s */ + u32 address; + u32 length; + u32 dropped; + u32 firstbuf; + u32 debug_hdr_ptr; + + if (!ar->dbglog_init_done) return A_ERROR; + + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + if (ar->dbgLogFetchInProgress) { + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + return A_EBUSY; + } + + /* block out others */ + ar->dbgLogFetchInProgress = true; + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar); + printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr); + + /* Get the contents of the ring buffer */ + if (debug_hdr_ptr) { + address = TARG_VTOP(ar->arTargetType, debug_hdr_ptr); + length = 4 /* sizeof(dbuf) */ + 4 /* sizeof(dropped) */; + A_MEMZERO(data, sizeof(data)); + ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)data, length); + address = TARG_VTOP(ar->arTargetType, data[0] /* dbuf */); + firstbuf = address; + dropped = data[1]; /* dropped */ + length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */; + A_MEMZERO(data, sizeof(data)); + ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)&data, length); + + do { + address = TARG_VTOP(ar->arTargetType, data[1] /* buffer*/); + length = data[3]; /* length */ + if ((length) && (length <= data[2] /* bufsize*/)) { + /* Rewind the index if it is about to overrun the buffer */ + if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) { + ar->log_cnt = 0; + } + if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address, + (u8 *)&ar->log_buffer[ar->log_cnt], length)) + { + break; + } + ar6000_dbglog_event(ar, dropped, (s8 *)&ar->log_buffer[ar->log_cnt], length); + ar->log_cnt += length; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("Length: %d (Total size: %d)\n", + data[3], data[2])); + } + + address = TARG_VTOP(ar->arTargetType, data[0] /* next */); + length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */; + A_MEMZERO(data, sizeof(data)); + if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address, + (u8 *)&data, length)) + { + break; + } + + } while (address != firstbuf); + } + + ar->dbgLogFetchInProgress = false; + + return 0; +} + +void +ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped, + s8 *buffer, u32 length) +{ +#ifdef REPORT_DEBUG_LOGS_TO_APP + #define MAX_WIRELESS_EVENT_SIZE 252 + /* + * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages. + * There seems to be a limitation on the length of message that could be + * transmitted to the user app via this mechanism. + */ + u32 send, sent; + + sent = 0; + send = dbglog_get_debug_fragment(&buffer[sent], length - sent, + MAX_WIRELESS_EVENT_SIZE); + while (send) { + sent += send; + send = dbglog_get_debug_fragment(&buffer[sent], length - sent, + MAX_WIRELESS_EVENT_SIZE); + } +#else + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Dropped logs: 0x%x\nDebug info length: %d\n", + dropped, length)); + + /* Interpret the debug logs */ + dbglog_parse_debug_logs((s8 *)buffer, length); +#endif /* REPORT_DEBUG_LOGS_TO_APP */ +} + + +static int __init +ar6000_init_module(void) +{ + static int probed = 0; + int r; + OSDRV_CALLBACKS osdrvCallbacks; + + a_module_debug_support_init(); + +#ifdef DEBUG + /* check for debug mask overrides */ + if (debughtc != 0) { + ATH_DEBUG_SET_DEBUG_MASK(htc,debughtc); + } + if (debugbmi != 0) { + ATH_DEBUG_SET_DEBUG_MASK(bmi,debugbmi); + } + if (debughif != 0) { + ATH_DEBUG_SET_DEBUG_MASK(hif,debughif); + } + if (debugdriver != 0) { + ATH_DEBUG_SET_DEBUG_MASK(driver,debugdriver); + } + +#endif + + A_REGISTER_MODULE_DEBUG_INFO(driver); + + A_MEMZERO(&osdrvCallbacks,sizeof(osdrvCallbacks)); + osdrvCallbacks.deviceInsertedHandler = ar6000_avail_ev; + osdrvCallbacks.deviceRemovedHandler = ar6000_unavail_ev; +#ifdef CONFIG_PM + osdrvCallbacks.deviceSuspendHandler = ar6000_suspend_ev; + osdrvCallbacks.deviceResumeHandler = ar6000_resume_ev; + osdrvCallbacks.devicePowerChangeHandler = ar6000_power_change_ev; +#endif + +#ifdef DEBUG + /* Set the debug flags if specified at load time */ + if(debugflags != 0) + { + g_dbg_flags = debugflags; + } +#endif + + if (probed) { + return -ENODEV; + } + probed++; + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD)); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + + r = HIFInit(&osdrvCallbacks); + if (r) + return r; + + return 0; +} + +static void __exit +ar6000_cleanup_module(void) +{ + int i = 0; + struct net_device *ar6000_netdev; + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + /* Delete the Adaptive Power Control timer */ + if (timer_pending(&aptcTimer)) { + del_timer_sync(&aptcTimer); + } +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + + for (i=0; i < MAX_AR6000; i++) { + if (ar6000_devices[i] != NULL) { + ar6000_netdev = ar6000_devices[i]; + ar6000_devices[i] = NULL; + ar6000_destroy(ar6000_netdev, 1); + } + } + + HIFShutDownDevice(NULL); + + a_module_debug_support_cleanup(); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_cleanup: success\n")); +} + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +void +aptcTimerHandler(unsigned long arg) +{ + u32 numbytes; + u32 throughput; + struct ar6_softc *ar; + int status; + + ar = (struct ar6_softc *)arg; + A_ASSERT(ar != NULL); + A_ASSERT(!timer_pending(&aptcTimer)); + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + /* Get the number of bytes transferred */ + numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; + aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; + + /* Calculate and decide based on throughput thresholds */ + throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */ + if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) { + /* Enable Sleep and delete the timer */ + A_ASSERT(ar->arWmiReady == true); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + status = wmi_powermode_cmd(ar->arWmi, REC_POWER); + AR6000_SPIN_LOCK(&ar->arLock, 0); + A_ASSERT(status == 0); + aptcTR.timerScheduled = false; + } else { + A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); +} +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + +static void +ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num) +{ + void * osbuf; + + while(num) { + if((osbuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE))) { + A_NETBUF_ENQUEUE(q, osbuf); + } else { + break; + } + num--; + } + + if(num) { + A_PRINTF("%s(), allocation of netbuf failed", __func__); + } +} + +static struct bin_attribute bmi_attr = { + .attr = {.name = "bmi", .mode = 0600}, + .read = ar6000_sysfs_bmi_read, + .write = ar6000_sysfs_bmi_write, +}; + +static ssize_t +ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count) +{ + int index; + struct ar6_softc *ar; + struct hif_device_os_device_info *osDevInfo; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", (u32)count)); + for (index=0; index < MAX_AR6000; index++) { + ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]); + osDevInfo = &ar->osDevInfo; + if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) { + break; + } + } + + if (index == MAX_AR6000) return 0; + + if ((BMIRawRead(ar->arHifDevice, (u8*)buf, count, true)) != 0) { + return 0; + } + + return count; +} + +static ssize_t +ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count) +{ + int index; + struct ar6_softc *ar; + struct hif_device_os_device_info *osDevInfo; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", (u32)count)); + for (index=0; index < MAX_AR6000; index++) { + ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]); + osDevInfo = &ar->osDevInfo; + if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) { + break; + } + } + + if (index == MAX_AR6000) return 0; + + if ((BMIRawWrite(ar->arHifDevice, (u8*)buf, count)) != 0) { + return 0; + } + + return count; +} + +static int +ar6000_sysfs_bmi_init(struct ar6_softc *ar) +{ + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Creating sysfs entry\n")); + A_MEMZERO(&ar->osDevInfo, sizeof(struct hif_device_os_device_info)); + + /* Get the underlying OS device */ + status = HIFConfigureDevice(ar->arHifDevice, + HIF_DEVICE_GET_OS_DEVICE, + &ar->osDevInfo, + sizeof(struct hif_device_os_device_info)); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failed to get OS device info from HIF\n")); + return A_ERROR; + } + + /* Create a bmi entry in the sysfs filesystem */ + if ((sysfs_create_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr)) < 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to create entry for bmi in sysfs filesystem\n")); + return A_ERROR; + } + + return 0; +} + +static void +ar6000_sysfs_bmi_deinit(struct ar6_softc *ar) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Deleting sysfs entry\n")); + + sysfs_remove_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr); +} + +#define bmifn(fn) do { \ + if ((fn) < 0) { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); \ + return A_ERROR; \ + } \ +} while(0) + +#ifdef SOFTMAC_FILE_USED +#define AR6002_MAC_ADDRESS_OFFSET 0x0A +#define AR6003_MAC_ADDRESS_OFFSET 0x16 +static +void calculate_crc(u32 TargetType, u8 *eeprom_data) +{ + u16 *ptr_crc; + u16 *ptr16_eeprom; + u16 checksum; + u32 i; + u32 eeprom_size; + + if (TargetType == TARGET_TYPE_AR6001) + { + eeprom_size = 512; + ptr_crc = (u16 *)eeprom_data; + } + else if (TargetType == TARGET_TYPE_AR6003) + { + eeprom_size = 1024; + ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04); + } + else + { + eeprom_size = 768; + ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04); + } + + + // Clear the crc + *ptr_crc = 0; + + // Recalculate new CRC + checksum = 0; + ptr16_eeprom = (u16 *)eeprom_data; + for (i = 0;i < eeprom_size; i += 2) + { + checksum = checksum ^ (*ptr16_eeprom); + ptr16_eeprom++; + } + checksum = 0xFFFF ^ checksum; + *ptr_crc = checksum; +} + +static void +ar6000_softmac_update(struct ar6_softc *ar, u8 *eeprom_data, size_t size) +{ + const char *source = "random generated"; + const struct firmware *softmac_entry; + u8 *ptr_mac; + switch (ar->arTargetType) { + case TARGET_TYPE_AR6002: + ptr_mac = (u8 *)((u8 *)eeprom_data + AR6002_MAC_ADDRESS_OFFSET); + break; + case TARGET_TYPE_AR6003: + ptr_mac = (u8 *)((u8 *)eeprom_data + AR6003_MAC_ADDRESS_OFFSET); + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Target Type\n")); + return; + } + printk(KERN_DEBUG "MAC from EEPROM %pM\n", ptr_mac); + + /* create a random MAC in case we cannot read file from system */ + ptr_mac[0] = 0; + ptr_mac[1] = 0x03; + ptr_mac[2] = 0x7F; + ptr_mac[3] = random32() & 0xff; + ptr_mac[4] = random32() & 0xff; + ptr_mac[5] = random32() & 0xff; + if ((A_REQUEST_FIRMWARE(&softmac_entry, "softmac", ((struct device *)ar->osDevInfo.pOSDevice))) == 0) + { + char *macbuf = A_MALLOC_NOWAIT(softmac_entry->size+1); + if (macbuf) { + unsigned int softmac[6]; + memcpy(macbuf, softmac_entry->data, softmac_entry->size); + macbuf[softmac_entry->size] = '\0'; + if (sscanf(macbuf, "%02x:%02x:%02x:%02x:%02x:%02x", + &softmac[0], &softmac[1], &softmac[2], + &softmac[3], &softmac[4], &softmac[5])==6) { + int i; + for (i=0; i<6; ++i) { + ptr_mac[i] = softmac[i] & 0xff; + } + source = "softmac file"; + } + kfree(macbuf); + } + A_RELEASE_FIRMWARE(softmac_entry); + } + printk(KERN_DEBUG "MAC from %s %pM\n", source, ptr_mac); + calculate_crc(ar->arTargetType, eeprom_data); +} +#endif /* SOFTMAC_FILE_USED */ + +static int +ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, bool compressed) +{ + int status; + const char *filename; + const struct firmware *fw_entry; + u32 fw_entry_size; + u8 **buf; + size_t *buf_len; + + switch (file) { + case AR6K_OTP_FILE: + buf = &ar->fw_otp; + buf_len = &ar->fw_otp_len; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_OTP_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_OTP_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_OTP_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + break; + + case AR6K_FIRMWARE_FILE: + buf = &ar->fw; + buf_len = &ar->fw_len; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_FIRMWARE_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + + if (eppingtest) { + bypasswmi = true; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_EPPING_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_EPPING_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_EPPING_FIRMWARE_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("eppingtest : unsupported firmware revision: %d\n", + ar->arVersion.target_ver)); + return A_ERROR; + } + compressed = false; + } + +#ifdef CONFIG_HOST_TCMD_SUPPORT + if(testmode) { + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_TCMD_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_TCMD_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_TCMD_FIRMWARE_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + compressed = false; + } +#endif +#ifdef HTC_RAW_INTERFACE + if (!eppingtest && bypasswmi) { + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_ART_FIRMWARE_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_ART_FIRMWARE_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + compressed = false; + } +#endif + break; + + case AR6K_PATCH_FILE: + buf = &ar->fw_patch; + buf_len = &ar->fw_patch_len; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_PATCH_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_PATCH_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_PATCH_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + break; + + case AR6K_BOARD_DATA_FILE: + buf = &ar->fw_data; + buf_len = &ar->fw_data_len; + if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { + filename = AR6003_REV1_BOARD_DATA_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + filename = AR6003_REV2_BOARD_DATA_FILE; + } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { + filename = AR6003_REV3_BOARD_DATA_FILE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); + return A_ERROR; + } + break; + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown file type: %d\n", file)); + return A_ERROR; + } + + if (*buf == NULL) { + if ((A_REQUEST_FIRMWARE(&fw_entry, filename, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to get %s\n", filename)); + return A_ENOENT; + } + + *buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); + *buf_len = fw_entry->size; + A_RELEASE_FIRMWARE(fw_entry); + } + +#ifdef SOFTMAC_FILE_USED + if (file==AR6K_BOARD_DATA_FILE && *buf_len) { + ar6000_softmac_update(ar, *buf, *buf_len); + } +#endif + + + fw_entry_size = *buf_len; + + /* Load extended board data for AR6003 */ + if ((file==AR6K_BOARD_DATA_FILE) && *buf) { + u32 board_ext_address; + u32 board_ext_data_size; + u32 board_data_size; + + board_ext_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_EXT_DATA_SZ : \ + (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_EXT_DATA_SZ : 0)); + + board_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_DATA_SZ : \ + (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_DATA_SZ : 0)); + + /* Determine where in Target RAM to write Board Data */ + bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), (u8 *)&board_ext_address, 4)); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board extended Data download address: 0x%x\n", board_ext_address)); + + /* check whether the target has allocated memory for extended board data and file contains extended board data */ + if ((board_ext_address) && (*buf_len == (board_data_size + board_ext_data_size))) { + u32 param; + + status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(*buf + board_data_size), board_ext_data_size); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); + return A_ERROR; + } + + /* Record the fact that extended board Data IS initialized */ + param = (board_ext_data_size << 16) | 1; + bmifn(BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data_config), + (unsigned char *)¶m, 4)); + } + fw_entry_size = board_data_size; + } + + if (compressed) { + status = BMIFastDownload(ar->arHifDevice, address, *buf, fw_entry_size); + } else { + status = BMIWriteMemory(ar->arHifDevice, address, *buf, fw_entry_size); + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); + return A_ERROR; + } + + return 0; +} + +int +ar6000_update_bdaddr(struct ar6_softc *ar) +{ + + if (setupbtdev != 0) { + u32 address; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for hi_board_data failed\n")); + return A_ERROR; + } + + if (BMIReadMemory(ar->arHifDevice, address + BDATA_BDADDR_OFFSET, (u8 *)ar->bdaddr, 6) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for BD address failed\n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BDADDR 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", ar->bdaddr[0], + ar->bdaddr[1], ar->bdaddr[2], ar->bdaddr[3], + ar->bdaddr[4], ar->bdaddr[5])); + } + +return 0; +} + +int +ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Requesting device specific configuration\n")); + + if (mode == WLAN_INIT_MODE_UDEV) { + char version[16]; + const struct firmware *fw_entry; + + /* Get config using udev through a script in user space */ + sprintf(version, "%2.2x", ar->arVersion.target_ver); + if ((A_REQUEST_FIRMWARE(&fw_entry, version, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get configuration for target version: %s\n", version)); + return A_ERROR; + } + + A_RELEASE_FIRMWARE(fw_entry); + } else { + /* The config is contained within the driver itself */ + int status; + u32 param, options, sleep, address; + + /* Temporarily disable system sleep */ + address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; + bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); + options = param; + param |= AR6K_OPTION_SLEEP_DISABLE; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; + bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); + sleep = param; + param |= WLAN_SYSTEM_SLEEP_DISABLE_SET(1); + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("old options: %d, old sleep: %d\n", options, sleep)); + + if (ar->arTargetType == TARGET_TYPE_AR6003) { + /* Program analog PLL register */ + bmifn(BMIWriteSOCRegister(ar->arHifDevice, ANALOG_INTF_BASE_ADDRESS + 0x284, 0xF9104001)); + /* Run at 80/88MHz by default */ + param = CPU_CLOCK_STANDARD_SET(1); + } else { + /* Run at 40/44MHz by default */ + param = CPU_CLOCK_STANDARD_SET(0); + } + address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + param = 0; + if (ar->arTargetType == TARGET_TYPE_AR6002) { + bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)¶m, 4)); + } + + /* LPO_CAL.ENABLE = 1 if no external clk is detected */ + if (param != 1) { + address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS; + param = LPO_CAL_ENABLE_SET(1); + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + } + + /* Venus2.0: Lower SDIO pad drive strength, + * temporary WAR to avoid SDIO CRC error */ + if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6K: Temporary WAR to avoid SDIO CRC error\n")); + param = 0x20; + address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + } + +#ifdef FORCE_INTERNAL_CLOCK + /* Ignore external clock, if any, and force use of internal clock */ + if (ar->arTargetType == TARGET_TYPE_AR6003) { + /* hi_ext_clk_detected = 0 */ + param = 0; + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)¶m, 4)); + + /* CLOCK_CONTROL &= ~LF_CLK32 */ + address = RTC_BASE_ADDRESS + CLOCK_CONTROL_ADDRESS; + bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); + param &= (~CLOCK_CONTROL_LF_CLK32_SET(1)); + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + } +#endif /* FORCE_INTERNAL_CLOCK */ + + /* Transfer Board Data from Target EEPROM to Target RAM */ + if (ar->arTargetType == TARGET_TYPE_AR6003) { + /* Determine where in Target RAM to write Board Data */ + bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4)); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board Data download address: 0x%x\n", address)); + + /* Write EEPROM data to Target RAM */ + if ((ar6000_transfer_bin_file(ar, AR6K_BOARD_DATA_FILE, address, false)) != 0) { + return A_ERROR; + } + + /* Record the fact that Board Data IS initialized */ + param = 1; + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data_initialized), (u8 *)¶m, 4)); + + /* Transfer One time Programmable data */ + AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver); + if (ar->arVersion.target_ver == AR6003_REV3_VERSION) + address = 0x1234; + status = ar6000_transfer_bin_file(ar, AR6K_OTP_FILE, address, true); + if (status == 0) { + /* Execute the OTP code */ + param = 0; + AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver); + bmifn(BMIExecute(ar->arHifDevice, address, ¶m)); + } else if (status != A_ENOENT) { + return A_ERROR; + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Programming of board data for chip %d not supported\n", ar->arTargetType)); + return A_ERROR; + } + + /* Download Target firmware */ + AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver); + if (ar->arVersion.target_ver == AR6003_REV3_VERSION) + address = 0x1234; + if ((ar6000_transfer_bin_file(ar, AR6K_FIRMWARE_FILE, address, true)) != 0) { + return A_ERROR; + } + + /* Set starting address for firmware */ + AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver); + bmifn(BMISetAppStart(ar->arHifDevice, address)); + + if(ar->arTargetType == TARGET_TYPE_AR6003) { + AR6K_DATASET_PATCH_ADDRESS(address, ar->arVersion.target_ver); + if ((ar6000_transfer_bin_file(ar, AR6K_PATCH_FILE, + address, false)) != 0) + return A_ERROR; + param = address; + bmifn(BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_dset_list_head), + (unsigned char *)¶m, 4)); + } + + /* Restore system sleep */ + address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, sleep)); + + address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; + param = options | 0x20; + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + + if (ar->arTargetType == TARGET_TYPE_AR6003) { + /* Configure GPIO AR6003 UART */ +#ifndef CONFIG_AR600x_DEBUG_UART_TX_PIN +#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8 +#endif + param = CONFIG_AR600x_DEBUG_UART_TX_PIN; + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbg_uart_txpin), (u8 *)¶m, 4)); + +#if (CONFIG_AR600x_DEBUG_UART_TX_PIN == 23) + { + address = GPIO_BASE_ADDRESS + CLOCK_GPIO_ADDRESS; + bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); + param |= CLOCK_GPIO_BT_CLK_OUT_EN_SET(1); + bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); + } +#endif + + /* Configure GPIO for BT Reset */ +#ifdef ATH6KL_CONFIG_GPIO_BT_RESET +#define CONFIG_AR600x_BT_RESET_PIN 0x16 + param = CONFIG_AR600x_BT_RESET_PIN; + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_support_pins), (u8 *)¶m, 4)); +#endif /* ATH6KL_CONFIG_GPIO_BT_RESET */ + + /* Configure UART flow control polarity */ +#ifndef CONFIG_ATH6KL_BT_UART_FC_POLARITY +#define CONFIG_ATH6KL_BT_UART_FC_POLARITY 0 +#endif + +#if (CONFIG_ATH6KL_BT_UART_FC_POLARITY == 1) + if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + param = ((CONFIG_ATH6KL_BT_UART_FC_POLARITY << 1) & 0x2); + bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_pwr_mgmt_params), (u8 *)¶m, 4)); + } +#endif /* CONFIG_ATH6KL_BT_UART_FC_POLARITY */ + } + +#ifdef HTC_RAW_INTERFACE + if (!eppingtest && bypasswmi) { + /* Don't run BMIDone for ART mode and force resetok=0 */ + resetok = 0; + msleep(1000); + } +#endif /* HTC_RAW_INTERFACE */ + } + + return 0; +} + +int +ar6000_configure_target(struct ar6_softc *ar) +{ + u32 param; + if (enableuartprint) { + param = 1; + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enableuartprint failed \n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Serial console prints enabled\n")); + } + + /* Tell target which HTC version it is used*/ + param = HTC_PROTOCOL_VERSION; + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for htc version failed \n")); + return A_ERROR; + } + +#ifdef CONFIG_HOST_TCMD_SUPPORT + if(testmode) { + ar->arTargetMode = AR6000_TCMD_MODE; + }else { + ar->arTargetMode = AR6000_WLAN_MODE; + } +#endif + if (enabletimerwar) { + u32 param; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for enabletimerwar failed \n")); + return A_ERROR; + } + + param |= HI_OPTION_TIMER_WAR; + + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enabletimerwar failed \n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Timer WAR enabled\n")); + } + + /* set the firmware mode to STA/IBSS/AP */ + { + u32 param; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for setting fwmode failed \n")); + return A_ERROR; + } + + param |= (num_device << HI_OPTION_NUM_DEV_SHIFT); + param |= (fwmode << HI_OPTION_FW_MODE_SHIFT); + param |= (mac_addr_method << HI_OPTION_MAC_ADDR_METHOD_SHIFT); + param |= (firmware_bridge << HI_OPTION_FW_BRIDGE_SHIFT); + + + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for setting fwmode failed \n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n")); + } + +#ifdef ATH6KL_DISABLE_TARGET_DBGLOGS + { + u32 param; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4)!= 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for disabling debug logs failed\n")); + return A_ERROR; + } + + param |= HI_OPTION_DISABLE_DBGLOG; + + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), + (u8 *)¶m, + 4) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for HI_OPTION_DISABLE_DBGLOG\n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n")); + } +#endif /* ATH6KL_DISABLE_TARGET_DBGLOGS */ + + /* + * Hardcode the address use for the extended board data + * Ideally this should be pre-allocate by the OS at boot time + * But since it is a new feature and board data is loaded + * at init time, we have to workaround this from host. + * It is difficult to patch the firmware boot code, + * but possible in theory. + */ + + if (ar->arTargetType == TARGET_TYPE_AR6003) { + u32 ramReservedSz; + if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { + param = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; + ramReservedSz = AR6003_REV2_RAM_RESERVE_SIZE; + } else { + param = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; + ramReservedSz = AR6003_REV3_RAM_RESERVE_SIZE; + } + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), + (u8 *)¶m, 4) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("BMIWriteMemory for " + "hi_board_ext_data failed\n")); + return A_ERROR; + } + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, + hi_end_RAM_reserve_sz), + (u8 *)&ramReservedSz, 4) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR , + ("BMIWriteMemory for " + "hi_end_RAM_reserve_sz failed\n")); + return A_ERROR; + } + } + + /* since BMIInit is called in the driver layer, we have to set the block + * size here for the target */ + + if (ar6000_set_htc_params(ar->arHifDevice, ar->arTargetType, + mbox_yield_limit, 0)) { + /* use default number of control buffers */ + return A_ERROR; + } + + if (setupbtdev != 0) { + if (ar6000_set_hci_bridge_flags(ar->arHifDevice, + ar->arTargetType, + setupbtdev)) { + return A_ERROR; + } + } + return 0; +} + +static void +init_netdev(struct net_device *dev, char *name) +{ + dev->netdev_ops = &ar6000_netdev_ops; + dev->watchdog_timeo = AR6000_TX_TIMEOUT; + + /* + * We need the OS to provide us with more headroom in order to + * perform dix to 802.3, WMI header encap, and the HTC header + */ + if (processDot11Hdr) { + dev->hard_header_len = sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX_HACK_FUDGE_FACTOR; + } else { + dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) + + sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX_HACK_FUDGE_FACTOR; + } + + if (name[0]) + { + strcpy(dev->name, name); + } + +#ifdef CONFIG_CHECKSUM_OFFLOAD + if(csumOffload){ + dev->features |= NETIF_F_IP_CSUM; /*advertise kernel capability to do TCP/UDP CSUM offload for IPV4*/ + } +#endif + + return; +} + +static int __ath6kl_init_netdev(struct net_device *dev) +{ + int r; + + rtnl_lock(); + r = ar6000_init(dev); + rtnl_unlock(); + + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_init\n")); + return r; + } + + return 0; +} + +#ifdef HTC_RAW_INTERFACE +static int ath6kl_init_netdev_wmi(struct net_device *dev) +{ + if (!eppingtest && bypasswmi) + return 0; + + return __ath6kl_init_netdev(dev); +} +#else +static int ath6kl_init_netdev_wmi(struct net_device *dev) +{ + return __ath6kl_init_netdev(dev); +} +#endif + +static int ath6kl_init_netdev(struct ar6_softc *ar) +{ + int r; + + r = ar6000_sysfs_bmi_get_config(ar, wlaninitmode); + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("ar6000_avail: " + "ar6000_sysfs_bmi_get_config failed\n")); + return r; + } + + return ath6kl_init_netdev_wmi(ar->arNetDev); +} + +/* + * HTC Event handlers + */ +static int +ar6000_avail_ev(void *context, void *hif_handle) +{ + int i; + struct net_device *dev; + void *ar_netif; + struct ar6_softc *ar; + int device_index = 0; + struct htc_init_info htcInfo; + struct wireless_dev *wdev; + int r = 0; + struct hif_device_os_device_info osDevInfo; + + memset(&osDevInfo, 0, sizeof(osDevInfo)); + if (HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_OS_DEVICE, + &osDevInfo, sizeof(osDevInfo))) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Failed to get OS device instance\n", __func__)); + return A_ERROR; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_available\n")); + + for (i=0; i < MAX_AR6000; i++) { + if (ar6000_devices[i] == NULL) { + break; + } + } + + if (i == MAX_AR6000) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_available: max devices reached\n")); + return A_ERROR; + } + + /* Save this. It gives a bit better readability especially since */ + /* we use another local "i" variable below. */ + device_index = i; + + wdev = ar6k_cfg80211_init(osDevInfo.pOSDevice); + if (IS_ERR(wdev)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ar6k_cfg80211_init failed\n", __func__)); + return A_ERROR; + } + ar_netif = wdev_priv(wdev); + + if (ar_netif == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Can't allocate ar6k priv memory\n", __func__)); + return A_ERROR; + } + + A_MEMZERO(ar_netif, sizeof(struct ar6_softc)); + ar = (struct ar6_softc *)ar_netif; + + ar->wdev = wdev; + wdev->iftype = NL80211_IFTYPE_STATION; + + dev = alloc_netdev_mq(0, "wlan%d", ether_setup, 1); + if (!dev) { + printk(KERN_CRIT "AR6K: no memory for network device instance\n"); + ar6k_cfg80211_deinit(ar); + return A_ERROR; + } + + dev->ieee80211_ptr = wdev; + SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); + wdev->netdev = dev; + ar->arNetworkType = INFRA_NETWORK; + ar->smeState = SME_DISCONNECTED; + ar->arAutoAuthStage = AUTH_IDLE; + + init_netdev(dev, ifname); + + + ar->arNetDev = dev; + ar->arHifDevice = hif_handle; + ar->arWlanState = WLAN_ENABLED; + ar->arDeviceIndex = device_index; + + ar->arWlanPowerState = WLAN_POWER_STATE_ON; + ar->arWlanOff = false; /* We are in ON state */ +#ifdef CONFIG_PM + ar->arWowState = WLAN_WOW_STATE_NONE; + ar->arBTOff = true; /* BT chip assumed to be OFF */ + ar->arBTSharing = WLAN_CONFIG_BT_SHARING; + ar->arWlanOffConfig = WLAN_CONFIG_WLAN_OFF; + ar->arSuspendConfig = WLAN_CONFIG_PM_SUSPEND; + ar->arWow2Config = WLAN_CONFIG_PM_WOW2; +#endif /* CONFIG_PM */ + + A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev); + ar->arHBChallengeResp.seqNum = 0; + ar->arHBChallengeResp.outstanding = false; + ar->arHBChallengeResp.missCnt = 0; + ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT; + ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT; + + ar6000_init_control_info(ar); + init_waitqueue_head(&arEvent); + sema_init(&ar->arSem, 1); + ar->bIsDestroyProgress = false; + + INIT_HTC_PACKET_QUEUE(&ar->amsdu_rx_buffer_queue); + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + + A_INIT_TIMER(&ar->disconnect_timer, disconnect_timer_handler, dev); + + BMIInit(); + + ar6000_sysfs_bmi_init(ar); + + { + struct bmi_target_info targ_info; + + r = BMIGetTargetInfo(ar->arHifDevice, &targ_info); + if (r) + goto avail_ev_failed; + + ar->arVersion.target_ver = targ_info.target_ver; + ar->arTargetType = targ_info.target_type; + wdev->wiphy->hw_version = targ_info.target_ver; + } + + r = ar6000_configure_target(ar); + if (r) + goto avail_ev_failed; + + A_MEMZERO(&htcInfo,sizeof(htcInfo)); + htcInfo.pContext = ar; + htcInfo.TargetFailure = ar6000_target_failure; + + ar->arHtcTarget = HTCCreate(ar->arHifDevice,&htcInfo); + + if (!ar->arHtcTarget) { + r = -ENOMEM; + goto avail_ev_failed; + } + + spin_lock_init(&ar->arLock); + +#ifdef WAPI_ENABLE + ar->arWapiEnable = 0; +#endif + + + if(csumOffload){ + /*if external frame work is also needed, change and use an extended rxMetaVerion*/ + ar->rxMetaVersion=WMI_META_VERSION_2; + } + + ar->aggr_cntxt = aggr_init(ar6000_alloc_netbufs); + if (!ar->aggr_cntxt) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize aggr.\n", __func__)); + r = -ENOMEM; + goto avail_ev_failed; + } + + aggr_register_rx_dispatcher(ar->aggr_cntxt, (void *)dev, ar6000_deliver_frames_to_nw_stack); + + HIFClaimDevice(ar->arHifDevice, ar); + + /* We only register the device in the global list if we succeed. */ + /* If the device is in the global list, it will be destroyed */ + /* when the module is unloaded. */ + ar6000_devices[device_index] = dev; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("BMI enabled: %d\n", wlaninitmode)); + if ((wlaninitmode == WLAN_INIT_MODE_UDEV) || + (wlaninitmode == WLAN_INIT_MODE_DRV)) { + r = ath6kl_init_netdev(ar); + if (r) + goto avail_ev_failed; + } + + /* This runs the init function if registered */ + r = register_netdev(dev); + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: register_netdev failed\n")); + ar6000_destroy(dev, 0); + return r; + } + + is_netdev_registered = 1; + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT + arApNetDev = NULL; +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_avail: name=%s hifdevice=0x%lx, dev=0x%lx (%d), ar=0x%lx\n", + dev->name, (unsigned long)ar->arHifDevice, (unsigned long)dev, device_index, + (unsigned long)ar)); + +avail_ev_failed : + if (r) + ar6000_sysfs_bmi_deinit(ar); + + return r; +} + +static void ar6000_target_failure(void *Instance, int Status) +{ + struct ar6_softc *ar = (struct ar6_softc *)Instance; + WMI_TARGET_ERROR_REPORT_EVENT errEvent; + static bool sip = false; + + if (Status != 0) { + + printk(KERN_ERR "ar6000_target_failure: target asserted \n"); + + if (timer_pending(&ar->arHBChallengeResp.timer)) { + A_UNTIMEOUT(&ar->arHBChallengeResp.timer); + } + + /* try dumping target assertion information (if any) */ + ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType); + + /* + * Fetch the logs from the target via the diagnostic + * window. + */ + ar6000_dbglog_get_debug_logs(ar); + + /* Report the error only once */ + if (!sip) { + sip = true; + errEvent.errorVal = WMI_TARGET_COM_ERR | + WMI_TARGET_FATAL_ERR; + } + } +} + +static int +ar6000_unavail_ev(void *context, void *hif_handle) +{ + struct ar6_softc *ar = (struct ar6_softc *)context; + /* NULL out it's entry in the global list */ + ar6000_devices[ar->arDeviceIndex] = NULL; + ar6000_destroy(ar->arNetDev, 1); + + return 0; +} + +void +ar6000_restart_endpoint(struct net_device *dev) +{ + int status = 0; + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + BMIInit(); + do { + if ( (status=ar6000_configure_target(ar))!= 0) + break; + if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != 0) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_bmi_get_config failed\n")); + break; + } + rtnl_lock(); + status = (ar6000_init(dev)==0) ? 0 : A_ERROR; + rtnl_unlock(); + + if (status) { + break; + } + if (ar->arSsidLen && ar->arWlanState == WLAN_ENABLED) { + ar6000_connect_to_ap(ar); + } + } while (0); + + if (status== 0) { + return; + } + + ar6000_devices[ar->arDeviceIndex] = NULL; + ar6000_destroy(ar->arNetDev, 1); +} + +void +ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + /* Stop the transmit queues */ + netif_stop_queue(dev); + + /* Disable the target and the interrupts associated with it */ + if (ar->arWmiReady == true) + { + if (!bypasswmi) + { + bool disconnectIssued; + + disconnectIssued = (ar->arConnected) || (ar->arConnectPending); + ar6000_disconnect(ar); + if (!keepprofile) { + ar6000_init_profile_info(ar); + } + + A_UNTIMEOUT(&ar->disconnect_timer); + + if (getdbglogs) { + ar6000_dbglog_get_debug_logs(ar); + } + + ar->arWmiReady = false; + wmi_shutdown(ar->arWmi); + ar->arWmiEnabled = false; + ar->arWmi = NULL; + /* + * After wmi_shudown all WMI events will be dropped. + * We need to cleanup the buffers allocated in AP mode + * and give disconnect notification to stack, which usually + * happens in the disconnect_event. + * Simulate the disconnect_event by calling the function directly. + * Sometimes disconnect_event will be received when the debug logs + * are collected. + */ + if (disconnectIssued) { + if(ar->arNetworkType & AP_NETWORK) { + ar6000_disconnect_event(ar, DISCONNECT_CMD, bcast_mac, 0, NULL, 0); + } else { + ar6000_disconnect_event(ar, DISCONNECT_CMD, ar->arBssid, 0, NULL, 0); + } + } + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; + ar->user_key_ctrl = 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI stopped\n", __func__)); + } + else + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI not ready 0x%lx 0x%lx\n", + __func__, (unsigned long) ar, (unsigned long) ar->arWmi)); + + /* Shut down WMI if we have started it */ + if(ar->arWmiEnabled == true) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Shut down WMI\n", __func__)); + wmi_shutdown(ar->arWmi); + ar->arWmiEnabled = false; + ar->arWmi = NULL; + } + } + + if (ar->arHtcTarget != NULL) { +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + if (NULL != ar6kHciTransCallbacks.cleanupTransport) { + ar6kHciTransCallbacks.cleanupTransport(NULL); + } +#else + // FIXME: workaround to reset BT's UART baud rate to default + if (NULL != ar->exitCallback) { + struct ar3k_config_info ar3kconfig; + int status; + + A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig)); + ar6000_set_default_ar3kconfig(ar, (void *)&ar3kconfig); + status = ar->exitCallback(&ar3kconfig); + if (0 != status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to reset AR3K baud rate! \n")); + } + } + // END workaround + if (setuphci) + ar6000_cleanup_hci(ar); +#endif + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Shutting down HTC .... \n")); + /* stop HTC */ + HTCStop(ar->arHtcTarget); + } + + if (resetok) { + /* try to reset the device if we can + * The driver may have been configure NOT to reset the target during + * a debug session */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Attempting to reset target on instance destroy.... \n")); + if (ar->arHifDevice != NULL) { + bool coldReset = (ar->arTargetType == TARGET_TYPE_AR6003) ? true: false; + ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, coldReset); + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Host does not want target reset. \n")); + } + /* Done with cookies */ + ar6000_cookie_cleanup(ar); + + /* cleanup any allocated AMSDU buffers */ + ar6000_cleanup_amsdu_rxbufs(ar); +} +/* + * We need to differentiate between the surprise and planned removal of the + * device because of the following consideration: + * - In case of surprise removal, the hcd already frees up the pending + * for the device and hence there is no need to unregister the function + * driver inorder to get these requests. For planned removal, the function + * driver has to explicitly unregister itself to have the hcd return all the + * pending requests before the data structures for the devices are freed up. + * Note that as per the current implementation, the function driver will + * end up releasing all the devices since there is no API to selectively + * release a particular device. + * - Certain commands issued to the target can be skipped for surprise + * removal since they will anyway not go through. + */ +void +ar6000_destroy(struct net_device *dev, unsigned int unregister) +{ + struct ar6_softc *ar; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("+ar6000_destroy \n")); + + if((dev == NULL) || ((ar = ar6k_priv(dev)) == NULL)) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): Failed to get device structure.\n", __func__)); + return; + } + + ar->bIsDestroyProgress = true; + + if (down_interruptible(&ar->arSem)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): down_interruptible failed \n", __func__)); + return; + } + + if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) { + /* only stop endpoint if we are not stop it in suspend_ev */ + ar6000_stop_endpoint(dev, false, true); + } + + ar->arWlanState = WLAN_DISABLED; + if (ar->arHtcTarget != NULL) { + /* destroy HTC */ + HTCDestroy(ar->arHtcTarget); + } + if (ar->arHifDevice != NULL) { + /*release the device so we do not get called back on remove incase we + * we're explicity destroyed by module unload */ + HIFReleaseDevice(ar->arHifDevice); + HIFShutDownDevice(ar->arHifDevice); + } + aggr_module_destroy(ar->aggr_cntxt); + + /* Done with cookies */ + ar6000_cookie_cleanup(ar); + + /* cleanup any allocated AMSDU buffers */ + ar6000_cleanup_amsdu_rxbufs(ar); + + ar6000_sysfs_bmi_deinit(ar); + + /* Cleanup BMI */ + BMICleanup(); + + /* Clear the tx counters */ + memset(tx_attempt, 0, sizeof(tx_attempt)); + memset(tx_post, 0, sizeof(tx_post)); + memset(tx_complete, 0, sizeof(tx_complete)); + +#ifdef HTC_RAW_INTERFACE + if (ar->arRawHtc) { + kfree(ar->arRawHtc); + ar->arRawHtc = NULL; + } +#endif + /* Free up the device data structure */ + if (unregister && is_netdev_registered) { + unregister_netdev(dev); + is_netdev_registered = 0; + } + free_netdev(dev); + + ar6k_cfg80211_deinit(ar); + +#ifdef CONFIG_AP_VIRTUL_ADAPTER_SUPPORT + ar6000_remove_ap_interface(); +#endif /*CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + + kfree(ar->fw_otp); + kfree(ar->fw); + kfree(ar->fw_patch); + kfree(ar->fw_data); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("-ar6000_destroy \n")); +} + +static void disconnect_timer_handler(unsigned long ptr) +{ + struct net_device *dev = (struct net_device *)ptr; + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + A_UNTIMEOUT(&ar->disconnect_timer); + + ar6000_init_profile_info(ar); + ar6000_disconnect(ar); +} + +static void ar6000_detect_error(unsigned long ptr) +{ + struct net_device *dev = (struct net_device *)ptr; + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + WMI_TARGET_ERROR_REPORT_EVENT errEvent; + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + if (ar->arHBChallengeResp.outstanding) { + ar->arHBChallengeResp.missCnt++; + } else { + ar->arHBChallengeResp.missCnt = 0; + } + + if (ar->arHBChallengeResp.missCnt > ar->arHBChallengeResp.missThres) { + /* Send Error Detect event to the application layer and do not reschedule the error detection module timer */ + ar->arHBChallengeResp.missCnt = 0; + ar->arHBChallengeResp.seqNum = 0; + errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR; + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + return; + } + + /* Generate the sequence number for the next challenge */ + ar->arHBChallengeResp.seqNum++; + ar->arHBChallengeResp.outstanding = true; + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + /* Send the challenge on the control channel */ + if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to send heart beat challenge\n")); + } + + + /* Reschedule the timer for the next challenge */ + A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0); +} + +void ar6000_init_profile_info(struct ar6_softc *ar) +{ + ar->arSsidLen = 0; + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + + switch(fwmode) { + case HI_OPTION_FW_MODE_IBSS: + ar->arNetworkType = ar->arNextMode = ADHOC_NETWORK; + break; + case HI_OPTION_FW_MODE_BSS_STA: + ar->arNetworkType = ar->arNextMode = INFRA_NETWORK; + break; + case HI_OPTION_FW_MODE_AP: + ar->arNetworkType = ar->arNextMode = AP_NETWORK; + break; + } + + ar->arDot11AuthMode = OPEN_AUTH; + ar->arAuthMode = NONE_AUTH; + ar->arPairwiseCrypto = NONE_CRYPT; + ar->arPairwiseCryptoLen = 0; + ar->arGroupCrypto = NONE_CRYPT; + ar->arGroupCryptoLen = 0; + A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); + A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); + ar->arBssChannel = 0; +} + +static void +ar6000_init_control_info(struct ar6_softc *ar) +{ + ar->arWmiEnabled = false; + ar6000_init_profile_info(ar); + ar->arDefTxKeyIndex = 0; + A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); + ar->arChannelHint = 0; + ar->arListenIntervalT = A_DEFAULT_LISTEN_INTERVAL; + ar->arListenIntervalB = 0; + ar->arVersion.host_ver = AR6K_SW_VERSION; + ar->arRssi = 0; + ar->arTxPwr = 0; + ar->arTxPwrSet = false; + ar->arSkipScan = 0; + ar->arBeaconInterval = 0; + ar->arBitRate = 0; + ar->arMaxRetries = 0; + ar->arWmmEnabled = true; + ar->intra_bss = 1; + ar->scan_triggered = 0; + A_MEMZERO(&ar->scParams, sizeof(ar->scParams)); + ar->scParams.shortScanRatio = WMI_SHORTSCANRATIO_DEFAULT; + ar->scParams.scanCtrlFlags = DEFAULT_SCAN_CTRL_FLAGS; + + /* Initialize the AP mode state info */ + { + u8 ctr; + A_MEMZERO((u8 *)ar->sta_list, AP_MAX_NUM_STA * sizeof(sta_t)); + + /* init the Mutexes */ + A_MUTEX_INIT(&ar->mcastpsqLock); + + /* Init the PS queues */ + for (ctr=0; ctr < AP_MAX_NUM_STA ; ctr++) { + A_MUTEX_INIT(&ar->sta_list[ctr].psqLock); + A_NETBUF_QUEUE_INIT(&ar->sta_list[ctr].psq); + } + + ar->ap_profile_flag = 0; + A_NETBUF_QUEUE_INIT(&ar->mcastpsq); + + memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); + ar->ap_wmode = DEF_AP_WMODE_G; + ar->ap_dtim_period = DEF_AP_DTIM; + ar->ap_beacon_interval = DEF_BEACON_INTERVAL; + } +} + +static int +ar6000_open(struct net_device *dev) +{ + unsigned long flags; + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + spin_lock_irqsave(&ar->arLock, flags); + + if(ar->arWlanState == WLAN_DISABLED) { + ar->arWlanState = WLAN_ENABLED; + } + + if( ar->arConnected || bypasswmi) { + netif_carrier_on(dev); + /* Wake up the queues */ + netif_wake_queue(dev); + } + else + netif_carrier_off(dev); + + spin_unlock_irqrestore(&ar->arLock, flags); + return 0; +} + +static int +ar6000_close(struct net_device *dev) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + netif_stop_queue(dev); + + ar6000_disconnect(ar); + + if(ar->arWmiReady == true) { + if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, + 0, 0, 0, 0, 0, 0, 0, 0) != 0) { + return -EIO; + } + ar->arWlanState = WLAN_DISABLED; + } + ar6k_cfg80211_scanComplete_event(ar, A_ECANCELED); + + return 0; +} + +/* connect to a service */ +static int ar6000_connectservice(struct ar6_softc *ar, + struct htc_service_connect_req *pConnect, + char *pDesc) +{ + int status; + struct htc_service_connect_resp response; + + do { + + A_MEMZERO(&response,sizeof(response)); + + status = HTCConnectService(ar->arHtcTarget, + pConnect, + &response); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Failed to connect to %s service status:%d \n", + pDesc, status)); + break; + } + switch (pConnect->ServiceID) { + case WMI_CONTROL_SVC : + if (ar->arWmiEnabled) { + /* set control endpoint for WMI use */ + wmi_set_control_ep(ar->arWmi, response.Endpoint); + } + /* save EP for fast lookup */ + ar->arControlEp = response.Endpoint; + break; + case WMI_DATA_BE_SVC : + arSetAc2EndpointIDMap(ar, WMM_AC_BE, response.Endpoint); + break; + case WMI_DATA_BK_SVC : + arSetAc2EndpointIDMap(ar, WMM_AC_BK, response.Endpoint); + break; + case WMI_DATA_VI_SVC : + arSetAc2EndpointIDMap(ar, WMM_AC_VI, response.Endpoint); + break; + case WMI_DATA_VO_SVC : + arSetAc2EndpointIDMap(ar, WMM_AC_VO, response.Endpoint); + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ServiceID not mapped %d\n", pConnect->ServiceID)); + status = A_EINVAL; + break; + } + + } while (false); + + return status; +} + +void ar6000_TxDataCleanup(struct ar6_softc *ar) +{ + /* flush all the data (non-control) streams + * we only flush packets that are tagged as data, we leave any control packets that + * were in the TX queues alone */ + HTCFlushEndpoint(ar->arHtcTarget, + arAc2EndpointID(ar, WMM_AC_BE), + AR6K_DATA_PKT_TAG); + HTCFlushEndpoint(ar->arHtcTarget, + arAc2EndpointID(ar, WMM_AC_BK), + AR6K_DATA_PKT_TAG); + HTCFlushEndpoint(ar->arHtcTarget, + arAc2EndpointID(ar, WMM_AC_VI), + AR6K_DATA_PKT_TAG); + HTCFlushEndpoint(ar->arHtcTarget, + arAc2EndpointID(ar, WMM_AC_VO), + AR6K_DATA_PKT_TAG); +} + +HTC_ENDPOINT_ID +ar6000_ac2_endpoint_id ( void * devt, u8 ac) +{ + struct ar6_softc *ar = (struct ar6_softc *) devt; + return(arAc2EndpointID(ar, ac)); +} + +u8 ar6000_endpoint_id2_ac(void * devt, HTC_ENDPOINT_ID ep ) +{ + struct ar6_softc *ar = (struct ar6_softc *) devt; + return(arEndpoint2Ac(ar, ep )); +} + +#if defined(CONFIG_ATH6KL_ENABLE_COEXISTENCE) +static int ath6kl_config_btcoex_params(struct ar6_softc *ar) +{ + int r; + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD sbcb_cmd; + WMI_SET_BTCOEX_FE_ANT_CMD sbfa_cmd; + + /* Configure the type of BT collocated with WLAN */ + memset(&sbcb_cmd, 0, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)); + sbcb_cmd.btcoexCoLocatedBTdev = ATH6KL_BT_DEV; + + r = wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &sbcb_cmd); + + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Unable to set collocated BT type\n")); + return r; + } + + /* Configure the type of BT collocated with WLAN */ + memset(&sbfa_cmd, 0, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)); + + sbfa_cmd.btcoexFeAntType = ATH6KL_BT_ANTENNA; + + r = wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &sbfa_cmd); + if (r) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Unable to set fornt end antenna configuration\n")); + return r; + } + + return 0; +} +#else +static int ath6kl_config_btcoex_params(struct ar6_softc *ar) +{ + return 0; +} +#endif /* CONFIG_ATH6KL_ENABLE_COEXISTENCE */ + +/* + * This function applies WLAN specific configuration defined in wlan_config.h + */ +int ar6000_target_config_wlan_params(struct ar6_softc *ar) +{ + int status = 0; + +#ifdef CONFIG_HOST_TCMD_SUPPORT + if (ar->arTargetMode != AR6000_WLAN_MODE) { + return 0; + } +#endif /* CONFIG_HOST_TCMD_SUPPORT */ + + /* + * configure the device for rx dot11 header rules 0,0 are the default values + * therefore this command can be skipped if the inputs are 0,FALSE,FALSE.Required + * if checksum offload is needed. Set RxMetaVersion to 2 + */ + if ((wmi_set_rx_frame_format_cmd(ar->arWmi,ar->rxMetaVersion, processDot11Hdr, processDot11Hdr)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the rx frame format.\n")); + status = A_ERROR; + } + + status = ath6kl_config_btcoex_params(ar); + if (status) + return status; + +#if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN + if ((wmi_pmparams_cmd(ar->arWmi, 0, 1, 0, 0, 1, IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power save fail event policy\n")); + status = A_ERROR; + } +#endif + +#if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP + if ((wmi_set_lpreamble_cmd(ar->arWmi, 0, WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set barker preamble policy\n")); + status = A_ERROR; + } +#endif + + if ((wmi_set_keepalive_cmd(ar->arWmi, WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set keep alive interval\n")); + status = A_ERROR; + } + +#if WLAN_CONFIG_DISABLE_11N + { + WMI_SET_HT_CAP_CMD htCap; + + memset(&htCap, 0, sizeof(WMI_SET_HT_CAP_CMD)); + htCap.band = 0; + if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n")); + status = A_ERROR; + } + + htCap.band = 1; + if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n")); + status = A_ERROR; + } + } +#endif /* WLAN_CONFIG_DISABLE_11N */ + +#ifdef ATH6K_CONFIG_OTA_MODE + if ((wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power mode \n")); + status = A_ERROR; + } +#endif + + if ((wmi_disctimeout_cmd(ar->arWmi, WLAN_CONFIG_DISCONNECT_TIMEOUT)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set disconnect timeout \n")); + status = A_ERROR; + } + +#if WLAN_CONFIG_DISABLE_TX_BURSTING + if ((wmi_set_wmm_txop(ar->arWmi, WMI_TXOP_DISABLED)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set txop bursting \n")); + status = A_ERROR; + } +#endif + + return status; +} + +/* This function does one time initialization for the lifetime of the device */ +int ar6000_init(struct net_device *dev) +{ + struct ar6_softc *ar; + int status; + s32 timeleft; + s16 i; + int ret = 0; + + if((ar = ar6k_priv(dev)) == NULL) + { + return -EIO; + } + + if (wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) { + + ar6000_update_bdaddr(ar); + + if (enablerssicompensation) { + ar6000_copy_cust_data_from_target(ar->arHifDevice, ar->arTargetType); + read_rssi_compensation_param(ar); + for (i=-95; i<=0; i++) { + rssi_compensation_table[0-i] = rssi_compensation_calc(ar,i); + } + } + } + + dev_hold(dev); + rtnl_unlock(); + + /* Do we need to finish the BMI phase */ + if ((wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) && + (BMIDone(ar->arHifDevice) != 0)) + { + ret = -EIO; + goto ar6000_init_done; + } + + if (!bypasswmi) + { +#if 0 /* TBDXXX */ + if (ar->arVersion.host_ver != ar->arVersion.target_ver) { + A_PRINTF("WARNING: Host version 0x%x does not match Target " + " version 0x%x!\n", + ar->arVersion.host_ver, ar->arVersion.target_ver); + } +#endif + + /* Indicate that WMI is enabled (although not ready yet) */ + ar->arWmiEnabled = true; + if ((ar->arWmi = wmi_init((void *) ar)) == NULL) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize WMI.\n", __func__)); + ret = -EIO; + goto ar6000_init_done; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Got WMI @ 0x%lx.\n", __func__, + (unsigned long) ar->arWmi)); + } + + do { + struct htc_service_connect_req connect; + + /* the reason we have to wait for the target here is that the driver layer + * has to init BMI in order to set the host block size, + */ + status = HTCWaitTarget(ar->arHtcTarget); + + if (status) { + break; + } + + A_MEMZERO(&connect,sizeof(connect)); + /* meta data is unused for now */ + connect.pMetaData = NULL; + connect.MetaDataLength = 0; + /* these fields are the same for all service endpoints */ + connect.EpCallbacks.pContext = ar; + connect.EpCallbacks.EpTxCompleteMultiple = ar6000_tx_complete; + connect.EpCallbacks.EpRecv = ar6000_rx; + connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill; + connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full; + /* set the max queue depth so that our ar6000_tx_queue_full handler gets called. + * Linux has the peculiarity of not providing flow control between the + * NIC and the network stack. There is no API to indicate that a TX packet + * was sent which could provide some back pressure to the network stack. + * Under linux you would have to wait till the network stack consumed all sk_buffs + * before any back-flow kicked in. Which isn't very friendly. + * So we have to manage this ourselves */ + connect.MaxSendQueueDepth = MAX_DEFAULT_SEND_QUEUE_DEPTH; + connect.EpCallbacks.RecvRefillWaterMark = AR6000_MAX_RX_BUFFERS / 4; /* set to 25 % */ + if (0 == connect.EpCallbacks.RecvRefillWaterMark) { + connect.EpCallbacks.RecvRefillWaterMark++; + } + /* connect to control service */ + connect.ServiceID = WMI_CONTROL_SVC; + status = ar6000_connectservice(ar, + &connect, + "WMI CONTROL"); + if (status) { + break; + } + + connect.LocalConnectionFlags |= HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING; + /* limit the HTC message size on the send path, although we can receive A-MSDU frames of + * 4K, we will only send ethernet-sized (802.3) frames on the send path. */ + connect.MaxSendMsgSize = WMI_MAX_TX_DATA_FRAME_LENGTH; + + /* to reduce the amount of committed memory for larger A_MSDU frames, use the recv-alloc threshold + * mechanism for larger packets */ + connect.EpCallbacks.RecvAllocThreshold = AR6000_BUFFER_SIZE; + connect.EpCallbacks.EpRecvAllocThresh = ar6000_alloc_amsdu_rxbuf; + + /* for the remaining data services set the connection flag to reduce dribbling, + * if configured to do so */ + if (reduce_credit_dribble) { + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE; + /* the credit dribble trigger threshold is (reduce_credit_dribble - 1) for a value + * of 0-3 */ + connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK; + connect.ConnectionFlags |= + ((u16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK; + } + /* connect to best-effort service */ + connect.ServiceID = WMI_DATA_BE_SVC; + + status = ar6000_connectservice(ar, + &connect, + "WMI DATA BE"); + if (status) { + break; + } + + /* connect to back-ground + * map this to WMI LOW_PRI */ + connect.ServiceID = WMI_DATA_BK_SVC; + status = ar6000_connectservice(ar, + &connect, + "WMI DATA BK"); + if (status) { + break; + } + + /* connect to Video service, map this to + * to HI PRI */ + connect.ServiceID = WMI_DATA_VI_SVC; + status = ar6000_connectservice(ar, + &connect, + "WMI DATA VI"); + if (status) { + break; + } + + /* connect to VO service, this is currently not + * mapped to a WMI priority stream due to historical reasons. + * WMI originally defined 3 priorities over 3 mailboxes + * We can change this when WMI is reworked so that priorities are not + * dependent on mailboxes */ + connect.ServiceID = WMI_DATA_VO_SVC; + status = ar6000_connectservice(ar, + &connect, + "WMI DATA VO"); + if (status) { + break; + } + + A_ASSERT(arAc2EndpointID(ar,WMM_AC_BE) != 0); + A_ASSERT(arAc2EndpointID(ar,WMM_AC_BK) != 0); + A_ASSERT(arAc2EndpointID(ar,WMM_AC_VI) != 0); + A_ASSERT(arAc2EndpointID(ar,WMM_AC_VO) != 0); + + /* setup access class priority mappings */ + ar->arAcStreamPriMap[WMM_AC_BK] = 0; /* lowest */ + ar->arAcStreamPriMap[WMM_AC_BE] = 1; /* */ + ar->arAcStreamPriMap[WMM_AC_VI] = 2; /* */ + ar->arAcStreamPriMap[WMM_AC_VO] = 3; /* highest */ + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + if (setuphci && (NULL != ar6kHciTransCallbacks.setupTransport)) { + struct hci_transport_misc_handles hciHandles; + + hciHandles.netDevice = ar->arNetDev; + hciHandles.hifDevice = ar->arHifDevice; + hciHandles.htcHandle = ar->arHtcTarget; + status = (int)(ar6kHciTransCallbacks.setupTransport(&hciHandles)); + } +#else + if (setuphci) { + /* setup HCI */ + status = ar6000_setup_hci(ar); + } +#endif + + } while (false); + + if (status) { + ret = -EIO; + goto ar6000_init_done; + } + + if (regscanmode) { + u32 param; + + if (BMIReadMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, + hi_option_flag), + (u8 *)¶m, + 4) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("BMIReadMemory forsetting " + "regscanmode failed\n")); + return A_ERROR; + } + + if (regscanmode == 1) + param |= HI_OPTION_SKIP_REG_SCAN; + else if (regscanmode == 2) + param |= HI_OPTION_INIT_REG_SCAN; + + if (BMIWriteMemory(ar->arHifDevice, + HOST_INTEREST_ITEM_ADDRESS(ar, + hi_option_flag), + (u8 *)¶m, + 4) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("BMIWriteMemory forsetting " + "regscanmode failed\n")); + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Regulatory scan mode set\n")); + } + + /* + * give our connected endpoints some buffers + */ + + ar6000_rx_refill(ar, ar->arControlEp); + ar6000_rx_refill(ar, arAc2EndpointID(ar,WMM_AC_BE)); + + /* + * We will post the receive buffers only for SPE or endpoint ping testing so we are + * making it conditional on the 'bypasswmi' flag. + */ + if (bypasswmi) { + ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_BK)); + ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VI)); + ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VO)); + } + + /* allocate some buffers that handle larger AMSDU frames */ + ar6000_refill_amsdu_rxbufs(ar,AR6000_MAX_AMSDU_RX_BUFFERS); + + /* setup credit distribution */ + ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo); + + /* Since cookies are used for HTC transports, they should be */ + /* initialized prior to enabling HTC. */ + ar6000_cookie_init(ar); + + /* start HTC */ + status = HTCStart(ar->arHtcTarget); + + if (status) { + if (ar->arWmiEnabled == true) { + wmi_shutdown(ar->arWmi); + ar->arWmiEnabled = false; + ar->arWmi = NULL; + } + ar6000_cookie_cleanup(ar); + ret = -EIO; + goto ar6000_init_done; + } + + if (!bypasswmi) { + /* Wait for Wmi event to be ready */ + timeleft = wait_event_interruptible_timeout(arEvent, + (ar->arWmiReady == true), wmitimeout * HZ); + + if (ar->arVersion.abi_ver != AR6K_ABI_VERSION) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ABI Version mismatch: Host(0x%x), Target(0x%x)\n", AR6K_ABI_VERSION, ar->arVersion.abi_ver)); +#ifndef ATH6K_SKIP_ABI_VERSION_CHECK + ret = -EIO; + goto ar6000_init_done; +#endif /* ATH6K_SKIP_ABI_VERSION_CHECK */ + } + + if(!timeleft || signal_pending(current)) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI is not ready or wait was interrupted\n")); + ret = -EIO; + goto ar6000_init_done; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() WMI is ready\n", __func__)); + + /* Communicate the wmi protocol verision to the target */ + if ((ar6000_set_host_app_area(ar)) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the host app area\n")); + } + ar6000_target_config_wlan_params(ar); + } + + ar->arNumDataEndPts = 1; + + if (bypasswmi) { + /* for tests like endpoint ping, the MAC address needs to be non-zero otherwise + * the data path through a raw socket is disabled */ + dev->dev_addr[0] = 0x00; + dev->dev_addr[1] = 0x01; + dev->dev_addr[2] = 0x02; + dev->dev_addr[3] = 0xAA; + dev->dev_addr[4] = 0xBB; + dev->dev_addr[5] = 0xCC; + } + +ar6000_init_done: + rtnl_lock(); + dev_put(dev); + + return ret; +} + + +void +ar6000_bitrate_rx(void *devt, s32 rateKbps) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + ar->arBitRate = rateKbps; + wake_up(&arEvent); +} + +void +ar6000_ratemask_rx(void *devt, u32 ratemask) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + ar->arRateMask = ratemask; + wake_up(&arEvent); +} + +void +ar6000_txPwr_rx(void *devt, u8 txPwr) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + ar->arTxPwr = txPwr; + wake_up(&arEvent); +} + + +void +ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + memcpy(ar->arChannelList, chanList, numChan * sizeof (u16)); + ar->arNumChannels = numChan; + + wake_up(&arEvent); +} + +u8 ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, u32 *mapNo) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + u8 *datap; + ATH_MAC_HDR *macHdr; + u32 i, eptMap; + + (*mapNo) = 0; + datap = A_NETBUF_DATA(skb); + macHdr = (ATH_MAC_HDR *)(datap + sizeof(WMI_DATA_HDR)); + if (IEEE80211_IS_MULTICAST(macHdr->dstMac)) { + return ENDPOINT_2; + } + + eptMap = -1; + for (i = 0; i < ar->arNodeNum; i ++) { + if (IEEE80211_ADDR_EQ(macHdr->dstMac, ar->arNodeMap[i].macAddress)) { + (*mapNo) = i + 1; + ar->arNodeMap[i].txPending ++; + return ar->arNodeMap[i].epId; + } + + if ((eptMap == -1) && !ar->arNodeMap[i].txPending) { + eptMap = i; + } + } + + if (eptMap == -1) { + eptMap = ar->arNodeNum; + ar->arNodeNum ++; + A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM); + } + + memcpy(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN); + + for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) { + if (!ar->arTxPending[i]) { + ar->arNodeMap[eptMap].epId = i; + break; + } + // No free endpoint is available, start redistribution on the inuse endpoints. + if (i == ENDPOINT_5) { + ar->arNodeMap[eptMap].epId = ar->arNexEpId; + ar->arNexEpId ++; + if (ar->arNexEpId > ENDPOINT_5) { + ar->arNexEpId = ENDPOINT_2; + } + } + } + + (*mapNo) = eptMap + 1; + ar->arNodeMap[eptMap].txPending ++; + + return ar->arNodeMap[eptMap].epId; +} + +#ifdef DEBUG +static void ar6000_dump_skb(struct sk_buff *skb) +{ + u_char *ch; + for (ch = A_NETBUF_DATA(skb); + (unsigned long)ch < ((unsigned long)A_NETBUF_DATA(skb) + + A_NETBUF_LEN(skb)); ch++) + { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("%2.2x ", *ch)); + } + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("\n")); +} +#endif + +#ifdef HTC_TEST_SEND_PKTS +static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *skb); +#endif + +static int +ar6000_data_tx(struct sk_buff *skb, struct net_device *dev) +{ +#define AC_NOT_MAPPED 99 + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + u8 ac = AC_NOT_MAPPED; + HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; + u32 mapNo = 0; + int len; + struct ar_cookie *cookie; + bool checkAdHocPsMapping = false,bMoreData = false; + HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; + u8 dot11Hdr = processDot11Hdr; +#ifdef CONFIG_PM + if (ar->arWowState != WLAN_WOW_STATE_NONE) { + A_NETBUF_FREE(skb); + return 0; + } +#endif /* CONFIG_PM */ + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_data_tx start - skb=0x%lx, data=0x%lx, len=0x%x\n", + (unsigned long)skb, (unsigned long)A_NETBUF_DATA(skb), + A_NETBUF_LEN(skb))); + + /* If target is not associated */ + if( (!ar->arConnected && !bypasswmi) +#ifdef CONFIG_HOST_TCMD_SUPPORT + /* TCMD doesn't support any data, free the buf and return */ + || (ar->arTargetMode == AR6000_TCMD_MODE) +#endif + ) { + A_NETBUF_FREE(skb); + return 0; + } + + do { + + if (ar->arWmiReady == false && bypasswmi == 0) { + break; + } + +#ifdef BLOCK_TX_PATH_FLAG + if (blocktx) { + break; + } +#endif /* BLOCK_TX_PATH_FLAG */ + + /* AP mode Power save processing */ + /* If the dst STA is in sleep state, queue the pkt in its PS queue */ + + if (ar->arNetworkType == AP_NETWORK) { + ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); + sta_t *conn = NULL; + + /* If the dstMac is a Multicast address & atleast one of the + * associated STA is in PS mode, then queue the pkt to the + * mcastq + */ + if (IEEE80211_IS_MULTICAST(datap->dstMac)) { + u8 ctr=0; + bool qMcast=false; + + + for (ctr=0; ctrsta_list[ctr]))) { + qMcast = true; + } + } + if(qMcast) { + + /* If this transmit is not because of a Dtim Expiry q it */ + if (ar->DTIMExpired == false) { + bool isMcastqEmpty = false; + + A_MUTEX_LOCK(&ar->mcastpsqLock); + isMcastqEmpty = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq); + A_NETBUF_ENQUEUE(&ar->mcastpsq, skb); + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + /* If this is the first Mcast pkt getting queued + * indicate to the target to set the BitmapControl LSB + * of the TIM IE. + */ + if (isMcastqEmpty) { + wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 1); + } + return 0; + } else { + /* This transmit is because of Dtim expiry. Determine if + * MoreData bit has to be set. + */ + A_MUTEX_LOCK(&ar->mcastpsqLock); + if(!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { + bMoreData = true; + } + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + } + } + } else { + conn = ieee80211_find_conn(ar, datap->dstMac); + if (conn) { + if (STA_IS_PWR_SLEEP(conn)) { + /* If this transmit is not because of a PsPoll q it*/ + if (!STA_IS_PS_POLLED(conn)) { + bool isPsqEmpty = false; + /* Queue the frames if the STA is sleeping */ + A_MUTEX_LOCK(&conn->psqLock); + isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); + A_NETBUF_ENQUEUE(&conn->psq, skb); + A_MUTEX_UNLOCK(&conn->psqLock); + + /* If this is the first pkt getting queued + * for this STA, update the PVB for this STA + */ + if (isPsqEmpty) { + wmi_set_pvb_cmd(ar->arWmi, conn->aid, 1); + } + + return 0; + } else { + /* This tx is because of a PsPoll. Determine if + * MoreData bit has to be set + */ + A_MUTEX_LOCK(&conn->psqLock); + if (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) { + bMoreData = true; + } + A_MUTEX_UNLOCK(&conn->psqLock); + } + } + } else { + + /* non existent STA. drop the frame */ + A_NETBUF_FREE(skb); + return 0; + } + } + } + + if (ar->arWmiEnabled) { + u8 csumStart=0; + u8 csumDest=0; + u8 csum=skb->ip_summed; + if(csumOffload && (csum==CHECKSUM_PARTIAL)){ + csumStart = (skb->head + skb->csum_start - skb_network_header(skb) + + sizeof(ATH_LLC_SNAP_HDR)); + csumDest=skb->csum_offset+csumStart; + } + if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len - LINUX_HACK_FUDGE_FACTOR) { + struct sk_buff *newbuf; + + /* + * We really should have gotten enough headroom but sometimes + * we still get packets with not enough headroom. Copy the packet. + */ + len = A_NETBUF_LEN(skb); + newbuf = A_NETBUF_ALLOC(len); + if (newbuf == NULL) { + break; + } + A_NETBUF_PUT(newbuf, len); + memcpy(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len); + A_NETBUF_FREE(skb); + skb = newbuf; + /* fall through and assemble header */ + } + + if (dot11Hdr) { + if (wmi_dot11_hdr_add(ar->arWmi,skb,ar->arNetworkType) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx-wmi_dot11_hdr_add failed\n")); + break; + } + } else { + if (wmi_dix_2_dot3(ar->arWmi, skb) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_dix_2_dot3 failed\n")); + break; + } + } + if(csumOffload && (csum ==CHECKSUM_PARTIAL)){ + WMI_TX_META_V2 metaV2; + metaV2.csumStart =csumStart; + metaV2.csumDest = csumDest; + metaV2.csumFlags = 0x1;/*instruct target to calculate checksum*/ + if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr, + WMI_META_VERSION_2,&metaV2) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n")); + break; + } + + } + else + { + if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,0,NULL) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n")); + break; + } + } + + + if ((ar->arNetworkType == ADHOC_NETWORK) && + ar->arIbssPsEnable && ar->arConnected) { + /* flag to check adhoc mapping once we take the lock below: */ + checkAdHocPsMapping = true; + + } else { + /* get the stream mapping */ + ac = wmi_implicit_create_pstream(ar->arWmi, skb, 0, ar->arWmmEnabled); + } + + } else { + EPPING_HEADER *eppingHdr; + + eppingHdr = A_NETBUF_DATA(skb); + + if (IS_EPPING_PACKET(eppingHdr)) { + /* the stream ID is mapped to an access class */ + ac = eppingHdr->StreamNo_h; + /* some EPPING packets cannot be dropped no matter what access class it was + * sent on. We can change the packet tag to guarantee it will not get dropped */ + if (IS_EPING_PACKET_NO_DROP(eppingHdr)) { + htc_tag = AR6K_CONTROL_PKT_TAG; + } + + if (ac == HCI_TRANSPORT_STREAM_NUM) { + /* pass this to HCI */ +#ifndef EXPORT_HCI_BRIDGE_INTERFACE + if (!hci_test_send(ar,skb)) { + return 0; + } +#endif + /* set AC to discard this skb */ + ac = AC_NOT_MAPPED; + } else { + /* a quirk of linux, the payload of the frame is 32-bit aligned and thus the addition + * of the HTC header will mis-align the start of the HTC frame, so we add some + * padding which will be stripped off in the target */ + if (EPPING_ALIGNMENT_PAD > 0) { + A_NETBUF_PUSH(skb, EPPING_ALIGNMENT_PAD); + } + } + + } else { + /* not a ping packet, drop it */ + ac = AC_NOT_MAPPED; + } + } + + } while (false); + + /* did we succeed ? */ + if ((ac == AC_NOT_MAPPED) && !checkAdHocPsMapping) { + /* cleanup and exit */ + A_NETBUF_FREE(skb); + AR6000_STAT_INC(ar, tx_dropped); + AR6000_STAT_INC(ar, tx_aborted_errors); + return 0; + } + + cookie = NULL; + + /* take the lock to protect driver data */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + + do { + + if (checkAdHocPsMapping) { + eid = ar6000_ibss_map_epid(skb, dev, &mapNo); + }else { + eid = arAc2EndpointID (ar, ac); + } + /* validate that the endpoint is connected */ + if (eid == 0 || eid == ENDPOINT_UNUSED ) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" eid %d is NOT mapped!\n", eid)); + break; + } + /* allocate resource for this packet */ + cookie = ar6000_alloc_cookie(ar); + + if (cookie != NULL) { + /* update counts while the lock is held */ + ar->arTxPending[eid]++; + ar->arTotalTxDataPending++; + } + + } while (false); + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (cookie != NULL) { + cookie->arc_bp[0] = (unsigned long)skb; + cookie->arc_bp[1] = mapNo; + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, + A_NETBUF_DATA(skb), + A_NETBUF_LEN(skb), + eid, + htc_tag); + +#ifdef DEBUG + if (debugdriver >= 3) { + ar6000_dump_skb(skb); + } +#endif +#ifdef HTC_TEST_SEND_PKTS + DoHTCSendPktsTest(ar,mapNo,eid,skb); +#endif + /* HTC interface is asynchronous, if this fails, cleanup will happen in + * the ar6000_tx_complete callback */ + HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); + } else { + /* no packet to send, cleanup */ + A_NETBUF_FREE(skb); + AR6000_STAT_INC(ar, tx_dropped); + AR6000_STAT_INC(ar, tx_aborted_errors); + } + + return 0; +} + +int +ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + struct ar_cookie *cookie; + HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; + + cookie = NULL; + AR6000_SPIN_LOCK(&ar->arLock, 0); + + /* For now we send ACL on BE endpoint: We can also have a dedicated EP */ + eid = arAc2EndpointID (ar, 0); + /* allocate resource for this packet */ + cookie = ar6000_alloc_cookie(ar); + + if (cookie != NULL) { + /* update counts while the lock is held */ + ar->arTxPending[eid]++; + ar->arTotalTxDataPending++; + } + + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (cookie != NULL) { + cookie->arc_bp[0] = (unsigned long)skb; + cookie->arc_bp[1] = 0; + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, + A_NETBUF_DATA(skb), + A_NETBUF_LEN(skb), + eid, + AR6K_DATA_PKT_TAG); + + /* HTC interface is asynchronous, if this fails, cleanup will happen in + * the ar6000_tx_complete callback */ + HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); + } else { + /* no packet to send, cleanup */ + A_NETBUF_FREE(skb); + AR6000_STAT_INC(ar, tx_dropped); + AR6000_STAT_INC(ar, tx_aborted_errors); + } + return 0; +} + + +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL +static void +tvsub(register struct timeval *out, register struct timeval *in) +{ + if((out->tv_usec -= in->tv_usec) < 0) { + out->tv_sec--; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; +} + +void +applyAPTCHeuristics(struct ar6_softc *ar) +{ + u32 duration; + u32 numbytes; + u32 throughput; + struct timeval ts; + int status; + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + if ((enableAPTCHeuristics) && (!aptcTR.timerScheduled)) { + do_gettimeofday(&ts); + tvsub(&ts, &aptcTR.samplingTS); + duration = ts.tv_sec * 1000 + ts.tv_usec / 1000; /* ms */ + numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; + + if (duration > APTC_TRAFFIC_SAMPLING_INTERVAL) { + /* Initialize the time stamp and byte count */ + aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; + do_gettimeofday(&aptcTR.samplingTS); + + /* Calculate and decide based on throughput thresholds */ + throughput = ((numbytes * 8) / duration); + if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) { + /* Disable Sleep and schedule a timer */ + A_ASSERT(ar->arWmiReady == true); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER); + AR6000_SPIN_LOCK(&ar->arLock, 0); + A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); + aptcTR.timerScheduled = true; + } + } + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); +} +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + +static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + HTC_SEND_FULL_ACTION action = HTC_SEND_FULL_KEEP; + bool stopNet = false; + HTC_ENDPOINT_ID Endpoint = HTC_GET_ENDPOINT_FROM_PKT(pPacket); + + do { + + if (bypasswmi) { + int accessClass; + + if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) { + /* don't drop special control packets */ + break; + } + + accessClass = arEndpoint2Ac(ar,Endpoint); + /* for endpoint ping testing drop Best Effort and Background */ + if ((accessClass == WMM_AC_BE) || (accessClass == WMM_AC_BK)) { + action = HTC_SEND_FULL_DROP; + stopNet = false; + } else { + /* keep but stop the netqueues */ + stopNet = true; + } + break; + } + + if (Endpoint == ar->arControlEp) { + /* under normal WMI if this is getting full, then something is running rampant + * the host should not be exhausting the WMI queue with too many commands + * the only exception to this is during testing using endpointping */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + /* set flag to handle subsequent messages */ + ar->arWMIControlEpFull = true; + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI Control Endpoint is FULL!!! \n")); + /* no need to stop the network */ + stopNet = false; + break; + } + + /* if we get here, we are dealing with data endpoints getting full */ + + if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) { + /* don't drop control packets issued on ANY data endpoint */ + break; + } + + if (ar->arNetworkType == ADHOC_NETWORK) { + /* in adhoc mode, we cannot differentiate traffic priorities so there is no need to + * continue, however we should stop the network */ + stopNet = true; + break; + } + /* the last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for the highest + * active stream */ + if (ar->arAcStreamPriMap[arEndpoint2Ac(ar,Endpoint)] < ar->arHiAcStreamActivePri && + ar->arCookieCount <= MAX_HI_COOKIE_NUM) { + /* this stream's priority is less than the highest active priority, we + * give preference to the highest priority stream by directing + * HTC to drop the packet that overflowed */ + action = HTC_SEND_FULL_DROP; + /* since we are dropping packets, no need to stop the network */ + stopNet = false; + break; + } + + } while (false); + + if (stopNet) { + AR6000_SPIN_LOCK(&ar->arLock, 0); + ar->arNetQueueStopped = true; + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + /* one of the data endpoints queues is getting full..need to stop network stack + * the queue will resume in ar6000_tx_complete() */ + netif_stop_queue(ar->arNetDev); + } + + return action; +} + + +static void +ar6000_tx_complete(void *Context, struct htc_packet_queue *pPacketQueue) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + u32 mapNo = 0; + int status; + struct ar_cookie * ar_cookie; + HTC_ENDPOINT_ID eid; + bool wakeEvent = false; + struct sk_buff_head skb_queue; + struct htc_packet *pPacket; + struct sk_buff *pktSkb; + bool flushing = false; + + skb_queue_head_init(&skb_queue); + + /* lock the driver as we update internal state */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + + /* reap completed packets */ + while (!HTC_QUEUE_EMPTY(pPacketQueue)) { + + pPacket = HTC_PACKET_DEQUEUE(pPacketQueue); + + ar_cookie = (struct ar_cookie *)pPacket->pPktContext; + A_ASSERT(ar_cookie); + + status = pPacket->Status; + pktSkb = (struct sk_buff *)ar_cookie->arc_bp[0]; + eid = pPacket->Endpoint; + mapNo = ar_cookie->arc_bp[1]; + + A_ASSERT(pktSkb); + A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(pktSkb)); + + /* add this to the list, use faster non-lock API */ + __skb_queue_tail(&skb_queue,pktSkb); + + if (!status) { + A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(pktSkb)); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_tx_complete skb=0x%lx data=0x%lx len=0x%x eid=%d ", + (unsigned long)pktSkb, (unsigned long)pPacket->pBuffer, + pPacket->ActualLength, + eid)); + + ar->arTxPending[eid]--; + + if ((eid != ar->arControlEp) || bypasswmi) { + ar->arTotalTxDataPending--; + } + + if (eid == ar->arControlEp) + { + if (ar->arWMIControlEpFull) { + /* since this packet completed, the WMI EP is no longer full */ + ar->arWMIControlEpFull = false; + } + + if (ar->arTxPending[eid] == 0) { + wakeEvent = true; + } + } + + if (status) { + if (status == A_ECANCELED) { + /* a packet was flushed */ + flushing = true; + } + AR6000_STAT_INC(ar, tx_errors); + if (status != A_NO_RESOURCE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() -TX ERROR, status: 0x%x\n", __func__, + status)); + } + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("OK\n")); + flushing = false; + AR6000_STAT_INC(ar, tx_packets); + ar->arNetStats.tx_bytes += A_NETBUF_LEN(pktSkb); +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + aptcTR.bytesTransmitted += a_netbuf_to_len(pktSkb); + applyAPTCHeuristics(ar); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + } + + // TODO this needs to be looked at + if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable + && (eid != ar->arControlEp) && mapNo) + { + mapNo --; + ar->arNodeMap[mapNo].txPending --; + + if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) { + u32 i; + for (i = ar->arNodeNum; i > 0; i --) { + if (!ar->arNodeMap[i - 1].txPending) { + A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping)); + ar->arNodeNum --; + } else { + break; + } + } + } + } + + ar6000_free_cookie(ar, ar_cookie); + + if (ar->arNetQueueStopped) { + ar->arNetQueueStopped = false; + } + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + /* lock is released, we can freely call other kernel APIs */ + + /* free all skbs in our local list */ + while (!skb_queue_empty(&skb_queue)) { + /* use non-lock version */ + pktSkb = __skb_dequeue(&skb_queue); + A_NETBUF_FREE(pktSkb); + } + + if ((ar->arConnected == true) || bypasswmi) { + if (!flushing) { + /* don't wake the queue if we are flushing, other wise it will just + * keep queueing packets, which will keep failing */ + netif_wake_queue(ar->arNetDev); + } + } + + if (wakeEvent) { + wake_up(&arEvent); + } + +} + +sta_t * +ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr) +{ + sta_t *conn = NULL; + u8 i, max_conn; + + switch(ar->arNetworkType) { + case AP_NETWORK: + max_conn = AP_MAX_NUM_STA; + break; + default: + max_conn=0; + break; + } + + for (i = 0; i < max_conn; i++) { + if (IEEE80211_ADDR_EQ(node_addr, ar->sta_list[i].mac)) { + conn = &ar->sta_list[i]; + break; + } + } + + return conn; +} + +sta_t *ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid) +{ + sta_t *conn = NULL; + u8 ctr; + + for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { + if (ar->sta_list[ctr].aid == aid) { + conn = &ar->sta_list[ctr]; + break; + } + } + return conn; +} + +/* + * Receive event handler. This is called by HTC when a packet is received + */ +int pktcount; +static void +ar6000_rx(void *Context, struct htc_packet *pPacket) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext; + int minHdrLen; + u8 containsDot11Hdr = 0; + int status = pPacket->Status; + HTC_ENDPOINT_ID ept = pPacket->Endpoint; + + A_ASSERT((status) || + (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN))); + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx ar=0x%lx eid=%d, skb=0x%lx, data=0x%lx, len=0x%x status:%d", + (unsigned long)ar, ept, (unsigned long)skb, (unsigned long)pPacket->pBuffer, + pPacket->ActualLength, status)); + if (status) { + if (status != A_ECANCELED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("RX ERR (%d) \n",status)); + } + } + + /* take lock to protect buffer counts + * and adaptive power throughput state */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + + if (!status) { + AR6000_STAT_INC(ar, rx_packets); + ar->arNetStats.rx_bytes += pPacket->ActualLength; +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL + aptcTR.bytesReceived += a_netbuf_to_len(skb); + applyAPTCHeuristics(ar); +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ + + A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN); + A_NETBUF_PULL(skb, HTC_HEADER_LEN); + +#ifdef DEBUG + if (debugdriver >= 2) { + ar6000_dump_skb(skb); + } +#endif /* DEBUG */ + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + skb->dev = ar->arNetDev; + if (status) { + AR6000_STAT_INC(ar, rx_errors); + A_NETBUF_FREE(skb); + } else if (ar->arWmiEnabled == true) { + if (ept == ar->arControlEp) { + /* + * this is a wmi control msg + */ +#ifdef CONFIG_PM + ar6000_check_wow_status(ar, skb, true); +#endif /* CONFIG_PM */ + wmi_control_rx(ar->arWmi, skb); + } else { + WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb); + bool is_amsdu; + u8 tid; + + /* + * This check can be removed if after a while we do not + * see the warning. For now we leave it to ensure + * we drop these frames accordingly in case the + * target generates them for some reason. These + * were used for an internal PAL but that's not + * used or supported anymore. These frames should + * not come up from the target. + */ + if (WARN_ON(WMI_DATA_HDR_GET_DATA_TYPE(dhdr) == + WMI_DATA_HDR_DATA_TYPE_ACL)) { + AR6000_STAT_INC(ar, rx_errors); + A_NETBUF_FREE(skb); + return; + } + +#ifdef CONFIG_PM + ar6000_check_wow_status(ar, NULL, false); +#endif /* CONFIG_PM */ + /* + * this is a wmi data packet + */ + // NWF + + if (processDot11Hdr) { + minHdrLen = sizeof(WMI_DATA_HDR) + sizeof(struct ieee80211_frame) + sizeof(ATH_LLC_SNAP_HDR); + } else { + minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + + sizeof(ATH_LLC_SNAP_HDR); + } + + /* In the case of AP mode we may receive NULL data frames + * that do not have LLC hdr. They are 16 bytes in size. + * Allow these frames in the AP mode. + * ACL data frames don't follow ethernet frame bounds for + * min length + */ + if (ar->arNetworkType != AP_NETWORK && + ((pPacket->ActualLength < minHdrLen) || + (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_SIZE))) + { + /* + * packet is too short or too long + */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("TOO SHORT or TOO LONG\n")); + AR6000_STAT_INC(ar, rx_errors); + AR6000_STAT_INC(ar, rx_length_errors); + A_NETBUF_FREE(skb); + } else { + u16 seq_no; + u8 meta_type; + +#if 0 + /* Access RSSI values here */ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("RSSI %d\n", + ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi)); +#endif + /* Get the Power save state of the STA */ + if (ar->arNetworkType == AP_NETWORK) { + sta_t *conn = NULL; + u8 psState=0,prevPsState; + ATH_MAC_HDR *datap=NULL; + u16 offset; + + meta_type = WMI_DATA_HDR_GET_META(dhdr); + + psState = (((WMI_DATA_HDR *)A_NETBUF_DATA(skb))->info + >> WMI_DATA_HDR_PS_SHIFT) & WMI_DATA_HDR_PS_MASK; + + offset = sizeof(WMI_DATA_HDR); + + switch (meta_type) { + case 0: + break; + case WMI_META_VERSION_1: + offset += sizeof(WMI_RX_META_V1); + break; + case WMI_META_VERSION_2: + offset += sizeof(WMI_RX_META_V2); + break; + default: + break; + } + + datap = (ATH_MAC_HDR *)(A_NETBUF_DATA(skb)+offset); + conn = ieee80211_find_conn(ar, datap->srcMac); + + if (conn) { + /* if there is a change in PS state of the STA, + * take appropriate steps. + * 1. If Sleep-->Awake, flush the psq for the STA + * Clear the PVB for the STA. + * 2. If Awake-->Sleep, Starting queueing frames + * the STA. + */ + prevPsState = STA_IS_PWR_SLEEP(conn); + if (psState) { + STA_SET_PWR_SLEEP(conn); + } else { + STA_CLR_PWR_SLEEP(conn); + } + + if (prevPsState ^ STA_IS_PWR_SLEEP(conn)) { + + if (!STA_IS_PWR_SLEEP(conn)) { + + A_MUTEX_LOCK(&conn->psqLock); + while (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) { + struct sk_buff *skb=NULL; + + skb = A_NETBUF_DEQUEUE(&conn->psq); + A_MUTEX_UNLOCK(&conn->psqLock); + ar6000_data_tx(skb,ar->arNetDev); + A_MUTEX_LOCK(&conn->psqLock); + } + A_MUTEX_UNLOCK(&conn->psqLock); + /* Clear the PVB for this STA */ + wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0); + } + } + } else { + /* This frame is from a STA that is not associated*/ + A_ASSERT(false); + } + + /* Drop NULL data frames here */ + if((pPacket->ActualLength < minHdrLen) || + (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_SIZE)) { + A_NETBUF_FREE(skb); + goto rx_done; + } + } + + is_amsdu = WMI_DATA_HDR_IS_AMSDU(dhdr) ? true : false; + tid = WMI_DATA_HDR_GET_UP(dhdr); + seq_no = WMI_DATA_HDR_GET_SEQNO(dhdr); + meta_type = WMI_DATA_HDR_GET_META(dhdr); + containsDot11Hdr = WMI_DATA_HDR_GET_DOT11(dhdr); + + wmi_data_hdr_remove(ar->arWmi, skb); + + switch (meta_type) { + case WMI_META_VERSION_1: + { + WMI_RX_META_V1 *pMeta = (WMI_RX_META_V1 *)A_NETBUF_DATA(skb); + A_PRINTF("META %d %d %d %d %x\n", pMeta->status, pMeta->rix, pMeta->rssi, pMeta->channel, pMeta->flags); + A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V1)); + break; + } + case WMI_META_VERSION_2: + { + WMI_RX_META_V2 *pMeta = (WMI_RX_META_V2 *)A_NETBUF_DATA(skb); + if(pMeta->csumFlags & 0x1){ + skb->ip_summed=CHECKSUM_COMPLETE; + skb->csum=(pMeta->csum); + } + A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V2)); + break; + } + default: + break; + } + + A_ASSERT(status == 0); + + /* NWF: print the 802.11 hdr bytes */ + if(containsDot11Hdr) { + status = wmi_dot11_hdr_remove(ar->arWmi,skb); + } else if(!is_amsdu) { + status = wmi_dot3_2_dix(skb); + } + + if (status) { + /* Drop frames that could not be processed (lack of memory, etc.) */ + A_NETBUF_FREE(skb); + goto rx_done; + } + + if ((ar->arNetDev->flags & IFF_UP) == IFF_UP) { + if (ar->arNetworkType == AP_NETWORK) { + struct sk_buff *skb1 = NULL; + ATH_MAC_HDR *datap; + + datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); + if (IEEE80211_IS_MULTICAST(datap->dstMac)) { + /* Bcast/Mcast frames should be sent to the OS + * stack as well as on the air. + */ + skb1 = skb_copy(skb,GFP_ATOMIC); + } else { + /* Search for a connected STA with dstMac as + * the Mac address. If found send the frame to + * it on the air else send the frame up the + * stack + */ + sta_t *conn = NULL; + conn = ieee80211_find_conn(ar, datap->dstMac); + + if (conn && ar->intra_bss) { + skb1 = skb; + skb = NULL; + } else if(conn && !ar->intra_bss) { + A_NETBUF_FREE(skb); + skb = NULL; + } + } + if (skb1) { + ar6000_data_tx(skb1, ar->arNetDev); + } + } + } + aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, is_amsdu, (void **)&skb); + ar6000_deliver_frames_to_nw_stack((void *) ar->arNetDev, (void *)skb); + } + } + } else { + if (EPPING_ALIGNMENT_PAD > 0) { + A_NETBUF_PULL(skb, EPPING_ALIGNMENT_PAD); + } + ar6000_deliver_frames_to_nw_stack((void *)ar->arNetDev, (void *)skb); + } + +rx_done: + + return; +} + +static void +ar6000_deliver_frames_to_nw_stack(void *dev, void *osbuf) +{ + struct sk_buff *skb = (struct sk_buff *)osbuf; + + if(skb) { + skb->dev = dev; + if ((skb->dev->flags & IFF_UP) == IFF_UP) { +#ifdef CONFIG_PM + ar6000_check_wow_status((struct ar6_softc *)ar6k_priv(dev), skb, false); +#endif /* CONFIG_PM */ + skb->protocol = eth_type_trans(skb, skb->dev); + /* + * If this routine is called on a ISR (Hard IRQ) or DSR (Soft IRQ) + * or tasklet use the netif_rx to deliver the packet to the stack + * netif_rx will queue the packet onto the receive queue and mark + * the softirq thread has a pending action to complete. Kernel will + * schedule the softIrq kernel thread after processing the DSR. + * + * If this routine is called on a process context, use netif_rx_ni + * which will schedle the softIrq kernel thread after queuing the packet. + */ + if (in_interrupt()) { + netif_rx(skb); + } else { + netif_rx_ni(skb); + } + } else { + A_NETBUF_FREE(skb); + } + } +} + +#if 0 +static void +ar6000_deliver_frames_to_bt_stack(void *dev, void *osbuf) +{ + struct sk_buff *skb = (struct sk_buff *)osbuf; + + if(skb) { + skb->dev = dev; + if ((skb->dev->flags & IFF_UP) == IFF_UP) { + skb->protocol = htons(ETH_P_CONTROL); + netif_rx(skb); + } else { + A_NETBUF_FREE(skb); + } + } +} +#endif + +static void +ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + void *osBuf; + int RxBuffers; + int buffersToRefill; + struct htc_packet *pPacket; + struct htc_packet_queue queue; + + buffersToRefill = (int)AR6000_MAX_RX_BUFFERS - + HTCGetNumRecvBuffers(ar->arHtcTarget, Endpoint); + + if (buffersToRefill <= 0) { + /* fast return, nothing to fill */ + return; + } + + INIT_HTC_PACKET_QUEUE(&queue); + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx_refill: providing htc with %d buffers at eid=%d\n", + buffersToRefill, Endpoint)); + + for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) { + osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE); + if (NULL == osBuf) { + break; + } + /* the HTC packet wrapper is at the head of the reserved area + * in the skb */ + pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf)); + /* set re-fill info */ + SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint); + /* add to queue */ + HTC_PACKET_ENQUEUE(&queue,pPacket); + } + + if (!HTC_QUEUE_EMPTY(&queue)) { + /* add packets */ + HTCAddReceivePktMultiple(ar->arHtcTarget, &queue); + } + +} + + /* clean up our amsdu buffer list */ +static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar) +{ + struct htc_packet *pPacket; + void *osBuf; + + /* empty AMSDU buffer queue and free OS bufs */ + while (true) { + + AR6000_SPIN_LOCK(&ar->arLock, 0); + pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (NULL == pPacket) { + break; + } + + osBuf = pPacket->pPktContext; + if (NULL == osBuf) { + A_ASSERT(false); + break; + } + + A_NETBUF_FREE(osBuf); + } + +} + + + /* refill the amsdu buffer list */ +static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count) +{ + struct htc_packet *pPacket; + void *osBuf; + + while (Count > 0) { + osBuf = A_NETBUF_ALLOC(AR6000_AMSDU_BUFFER_SIZE); + if (NULL == osBuf) { + break; + } + /* the HTC packet wrapper is at the head of the reserved area + * in the skb */ + pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf)); + /* set re-fill info */ + SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_AMSDU_BUFFER_SIZE,0); + + AR6000_SPIN_LOCK(&ar->arLock, 0); + /* put it in the list */ + HTC_PACKET_ENQUEUE(&ar->amsdu_rx_buffer_queue,pPacket); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + Count--; + } + +} + + /* callback to allocate a large receive buffer for a pending packet. This function is called when + * an HTC packet arrives whose length exceeds a threshold value + * + * We use a pre-allocated list of buffers of maximum AMSDU size (4K). Under linux it is more optimal to + * keep the allocation size the same to optimize cached-slab allocations. + * + * */ +static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length) +{ + struct htc_packet *pPacket = NULL; + struct ar6_softc *ar = (struct ar6_softc *)Context; + int refillCount = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_alloc_amsdu_rxbuf: eid=%d, Length:%d\n",Endpoint,Length)); + + do { + + if (Length <= AR6000_BUFFER_SIZE) { + /* shouldn't be getting called on normal sized packets */ + A_ASSERT(false); + break; + } + + if (Length > AR6000_AMSDU_BUFFER_SIZE) { + A_ASSERT(false); + break; + } + + AR6000_SPIN_LOCK(&ar->arLock, 0); + /* allocate a packet from the list */ + pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue); + /* see if we need to refill again */ + refillCount = AR6000_MAX_AMSDU_RX_BUFFERS - HTC_PACKET_QUEUE_DEPTH(&ar->amsdu_rx_buffer_queue); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (NULL == pPacket) { + break; + } + /* set actual endpoint ID */ + pPacket->Endpoint = Endpoint; + + } while (false); + + if (refillCount >= AR6000_AMSDU_REFILL_THRESHOLD) { + ar6000_refill_amsdu_rxbufs(ar,refillCount); + } + + return pPacket; +} + +static void +ar6000_set_multicast_list(struct net_device *dev) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000: Multicast filter not supported\n")); +} + +static struct net_device_stats * +ar6000_get_stats(struct net_device *dev) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + return &ar->arNetStats; +} + +void +ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, u32 sw_ver, u32 abi_ver) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + struct net_device *dev = ar->arNetDev; + + memcpy(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5])); + + ar->arPhyCapability = phyCap; + ar->arVersion.wlan_ver = sw_ver; + ar->arVersion.abi_ver = abi_ver; + + snprintf(ar->wdev->wiphy->fw_version, sizeof(ar->wdev->wiphy->fw_version), + "%u:%u:%u:%u", + (ar->arVersion.wlan_ver & 0xf0000000) >> 28, + (ar->arVersion.wlan_ver & 0x0f000000) >> 24, + (ar->arVersion.wlan_ver & 0x00ff0000) >> 16, + (ar->arVersion.wlan_ver & 0x0000ffff)); + + /* Indicate to the waiting thread that the ready event was received */ + ar->arWmiReady = true; + wake_up(&arEvent); +} + +void ar6000_install_static_wep_keys(struct ar6_softc *ar) +{ + u8 index; + u8 keyUsage; + + for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { + if (ar->arWepKeyList[index].arKeyLen) { + keyUsage = GROUP_USAGE; + if (index == ar->arDefTxKeyIndex) { + keyUsage |= TX_USAGE; + } + wmi_addKey_cmd(ar->arWmi, + index, + WEP_CRYPT, + keyUsage, + ar->arWepKeyList[index].arKeyLen, + NULL, + ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + } + } +} + +void +add_new_sta(struct ar6_softc *ar, u8 *mac, u16 aid, u8 *wpaie, + u8 ielen, u8 keymgmt, u8 ucipher, u8 auth) +{ + u8 free_slot=aid-1; + + memcpy(ar->sta_list[free_slot].mac, mac, ATH_MAC_LEN); + memcpy(ar->sta_list[free_slot].wpa_ie, wpaie, ielen); + ar->sta_list[free_slot].aid = aid; + ar->sta_list[free_slot].keymgmt = keymgmt; + ar->sta_list[free_slot].ucipher = ucipher; + ar->sta_list[free_slot].auth = auth; + ar->sta_list_index = ar->sta_list_index | (1 << free_slot); + ar->arAPStats.sta[free_slot].aid = aid; +} + +void +ar6000_connect_event(struct ar6_softc *ar, u16 channel, u8 *bssid, + u16 listenInterval, u16 beaconInterval, + NETWORK_TYPE networkType, u8 beaconIeLen, + u8 assocReqLen, u8 assocRespLen, + u8 *assocInfo) +{ + union iwreq_data wrqu; + int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos; + static const char *tag1 = "ASSOCINFO(ReqIEs="; + static const char *tag2 = "ASSOCRESPIE="; + static const char *beaconIetag = "BEACONIE="; + char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + strlen(tag1) + 1]; + char *pos; + u8 key_op_ctrl; + unsigned long flags; + struct ieee80211req_key *ik; + CRYPTO_TYPE keyType = NONE_CRYPT; + + if(ar->arNetworkType & AP_NETWORK) { + struct net_device *dev = ar->arNetDev; + if(memcmp(dev->dev_addr, bssid, ATH_MAC_LEN)==0) { + ar->arACS = channel; + ik = &ar->ap_mode_bkey; + + switch(ar->arAuthMode) { + case NONE_AUTH: + if(ar->arPairwiseCrypto == WEP_CRYPT) { + ar6000_install_static_wep_keys(ar); + } +#ifdef WAPI_ENABLE + else if(ar->arPairwiseCrypto == WAPI_CRYPT) { + ap_set_wapi_key(ar, ik); + } +#endif + break; + case WPA_PSK_AUTH: + case WPA2_PSK_AUTH: + case (WPA_PSK_AUTH|WPA2_PSK_AUTH): + switch (ik->ik_type) { + case IEEE80211_CIPHER_TKIP: + keyType = TKIP_CRYPT; + break; + case IEEE80211_CIPHER_AES_CCM: + keyType = AES_CRYPT; + break; + default: + goto skip_key; + } + wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, GROUP_USAGE, + ik->ik_keylen, (u8 *)&ik->ik_keyrsc, + ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr, + SYNC_BOTH_WMIFLAG); + + break; + } +skip_key: + ar->arConnected = true; + return; + } + + A_PRINTF("NEW STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n " + " AID=%d \n", bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5], channel); + switch ((listenInterval>>8)&0xFF) { + case OPEN_AUTH: + A_PRINTF("AUTH: OPEN\n"); + break; + case SHARED_AUTH: + A_PRINTF("AUTH: SHARED\n"); + break; + default: + A_PRINTF("AUTH: Unknown\n"); + break; + } + switch (listenInterval&0xFF) { + case WPA_PSK_AUTH: + A_PRINTF("KeyMgmt: WPA-PSK\n"); + break; + case WPA2_PSK_AUTH: + A_PRINTF("KeyMgmt: WPA2-PSK\n"); + break; + default: + A_PRINTF("KeyMgmt: NONE\n"); + break; + } + switch (beaconInterval) { + case AES_CRYPT: + A_PRINTF("Cipher: AES\n"); + break; + case TKIP_CRYPT: + A_PRINTF("Cipher: TKIP\n"); + break; + case WEP_CRYPT: + A_PRINTF("Cipher: WEP\n"); + break; +#ifdef WAPI_ENABLE + case WAPI_CRYPT: + A_PRINTF("Cipher: WAPI\n"); + break; +#endif + default: + A_PRINTF("Cipher: NONE\n"); + break; + } + + add_new_sta(ar, bssid, channel /*aid*/, + assocInfo /* WPA IE */, assocRespLen /* IE len */, + listenInterval&0xFF /* Keymgmt */, beaconInterval /* cipher */, + (listenInterval>>8)&0xFF /* auth alg */); + + /* Send event to application */ + A_MEMZERO(&wrqu, sizeof(wrqu)); + memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN); + wireless_send_event(ar->arNetDev, IWEVREGISTERED, &wrqu, NULL); + /* In case the queue is stopped when we switch modes, this will + * wake it up + */ + netif_wake_queue(ar->arNetDev); + return; + } + + ar6k_cfg80211_connect_event(ar, channel, bssid, + listenInterval, beaconInterval, + networkType, beaconIeLen, + assocReqLen, assocRespLen, + assocInfo); + + memcpy(ar->arBssid, bssid, sizeof(ar->arBssid)); + ar->arBssChannel = channel; + + A_PRINTF("AR6000 connected event on freq %d ", channel); + A_PRINTF("with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " + " listenInterval=%d, beaconInterval = %d, beaconIeLen = %d assocReqLen=%d" + " assocRespLen =%d\n", + bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5], + listenInterval, beaconInterval, + beaconIeLen, assocReqLen, assocRespLen); + if (networkType & ADHOC_NETWORK) { + if (networkType & ADHOC_CREATOR) { + A_PRINTF("Network: Adhoc (Creator)\n"); + } else { + A_PRINTF("Network: Adhoc (Joiner)\n"); + } + } else { + A_PRINTF("Network: Infrastructure\n"); + } + + if ((ar->arNetworkType == INFRA_NETWORK)) { + wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB); + } + + if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nBeaconIEs= ")); + + beacon_ie_pos = 0; + A_MEMZERO(buf, sizeof(buf)); + sprintf(buf, "%s", beaconIetag); + pos = buf + 9; + for (i = beacon_ie_pos; i < beacon_ie_pos + beaconIeLen; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); + sprintf(pos, "%2.2x", assocInfo[i]); + pos += 2; + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); + } + + if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2)))) + { + assoc_resp_ie_pos = beaconIeLen + assocReqLen + + sizeof(u16) + /* capinfo*/ + sizeof(u16) + /* status Code */ + sizeof(u16) ; /* associd */ + A_MEMZERO(buf, sizeof(buf)); + sprintf(buf, "%s", tag2); + pos = buf + 12; + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocRespIEs= ")); + /* + * The Association Response Frame w.o. the WLAN header is delivered to + * the host, so skip over to the IEs + */ + for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i++) + { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); + sprintf(pos, "%2.2x", assocInfo[i]); + pos += 2; + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); + } + + if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) { + /* + * assoc Request includes capability and listen interval. Skip these. + */ + assoc_req_ie_pos = beaconIeLen + + sizeof(u16) + /* capinfo*/ + sizeof(u16); /* listen interval */ + + A_MEMZERO(buf, sizeof(buf)); + sprintf(buf, "%s", tag1); + pos = buf + 17; + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AssocReqIEs= ")); + for (i = assoc_req_ie_pos; i < assoc_req_ie_pos + assocReqLen - 4; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); + sprintf(pos, "%2.2x", assocInfo[i]); + pos += 2; + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); + } + + if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN && + ar->user_saved_keys.keyOk == true) + { + key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC; + + if (ar->user_key_ctrl & AR6000_USER_SETKEYS_RSC_UNCHANGED) { + key_op_ctrl &= ~KEY_OP_INIT_RSC; + } else { + key_op_ctrl |= KEY_OP_INIT_RSC; + } + ar6000_reinstall_keys(ar, key_op_ctrl); + } + + netif_wake_queue(ar->arNetDev); + + /* Update connect & link status atomically */ + spin_lock_irqsave(&ar->arLock, flags); + ar->arConnected = true; + ar->arConnectPending = false; + netif_carrier_on(ar->arNetDev); + spin_unlock_irqrestore(&ar->arLock, flags); + /* reset the rx aggr state */ + aggr_reset_state(ar->aggr_cntxt); + reconnect_flag = 0; + + A_MEMZERO(&wrqu, sizeof(wrqu)); + memcpy(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN); + wrqu.addr.sa_family = ARPHRD_ETHER; + wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL); + if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) { + A_MEMZERO(ar->arNodeMap, sizeof(ar->arNodeMap)); + ar->arNodeNum = 0; + ar->arNexEpId = ENDPOINT_2; + } + if (!ar->arUserBssFilter) { + wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); + } + +} + +void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num) +{ + A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1)); + ar->arNumDataEndPts = num; +} + +void +sta_cleanup(struct ar6_softc *ar, u8 i) +{ + struct sk_buff *skb; + + /* empty the queued pkts in the PS queue if any */ + A_MUTEX_LOCK(&ar->sta_list[i].psqLock); + while (!A_NETBUF_QUEUE_EMPTY(&ar->sta_list[i].psq)) { + skb = A_NETBUF_DEQUEUE(&ar->sta_list[i].psq); + A_NETBUF_FREE(skb); + } + A_MUTEX_UNLOCK(&ar->sta_list[i].psqLock); + + /* Zero out the state fields */ + A_MEMZERO(&ar->arAPStats.sta[ar->sta_list[i].aid-1], sizeof(WMI_PER_STA_STAT)); + A_MEMZERO(&ar->sta_list[i].mac, ATH_MAC_LEN); + A_MEMZERO(&ar->sta_list[i].wpa_ie, IEEE80211_MAX_IE); + ar->sta_list[i].aid = 0; + ar->sta_list[i].flags = 0; + + ar->sta_list_index = ar->sta_list_index & ~(1 << i); + +} + +u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason) +{ + u8 i, removed=0; + + if(IS_MAC_NULL(mac)) { + return removed; + } + + if(IS_MAC_BCAST(mac)) { + A_PRINTF("DEL ALL STA\n"); + for(i=0; i < AP_MAX_NUM_STA; i++) { + if(!IS_MAC_NULL(ar->sta_list[i].mac)) { + sta_cleanup(ar, i); + removed = 1; + } + } + } else { + for(i=0; i < AP_MAX_NUM_STA; i++) { + if(memcmp(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) { + A_PRINTF("DEL STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " + " aid=%d REASON=%d\n", mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5], ar->sta_list[i].aid, reason); + + sta_cleanup(ar, i); + removed = 1; + break; + } + } + } + return removed; +} + +void +ar6000_disconnect_event(struct ar6_softc *ar, u8 reason, u8 *bssid, + u8 assocRespLen, u8 *assocInfo, u16 protocolReasonStatus) +{ + u8 i; + unsigned long flags; + union iwreq_data wrqu; + + if(ar->arNetworkType & AP_NETWORK) { + union iwreq_data wrqu; + struct sk_buff *skb; + + if(!remove_sta(ar, bssid, protocolReasonStatus)) { + return; + } + + /* If there are no more associated STAs, empty the mcast PS q */ + if (ar->sta_list_index == 0) { + A_MUTEX_LOCK(&ar->mcastpsqLock); + while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { + skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); + A_NETBUF_FREE(skb); + } + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + /* Clear the LSB of the BitMapCtl field of the TIM IE */ + if (ar->arWmiReady) { + wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0); + } + } + + if(!IS_MAC_BCAST(bssid)) { + /* Send event to application */ + A_MEMZERO(&wrqu, sizeof(wrqu)); + memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN); + wireless_send_event(ar->arNetDev, IWEVEXPIRED, &wrqu, NULL); + } + + ar->arConnected = false; + return; + } + + ar6k_cfg80211_disconnect_event(ar, reason, bssid, + assocRespLen, assocInfo, + protocolReasonStatus); + + /* Send disconnect event to supplicant */ + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.addr.sa_family = ARPHRD_ETHER; + wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL); + + /* it is necessary to clear the host-side rx aggregation state */ + aggr_reset_state(ar->aggr_cntxt); + + A_UNTIMEOUT(&ar->disconnect_timer); + + A_PRINTF("AR6000 disconnected"); + if (bssid[0] || bssid[1] || bssid[2] || bssid[3] || bssid[4] || bssid[5]) { + A_PRINTF(" from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nDisconnect Reason is %d", reason)); + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nProtocol Reason/Status Code is %d", protocolReasonStatus)); + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocResp Frame = %s", + assocRespLen ? " " : "NULL")); + for (i = 0; i < assocRespLen; i++) { + if (!(i % 0x10)) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); + /* + * If the event is due to disconnect cmd from the host, only they the target + * would stop trying to connect. Under any other condition, target would + * keep trying to connect. + * + */ + if( reason == DISCONNECT_CMD) + { + if ((!ar->arUserBssFilter) && (ar->arWmiReady)) { + wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); + } + } else { + ar->arConnectPending = true; + if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) || + ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) { + ar->arConnected = true; + return; + } + } + + if ((reason == NO_NETWORK_AVAIL) && (ar->arWmiReady)) + { + bss_t *pWmiSsidnode = NULL; + + /* remove the current associated bssid node */ + wmi_free_node (ar->arWmi, bssid); + + /* + * In case any other same SSID nodes are present + * remove it, since those nodes also not available now + */ + do + { + /* + * Find the nodes based on SSID and remove it + * NOTE :: This case will not work out for Hidden-SSID + */ + pWmiSsidnode = wmi_find_Ssidnode (ar->arWmi, ar->arSsid, ar->arSsidLen, false, true); + + if (pWmiSsidnode) + { + wmi_free_node (ar->arWmi, pWmiSsidnode->ni_macaddr); + } + + } while (pWmiSsidnode); + } + + /* Update connect & link status atomically */ + spin_lock_irqsave(&ar->arLock, flags); + ar->arConnected = false; + netif_carrier_off(ar->arNetDev); + spin_unlock_irqrestore(&ar->arLock, flags); + + if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) { + reconnect_flag = 0; + } + + if (reason != CSERV_DISCONNECT) + { + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; + ar->user_key_ctrl = 0; + } + + netif_stop_queue(ar->arNetDev); + A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); + ar->arBssChannel = 0; + ar->arBeaconInterval = 0; + + ar6000_TxDataCleanup(ar); +} + +void +ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode) +{ + A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode); + ar->arRegCode = regCode; +} + +void +ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *evt) +{ + if(evt->status == 0) { + aggr_recv_addba_req_evt(ar->aggr_cntxt, evt->tid, evt->st_seq_no, evt->win_sz); + } +} + +void +ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *evt) +{ + A_PRINTF("ADDBA RESP. tid %d status %d, sz %d\n", evt->tid, evt->status, evt->amsdu_sz); + if(evt->status == 0) { + } +} + +void +ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *evt) +{ + aggr_recv_delba_req_evt(ar->aggr_cntxt, evt->tid); +} + +void register_pal_cb(ar6k_pal_config_t *palConfig_p) +{ + ar6k_pal_config_g = *palConfig_p; +} + +void +ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd) +{ + void *osbuf = NULL; + s8 i; + u8 size, *buf; + int ret = 0; + + size = cmd->evt_buf_sz + 4; + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + ret = A_NO_MEMORY; + A_PRINTF("Error in allocating netbuf \n"); + return; + } + + A_NETBUF_PUT(osbuf, size); + buf = (u8 *)A_NETBUF_DATA(osbuf); + /* First 2-bytes carry HCI event/ACL data type + * the next 2 are free + */ + *((short *)buf) = WMI_HCI_EVENT_EVENTID; + buf += sizeof(int); + memcpy(buf, cmd->buf, cmd->evt_buf_sz); + + ar6000_deliver_frames_to_nw_stack(ar->arNetDev, osbuf); + if(loghci) { + A_PRINTF_LOG("HCI Event From PAL <-- \n"); + for(i = 0; i < cmd->evt_buf_sz; i++) { + A_PRINTF_LOG("0x%02x ", cmd->buf[i]); + if((i % 10) == 0) { + A_PRINTF_LOG("\n"); + } + } + A_PRINTF_LOG("\n"); + A_PRINTF_LOG("==================================\n"); + } +} + +void +ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, WMI_NEIGHBOR_INFO *info) +{ +#if WIRELESS_EXT >= 18 + struct iw_pmkid_cand *pmkcand; +#else /* WIRELESS_EXT >= 18 */ + static const char *tag = "PRE-AUTH"; + char buf[128]; +#endif /* WIRELESS_EXT >= 18 */ + + union iwreq_data wrqu; + int i; + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("AR6000 Neighbor Report Event\n")); + for (i=0; i < numAps; info++, i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", + info->bssid[0], info->bssid[1], info->bssid[2], + info->bssid[3], info->bssid[4], info->bssid[5])); + if (info->bssFlags & WMI_PREAUTH_CAPABLE_BSS) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("preauth-cap")); + } + if (info->bssFlags & WMI_PMKID_VALID_BSS) { + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,(" pmkid-valid\n")); + continue; /* we skip bss if the pmkid is already valid */ + } + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("\n")); + A_MEMZERO(&wrqu, sizeof(wrqu)); +#if WIRELESS_EXT >= 18 + pmkcand = A_MALLOC_NOWAIT(sizeof(struct iw_pmkid_cand)); + A_MEMZERO(pmkcand, sizeof(struct iw_pmkid_cand)); + pmkcand->index = i; + pmkcand->flags = info->bssFlags; + memcpy(pmkcand->bssid.sa_data, info->bssid, ATH_MAC_LEN); + wrqu.data.length = sizeof(struct iw_pmkid_cand); + wireless_send_event(ar->arNetDev, IWEVPMKIDCAND, &wrqu, (char *)pmkcand); + kfree(pmkcand); +#else /* WIRELESS_EXT >= 18 */ + snprintf(buf, sizeof(buf), "%s%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x", + tag, + info->bssid[0], info->bssid[1], info->bssid[2], + info->bssid[3], info->bssid[4], info->bssid[5], + i, info->bssFlags); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); +#endif /* WIRELESS_EXT >= 18 */ + } +} + +void +ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast) +{ + static const char *tag = "MLME-MICHAELMICFAILURE.indication"; + char buf[128]; + union iwreq_data wrqu; + + /* + * For AP case, keyid will have aid of STA which sent pkt with + * MIC error. Use this aid to get MAC & send it to hostapd. + */ + if (ar->arNetworkType == AP_NETWORK) { + sta_t *s = ieee80211_find_conn_for_aid(ar, (keyid >> 2)); + if(!s){ + A_PRINTF("AP TKIP MIC error received from Invalid aid / STA not found =%d\n", keyid); + return; + } + A_PRINTF("AP TKIP MIC error received from aid=%d\n", keyid); + snprintf(buf,sizeof(buf), "%s addr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + tag, s->mac[0],s->mac[1],s->mac[2],s->mac[3],s->mac[4],s->mac[5]); + } else { + + ar6k_cfg80211_tkip_micerr_event(ar, keyid, ismcast); + + A_PRINTF("AR6000 TKIP MIC error received for keyid %d %scast\n", + keyid & 0x3, ismcast ? "multi": "uni"); + snprintf(buf, sizeof(buf), "%s(keyid=%d %sicast)", tag, keyid & 0x3, + ismcast ? "mult" : "un"); + } + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); +} + +void +ar6000_scanComplete_event(struct ar6_softc *ar, int status) +{ + + ar6k_cfg80211_scanComplete_event(ar, status); + + if (!ar->arUserBssFilter) { + wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); + } + if (ar->scan_triggered) { + if (status== 0) { + union iwreq_data wrqu; + A_MEMZERO(&wrqu, sizeof(wrqu)); + wireless_send_event(ar->arNetDev, SIOCGIWSCAN, &wrqu, NULL); + } + ar->scan_triggered = 0; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,( "AR6000 scan complete: %d\n", status)); +} + +void +ar6000_targetStats_event(struct ar6_softc *ar, u8 *ptr, u32 len) +{ + u8 ac; + + if(ar->arNetworkType == AP_NETWORK) { + WMI_AP_MODE_STAT *p = (WMI_AP_MODE_STAT *)ptr; + WMI_AP_MODE_STAT *ap = &ar->arAPStats; + + if (len < sizeof(*p)) { + return; + } + + for(ac=0;acsta[ac].tx_bytes += p->sta[ac].tx_bytes; + ap->sta[ac].tx_pkts += p->sta[ac].tx_pkts; + ap->sta[ac].tx_error += p->sta[ac].tx_error; + ap->sta[ac].tx_discard += p->sta[ac].tx_discard; + ap->sta[ac].rx_bytes += p->sta[ac].rx_bytes; + ap->sta[ac].rx_pkts += p->sta[ac].rx_pkts; + ap->sta[ac].rx_error += p->sta[ac].rx_error; + ap->sta[ac].rx_discard += p->sta[ac].rx_discard; + } + + } else { + WMI_TARGET_STATS *pTarget = (WMI_TARGET_STATS *)ptr; + TARGET_STATS *pStats = &ar->arTargetStats; + + if (len < sizeof(*pTarget)) { + return; + } + + // Update the RSSI of the connected bss. + if (ar->arConnected) { + bss_t *pConnBss = NULL; + + pConnBss = wmi_find_node(ar->arWmi,ar->arBssid); + if (pConnBss) + { + pConnBss->ni_rssi = pTarget->cservStats.cs_aveBeacon_rssi; + pConnBss->ni_snr = pTarget->cservStats.cs_aveBeacon_snr; + wmi_node_return(ar->arWmi, pConnBss); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 updating target stats\n")); + pStats->tx_packets += pTarget->txrxStats.tx_stats.tx_packets; + pStats->tx_bytes += pTarget->txrxStats.tx_stats.tx_bytes; + pStats->tx_unicast_pkts += pTarget->txrxStats.tx_stats.tx_unicast_pkts; + pStats->tx_unicast_bytes += pTarget->txrxStats.tx_stats.tx_unicast_bytes; + pStats->tx_multicast_pkts += pTarget->txrxStats.tx_stats.tx_multicast_pkts; + pStats->tx_multicast_bytes += pTarget->txrxStats.tx_stats.tx_multicast_bytes; + pStats->tx_broadcast_pkts += pTarget->txrxStats.tx_stats.tx_broadcast_pkts; + pStats->tx_broadcast_bytes += pTarget->txrxStats.tx_stats.tx_broadcast_bytes; + pStats->tx_rts_success_cnt += pTarget->txrxStats.tx_stats.tx_rts_success_cnt; + for(ac = 0; ac < WMM_NUM_AC; ac++) + pStats->tx_packet_per_ac[ac] += pTarget->txrxStats.tx_stats.tx_packet_per_ac[ac]; + pStats->tx_errors += pTarget->txrxStats.tx_stats.tx_errors; + pStats->tx_failed_cnt += pTarget->txrxStats.tx_stats.tx_failed_cnt; + pStats->tx_retry_cnt += pTarget->txrxStats.tx_stats.tx_retry_cnt; + pStats->tx_mult_retry_cnt += pTarget->txrxStats.tx_stats.tx_mult_retry_cnt; + pStats->tx_rts_fail_cnt += pTarget->txrxStats.tx_stats.tx_rts_fail_cnt; + pStats->tx_unicast_rate = wmi_get_rate(pTarget->txrxStats.tx_stats.tx_unicast_rate); + + pStats->rx_packets += pTarget->txrxStats.rx_stats.rx_packets; + pStats->rx_bytes += pTarget->txrxStats.rx_stats.rx_bytes; + pStats->rx_unicast_pkts += pTarget->txrxStats.rx_stats.rx_unicast_pkts; + pStats->rx_unicast_bytes += pTarget->txrxStats.rx_stats.rx_unicast_bytes; + pStats->rx_multicast_pkts += pTarget->txrxStats.rx_stats.rx_multicast_pkts; + pStats->rx_multicast_bytes += pTarget->txrxStats.rx_stats.rx_multicast_bytes; + pStats->rx_broadcast_pkts += pTarget->txrxStats.rx_stats.rx_broadcast_pkts; + pStats->rx_broadcast_bytes += pTarget->txrxStats.rx_stats.rx_broadcast_bytes; + pStats->rx_fragment_pkt += pTarget->txrxStats.rx_stats.rx_fragment_pkt; + pStats->rx_errors += pTarget->txrxStats.rx_stats.rx_errors; + pStats->rx_crcerr += pTarget->txrxStats.rx_stats.rx_crcerr; + pStats->rx_key_cache_miss += pTarget->txrxStats.rx_stats.rx_key_cache_miss; + pStats->rx_decrypt_err += pTarget->txrxStats.rx_stats.rx_decrypt_err; + pStats->rx_duplicate_frames += pTarget->txrxStats.rx_stats.rx_duplicate_frames; + pStats->rx_unicast_rate = wmi_get_rate(pTarget->txrxStats.rx_stats.rx_unicast_rate); + + + pStats->tkip_local_mic_failure + += pTarget->txrxStats.tkipCcmpStats.tkip_local_mic_failure; + pStats->tkip_counter_measures_invoked + += pTarget->txrxStats.tkipCcmpStats.tkip_counter_measures_invoked; + pStats->tkip_replays += pTarget->txrxStats.tkipCcmpStats.tkip_replays; + pStats->tkip_format_errors += pTarget->txrxStats.tkipCcmpStats.tkip_format_errors; + pStats->ccmp_format_errors += pTarget->txrxStats.tkipCcmpStats.ccmp_format_errors; + pStats->ccmp_replays += pTarget->txrxStats.tkipCcmpStats.ccmp_replays; + + pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cnt; + pStats->noise_floor_calibation = pTarget->noise_floor_calibation; + + pStats->cs_bmiss_cnt += pTarget->cservStats.cs_bmiss_cnt; + pStats->cs_lowRssi_cnt += pTarget->cservStats.cs_lowRssi_cnt; + pStats->cs_connect_cnt += pTarget->cservStats.cs_connect_cnt; + pStats->cs_disconnect_cnt += pTarget->cservStats.cs_disconnect_cnt; + pStats->cs_aveBeacon_snr = pTarget->cservStats.cs_aveBeacon_snr; + pStats->cs_aveBeacon_rssi = pTarget->cservStats.cs_aveBeacon_rssi; + + if (enablerssicompensation) { + pStats->cs_aveBeacon_rssi = + rssi_compensation_calc(ar, pStats->cs_aveBeacon_rssi); + } + pStats->cs_lastRoam_msec = pTarget->cservStats.cs_lastRoam_msec; + pStats->cs_snr = pTarget->cservStats.cs_snr; + pStats->cs_rssi = pTarget->cservStats.cs_rssi; + + pStats->lq_val = pTarget->lqVal; + + pStats->wow_num_pkts_dropped += pTarget->wowStats.wow_num_pkts_dropped; + pStats->wow_num_host_pkt_wakeups += pTarget->wowStats.wow_num_host_pkt_wakeups; + pStats->wow_num_host_event_wakeups += pTarget->wowStats.wow_num_host_event_wakeups; + pStats->wow_num_events_discarded += pTarget->wowStats.wow_num_events_discarded; + pStats->arp_received += pTarget->arpStats.arp_received; + pStats->arp_matched += pTarget->arpStats.arp_matched; + pStats->arp_replied += pTarget->arpStats.arp_replied; + + if (ar->statsUpdatePending) { + ar->statsUpdatePending = false; + wake_up(&arEvent); + } + } +} + +void +ar6000_rssiThreshold_event(struct ar6_softc *ar, WMI_RSSI_THRESHOLD_VAL newThreshold, s16 rssi) +{ + USER_RSSI_THOLD userRssiThold; + + rssi = rssi + SIGNAL_QUALITY_NOISE_FLOOR; + + if (enablerssicompensation) { + rssi = rssi_compensation_calc(ar, rssi); + } + + /* Send an event to the app */ + userRssiThold.tag = ar->rssi_map[newThreshold].tag; + userRssiThold.rssi = rssi; + A_PRINTF("rssi Threshold range = %d tag = %d rssi = %d\n", newThreshold, + userRssiThold.tag, userRssiThold.rssi); +} + + +void +ar6000_hbChallengeResp_event(struct ar6_softc *ar, u32 cookie, u32 source) +{ + if (source != APP_HB_CHALLENGE) { + /* This would ignore the replys that come in after their due time */ + if (cookie == ar->arHBChallengeResp.seqNum) { + ar->arHBChallengeResp.outstanding = false; + } + } +} + + +void +ar6000_reportError_event(struct ar6_softc *ar, WMI_TARGET_ERROR_VAL errorVal) +{ + static const char * const errString[] = { + [WMI_TARGET_PM_ERR_FAIL] "WMI_TARGET_PM_ERR_FAIL", + [WMI_TARGET_KEY_NOT_FOUND] "WMI_TARGET_KEY_NOT_FOUND", + [WMI_TARGET_DECRYPTION_ERR] "WMI_TARGET_DECRYPTION_ERR", + [WMI_TARGET_BMISS] "WMI_TARGET_BMISS", + [WMI_PSDISABLE_NODE_JOIN] "WMI_PSDISABLE_NODE_JOIN" + }; + + A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal); + + /* One error is reported at a time, and errorval is a bitmask */ + if(errorVal & (errorVal - 1)) + return; + + A_PRINTF("AR6000 Error type = "); + switch(errorVal) + { + case WMI_TARGET_PM_ERR_FAIL: + case WMI_TARGET_KEY_NOT_FOUND: + case WMI_TARGET_DECRYPTION_ERR: + case WMI_TARGET_BMISS: + case WMI_PSDISABLE_NODE_JOIN: + A_PRINTF("%s\n", errString[errorVal]); + break; + default: + A_PRINTF("INVALID\n"); + break; + } + +} + + +void +ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cacIndication, + u8 statusCode, u8 *tspecSuggestion) +{ + WMM_TSPEC_IE *tspecIe; + + /* + * This is the TSPEC IE suggestion from AP. + * Suggestion provided by AP under some error + * cases, could be helpful for the host app. + * Check documentation. + */ + tspecIe = (WMM_TSPEC_IE *)tspecSuggestion; + + /* + * What do we do, if we get TSPEC rejection? One thought + * that comes to mind is implictly delete the pstream... + */ + A_PRINTF("AR6000 CAC notification. " + "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n", + ac, cacIndication, statusCode); +} + +void +ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel, + u16 newChannel) +{ + A_PRINTF("Channel Change notification\nOld Channel: %d, New Channel: %d\n", + oldChannel, newChannel); +} + +#define AR6000_PRINT_BSSID(_pBss) do { \ + A_PRINTF("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",\ + (_pBss)[0],(_pBss)[1],(_pBss)[2],(_pBss)[3],\ + (_pBss)[4],(_pBss)[5]); \ +} while(0) + +void +ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl) +{ + u8 i; + + A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n", + pTbl->numEntries, pTbl->roamMode); + for (i= 0; i < pTbl->numEntries; i++) { + A_PRINTF("[%d]bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", i, + pTbl->bssRoamInfo[i].bssid[0], pTbl->bssRoamInfo[i].bssid[1], + pTbl->bssRoamInfo[i].bssid[2], + pTbl->bssRoamInfo[i].bssid[3], + pTbl->bssRoamInfo[i].bssid[4], + pTbl->bssRoamInfo[i].bssid[5]); + A_PRINTF("RSSI %d RSSIDT %d LAST RSSI %d UTIL %d ROAM_UTIL %d" + " BIAS %d\n", + pTbl->bssRoamInfo[i].rssi, + pTbl->bssRoamInfo[i].rssidt, + pTbl->bssRoamInfo[i].last_rssi, + pTbl->bssRoamInfo[i].util, + pTbl->bssRoamInfo[i].roam_util, + pTbl->bssRoamInfo[i].bias); + } +} + +void +ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply) +{ + u8 i,j; + + /*Each event now contains exactly one filter, see bug 26613*/ + A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num, wow_reply->num_filters); + A_PRINTF("wow mode = %s host mode = %s\n", + (wow_reply->wow_mode == 0? "disabled":"enabled"), + (wow_reply->host_mode == 1 ? "awake":"asleep")); + + + /*If there are no patterns, the reply will only contain generic + WoW information. Pattern information will exist only if there are + patterns present. Bug 26716*/ + + /* If this event contains pattern information, display it*/ + if (wow_reply->this_filter_num) { + i=0; + A_PRINTF("id=%d size=%d offset=%d\n", + wow_reply->wow_filters[i].wow_filter_id, + wow_reply->wow_filters[i].wow_filter_size, + wow_reply->wow_filters[i].wow_filter_offset); + A_PRINTF("wow pattern = "); + for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { + A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_pattern[j]); + } + + A_PRINTF("\nwow mask = "); + for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { + A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_mask[j]); + } + A_PRINTF("\n"); + } +} + +/* + * Report the Roaming related data collected on the target + */ +void +ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p) +{ + A_PRINTF("Disconnect Data : BSSID: "); + AR6000_PRINT_BSSID(p->disassoc_bssid); + A_PRINTF(" RSSI %d DISASSOC Time %d NO_TXRX_TIME %d\n", + p->disassoc_bss_rssi,p->disassoc_time, + p->no_txrx_time); + A_PRINTF("Connect Data: BSSID: "); + AR6000_PRINT_BSSID(p->assoc_bssid); + A_PRINTF(" RSSI %d ASSOC Time %d TXRX_TIME %d\n", + p->assoc_bss_rssi,p->assoc_time, + p->allow_txrx_time); +} + +void +ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p) +{ + switch (p->roamDataType) { + case ROAM_DATA_TIME: + ar6000_display_roam_time(&p->u.roamTime); + break; + default: + break; + } +} + +void +ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *datap, int len) +{ + struct sk_buff *skb; + WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap; + + + if (!ar->arMgmtFilter) { + return; + } + if (((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_BEACON) && + (bih->frameType != BEACON_FTYPE)) || + ((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_PROBE_RESP) && + (bih->frameType != PROBERESP_FTYPE))) + { + return; + } + + if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) { + + A_NETBUF_PUT(skb, len); + memcpy(A_NETBUF_DATA(skb), datap, len); + skb->dev = ar->arNetDev; + memcpy(skb_mac_header(skb), A_NETBUF_DATA(skb), 6); + skb->ip_summed = CHECKSUM_NONE; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = __constant_htons(0x0019); + netif_rx(skb); + } +} + +u32 wmiSendCmdNum; + +int +ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + int status = 0; + struct ar_cookie *cookie = NULL; + int i; +#ifdef CONFIG_PM + if (ar->arWowState != WLAN_WOW_STATE_NONE) { + A_NETBUF_FREE(osbuf); + return A_EACCES; + } +#endif /* CONFIG_PM */ + /* take lock to protect ar6000_alloc_cookie() */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + + do { + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar_contrstatus = ol_tx: skb=0x%lx, len=0x%x eid =%d\n", + (unsigned long)osbuf, A_NETBUF_LEN(osbuf), eid)); + + if (ar->arWMIControlEpFull && (eid == ar->arControlEp)) { + /* control endpoint is full, don't allocate resources, we + * are just going to drop this packet */ + cookie = NULL; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" WMI Control EP full, dropping packet : 0x%lX, len:%d \n", + (unsigned long)osbuf, A_NETBUF_LEN(osbuf))); + } else { + cookie = ar6000_alloc_cookie(ar); + } + + if (cookie == NULL) { + status = A_NO_MEMORY; + break; + } + + if(logWmiRawMsgs) { + A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum); + for(i = 0; i < a_netbuf_to_len(osbuf); i++) + A_PRINTF("%x ", ((u8 *)a_netbuf_to_data(osbuf))[i]); + A_PRINTF("\n"); + } + + wmiSendCmdNum++; + + } while (false); + + if (cookie != NULL) { + /* got a structure to send it out on */ + ar->arTxPending[eid]++; + + if (eid != ar->arControlEp) { + ar->arTotalTxDataPending++; + } + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (cookie != NULL) { + cookie->arc_bp[0] = (unsigned long)osbuf; + cookie->arc_bp[1] = 0; + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, + A_NETBUF_DATA(osbuf), + A_NETBUF_LEN(osbuf), + eid, + AR6K_CONTROL_PKT_TAG); + /* this interface is asynchronous, if there is an error, cleanup will happen in the + * TX completion callback */ + HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); + status = 0; + } + + if (status) { + A_NETBUF_FREE(osbuf); + } + return status; +} + +/* indicate tx activity or inactivity on a WMI stream */ +void ar6000_indicate_tx_activity(void *devt, u8 TrafficClass, bool Active) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + HTC_ENDPOINT_ID eid ; + int i; + + if (ar->arWmiEnabled) { + eid = arAc2EndpointID(ar, TrafficClass); + + AR6000_SPIN_LOCK(&ar->arLock, 0); + + ar->arAcStreamActive[TrafficClass] = Active; + + if (Active) { + /* when a stream goes active, keep track of the active stream with the highest priority */ + + if (ar->arAcStreamPriMap[TrafficClass] > ar->arHiAcStreamActivePri) { + /* set the new highest active priority */ + ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[TrafficClass]; + } + + } else { + /* when a stream goes inactive, we may have to search for the next active stream + * that is the highest priority */ + + if (ar->arHiAcStreamActivePri == ar->arAcStreamPriMap[TrafficClass]) { + + /* the highest priority stream just went inactive */ + + /* reset and search for the "next" highest "active" priority stream */ + ar->arHiAcStreamActivePri = 0; + for (i = 0; i < WMM_NUM_AC; i++) { + if (ar->arAcStreamActive[i]) { + if (ar->arAcStreamPriMap[i] > ar->arHiAcStreamActivePri) { + /* set the new highest active priority */ + ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[i]; + } + } + } + } + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + } else { + /* for mbox ping testing, the traffic class is mapped directly as a stream ID, + * see handling of AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE in ioctl.c + * convert the stream ID to a endpoint */ + eid = arAc2EndpointID(ar, TrafficClass); + } + + /* notify HTC, this may cause credit distribution changes */ + + HTCIndicateActivityChange(ar->arHtcTarget, + eid, + Active); + +} + +void +ar6000_btcoex_config_event(struct ar6_softc *ar, u8 *ptr, u32 len) +{ + + WMI_BTCOEX_CONFIG_EVENT *pBtcoexConfig = (WMI_BTCOEX_CONFIG_EVENT *)ptr; + WMI_BTCOEX_CONFIG_EVENT *pArbtcoexConfig =&ar->arBtcoexConfig; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n")); + + A_PRINTF("received config event\n"); + pArbtcoexConfig->btProfileType = pBtcoexConfig->btProfileType; + pArbtcoexConfig->linkId = pBtcoexConfig->linkId; + + switch (pBtcoexConfig->btProfileType) { + case WMI_BTCOEX_BT_PROFILE_SCO: + memcpy(&pArbtcoexConfig->info.scoConfigCmd, &pBtcoexConfig->info.scoConfigCmd, + sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD)); + break; + case WMI_BTCOEX_BT_PROFILE_A2DP: + memcpy(&pArbtcoexConfig->info.a2dpConfigCmd, &pBtcoexConfig->info.a2dpConfigCmd, + sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD)); + break; + case WMI_BTCOEX_BT_PROFILE_ACLCOEX: + memcpy(&pArbtcoexConfig->info.aclcoexConfig, &pBtcoexConfig->info.aclcoexConfig, + sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); + break; + case WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE: + memcpy(&pArbtcoexConfig->info.btinquiryPageConfigCmd, &pBtcoexConfig->info.btinquiryPageConfigCmd, + sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); + break; + } + if (ar->statsUpdatePending) { + ar->statsUpdatePending = false; + wake_up(&arEvent); + } +} + +void +ar6000_btcoex_stats_event(struct ar6_softc *ar, u8 *ptr, u32 len) +{ + WMI_BTCOEX_STATS_EVENT *pBtcoexStats = (WMI_BTCOEX_STATS_EVENT *)ptr; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n")); + + memcpy(&ar->arBtcoexStats, pBtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT)); + + if (ar->statsUpdatePending) { + ar->statsUpdatePending = false; + wake_up(&arEvent); + } + +} +module_init(ar6000_init_module); +module_exit(ar6000_cleanup_module); + +/* Init cookie queue */ +static void +ar6000_cookie_init(struct ar6_softc *ar) +{ + u32 i; + + ar->arCookieList = NULL; + ar->arCookieCount = 0; + + A_MEMZERO(s_ar_cookie_mem, sizeof(s_ar_cookie_mem)); + + for (i = 0; i < MAX_COOKIE_NUM; i++) { + ar6000_free_cookie(ar, &s_ar_cookie_mem[i]); + } +} + +/* cleanup cookie queue */ +static void +ar6000_cookie_cleanup(struct ar6_softc *ar) +{ + /* It is gone .... */ + ar->arCookieList = NULL; + ar->arCookieCount = 0; +} + +/* Init cookie queue */ +static void +ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie) +{ + /* Insert first */ + A_ASSERT(ar != NULL); + A_ASSERT(cookie != NULL); + + cookie->arc_list_next = ar->arCookieList; + ar->arCookieList = cookie; + ar->arCookieCount++; +} + +/* cleanup cookie queue */ +static struct ar_cookie * +ar6000_alloc_cookie(struct ar6_softc *ar) +{ + struct ar_cookie *cookie; + + cookie = ar->arCookieList; + if(cookie != NULL) + { + ar->arCookieList = cookie->arc_list_next; + ar->arCookieCount--; + } + + return cookie; +} + +void +ar6000_tx_retry_err_event(void *devt) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Tx retries reach maximum!\n")); +} + +void +ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, u8 snr) +{ + WMI_SNR_THRESHOLD_EVENT event; + + event.range = newThreshold; + event.snr = snr; +} + +void +ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, u8 lq) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("lq threshold range %d, lq %d\n", newThreshold, lq)); +} + + + +u32 a_copy_to_user(void *to, const void *from, u32 n) +{ + return(copy_to_user(to, from, n)); +} + +u32 a_copy_from_user(void *to, const void *from, u32 n) +{ + return(copy_from_user(to, from, n)); +} + + +int +ar6000_get_driver_cfg(struct net_device *dev, + u16 cfgParam, + void *result) +{ + + int ret = 0; + + switch(cfgParam) + { + case AR6000_DRIVER_CFG_GET_WLANNODECACHING: + *((u32 *)result) = wlanNodeCaching; + break; + case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS: + *((u32 *)result) = logWmiRawMsgs; + break; + default: + ret = EINVAL; + break; + } + + return ret; +} + +void +ar6000_keepalive_rx(void *devt, u8 configured) +{ + struct ar6_softc *ar = (struct ar6_softc *)devt; + + ar->arKeepaliveConfigured = configured; + wake_up(&arEvent); +} + +void +ar6000_pmkid_list_event(void *devt, u8 numPMKID, WMI_PMKID *pmkidList, + u8 *bssidList) +{ + u8 i, j; + + A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID); + + for (i = 0; i < numPMKID; i++) { + A_PRINTF("\nBSSID %d ", i); + for (j = 0; j < ATH_MAC_LEN; j++) { + A_PRINTF("%2.2x", bssidList[j]); + } + bssidList += (ATH_MAC_LEN + WMI_PMKID_LEN); + A_PRINTF("\nPMKID %d ", i); + for (j = 0; j < WMI_PMKID_LEN; j++) { + A_PRINTF("%2.2x", pmkidList->pmkid[j]); + } + pmkidList = (WMI_PMKID *)((u8 *)pmkidList + ATH_MAC_LEN + + WMI_PMKID_LEN); + } +} + +void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid) +{ + sta_t *conn=NULL; + bool isPsqEmpty = false; + + conn = ieee80211_find_conn_for_aid(ar, aid); + + /* If the PS q for this STA is not empty, dequeue and send a pkt from + * the head of the q. Also update the More data bit in the WMI_DATA_HDR + * if there are more pkts for this STA in the PS q. If there are no more + * pkts for this STA, update the PVB for this STA. + */ + A_MUTEX_LOCK(&conn->psqLock); + isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); + A_MUTEX_UNLOCK(&conn->psqLock); + + if (isPsqEmpty) { + /* TODO:No buffered pkts for this STA. Send out a NULL data frame */ + } else { + struct sk_buff *skb = NULL; + + A_MUTEX_LOCK(&conn->psqLock); + skb = A_NETBUF_DEQUEUE(&conn->psq); + A_MUTEX_UNLOCK(&conn->psqLock); + /* Set the STA flag to PSPolled, so that the frame will go out */ + STA_SET_PS_POLLED(conn); + ar6000_data_tx(skb, ar->arNetDev); + STA_CLR_PS_POLLED(conn); + + /* Clear the PVB for this STA if the queue has become empty */ + A_MUTEX_LOCK(&conn->psqLock); + isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); + A_MUTEX_UNLOCK(&conn->psqLock); + + if (isPsqEmpty) { + wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0); + } + } +} + +void ar6000_dtimexpiry_event(struct ar6_softc *ar) +{ + bool isMcastQueued = false; + struct sk_buff *skb = NULL; + + /* If there are no associated STAs, ignore the DTIM expiry event. + * There can be potential race conditions where the last associated + * STA may disconnect & before the host could clear the 'Indicate DTIM' + * request to the firmware, the firmware would have just indicated a DTIM + * expiry event. The race is between 'clear DTIM expiry cmd' going + * from the host to the firmware & the DTIM expiry event happening from + * the firmware to the host. + */ + if (ar->sta_list_index == 0) { + return; + } + + A_MUTEX_LOCK(&ar->mcastpsqLock); + isMcastQueued = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq); + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + A_ASSERT(isMcastQueued == false); + + /* Flush the mcast psq to the target */ + /* Set the STA flag to DTIMExpired, so that the frame will go out */ + ar->DTIMExpired = true; + + A_MUTEX_LOCK(&ar->mcastpsqLock); + while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { + skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + ar6000_data_tx(skb, ar->arNetDev); + + A_MUTEX_LOCK(&ar->mcastpsqLock); + } + A_MUTEX_UNLOCK(&ar->mcastpsqLock); + + /* Reset the DTIMExpired flag back to 0 */ + ar->DTIMExpired = false; + + /* Clear the LSB of the BitMapCtl field of the TIM IE */ + wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0); +} + +void +read_rssi_compensation_param(struct ar6_softc *ar) +{ + u8 *cust_data_ptr; + +//#define RSSICOMPENSATION_PRINT + +#ifdef RSSICOMPENSATION_PRINT + s16 i; + cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType); + for (i=0; i<16; i++) { + A_PRINTF("cust_data_%d = %x \n", i, *(u8 *)cust_data_ptr); + cust_data_ptr += 1; + } +#endif + + cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType); + + rssi_compensation_param.customerID = *(u16 *)cust_data_ptr & 0xffff; + rssi_compensation_param.enable = *(u16 *)(cust_data_ptr+2) & 0xffff; + rssi_compensation_param.bg_param_a = *(u16 *)(cust_data_ptr+4) & 0xffff; + rssi_compensation_param.bg_param_b = *(u16 *)(cust_data_ptr+6) & 0xffff; + rssi_compensation_param.a_param_a = *(u16 *)(cust_data_ptr+8) & 0xffff; + rssi_compensation_param.a_param_b = *(u16 *)(cust_data_ptr+10) &0xffff; + rssi_compensation_param.reserved = *(u32 *)(cust_data_ptr+12); + +#ifdef RSSICOMPENSATION_PRINT + A_PRINTF("customerID = 0x%x \n", rssi_compensation_param.customerID); + A_PRINTF("enable = 0x%x \n", rssi_compensation_param.enable); + A_PRINTF("bg_param_a = 0x%x and %d \n", rssi_compensation_param.bg_param_a, rssi_compensation_param.bg_param_a); + A_PRINTF("bg_param_b = 0x%x and %d \n", rssi_compensation_param.bg_param_b, rssi_compensation_param.bg_param_b); + A_PRINTF("a_param_a = 0x%x and %d \n", rssi_compensation_param.a_param_a, rssi_compensation_param.a_param_a); + A_PRINTF("a_param_b = 0x%x and %d \n", rssi_compensation_param.a_param_b, rssi_compensation_param.a_param_b); + A_PRINTF("Last 4 bytes = 0x%x \n", rssi_compensation_param.reserved); +#endif + + if (rssi_compensation_param.enable != 0x1) { + rssi_compensation_param.enable = 0; + } + + return; +} + +s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt) +{ + + if (freq > 5000) + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, totalPkt = %d\n", rssi,totalPkt)); + rssi = rssi * rssi_compensation_param.a_param_a + totalPkt * rssi_compensation_param.a_param_b; + rssi = (rssi-50) /100; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); + } + } + else + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, totalPkt = %d\n", rssi,totalPkt)); + rssi = rssi * rssi_compensation_param.bg_param_a + totalPkt * rssi_compensation_param.bg_param_b; + rssi = (rssi-50) /100; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); + } + } + + return rssi; +} + +s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi) +{ + if (ar->arBssChannel > 5000) + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n", rssi)); + rssi = rssi * rssi_compensation_param.a_param_a + rssi_compensation_param.a_param_b; + rssi = (rssi-50) /100; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); + } + } + else + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n", rssi)); + rssi = rssi * rssi_compensation_param.bg_param_a + rssi_compensation_param.bg_param_b; + rssi = (rssi-50) /100; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); + } + } + + return rssi; +} + +s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above) +{ + s16 i; + + if (ar->arBssChannel > 5000) + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d\n", rssi)); + rssi = rssi * 100; + rssi = (rssi - rssi_compensation_param.a_param_b) / rssi_compensation_param.a_param_a; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n", rssi)); + } + } + else + { + if (rssi_compensation_param.enable) + { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d\n", rssi)); + + if (Above) { + for (i=95; i>=0; i--) { + if (rssi <= rssi_compensation_table[i]) { + rssi = 0 - i; + break; + } + } + } else { + for (i=0; i<=95; i++) { + if (rssi >= rssi_compensation_table[i]) { + rssi = 0 - i; + break; + } + } + } + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n", rssi)); + } + } + + return rssi; +} + +#ifdef WAPI_ENABLE +void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac) +{ + union iwreq_data wrqu; + char buf[20]; + + A_MEMZERO(buf, sizeof(buf)); + + strcpy(buf, "WAPI_REKEY"); + buf[10] = type; + memcpy(&buf[11], mac, ATH_MAC_LEN); + + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = 10+1+ATH_MAC_LEN; + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); + + A_PRINTF("WAPI REKEY - %d - %02x:%02x\n", type, mac[4], mac[5]); +} +#endif + +static int +ar6000_reinstall_keys(struct ar6_softc *ar, u8 key_op_ctrl) +{ + int status = 0; + struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik; + struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik; + CRYPTO_TYPE keyType = ar->user_saved_keys.keyType; + + if (IEEE80211_CIPHER_CCKM_KRK != uik->ik_type) { + if (NONE_CRYPT == keyType) { + goto _reinstall_keys_out; + } + + if (uik->ik_keylen) { + status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix, + ar->user_saved_keys.keyType, PAIRWISE_USAGE, + uik->ik_keylen, (u8 *)&uik->ik_keyrsc, + uik->ik_keydata, key_op_ctrl, uik->ik_macaddr, SYNC_BEFORE_WMIFLAG); + } + + } else { + status = wmi_add_krk_cmd(ar->arWmi, uik->ik_keydata); + } + + if (IEEE80211_CIPHER_CCKM_KRK != bik->ik_type) { + if (NONE_CRYPT == keyType) { + goto _reinstall_keys_out; + } + + if (bik->ik_keylen) { + status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix, + ar->user_saved_keys.keyType, GROUP_USAGE, + bik->ik_keylen, (u8 *)&bik->ik_keyrsc, + bik->ik_keydata, key_op_ctrl, bik->ik_macaddr, NO_SYNC_WMIFLAG); + } + } else { + status = wmi_add_krk_cmd(ar->arWmi, bik->ik_keydata); + } + +_reinstall_keys_out: + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; + ar->user_key_ctrl = 0; + + return status; +} + + +void +ar6000_dset_open_req( + void *context, + u32 id, + u32 targHandle, + u32 targReplyFn, + u32 targReplyArg) +{ +} + +void +ar6000_dset_close( + void *context, + u32 access_cookie) +{ + return; +} + +void +ar6000_dset_data_req( + void *context, + u32 accessCookie, + u32 offset, + u32 length, + u32 targBuf, + u32 targReplyFn, + u32 targReplyArg) +{ +} + +int +ar6000_ap_mode_profile_commit(struct ar6_softc *ar) +{ + WMI_CONNECT_CMD p; + unsigned long flags; + + /* No change in AP's profile configuration */ + if(ar->ap_profile_flag==0) { + A_PRINTF("COMMIT: No change in profile!!!\n"); + return -ENODATA; + } + + if(!ar->arSsidLen) { + A_PRINTF("SSID not set!!!\n"); + return -ECHRNG; + } + + switch(ar->arAuthMode) { + case NONE_AUTH: + if((ar->arPairwiseCrypto != NONE_CRYPT) && +#ifdef WAPI_ENABLE + (ar->arPairwiseCrypto != WAPI_CRYPT) && +#endif + (ar->arPairwiseCrypto != WEP_CRYPT)) { + A_PRINTF("Cipher not supported in AP mode Open auth\n"); + return -EOPNOTSUPP; + } + break; + case WPA_PSK_AUTH: + case WPA2_PSK_AUTH: + case (WPA_PSK_AUTH|WPA2_PSK_AUTH): + break; + default: + A_PRINTF("This key mgmt type not supported in AP mode\n"); + return -EOPNOTSUPP; + } + + /* Update the arNetworkType */ + ar->arNetworkType = ar->arNextMode; + + A_MEMZERO(&p,sizeof(p)); + p.ssidLength = ar->arSsidLen; + memcpy(p.ssid,ar->arSsid,p.ssidLength); + p.channel = ar->arChannelHint; + p.networkType = ar->arNetworkType; + + p.dot11AuthMode = ar->arDot11AuthMode; + p.authMode = ar->arAuthMode; + p.pairwiseCryptoType = ar->arPairwiseCrypto; + p.pairwiseCryptoLen = ar->arPairwiseCryptoLen; + p.groupCryptoType = ar->arGroupCrypto; + p.groupCryptoLen = ar->arGroupCryptoLen; + p.ctrl_flags = ar->arConnectCtrlFlags; + + wmi_ap_profile_commit(ar->arWmi, &p); + spin_lock_irqsave(&ar->arLock, flags); + ar->arConnected = true; + netif_carrier_on(ar->arNetDev); + spin_unlock_irqrestore(&ar->arLock, flags); + ar->ap_profile_flag = 0; + return 0; +} + +int +ar6000_connect_to_ap(struct ar6_softc *ar) +{ + /* The ssid length check prevents second "essid off" from the user, + to be treated as a connect cmd. The second "essid off" is ignored. + */ + if((ar->arWmiReady == true) && (ar->arSsidLen > 0) && ar->arNetworkType!=AP_NETWORK) + { + int status; + if((ADHOC_NETWORK != ar->arNetworkType) && + (NONE_AUTH==ar->arAuthMode) && + (WEP_CRYPT==ar->arPairwiseCrypto)) { + ar6000_install_static_wep_keys(ar); + } + + if (!ar->arUserBssFilter) { + if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) { + return -EIO; + } + } +#ifdef WAPI_ENABLE + if (ar->arWapiEnable) { + ar->arPairwiseCrypto = WAPI_CRYPT; + ar->arPairwiseCryptoLen = 0; + ar->arGroupCrypto = WAPI_CRYPT; + ar->arGroupCryptoLen = 0; + ar->arAuthMode = NONE_AUTH; + ar->arConnectCtrlFlags |= CONNECT_IGNORE_WPAx_GROUP_CIPHER; + } +#endif + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Connect called with authmode %d dot11 auth %d"\ + " PW crypto %d PW crypto Len %d GRP crypto %d"\ + " GRP crypto Len %d\n", + ar->arAuthMode, ar->arDot11AuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto, ar->arGroupCryptoLen)); + reconnect_flag = 0; + /* Set the listen interval into 1000TUs or more. This value will be indicated to Ap in the conn. + later set it back locally at the STA to 100/1000 TUs depending on the power mode */ + if ((ar->arNetworkType == INFRA_NETWORK)) { + wmi_listeninterval_cmd(ar->arWmi, max(ar->arListenIntervalT, (u16)A_MAX_WOW_LISTEN_INTERVAL), 0); + } + status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, + ar->arDot11AuthMode, ar->arAuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto,ar->arGroupCryptoLen, + ar->arSsidLen, ar->arSsid, + ar->arReqBssid, ar->arChannelHint, + ar->arConnectCtrlFlags); + if (status) { + wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB); + if (!ar->arUserBssFilter) { + wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); + } + return status; + } + + if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) && + ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode))) + { + A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0); + } + + ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD; + + ar->arConnectPending = true; + return status; + } + return A_ERROR; +} + +int +ar6000_disconnect(struct ar6_softc *ar) +{ + if ((ar->arConnected == true) || (ar->arConnectPending == true)) { + wmi_disconnect_cmd(ar->arWmi); + /* + * Disconnect cmd is issued, clear connectPending. + * arConnected will be cleard in disconnect_event notification. + */ + ar->arConnectPending = false; + } + + return 0; +} + +int +ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie) +{ + sta_t *conn = NULL; + conn = ieee80211_find_conn(ar, wpaie->wpa_macaddr); + + A_MEMZERO(wpaie->wpa_ie, IEEE80211_MAX_IE); + A_MEMZERO(wpaie->rsn_ie, IEEE80211_MAX_IE); + + if(conn) { + memcpy(wpaie->wpa_ie, conn->wpa_ie, IEEE80211_MAX_IE); + } + + return 0; +} + +int +is_iwioctl_allowed(u8 mode, u16 cmd) +{ + if(cmd >= SIOCSIWCOMMIT && cmd <= SIOCGIWPOWER) { + cmd -= SIOCSIWCOMMIT; + if(sioctl_filter[cmd] == 0xFF) return 0; + if(sioctl_filter[cmd] & mode) return 0; + } else if(cmd >= SIOCIWFIRSTPRIV && cmd <= (SIOCIWFIRSTPRIV+30)) { + cmd -= SIOCIWFIRSTPRIV; + if(pioctl_filter[cmd] == 0xFF) return 0; + if(pioctl_filter[cmd] & mode) return 0; + } else { + return A_ERROR; + } + return A_ENOTSUP; +} + +int +is_xioctl_allowed(u8 mode, int cmd) +{ + if(sizeof(xioctl_filter)-1 < cmd) { + A_PRINTF("Filter for this cmd=%d not defined\n",cmd); + return 0; + } + if(xioctl_filter[cmd] == 0xFF) return 0; + if(xioctl_filter[cmd] & mode) return 0; + return A_ERROR; +} + +#ifdef WAPI_ENABLE +int +ap_set_wapi_key(struct ar6_softc *ar, void *ikey) +{ + struct ieee80211req_key *ik = (struct ieee80211req_key *)ikey; + KEY_USAGE keyUsage = 0; + int status; + + if (memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN) == 0) { + keyUsage = GROUP_USAGE; + } else { + keyUsage = PAIRWISE_USAGE; + } + A_PRINTF("WAPI_KEY: Type:%d ix:%d mac:%02x:%02x len:%d\n", + keyUsage, ik->ik_keyix, ik->ik_macaddr[4], ik->ik_macaddr[5], + ik->ik_keylen); + + status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, WAPI_CRYPT, keyUsage, + ik->ik_keylen, (u8 *)&ik->ik_keyrsc, + ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr, + SYNC_BOTH_WMIFLAG); + + if (0 != status) { + return -EIO; + } + return 0; +} +#endif + +void ar6000_peer_event( + void *context, + u8 eventCode, + u8 *macAddr) +{ + u8 pos; + + for (pos=0;pos<6;pos++) + printk("%02x: ",*(macAddr+pos)); + printk("\n"); +} + +#ifdef HTC_TEST_SEND_PKTS +#define HTC_TEST_DUPLICATE 8 +static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *dupskb) +{ + struct ar_cookie *cookie; + struct ar_cookie *cookieArray[HTC_TEST_DUPLICATE]; + struct sk_buff *new_skb; + int i; + int pkts = 0; + struct htc_packet_queue pktQueue; + EPPING_HEADER *eppingHdr; + + eppingHdr = A_NETBUF_DATA(dupskb); + + if (eppingHdr->Cmd_h == EPPING_CMD_NO_ECHO) { + /* skip test if this is already a tx perf test */ + return; + } + + for (i = 0; i < HTC_TEST_DUPLICATE; i++,pkts++) { + AR6000_SPIN_LOCK(&ar->arLock, 0); + cookie = ar6000_alloc_cookie(ar); + if (cookie != NULL) { + ar->arTxPending[eid]++; + ar->arTotalTxDataPending++; + } + + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + + if (NULL == cookie) { + break; + } + + new_skb = A_NETBUF_ALLOC(A_NETBUF_LEN(dupskb)); + + if (new_skb == NULL) { + AR6000_SPIN_LOCK(&ar->arLock, 0); + ar6000_free_cookie(ar,cookie); + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + break; + } + + A_NETBUF_PUT_DATA(new_skb, A_NETBUF_DATA(dupskb), A_NETBUF_LEN(dupskb)); + cookie->arc_bp[0] = (unsigned long)new_skb; + cookie->arc_bp[1] = MapNo; + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, + A_NETBUF_DATA(new_skb), + A_NETBUF_LEN(new_skb), + eid, + AR6K_DATA_PKT_TAG); + + cookieArray[i] = cookie; + + { + EPPING_HEADER *pHdr = (EPPING_HEADER *)A_NETBUF_DATA(new_skb); + pHdr->Cmd_h = EPPING_CMD_NO_ECHO; /* do not echo the packet */ + } + } + + if (pkts == 0) { + return; + } + + INIT_HTC_PACKET_QUEUE(&pktQueue); + + for (i = 0; i < pkts; i++) { + HTC_PACKET_ENQUEUE(&pktQueue,&cookieArray[i]->HtcPkt); + } + + HTCSendPktsMultiple(ar->arHtcTarget, &pktQueue); + +} +#endif + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT +/* + * Add support for adding and removing a virtual adapter for soft AP. + * Some OS requires different adapters names for station and soft AP mode. + * To support these requirement, create and destroy a netdevice instance + * when the AP mode is operational. A full fledged support for virual device + * is not implemented. Rather a virtual interface is created and is linked + * with the existing physical device instance during the operation of the + * AP mode. + */ + +int ar6000_start_ap_interface(struct ar6_softc *ar) +{ + struct ar_virtual_interface *arApDev; + + /* Change net_device to point to AP instance */ + arApDev = (struct ar_virtual_interface *)ar->arApDev; + ar->arNetDev = arApDev->arNetDev; + + return 0; +} + +int ar6000_stop_ap_interface(struct ar6_softc *ar) +{ + struct ar_virtual_interface *arApDev; + + /* Change net_device to point to sta instance */ + arApDev = (struct ar_virtual_interface *)ar->arApDev; + if (arApDev) { + ar->arNetDev = arApDev->arStaNetDev; + } + + return 0; +} + + +int ar6000_create_ap_interface(struct ar6_softc *ar, char *ap_ifname) +{ + struct net_device *dev; + struct ar_virtual_interface *arApDev; + + dev = alloc_etherdev(sizeof(struct ar_virtual_interface)); + if (dev == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: can't alloc etherdev\n")); + return A_ERROR; + } + + ether_setup(dev); + init_netdev(dev, ap_ifname); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + + if (register_netdev(dev)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: register_netdev failed\n")); + return A_ERROR; + } + + arApDev = netdev_priv(dev); + arApDev->arDev = ar; + arApDev->arNetDev = dev; + arApDev->arStaNetDev = ar->arNetDev; + + ar->arApDev = arApDev; + arApNetDev = dev; + + /* Copy the MAC address */ + memcpy(dev->dev_addr, ar->arNetDev->dev_addr, AR6000_ETH_ADDR_LEN); + + return 0; +} + +int ar6000_add_ap_interface(struct ar6_softc *ar, char *ap_ifname) +{ + /* Interface already added, need not proceed further */ + if (ar->arApDev != NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_add_ap_interface: interface already present \n")); + return 0; + } + + if (ar6000_create_ap_interface(ar, ap_ifname) != 0) { + return A_ERROR; + } + + A_PRINTF("Add AP interface %s \n",ap_ifname); + + return ar6000_start_ap_interface(ar); +} + +int ar6000_remove_ap_interface(struct ar6_softc *ar) +{ + if (arApNetDev) { + ar6000_stop_ap_interface(ar); + + unregister_netdev(arApNetDev); + free_netdev(apApNetDev); + + A_PRINTF("Remove AP interface\n"); + } + ar->arApDev = NULL; + arApNetDev = NULL; + + + return 0; +} +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +EXPORT_SYMBOL(setupbtdev); +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/ar6000_pm.c b/trunk/drivers/staging/ath6kl/os/linux/ar6000_pm.c new file mode 100644 index 000000000000..1e0ace8b6d13 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/ar6000_pm.c @@ -0,0 +1,626 @@ +/* + * + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * +// +// Permission to use, copy, modify, and/or 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. +// +// + * + */ + +/* + * Implementation of system power management + */ + +#include "ar6000_drv.h" +#include +#include +#include "wlan_config.h" + +#define WOW_ENABLE_MAX_INTERVAL 0 +#define WOW_SET_SCAN_PARAMS 0 + +extern unsigned int wmitimeout; +extern wait_queue_head_t arEvent; + +#undef ATH_MODULE_NAME +#define ATH_MODULE_NAME pm +#define ATH_DEBUG_PM ATH_DEBUG_MAKE_MODULE_MASK(0) + +#ifdef DEBUG +static struct ath_debug_mask_description pm_debug_desc[] = { + { ATH_DEBUG_PM , "System power management"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(pm, + "pm", + "System Power Management", + ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_PM, + ATH_DEBUG_DESCRIPTION_COUNT(pm_debug_desc), + pm_debug_desc); + +#endif /* DEBUG */ + +int ar6000_exit_cut_power_state(struct ar6_softc *ar); + +#ifdef CONFIG_PM +static void ar6k_send_asleep_event_to_app(struct ar6_softc *ar, bool asleep) +{ + char buf[128]; + union iwreq_data wrqu; + + snprintf(buf, sizeof(buf), "HOST_ASLEEP=%s", asleep ? "asleep" : "awake"); + A_MEMZERO(&wrqu, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); +} + +static void ar6000_wow_resume(struct ar6_softc *ar) +{ + if (ar->arWowState!= WLAN_WOW_STATE_NONE) { + u16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period; + u16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period; + WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {true, false}; + ar->arWowState = WLAN_WOW_STATE_NONE; + if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!= 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n")); + } +#if WOW_SET_SCAN_PARAMS + wmi_scanparams_cmd(ar->arWmi, fg_start_period, + ar->scParams.fg_end_period, + bg_period, + ar->scParams.minact_chdwell_time, + ar->scParams.maxact_chdwell_time, + ar->scParams.pas_chdwell_time, + ar->scParams.shortScanRatio, + ar->scParams.scanCtrlFlags, + ar->scParams.max_dfsch_act_time, + ar->scParams.maxact_scan_per_ssid); +#else + (void)fg_start_period; + (void)bg_period; +#endif + + +#if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ + if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == 0) { + } +#endif + ar6k_send_asleep_event_to_app(ar, false); + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Resume WoW successfully\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WoW does not invoked. skip resume")); + } + ar->arWlanPowerState = WLAN_POWER_STATE_ON; +} + +static void ar6000_wow_suspend(struct ar6_softc *ar) +{ +#define WOW_LIST_ID 1 + if (ar->arNetworkType != AP_NETWORK) { + /* Setup WoW for unicast & Arp request for our own IP + disable background scan. Set listen interval into 1000 TUs + Enable keepliave for 110 seconds + */ + struct in_ifaddr **ifap = NULL; + struct in_ifaddr *ifa = NULL; + struct in_device *in_dev; + u8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + int status; + WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } }; + WMI_DEL_WOW_PATTERN_CMD delWowCmd; + WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {false, true}; + WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = true, + .hostReqDelay = 500 };/*500 ms delay*/ + + if (ar->arWowState!= WLAN_WOW_STATE_NONE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("System already go into wow mode!\n")); + return; + } + + ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/ + +#if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ + if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == 0) { + } +#endif + +#if WOW_SET_SCAN_PARAMS + status = wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0); +#endif + /* clear up our WoW pattern first */ + delWowCmd.filter_list_id = WOW_LIST_ID; + delWowCmd.filter_id = 0; + wmi_del_wow_pattern_cmd(ar->arWmi, &delWowCmd); + + /* setup unicast packet pattern for WoW */ + if (ar->arNetDev->dev_addr[1]) { + addWowCmd.filter_list_id = WOW_LIST_ID; + addWowCmd.filter_size = 6; /* MAC address */ + addWowCmd.filter_offset = 0; + status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n")); + } + } + /* setup ARP request for our own IP */ + if ((in_dev = __in_dev_get_rtnl(ar->arNetDev)) != NULL) { + for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { + if (!strcmp(ar->arNetDev->name, ifa->ifa_label)) { + break; /* found */ + } + } + } + if (ifa && ifa->ifa_local) { + WMI_SET_IP_CMD ipCmd; + memset(&ipCmd, 0, sizeof(ipCmd)); + ipCmd.ips[0] = ifa->ifa_local; + status = wmi_set_ip_cmd(ar->arWmi, &ipCmd); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n")); + } + } + +#ifndef ATH6K_CONFIG_OTA_MODE + wmi_powermode_cmd(ar->arWmi, REC_POWER); +#endif + + status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n")); + } + ar6k_send_asleep_event_to_app(ar, true); + + status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n")); + } + + ar->arWowState = WLAN_WOW_STATE_SUSPENDING; + if (ar->arTxPending[ar->arControlEp]) { + u32 timeleft = wait_event_interruptible_timeout(arEvent, + ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); + if (!timeleft || signal_pending(current)) { + /* what can I do? wow resume at once */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi control data %d\n", ar->arTxPending[ar->arControlEp])); + } + } + + status = hifWaitForPendingRecv(ar->arHifDevice); + + ar->arWowState = WLAN_WOW_STATE_SUSPENDED; + ar->arWlanPowerState = WLAN_POWER_STATE_WOW; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Not allowed to go to WOW at this moment.\n")); + } +} + +int ar6000_suspend_ev(void *context) +{ + int status = 0; + struct ar6_softc *ar = (struct ar6_softc *)context; + s16 pmmode = ar->arSuspendConfig; +wow_not_connected: + switch (pmmode) { + case WLAN_SUSPEND_WOW: + if (ar->arWmiReady && ar->arWlanState==WLAN_ENABLED && ar->arConnected) { + ar6000_wow_suspend(ar); + AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for wow mode %d\n", __func__, ar->arWlanPowerState)); + } else { + pmmode = ar->arWow2Config; + goto wow_not_connected; + } + break; + case WLAN_SUSPEND_CUT_PWR: + /* fall through */ + case WLAN_SUSPEND_CUT_PWR_IF_BT_OFF: + /* fall through */ + case WLAN_SUSPEND_DEEP_SLEEP: + /* fall through */ + default: + status = ar6000_update_wlan_pwr_state(ar, WLAN_DISABLED, true); + if (ar->arWlanPowerState==WLAN_POWER_STATE_ON || + ar->arWlanPowerState==WLAN_POWER_STATE_WOW) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Strange suspend state for not wow mode %d", ar->arWlanPowerState)); + } + AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for %d mode pwr %d status %d\n", __func__, pmmode, ar->arWlanPowerState, status)); + status = (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) ? 0 : A_EBUSY; + break; + } + + ar->scan_triggered = 0; + return status; +} + +int ar6000_resume_ev(void *context) +{ + struct ar6_softc *ar = (struct ar6_softc *)context; + u16 powerState = ar->arWlanPowerState; + + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: enter previous state %d wowState %d\n", __func__, powerState, ar->arWowState)); + switch (powerState) { + case WLAN_POWER_STATE_WOW: + ar6000_wow_resume(ar); + break; + case WLAN_POWER_STATE_CUT_PWR: + /* fall through */ + case WLAN_POWER_STATE_DEEP_SLEEP: + ar6000_update_wlan_pwr_state(ar, WLAN_ENABLED, true); + AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Resume for %d mode pwr %d\n", __func__, powerState, ar->arWlanPowerState)); + break; + case WLAN_POWER_STATE_ON: + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n")); + break; + } + return 0; +} + +void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent) +{ + if (ar->arWowState!=WLAN_WOW_STATE_NONE) { + if (ar->arWowState==WLAN_WOW_STATE_SUSPENDING) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM,("\n%s: Received IRQ while we are wow suspending!!!\n\n", __func__)); + return; + } + /* Wow resume from irq interrupt */ + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: WoW resume from irq thread status %d\n", __func__, ar->arWlanPowerState)); + ar6000_wow_resume(ar); + } +} + +int ar6000_power_change_ev(void *context, u32 config) +{ + struct ar6_softc *ar = (struct ar6_softc *)context; + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: power change event callback %d \n", __func__, config)); + switch (config) { + case HIF_DEVICE_POWER_UP: + ar6000_restart_endpoint(ar->arNetDev); + status = 0; + break; + case HIF_DEVICE_POWER_DOWN: + case HIF_DEVICE_POWER_CUT: + status = 0; + break; + } + return status; +} + +#endif /* CONFIG_PM */ + +int +ar6000_setup_cut_power_state(struct ar6_softc *ar, AR6000_WLAN_STATE state) +{ + int status = 0; + HIF_DEVICE_POWER_CHANGE_TYPE config; + + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Cut power %d %d \n", __func__,state, ar->arWlanPowerState)); +#ifdef CONFIG_PM + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff)); +#endif + do { + if (state == WLAN_ENABLED) { + /* Not in cut power state.. exit */ + if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) { + break; + } + + /* Change the state to ON */ + ar->arWlanPowerState = WLAN_POWER_STATE_ON; + + + /* Indicate POWER_UP to HIF */ + config = HIF_DEVICE_POWER_UP; + status = HIFConfigureDevice(ar->arHifDevice, + HIF_DEVICE_POWER_STATE_CHANGE, + &config, + sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); + + if (status == A_PENDING) { + } else if (status == 0) { + ar6000_restart_endpoint(ar->arNetDev); + status = 0; + } + } else if (state == WLAN_DISABLED) { + + + /* Already in cut power state.. exit */ + if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) { + break; + } + ar6000_stop_endpoint(ar->arNetDev, true, false); + + config = HIF_DEVICE_POWER_CUT; + status = HIFConfigureDevice(ar->arHifDevice, + HIF_DEVICE_POWER_STATE_CHANGE, + &config, + sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); + + ar->arWlanPowerState = WLAN_POWER_STATE_CUT_PWR; + } + } while (0); + + return status; +} + +int +ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state) +{ + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Deep sleep %d %d \n", __func__,state, ar->arWlanPowerState)); +#ifdef CONFIG_PM + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff)); +#endif + do { + WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode; + + if (state == WLAN_ENABLED) { + u16 fg_start_period; + + /* Not in deep sleep state.. exit */ + if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) { + if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we resume from deep sleep %d\n", ar->arWlanPowerState)); + } + break; + } + + fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period; + hostSleepMode.awake = true; + hostSleepMode.asleep = false; + + if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != 0) { + break; + } + + /* Change the state to ON */ + ar->arWlanPowerState = WLAN_POWER_STATE_ON; + + /* Enable foreground scanning */ + if ((status=wmi_scanparams_cmd(ar->arWmi, fg_start_period, + ar->scParams.fg_end_period, + ar->scParams.bg_period, + ar->scParams.minact_chdwell_time, + ar->scParams.maxact_chdwell_time, + ar->scParams.pas_chdwell_time, + ar->scParams.shortScanRatio, + ar->scParams.scanCtrlFlags, + ar->scParams.max_dfsch_act_time, + ar->scParams.maxact_scan_per_ssid)) != 0) + { + break; + } + + if (ar->arNetworkType != AP_NETWORK) + { + if (ar->arSsidLen) { + if (ar6000_connect_to_ap(ar) != 0) { + /* no need to report error if connection failed */ + break; + } + } + } + } else if (state == WLAN_DISABLED){ + WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = false }; + + /* Already in deep sleep state.. exit */ + if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) { + if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we suspend for deep sleep %d\n", ar->arWlanPowerState)); + } + break; + } + + if (ar->arNetworkType != AP_NETWORK) + { + /* Disconnect from the AP and disable foreground scanning */ + AR6000_SPIN_LOCK(&ar->arLock, 0); + if (ar->arConnected == true || ar->arConnectPending == true) { + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + wmi_disconnect_cmd(ar->arWmi); + } else { + AR6000_SPIN_UNLOCK(&ar->arLock, 0); + } + } + + ar->scan_triggered = 0; + + if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != 0) { + break; + } + + /* make sure we disable wow for deep sleep */ + if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!= 0) + { + break; + } + + ar6000_TxDataCleanup(ar); +#ifndef ATH6K_CONFIG_OTA_MODE + wmi_powermode_cmd(ar->arWmi, REC_POWER); +#endif + + hostSleepMode.awake = false; + hostSleepMode.asleep = true; + if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!= 0) { + break; + } + if (ar->arTxPending[ar->arControlEp]) { + u32 timeleft = wait_event_interruptible_timeout(arEvent, + ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); + if (!timeleft || signal_pending(current)) { + status = A_ERROR; + break; + } + } + status = hifWaitForPendingRecv(ar->arHifDevice); + + ar->arWlanPowerState = WLAN_POWER_STATE_DEEP_SLEEP; + } + } while (0); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enter/exit deep sleep %d\n", state)); + } + + return status; +} + +int +ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool pmEvent) +{ + int status = 0; + u16 powerState, oldPowerState; + AR6000_WLAN_STATE oldstate = ar->arWlanState; + bool wlanOff = ar->arWlanOff; +#ifdef CONFIG_PM + bool btOff = ar->arBTOff; +#endif /* CONFIG_PM */ + + if ((state!=WLAN_DISABLED && state!=WLAN_ENABLED)) { + return A_ERROR; + } + + if (ar->bIsDestroyProgress) { + return A_EBUSY; + } + + if (down_interruptible(&ar->arSem)) { + return A_ERROR; + } + + if (ar->bIsDestroyProgress) { + up(&ar->arSem); + return A_EBUSY; + } + + ar->arWlanState = wlanOff ? WLAN_DISABLED : state; + oldPowerState = ar->arWlanPowerState; + if (state == WLAN_ENABLED) { + powerState = ar->arWlanPowerState; + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to ENABLE^^\n")); + if (!wlanOff) { + if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) { + status = ar6000_setup_deep_sleep_state(ar, WLAN_ENABLED); + } else if (powerState == WLAN_POWER_STATE_CUT_PWR) { + status = ar6000_setup_cut_power_state(ar, WLAN_ENABLED); + } + } +#ifdef CONFIG_PM + else if (pmEvent && wlanOff) { + bool allowCutPwr = ((!ar->arBTSharing) || btOff); + if ((powerState==WLAN_POWER_STATE_CUT_PWR) && (!allowCutPwr)) { + /* Come out of cut power */ + ar6000_setup_cut_power_state(ar, WLAN_ENABLED); + status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED); + } + } +#endif /* CONFIG_PM */ + } else if (state == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to DISABLED~\n")); + powerState = WLAN_POWER_STATE_DEEP_SLEEP; +#ifdef CONFIG_PM + if (pmEvent) { /* disable due to suspend */ + bool suspendCutPwr = (ar->arSuspendConfig == WLAN_SUSPEND_CUT_PWR || + (ar->arSuspendConfig == WLAN_SUSPEND_WOW && + ar->arWow2Config==WLAN_SUSPEND_CUT_PWR)); + bool suspendCutIfBtOff = ((ar->arSuspendConfig == + WLAN_SUSPEND_CUT_PWR_IF_BT_OFF || + (ar->arSuspendConfig == WLAN_SUSPEND_WOW && + ar->arWow2Config==WLAN_SUSPEND_CUT_PWR_IF_BT_OFF)) && + (!ar->arBTSharing || btOff)); + if ((suspendCutPwr) || + (suspendCutIfBtOff) || + (ar->arWlanState==WLAN_POWER_STATE_CUT_PWR)) + { + powerState = WLAN_POWER_STATE_CUT_PWR; + } + } else { + if ((wlanOff) && + (ar->arWlanOffConfig == WLAN_OFF_CUT_PWR) && + (!ar->arBTSharing || btOff)) + { + /* For BT clock sharing designs, CUT_POWER depend on BT state */ + powerState = WLAN_POWER_STATE_CUT_PWR; + } + } +#endif /* CONFIG_PM */ + + if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) { + if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Load firmware before set to deep sleep\n")); + ar6000_setup_cut_power_state(ar, WLAN_ENABLED); + } + status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED); + } else if (powerState == WLAN_POWER_STATE_CUT_PWR) { + status = ar6000_setup_cut_power_state(ar, WLAN_DISABLED); + } + + } + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WLAN state %d\n", ar->arWlanState)); + ar->arWlanState = oldstate; + } else if (status == 0) { + WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent, *pSleepEvent = NULL; + if ((ar->arWlanPowerState == WLAN_POWER_STATE_ON) && (oldPowerState != WLAN_POWER_STATE_ON)) { + wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE; + pSleepEvent = &wmiSleepEvent; + } else if ((ar->arWlanPowerState != WLAN_POWER_STATE_ON) && (oldPowerState == WLAN_POWER_STATE_ON)) { + wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP; + pSleepEvent = &wmiSleepEvent; + } + if (pSleepEvent) { + AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("SENT WLAN Sleep Event %d\n", wmiSleepEvent.sleepState)); + } + } + up(&ar->arSem); + return status; +} + +int +ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 enable) +{ +#ifdef CONFIG_PM + bool off = (enable == 0); + int status; + if (ar->arBTOff == off) { + return 0; + } + ar->arBTOff = off; + status = ar6000_update_wlan_pwr_state(ar, ar->arWlanOff ? WLAN_DISABLED : WLAN_ENABLED, false); + return status; +#else + return 0; +#endif +} + +int +ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state) +{ + int status; + bool off = (state == WLAN_DISABLED); + if (ar->arWlanOff == off) { + return 0; + } + ar->arWlanOff = off; + status = ar6000_update_wlan_pwr_state(ar, state, false); + return status; +} diff --git a/trunk/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c b/trunk/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c new file mode 100644 index 000000000000..ae7c1dd96d83 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c @@ -0,0 +1,455 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#include "ar6000_drv.h" + +#ifdef HTC_RAW_INTERFACE + +static void +ar6000_htc_raw_read_cb(void *Context, struct htc_packet *pPacket) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + raw_htc_buffer *busy; + HTC_RAW_STREAM_ID streamID; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + busy = (raw_htc_buffer *)pPacket->pPktContext; + A_ASSERT(busy != NULL); + + if (pPacket->Status == A_ECANCELED) { + /* + * HTC provides A_ECANCELED status when it doesn't want to be refilled + * (probably due to a shutdown) + */ + return; + } + + streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint); + A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED); + +#ifdef CF + if (down_trylock(&arRaw->raw_htc_read_sem[streamID])) { +#else + if (down_interruptible(&arRaw->raw_htc_read_sem[streamID])) { +#endif /* CF */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n")); + } + + A_ASSERT((pPacket->Status != 0) || + (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN))); + + busy->length = pPacket->ActualLength + HTC_HEADER_LEN; + busy->currPtr = HTC_HEADER_LEN; + arRaw->read_buffer_available[streamID] = true; + //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("raw read cb: 0x%X 0x%X \n", busy->currPtr,busy->length); + up(&arRaw->raw_htc_read_sem[streamID]); + + /* Signal the waiting process */ + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) read process\n", streamID)); + wake_up_interruptible(&arRaw->raw_htc_read_queue[streamID]); +} + +static void +ar6000_htc_raw_write_cb(void *Context, struct htc_packet *pPacket) +{ + struct ar6_softc *ar = (struct ar6_softc *)Context; + raw_htc_buffer *free; + HTC_RAW_STREAM_ID streamID; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + free = (raw_htc_buffer *)pPacket->pPktContext; + A_ASSERT(free != NULL); + + if (pPacket->Status == A_ECANCELED) { + /* + * HTC provides A_ECANCELED status when it doesn't want to be refilled + * (probably due to a shutdown) + */ + return; + } + + streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint); + A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED); + +#ifdef CF + if (down_trylock(&arRaw->raw_htc_write_sem[streamID])) { +#else + if (down_interruptible(&arRaw->raw_htc_write_sem[streamID])) { +#endif + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n")); + } + + A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN)); + + free->length = 0; + arRaw->write_buffer_available[streamID] = true; + up(&arRaw->raw_htc_write_sem[streamID]); + + /* Signal the waiting process */ + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) write process\n", streamID)); + wake_up_interruptible(&arRaw->raw_htc_write_queue[streamID]); +} + +/* connect to a service */ +static int ar6000_connect_raw_service(struct ar6_softc *ar, + HTC_RAW_STREAM_ID StreamID) +{ + int status; + struct htc_service_connect_resp response; + u8 streamNo; + struct htc_service_connect_req connect; + + do { + + A_MEMZERO(&connect,sizeof(connect)); + /* pass the stream ID as meta data to the RAW streams service */ + streamNo = (u8)StreamID; + connect.pMetaData = &streamNo; + connect.MetaDataLength = sizeof(u8); + /* these fields are the same for all endpoints */ + connect.EpCallbacks.pContext = ar; + connect.EpCallbacks.EpTxComplete = ar6000_htc_raw_write_cb; + connect.EpCallbacks.EpRecv = ar6000_htc_raw_read_cb; + /* simple interface, we don't need these optional callbacks */ + connect.EpCallbacks.EpRecvRefill = NULL; + connect.EpCallbacks.EpSendFull = NULL; + connect.MaxSendQueueDepth = RAW_HTC_WRITE_BUFFERS_NUM; + + /* connect to the raw streams service, we may be able to get 1 or more + * connections, depending on WHAT is running on the target */ + connect.ServiceID = HTC_RAW_STREAMS_SVC; + + A_MEMZERO(&response,sizeof(response)); + + /* try to connect to the raw stream, it is okay if this fails with + * status HTC_SERVICE_NO_MORE_EP */ + status = HTCConnectService(ar->arHtcTarget, + &connect, + &response); + + if (status) { + if (response.ConnectRespCode == HTC_SERVICE_NO_MORE_EP) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC RAW , No more streams allowed \n")); + status = 0; + } + break; + } + + /* set endpoint mapping for the RAW HTC streams */ + arSetRawStream2EndpointIDMap(ar,StreamID,response.Endpoint); + + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("HTC RAW : stream ID: %d, endpoint: %d\n", + StreamID, arRawStream2EndpointID(ar,StreamID))); + + } while (false); + + return status; +} + +int ar6000_htc_raw_open(struct ar6_softc *ar) +{ + int status; + int streamID, endPt, count2; + raw_htc_buffer *buffer; + HTC_SERVICE_ID servicepriority; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + if (!arRaw) { + arRaw = ar->arRawHtc = A_MALLOC(sizeof(AR_RAW_HTC_T)); + if (arRaw) { + A_MEMZERO(arRaw, sizeof(AR_RAW_HTC_T)); + } + } + A_ASSERT(ar->arHtcTarget != NULL); + if (!arRaw) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Faile to allocate memory for HTC RAW interface\n")); + return -ENOMEM; + } + /* wait for target */ + status = HTCWaitTarget(ar->arHtcTarget); + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTCWaitTarget failed (%d)\n", status)); + return -ENODEV; + } + + for (endPt = 0; endPt < ENDPOINT_MAX; endPt++) { + arRaw->arEp2RawMapping[endPt] = HTC_RAW_STREAM_NOT_MAPPED; + } + + for (streamID = HTC_RAW_STREAM_0; streamID < HTC_RAW_STREAM_NUM_MAX; streamID++) { + /* Initialize the data structures */ + sema_init(&arRaw->raw_htc_read_sem[streamID], 1); + sema_init(&arRaw->raw_htc_write_sem[streamID], 1); + init_waitqueue_head(&arRaw->raw_htc_read_queue[streamID]); + init_waitqueue_head(&arRaw->raw_htc_write_queue[streamID]); + + /* try to connect to the raw service */ + status = ar6000_connect_raw_service(ar,streamID); + + if (status) { + break; + } + + if (arRawStream2EndpointID(ar,streamID) == 0) { + break; + } + + for (count2 = 0; count2 < RAW_HTC_READ_BUFFERS_NUM; count2 ++) { + /* Initialize the receive buffers */ + buffer = &arRaw->raw_htc_write_buffer[streamID][count2]; + memset(buffer, 0, sizeof(raw_htc_buffer)); + buffer = &arRaw->raw_htc_read_buffer[streamID][count2]; + memset(buffer, 0, sizeof(raw_htc_buffer)); + + SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket, + buffer, + buffer->data, + HTC_RAW_BUFFER_SIZE, + arRawStream2EndpointID(ar,streamID)); + + /* Queue buffers to HTC for receive */ + if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != 0) + { + BMIInit(); + return -EIO; + } + } + + for (count2 = 0; count2 < RAW_HTC_WRITE_BUFFERS_NUM; count2 ++) { + /* Initialize the receive buffers */ + buffer = &arRaw->raw_htc_write_buffer[streamID][count2]; + memset(buffer, 0, sizeof(raw_htc_buffer)); + } + + arRaw->read_buffer_available[streamID] = false; + arRaw->write_buffer_available[streamID] = true; + } + + if (status) { + return -EIO; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("HTC RAW, number of streams the target supports: %d \n", streamID)); + + servicepriority = HTC_RAW_STREAMS_SVC; /* only 1 */ + + /* set callbacks and priority list */ + HTCSetCreditDistribution(ar->arHtcTarget, + ar, + NULL, /* use default */ + NULL, /* use default */ + &servicepriority, + 1); + + /* Start the HTC component */ + if ((status = HTCStart(ar->arHtcTarget)) != 0) { + BMIInit(); + return -EIO; + } + + (ar)->arRawIfInit = true; + + return 0; +} + +int ar6000_htc_raw_close(struct ar6_softc *ar) +{ + A_PRINTF("ar6000_htc_raw_close called \n"); + HTCStop(ar->arHtcTarget); + + /* reset the device */ + ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, false); + /* Initialize the BMI component */ + BMIInit(); + + return 0; +} + +raw_htc_buffer * +get_filled_buffer(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID) +{ + int count; + raw_htc_buffer *busy; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + /* Check for data */ + for (count = 0; count < RAW_HTC_READ_BUFFERS_NUM; count ++) { + busy = &arRaw->raw_htc_read_buffer[StreamID][count]; + if (busy->length) { + break; + } + } + if (busy->length) { + arRaw->read_buffer_available[StreamID] = true; + } else { + arRaw->read_buffer_available[StreamID] = false; + } + + return busy; +} + +ssize_t ar6000_htc_raw_read(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID, + char __user *buffer, size_t length) +{ + int readPtr; + raw_htc_buffer *busy; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + if (arRawStream2EndpointID(ar,StreamID) == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID)); + return -EFAULT; + } + + if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) { + return -ERESTARTSYS; + } + + busy = get_filled_buffer(ar,StreamID); + while (!arRaw->read_buffer_available[StreamID]) { + up(&arRaw->raw_htc_read_sem[StreamID]); + + /* Wait for the data */ + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) read process\n", StreamID)); + if (wait_event_interruptible(arRaw->raw_htc_read_queue[StreamID], + arRaw->read_buffer_available[StreamID])) + { + return -EINTR; + } + if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) { + return -ERESTARTSYS; + } + busy = get_filled_buffer(ar,StreamID); + } + + /* Read the data */ + readPtr = busy->currPtr; + if (length > busy->length - HTC_HEADER_LEN) { + length = busy->length - HTC_HEADER_LEN; + } + if (copy_to_user(buffer, &busy->data[readPtr], length)) { + up(&arRaw->raw_htc_read_sem[StreamID]); + return -EFAULT; + } + + busy->currPtr += length; + + if (busy->currPtr == busy->length) + { + busy->currPtr = 0; + busy->length = 0; + HTC_PACKET_RESET_RX(&busy->HTCPacket); + //AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("raw read ioctl: ep for packet:%d \n", busy->HTCPacket.Endpoint)); + HTCAddReceivePkt(ar->arHtcTarget, &busy->HTCPacket); + } + arRaw->read_buffer_available[StreamID] = false; + up(&arRaw->raw_htc_read_sem[StreamID]); + + return length; +} + +static raw_htc_buffer * +get_free_buffer(struct ar6_softc *ar, HTC_ENDPOINT_ID StreamID) +{ + int count; + raw_htc_buffer *free; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + + free = NULL; + for (count = 0; count < RAW_HTC_WRITE_BUFFERS_NUM; count ++) { + free = &arRaw->raw_htc_write_buffer[StreamID][count]; + if (free->length == 0) { + break; + } + } + if (!free->length) { + arRaw->write_buffer_available[StreamID] = true; + } else { + arRaw->write_buffer_available[StreamID] = false; + } + + return free; +} + +ssize_t ar6000_htc_raw_write(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID, + char __user *buffer, size_t length) +{ + int writePtr; + raw_htc_buffer *free; + AR_RAW_HTC_T *arRaw = ar->arRawHtc; + if (arRawStream2EndpointID(ar,StreamID) == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID)); + return -EFAULT; + } + + if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) { + return -ERESTARTSYS; + } + + /* Search for a free buffer */ + free = get_free_buffer(ar,StreamID); + + /* Check if there is space to write else wait */ + while (!arRaw->write_buffer_available[StreamID]) { + up(&arRaw->raw_htc_write_sem[StreamID]); + + /* Wait for buffer to become free */ + AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) write process\n", StreamID)); + if (wait_event_interruptible(arRaw->raw_htc_write_queue[StreamID], + arRaw->write_buffer_available[StreamID])) + { + return -EINTR; + } + if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) { + return -ERESTARTSYS; + } + free = get_free_buffer(ar,StreamID); + } + + /* Send the data */ + writePtr = HTC_HEADER_LEN; + if (length > (HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN)) { + length = HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN; + } + + if (copy_from_user(&free->data[writePtr], buffer, length)) { + up(&arRaw->raw_htc_read_sem[StreamID]); + return -EFAULT; + } + + free->length = length; + + SET_HTC_PACKET_INFO_TX(&free->HTCPacket, + free, + &free->data[writePtr], + length, + arRawStream2EndpointID(ar,StreamID), + AR6K_DATA_PKT_TAG); + + HTCSendPkt(ar->arHtcTarget,&free->HTCPacket); + + arRaw->write_buffer_available[StreamID] = false; + up(&arRaw->raw_htc_write_sem[StreamID]); + + return length; +} +#endif /* HTC_RAW_INTERFACE */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/cfg80211.c b/trunk/drivers/staging/ath6kl/os/linux/cfg80211.c new file mode 100644 index 000000000000..5fdda4aa2fee --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/cfg80211.c @@ -0,0 +1,1892 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#include +#include +#include +#include + +#include "ar6000_drv.h" + + +extern A_WAITQUEUE_HEAD arEvent; +extern unsigned int wmitimeout; +extern int reconnect_flag; + + +#define RATETAB_ENT(_rate, _rateid, _flags) { \ + .bitrate = (_rate), \ + .flags = (_flags), \ + .hw_value = (_rateid), \ +} + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .hw_value = (_channel), \ + .center_freq = (_freq), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .hw_value = (_channel), \ + .center_freq = 5000 + (5 * (_channel)), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct +ieee80211_rate ar6k_rates[] = { + RATETAB_ENT(10, 0x1, 0), + RATETAB_ENT(20, 0x2, 0), + RATETAB_ENT(55, 0x4, 0), + RATETAB_ENT(110, 0x8, 0), + RATETAB_ENT(60, 0x10, 0), + RATETAB_ENT(90, 0x20, 0), + RATETAB_ENT(120, 0x40, 0), + RATETAB_ENT(180, 0x80, 0), + RATETAB_ENT(240, 0x100, 0), + RATETAB_ENT(360, 0x200, 0), + RATETAB_ENT(480, 0x400, 0), + RATETAB_ENT(540, 0x800, 0), +}; + +#define ar6k_a_rates (ar6k_rates + 4) +#define ar6k_a_rates_size 8 +#define ar6k_g_rates (ar6k_rates + 0) +#define ar6k_g_rates_size 12 + +static struct +ieee80211_channel ar6k_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +static struct +ieee80211_channel ar6k_5ghz_a_channels[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +static struct +ieee80211_supported_band ar6k_band_2ghz = { + .n_channels = ARRAY_SIZE(ar6k_2ghz_channels), + .channels = ar6k_2ghz_channels, + .n_bitrates = ar6k_g_rates_size, + .bitrates = ar6k_g_rates, +}; + +static struct +ieee80211_supported_band ar6k_band_5ghz = { + .n_channels = ARRAY_SIZE(ar6k_5ghz_a_channels), + .channels = ar6k_5ghz_a_channels, + .n_bitrates = ar6k_a_rates_size, + .bitrates = ar6k_a_rates, +}; + +static int +ar6k_set_wpa_version(struct ar6_softc *ar, enum nl80211_wpa_versions wpa_version) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: %u\n", __func__, wpa_version)); + + if (!wpa_version) { + ar->arAuthMode = NONE_AUTH; + } else if (wpa_version & NL80211_WPA_VERSION_1) { + ar->arAuthMode = WPA_AUTH; + } else if (wpa_version & NL80211_WPA_VERSION_2) { + ar->arAuthMode = WPA2_AUTH; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: %u not spported\n", __func__, wpa_version)); + return -ENOTSUPP; + } + + return 0; +} + +static int +ar6k_set_auth_type(struct ar6_softc *ar, enum nl80211_auth_type auth_type) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, auth_type)); + + switch (auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + ar->arDot11AuthMode = OPEN_AUTH; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + ar->arDot11AuthMode = SHARED_AUTH; + break; + case NL80211_AUTHTYPE_NETWORK_EAP: + ar->arDot11AuthMode = LEAP_AUTH; + break; + + case NL80211_AUTHTYPE_AUTOMATIC: + ar->arDot11AuthMode = OPEN_AUTH; + ar->arAutoAuthStage = AUTH_OPEN_IN_PROGRESS; + break; + + default: + ar->arDot11AuthMode = OPEN_AUTH; + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: 0x%x not spported\n", __func__, auth_type)); + return -ENOTSUPP; + } + + return 0; +} + +static int +ar6k_set_cipher(struct ar6_softc *ar, u32 cipher, bool ucast) +{ + u8 *ar_cipher = ucast ? &ar->arPairwiseCrypto : + &ar->arGroupCrypto; + u8 *ar_cipher_len = ucast ? &ar->arPairwiseCryptoLen : + &ar->arGroupCryptoLen; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: cipher 0x%x, ucast %u\n", __func__, cipher, ucast)); + + switch (cipher) { + case 0: + case IW_AUTH_CIPHER_NONE: + *ar_cipher = NONE_CRYPT; + *ar_cipher_len = 0; + break; + case WLAN_CIPHER_SUITE_WEP40: + *ar_cipher = WEP_CRYPT; + *ar_cipher_len = 5; + break; + case WLAN_CIPHER_SUITE_WEP104: + *ar_cipher = WEP_CRYPT; + *ar_cipher_len = 13; + break; + case WLAN_CIPHER_SUITE_TKIP: + *ar_cipher = TKIP_CRYPT; + *ar_cipher_len = 0; + break; + case WLAN_CIPHER_SUITE_CCMP: + *ar_cipher = AES_CRYPT; + *ar_cipher_len = 0; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: cipher 0x%x not supported\n", __func__, cipher)); + return -ENOTSUPP; + } + + return 0; +} + +static void +ar6k_set_key_mgmt(struct ar6_softc *ar, u32 key_mgmt) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, key_mgmt)); + + if (WLAN_AKM_SUITE_PSK == key_mgmt) { + if (WPA_AUTH == ar->arAuthMode) { + ar->arAuthMode = WPA_PSK_AUTH; + } else if (WPA2_AUTH == ar->arAuthMode) { + ar->arAuthMode = WPA2_PSK_AUTH; + } + } else if (WLAN_AKM_SUITE_8021X != key_mgmt) { + ar->arAuthMode = NONE_AUTH; + } +} + +static int +ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + struct ar6_softc *ar = ar6k_priv(dev); + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + ar->smeState = SME_CONNECTING; + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready yet\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(ar->bIsDestroyProgress) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: destroy in progress\n", __func__)); + return -EBUSY; + } + + if(!sme->ssid_len || IEEE80211_MAX_SSID_LEN < sme->ssid_len) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ssid invalid\n", __func__)); + return -EINVAL; + } + + if(ar->arSkipScan == true && + ((sme->channel && sme->channel->center_freq == 0) || + (sme->bssid && !sme->bssid[0] && !sme->bssid[1] && !sme->bssid[2] && + !sme->bssid[3] && !sme->bssid[4] && !sme->bssid[5]))) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s:SkipScan: channel or bssid invalid\n", __func__)); + return -EINVAL; + } + + if(down_interruptible(&ar->arSem)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__)); + return -ERESTARTSYS; + } + + if(ar->bIsDestroyProgress) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, destroy in progress\n", __func__)); + up(&ar->arSem); + return -EBUSY; + } + + if(ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) { + /* + * sleep until the command queue drains + */ + wait_event_interruptible_timeout(arEvent, + ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ); + if (signal_pending(current)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: cmd queue drain timeout\n", __func__)); + up(&ar->arSem); + return -EINTR; + } + } + + if(ar->arConnected == true && + ar->arSsidLen == sme->ssid_len && + !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) { + reconnect_flag = true; + status = wmi_reconnect_cmd(ar->arWmi, + ar->arReqBssid, + ar->arChannelHint); + + up(&ar->arSem); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_reconnect_cmd failed\n", __func__)); + return -EIO; + } + return 0; + } else if(ar->arSsidLen == sme->ssid_len && + !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) { + ar6000_disconnect(ar); + } + + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + ar->arSsidLen = sme->ssid_len; + memcpy(ar->arSsid, sme->ssid, sme->ssid_len); + + if(sme->channel){ + ar->arChannelHint = sme->channel->center_freq; + } + + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); + if(sme->bssid){ + if(memcmp(&sme->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) { + memcpy(ar->arReqBssid, sme->bssid, sizeof(ar->arReqBssid)); + } + } + + ar6k_set_wpa_version(ar, sme->crypto.wpa_versions); + ar6k_set_auth_type(ar, sme->auth_type); + + if(sme->crypto.n_ciphers_pairwise) { + ar6k_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true); + } else { + ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, true); + } + ar6k_set_cipher(ar, sme->crypto.cipher_group, false); + + if(sme->crypto.n_akm_suites) { + ar6k_set_key_mgmt(ar, sme->crypto.akm_suites[0]); + } + + if((sme->key_len) && + (NONE_AUTH == ar->arAuthMode) && + (WEP_CRYPT == ar->arPairwiseCrypto)) { + struct ar_key *key = NULL; + + if(sme->key_idx < WMI_MIN_KEY_INDEX || sme->key_idx > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: key index %d out of bounds\n", __func__, sme->key_idx)); + up(&ar->arSem); + return -ENOENT; + } + + key = &ar->keys[sme->key_idx]; + key->key_len = sme->key_len; + memcpy(key->key, sme->key, key->key_len); + key->cipher = ar->arPairwiseCrypto; + ar->arDefTxKeyIndex = sme->key_idx; + + wmi_addKey_cmd(ar->arWmi, sme->key_idx, + ar->arPairwiseCrypto, + GROUP_USAGE | TX_USAGE, + key->key_len, + NULL, + key->key, KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + } + + if (!ar->arUserBssFilter) { + if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__)); + up(&ar->arSem); + return -EIO; + } + } + + ar->arNetworkType = ar->arNextMode; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Connect called with authmode %d dot11 auth %d"\ + " PW crypto %d PW crypto Len %d GRP crypto %d"\ + " GRP crypto Len %d channel hint %u\n", + __func__, ar->arAuthMode, ar->arDot11AuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto, ar->arGroupCryptoLen, ar->arChannelHint)); + + reconnect_flag = 0; + status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, + ar->arDot11AuthMode, ar->arAuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto,ar->arGroupCryptoLen, + ar->arSsidLen, ar->arSsid, + ar->arReqBssid, ar->arChannelHint, + ar->arConnectCtrlFlags); + + up(&ar->arSem); + + if (A_EINVAL == status) { + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + ar->arSsidLen = 0; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Invalid request\n", __func__)); + return -ENOENT; + } else if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_connect_cmd failed\n", __func__)); + return -EIO; + } + + if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) && + ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode))) + { + A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0); + } + + ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD; + ar->arConnectPending = true; + + return 0; +} + +void +ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel, + u8 *bssid, u16 listenInterval, + u16 beaconInterval,NETWORK_TYPE networkType, + u8 beaconIeLen, u8 assocReqLen, + u8 assocRespLen, u8 *assocInfo) +{ + u16 size = 0; + u16 capability = 0; + struct cfg80211_bss *bss = NULL; + struct ieee80211_mgmt *mgmt = NULL; + struct ieee80211_channel *ibss_channel = NULL; + s32 signal = 50 * 100; + u8 ie_buf_len = 0; + unsigned char ie_buf[256]; + unsigned char *ptr_ie_buf = ie_buf; + unsigned char *ieeemgmtbuf = NULL; + u8 source_mac[ATH_MAC_LEN]; + + u8 assocReqIeOffset = sizeof(u16) + /* capinfo*/ + sizeof(u16); /* listen interval */ + u8 assocRespIeOffset = sizeof(u16) + /* capinfo*/ + sizeof(u16) + /* status Code */ + sizeof(u16); /* associd */ + u8 *assocReqIe = assocInfo + beaconIeLen + assocReqIeOffset; + u8 *assocRespIe = assocInfo + beaconIeLen + assocReqLen + assocRespIeOffset; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + assocReqLen -= assocReqIeOffset; + assocRespLen -= assocRespIeOffset; + + ar->arAutoAuthStage = AUTH_IDLE; + + if((ADHOC_NETWORK & networkType)) { + if(NL80211_IFTYPE_ADHOC != ar->wdev->iftype) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: ath6k not in ibss mode\n", __func__)); + return; + } + } + + if((INFRA_NETWORK & networkType)) { + if(NL80211_IFTYPE_STATION != ar->wdev->iftype) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: ath6k not in station mode\n", __func__)); + return; + } + } + + /* Before informing the join/connect event, make sure that + * bss entry is present in scan list, if it not present + * construct and insert into scan list, otherwise that + * event will be dropped on the way by cfg80211, due to + * this keys will not be plumbed in case of WEP and + * application will not be aware of join/connect status. */ + bss = cfg80211_get_bss(ar->wdev->wiphy, NULL, bssid, + ar->wdev->ssid, ar->wdev->ssid_len, + ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS), + ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS)); + + /* + * Earlier we were updating the cfg about bss by making a beacon frame + * only if the entry for bss is not there. This can have some issue if + * ROAM event is generated and a heavy traffic is ongoing. The ROAM + * event is handled through a work queue and by the time it really gets + * handled, BSS would have been aged out. So it is better to update the + * cfg about BSS irrespective of its entry being present right now or + * not. + */ + + if (ADHOC_NETWORK & networkType) { + /* construct 802.11 mgmt beacon */ + if(ptr_ie_buf) { + *ptr_ie_buf++ = WLAN_EID_SSID; + *ptr_ie_buf++ = ar->arSsidLen; + memcpy(ptr_ie_buf, ar->arSsid, ar->arSsidLen); + ptr_ie_buf +=ar->arSsidLen; + + *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS; + *ptr_ie_buf++ = 2; /* length */ + *ptr_ie_buf++ = 0; /* ATIM window */ + *ptr_ie_buf++ = 0; /* ATIM window */ + + /* TODO: update ibss params and include supported rates, + * DS param set, extened support rates, wmm. */ + + ie_buf_len = ptr_ie_buf - ie_buf; + } + + capability |= IEEE80211_CAPINFO_IBSS; + if(WEP_CRYPT == ar->arPairwiseCrypto) { + capability |= IEEE80211_CAPINFO_PRIVACY; + } + memcpy(source_mac, ar->arNetDev->dev_addr, ATH_MAC_LEN); + ptr_ie_buf = ie_buf; + } else { + capability = *(u16 *)(&assocInfo[beaconIeLen]); + memcpy(source_mac, bssid, ATH_MAC_LEN); + ptr_ie_buf = assocReqIe; + ie_buf_len = assocReqLen; + } + + size = offsetof(struct ieee80211_mgmt, u) + + sizeof(mgmt->u.beacon) + + ie_buf_len; + + ieeemgmtbuf = A_MALLOC_NOWAIT(size); + if(!ieeemgmtbuf) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: ieeeMgmtbuf alloc error\n", __func__)); + cfg80211_put_bss(bss); + return; + } + + A_MEMZERO(ieeemgmtbuf, size); + mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; + mgmt->frame_control = (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); + memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN); + memcpy(mgmt->sa, source_mac, ATH_MAC_LEN); + memcpy(mgmt->bssid, bssid, ATH_MAC_LEN); + mgmt->u.beacon.beacon_int = beaconInterval; + mgmt->u.beacon.capab_info = capability; + memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len); + + ibss_channel = ieee80211_get_channel(ar->wdev->wiphy, (int)channel); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: inform bss with bssid %pM channel %d beaconInterval %d " + "capability 0x%x\n", __func__, mgmt->bssid, + ibss_channel->hw_value, beaconInterval, capability)); + + bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, + ibss_channel, mgmt, + le16_to_cpu(size), + signal, GFP_KERNEL); + kfree(ieeemgmtbuf); + cfg80211_put_bss(bss); + + if((ADHOC_NETWORK & networkType)) { + cfg80211_ibss_joined(ar->arNetDev, bssid, GFP_KERNEL); + return; + } + + if (false == ar->arConnected) { + /* inform connect result to cfg80211 */ + ar->smeState = SME_DISCONNECTED; + cfg80211_connect_result(ar->arNetDev, bssid, + assocReqIe, assocReqLen, + assocRespIe, assocRespLen, + WLAN_STATUS_SUCCESS, GFP_KERNEL); + } else { + /* inform roam event to cfg80211 */ + cfg80211_roamed(ar->arNetDev, ibss_channel, bssid, + assocReqIe, assocReqLen, + assocRespIe, assocRespLen, + GFP_KERNEL); + } +} + +static int +ar6k_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason_code)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(ar->bIsDestroyProgress) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, destroy in progress\n", __func__)); + return -EBUSY; + } + + if(down_interruptible(&ar->arSem)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__)); + return -ERESTARTSYS; + } + + reconnect_flag = 0; + ar6000_disconnect(ar); + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + ar->arSsidLen = 0; + + if (ar->arSkipScan == false) { + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); + } + + up(&ar->arSem); + + return 0; +} + +void +ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason, + u8 *bssid, u8 assocRespLen, + u8 *assocInfo, u16 protocolReasonStatus) +{ + + u16 status; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason)); + + if (ar->scan_request) { + cfg80211_scan_done(ar->scan_request, true); + ar->scan_request = NULL; + } + if((ADHOC_NETWORK & ar->arNetworkType)) { + if(NL80211_IFTYPE_ADHOC != ar->wdev->iftype) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: ath6k not in ibss mode\n", __func__)); + return; + } + A_MEMZERO(bssid, ETH_ALEN); + cfg80211_ibss_joined(ar->arNetDev, bssid, GFP_KERNEL); + return; + } + + if((INFRA_NETWORK & ar->arNetworkType)) { + if(NL80211_IFTYPE_STATION != ar->wdev->iftype) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: ath6k not in station mode\n", __func__)); + return; + } + } + + if(true == ar->arConnectPending) { + if(NO_NETWORK_AVAIL == reason) { + /* connect cmd failed */ + wmi_disconnect_cmd(ar->arWmi); + } else if (reason == DISCONNECT_CMD) { + if (ar->arAutoAuthStage) { + /* + * If the current auth algorithm is open try shared + * and make autoAuthStage idle. We do not make it + * leap for now being. + */ + if (ar->arDot11AuthMode == OPEN_AUTH) { + struct ar_key *key = NULL; + key = &ar->keys[ar->arDefTxKeyIndex]; + if (down_interruptible(&ar->arSem)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__)); + return; + } + + + ar->arDot11AuthMode = SHARED_AUTH; + ar->arAutoAuthStage = AUTH_IDLE; + + wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, + ar->arPairwiseCrypto, + GROUP_USAGE | TX_USAGE, + key->key_len, + NULL, + key->key, KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + + status = wmi_connect_cmd(ar->arWmi, + ar->arNetworkType, + ar->arDot11AuthMode, + ar->arAuthMode, + ar->arPairwiseCrypto, + ar->arPairwiseCryptoLen, + ar->arGroupCrypto, + ar->arGroupCryptoLen, + ar->arSsidLen, + ar->arSsid, + ar->arReqBssid, + ar->arChannelHint, + ar->arConnectCtrlFlags); + up(&ar->arSem); + + } else if (ar->arDot11AuthMode == SHARED_AUTH) { + /* should not reach here */ + } + } else { + ar->arConnectPending = false; + if (ar->smeState == SME_CONNECTING) { + cfg80211_connect_result(ar->arNetDev, bssid, + NULL, 0, + NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } else { + cfg80211_disconnected(ar->arNetDev, + reason, + NULL, 0, + GFP_KERNEL); + } + ar->smeState = SME_DISCONNECTED; + } + } + } else { + if (reason != DISCONNECT_CMD) + wmi_disconnect_cmd(ar->arWmi); + } +} + +void +ar6k_cfg80211_scan_node(void *arg, bss_t *ni) +{ + struct wiphy *wiphy = (struct wiphy *)arg; + u16 size; + unsigned char *ieeemgmtbuf = NULL; + struct ieee80211_mgmt *mgmt; + struct ieee80211_channel *channel; + struct ieee80211_supported_band *band; + struct ieee80211_common_ie *cie; + s32 signal; + int freq; + + cie = &ni->ni_cie; + +#define CHAN_IS_11A(x) (!((x >= 2412) && (x <= 2484))) + if(CHAN_IS_11A(cie->ie_chan)) { + /* 11a */ + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + } else if((cie->ie_erp) || (cie->ie_xrates)) { + /* 11g */ + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + } else { + /* 11b */ + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + } + + size = ni->ni_framelen + offsetof(struct ieee80211_mgmt, u); + ieeemgmtbuf = A_MALLOC_NOWAIT(size); + if(!ieeemgmtbuf) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ieeeMgmtbuf alloc error\n", __func__)); + return; + } + + /* Note: + TODO: Update target to include 802.11 mac header while sending bss info. + Target removes 802.11 mac header while sending the bss info to host, + cfg80211 needs it, for time being just filling the da, sa and bssid fields alone. + */ + mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; + memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN); + memcpy(mgmt->sa, ni->ni_macaddr, ATH_MAC_LEN); + memcpy(mgmt->bssid, ni->ni_macaddr, ATH_MAC_LEN); + memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u), + ni->ni_buf, ni->ni_framelen); + + freq = cie->ie_chan; + channel = ieee80211_get_channel(wiphy, freq); + signal = ni->ni_snr * 100; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: bssid %pM channel %d freq %d size %d\n", __func__, + mgmt->bssid, channel->hw_value, freq, size)); + cfg80211_inform_bss_frame(wiphy, channel, mgmt, + le16_to_cpu(size), + signal, GFP_KERNEL); + + kfree (ieeemgmtbuf); +} + +static int +ar6k_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_scan_request *request) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + int ret = 0; + u32 forceFgScan = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if (!ar->arUserBssFilter) { + if (wmi_bssfilter_cmd(ar->arWmi, + (ar->arConnected ? ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), + 0) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__)); + return -EIO; + } + } + + if(request->n_ssids && + request->ssids[0].ssid_len) { + u8 i; + + if(request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) { + request->n_ssids = MAX_PROBED_SSID_INDEX - 1; + } + + for (i = 0; i < request->n_ssids; i++) { + wmi_probedSsid_cmd(ar->arWmi, i+1, SPECIFIC_SSID_FLAG, + request->ssids[i].ssid_len, + request->ssids[i].ssid); + } + } + + if(ar->arConnected) { + forceFgScan = 1; + } + + if(wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, forceFgScan, false, \ + 0, 0, 0, NULL) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_startscan_cmd failed\n", __func__)); + ret = -EIO; + } + + ar->scan_request = request; + + return ret; +} + +void +ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: status %d\n", __func__, status)); + + if (!ar->scan_request) + return; + + if ((status == A_ECANCELED) || (status == A_EBUSY)) { + cfg80211_scan_done(ar->scan_request, true); + goto out; + } + + /* Translate data to cfg80211 mgmt format */ + wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy); + + cfg80211_scan_done(ar->scan_request, false); + + if(ar->scan_request->n_ssids && + ar->scan_request->ssids[0].ssid_len) { + u8 i; + + for (i = 0; i < ar->scan_request->n_ssids; i++) { + wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG, + 0, NULL); + } + } + +out: + ar->scan_request = NULL; +} + +static int +ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, + struct key_params *params) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + struct ar_key *key = NULL; + u8 key_usage; + u8 key_type; + int status = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s:\n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: key index %d out of bounds\n", __func__, key_index)); + return -ENOENT; + } + + key = &ar->keys[key_index]; + A_MEMZERO(key, sizeof(struct ar_key)); + + if(!mac_addr || is_broadcast_ether_addr(mac_addr)) { + key_usage = GROUP_USAGE; + } else { + key_usage = PAIRWISE_USAGE; + } + + if(params) { + if(params->key_len > WLAN_MAX_KEY_LEN || + params->seq_len > IW_ENCODE_SEQ_MAX_SIZE) + return -EINVAL; + + key->key_len = params->key_len; + memcpy(key->key, params->key, key->key_len); + key->seq_len = params->seq_len; + memcpy(key->seq, params->seq, key->seq_len); + key->cipher = params->cipher; + } + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + key_type = WEP_CRYPT; + break; + + case WLAN_CIPHER_SUITE_TKIP: + key_type = TKIP_CRYPT; + break; + + case WLAN_CIPHER_SUITE_CCMP: + key_type = AES_CRYPT; + break; + + default: + return -ENOTSUPP; + } + + if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) && + (GROUP_USAGE & key_usage)) + { + A_UNTIMEOUT(&ar->disconnect_timer); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: index %d, key_len %d, key_type 0x%x,"\ + " key_usage 0x%x, seq_len %d\n", + __func__, key_index, key->key_len, key_type, + key_usage, key->seq_len)); + + ar->arDefTxKeyIndex = key_index; + status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, key_type, key_usage, + key->key_len, key->seq, key->key, KEY_OP_INIT_VAL, + (u8 *)mac_addr, SYNC_BOTH_WMIFLAG); + + + if (status) { + return -EIO; + } + + return 0; +} + +static int +ar6k_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: key index %d out of bounds\n", __func__, key_index)); + return -ENOENT; + } + + if(!ar->keys[key_index].key_len) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d is empty\n", __func__, key_index)); + return 0; + } + + ar->keys[key_index].key_len = 0; + + return wmi_deleteKey_cmd(ar->arWmi, key_index); +} + + +static int +ar6k_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, + void *cookie, + void (*callback)(void *cookie, struct key_params*)) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + struct ar_key *key = NULL; + struct key_params params; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: key index %d out of bounds\n", __func__, key_index)); + return -ENOENT; + } + + key = &ar->keys[key_index]; + A_MEMZERO(¶ms, sizeof(params)); + params.cipher = key->cipher; + params.key_len = key->key_len; + params.seq_len = key->seq_len; + params.seq = key->seq; + params.key = key->key; + + callback(cookie, ¶ms); + + return key->key_len ? 0 : -ENOENT; +} + + +static int +ar6k_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, bool unicast, bool multicast) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + struct ar_key *key = NULL; + int status = 0; + u8 key_usage; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: key index %d out of bounds\n", + __func__, key_index)); + return -ENOENT; + } + + if(!ar->keys[key_index].key_len) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: invalid key index %d\n", + __func__, key_index)); + return -EINVAL; + } + + ar->arDefTxKeyIndex = key_index; + key = &ar->keys[ar->arDefTxKeyIndex]; + key_usage = GROUP_USAGE; + if (WEP_CRYPT == ar->arPairwiseCrypto) { + key_usage |= TX_USAGE; + } + + status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, + ar->arPairwiseCrypto, key_usage, + key->key_len, key->seq, key->key, KEY_OP_INIT_VAL, + NULL, SYNC_BOTH_WMIFLAG); + if (status) { + return -EIO; + } + + return 0; +} + +static int +ar6k_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__)); + return -ENOTSUPP; +} + +void +ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, + ("%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast)); + + cfg80211_michael_mic_failure(ar->arNetDev, ar->arBssid, + (ismcast ? NL80211_KEYTYPE_GROUP : NL80211_KEYTYPE_PAIRWISE), + keyid, NULL, GFP_KERNEL); +} + +static int +ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: changed 0x%x\n", __func__, changed)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + if (wmi_set_rts_cmd(ar->arWmi,wiphy->rts_threshold) != 0){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_set_rts_cmd failed\n", __func__)); + return -EIO; + } + } + + return 0; +} + +static int +ar6k_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, + const struct cfg80211_bitrate_mask *mask) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Setting rates: Not supported\n")); + return -EIO; +} + +/* The type nl80211_tx_power_setting replaces the following data type from 2.6.36 onwards */ +static int +ar6k_cfg80211_set_txpower(struct wiphy *wiphy, enum nl80211_tx_power_setting type, int dbm) +{ + struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy); + u8 ar_dbm; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x, dbm %d\n", __func__, type, dbm)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + ar->arTxPwrSet = false; + switch(type) { + case NL80211_TX_POWER_AUTOMATIC: + return 0; + case NL80211_TX_POWER_LIMITED: + ar->arTxPwr = ar_dbm = dbm; + ar->arTxPwrSet = true; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x not supported\n", __func__, type)); + return -EOPNOTSUPP; + } + + wmi_set_txPwr_cmd(ar->arWmi, ar_dbm); + + return 0; +} + +static int +ar6k_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) +{ + struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if((ar->arConnected == true)) { + ar->arTxPwr = 0; + + if(wmi_get_txPwr_cmd(ar->arWmi) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_get_txPwr_cmd failed\n", __func__)); + return -EIO; + } + + wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, 5 * HZ); + + if(signal_pending(current)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Target did not respond\n", __func__)); + return -EINTR; + } + } + + *dbm = ar->arTxPwr; + return 0; +} + +static int +ar6k_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool pmgmt, int timeout) +{ + struct ar6_softc *ar = ar6k_priv(dev); + WMI_POWER_MODE_CMD pwrMode; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: pmgmt %d, timeout %d\n", __func__, pmgmt, timeout)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(pmgmt) { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Max Perf\n", __func__)); + pwrMode.powerMode = REC_POWER; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Rec Power\n", __func__)); + pwrMode.powerMode = MAX_PERF_POWER; + } + + if(wmi_powermode_cmd(ar->arWmi, pwrMode.powerMode) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_powermode_cmd failed\n", __func__)); + return -EIO; + } + + return 0; +} + +static struct net_device * +ar6k_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__)); + + /* Multiple virtual interface is not supported. + * The default interface supports STA and IBSS type + */ + return ERR_PTR(-EOPNOTSUPP); +} + +static int +ar6k_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__)); + + /* Multiple virtual interface is not supported. + * The default interface supports STA and IBSS type + */ + return -EOPNOTSUPP; +} + +static int +ar6k_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + struct ar6_softc *ar = ar6k_priv(ndev); + struct wireless_dev *wdev = ar->wdev; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type %u\n", __func__, type)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + switch (type) { + case NL80211_IFTYPE_STATION: + ar->arNextMode = INFRA_NETWORK; + break; + case NL80211_IFTYPE_ADHOC: + ar->arNextMode = ADHOC_NETWORK; + break; + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: type %u\n", __func__, type)); + return -EOPNOTSUPP; + } + + wdev->iftype = type; + + return 0; +} + +static int +ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *ibss_param) +{ + struct ar6_softc *ar = ar6k_priv(dev); + int status; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + if(!ibss_param->ssid_len || IEEE80211_MAX_SSID_LEN < ibss_param->ssid_len) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ssid invalid\n", __func__)); + return -EINVAL; + } + + ar->arSsidLen = ibss_param->ssid_len; + memcpy(ar->arSsid, ibss_param->ssid, ar->arSsidLen); + + if(ibss_param->channel) { + ar->arChannelHint = ibss_param->channel->center_freq; + } + + if(ibss_param->channel_fixed) { + /* TODO: channel_fixed: The channel should be fixed, do not search for + * IBSSs to join on other channels. Target firmware does not support this + * feature, needs to be updated.*/ + } + + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); + if(ibss_param->bssid) { + if(memcmp(&ibss_param->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) { + memcpy(ar->arReqBssid, ibss_param->bssid, sizeof(ar->arReqBssid)); + } + } + + ar6k_set_wpa_version(ar, 0); + ar6k_set_auth_type(ar, NL80211_AUTHTYPE_OPEN_SYSTEM); + + if(ibss_param->privacy) { + ar6k_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, true); + ar6k_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, false); + } else { + ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, true); + ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, false); + } + + ar->arNetworkType = ar->arNextMode; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Connect called with authmode %d dot11 auth %d"\ + " PW crypto %d PW crypto Len %d GRP crypto %d"\ + " GRP crypto Len %d channel hint %u\n", + __func__, ar->arAuthMode, ar->arDot11AuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto, ar->arGroupCryptoLen, ar->arChannelHint)); + + status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, + ar->arDot11AuthMode, ar->arAuthMode, + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, + ar->arGroupCrypto,ar->arGroupCryptoLen, + ar->arSsidLen, ar->arSsid, + ar->arReqBssid, ar->arChannelHint, + ar->arConnectCtrlFlags); + ar->arConnectPending = true; + + return 0; +} + +static int +ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->arWmiReady == false) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); + return -EIO; + } + + if(ar->arWlanState == WLAN_DISABLED) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); + return -EIO; + } + + ar6000_disconnect(ar); + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); + ar->arSsidLen = 0; + + return 0; +} + +#ifdef CONFIG_NL80211_TESTMODE +enum ar6k_testmode_attr { + __AR6K_TM_ATTR_INVALID = 0, + AR6K_TM_ATTR_CMD = 1, + AR6K_TM_ATTR_DATA = 2, + + /* keep last */ + __AR6K_TM_ATTR_AFTER_LAST, + AR6K_TM_ATTR_MAX = __AR6K_TM_ATTR_AFTER_LAST - 1 +}; + +enum ar6k_testmode_cmd { + AR6K_TM_CMD_TCMD = 0, + AR6K_TM_CMD_RX_REPORT = 1, +}; + +#define AR6K_TM_DATA_MAX_LEN 5000 + +static const struct nla_policy ar6k_testmode_policy[AR6K_TM_ATTR_MAX + 1] = { + [AR6K_TM_ATTR_CMD] = { .type = NLA_U32 }, + [AR6K_TM_ATTR_DATA] = { .type = NLA_BINARY, + .len = AR6K_TM_DATA_MAX_LEN }, +}; + +void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf, + int buf_len) +{ + if (down_interruptible(&ar->arSem)) + return; + + kfree(ar->tcmd_rx_report); + + ar->tcmd_rx_report = kmemdup(buf, buf_len, GFP_KERNEL); + ar->tcmd_rx_report_len = buf_len; + + up(&ar->arSem); + + wake_up(&arEvent); +} + +static int ar6000_testmode_rx_report(struct ar6_softc *ar, void *buf, + int buf_len, struct sk_buff *skb) +{ + int ret = 0; + long left; + + if (down_interruptible(&ar->arSem)) + return -ERESTARTSYS; + + if (ar->arWmiReady == false) { + ret = -EIO; + goto out; + } + + if (ar->bIsDestroyProgress) { + ret = -EBUSY; + goto out; + } + + WARN_ON(ar->tcmd_rx_report != NULL); + WARN_ON(ar->tcmd_rx_report_len > 0); + + if (wmi_test_cmd(ar->arWmi, buf, buf_len) < 0) { + up(&ar->arSem); + return -EIO; + } + + left = wait_event_interruptible_timeout(arEvent, + ar->tcmd_rx_report != NULL, + wmitimeout * HZ); + + if (left == 0) { + ret = -ETIMEDOUT; + goto out; + } else if (left < 0) { + ret = left; + goto out; + } + + if (ar->tcmd_rx_report == NULL || ar->tcmd_rx_report_len == 0) { + ret = -EINVAL; + goto out; + } + + NLA_PUT(skb, AR6K_TM_ATTR_DATA, ar->tcmd_rx_report_len, + ar->tcmd_rx_report); + + kfree(ar->tcmd_rx_report); + ar->tcmd_rx_report = NULL; + +out: + up(&ar->arSem); + + return ret; + +nla_put_failure: + ret = -ENOBUFS; + goto out; +} + +static int ar6k_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ + struct ar6_softc *ar = wiphy_priv(wiphy); + struct nlattr *tb[AR6K_TM_ATTR_MAX + 1]; + int err, buf_len, reply_len; + struct sk_buff *skb; + void *buf; + + err = nla_parse(tb, AR6K_TM_ATTR_MAX, data, len, + ar6k_testmode_policy); + if (err) + return err; + + if (!tb[AR6K_TM_ATTR_CMD]) + return -EINVAL; + + switch (nla_get_u32(tb[AR6K_TM_ATTR_CMD])) { + case AR6K_TM_CMD_TCMD: + if (!tb[AR6K_TM_ATTR_DATA]) + return -EINVAL; + + buf = nla_data(tb[AR6K_TM_ATTR_DATA]); + buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]); + + wmi_test_cmd(ar->arWmi, buf, buf_len); + + return 0; + + break; + case AR6K_TM_CMD_RX_REPORT: + if (!tb[AR6K_TM_ATTR_DATA]) + return -EINVAL; + + buf = nla_data(tb[AR6K_TM_ATTR_DATA]); + buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]); + + reply_len = nla_total_size(AR6K_TM_DATA_MAX_LEN); + skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); + if (!skb) + return -ENOMEM; + + err = ar6000_testmode_rx_report(ar, buf, buf_len, skb); + if (err < 0) { + kfree_skb(skb); + return err; + } + + return cfg80211_testmode_reply(skb); + default: + return -EOPNOTSUPP; + } +} +#endif + +static const +u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +}; + +bool is_rate_legacy(s32 rate) +{ + static const s32 legacy[] = { 1000, 2000, 5500, 11000, + 6000, 9000, 12000, 18000, 24000, + 36000, 48000, 54000 }; + u8 i; + + for (i = 0; i < ARRAY_SIZE(legacy); i++) { + if (rate == legacy[i]) + return true; + } + + return false; +} + +bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi) +{ + static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000, + 52000, 58500, 65000, 72200 }; + u8 i; + + for (i = 0; i < ARRAY_SIZE(ht20); i++) { + if (rate == ht20[i]) { + if (i == ARRAY_SIZE(ht20) - 1) + /* last rate uses sgi */ + *sgi = true; + else + *sgi = false; + + *mcs = i; + return true; + } + } + return false; +} + +bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi) +{ + static const s32 ht40[] = { 13500, 27000, 40500, 54000, + 81000, 108000, 121500, 135000, + 150000 }; + u8 i; + + for (i = 0; i < ARRAY_SIZE(ht40); i++) { + if (rate == ht40[i]) { + if (i == ARRAY_SIZE(ht40) - 1) + /* last rate uses sgi */ + *sgi = true; + else + *sgi = false; + + *mcs = i; + return true; + } + } + + return false; +} + +static int ar6k_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) +{ + struct ar6_softc *ar = ar6k_priv(dev); + long left; + bool sgi; + s32 rate; + int ret; + u8 mcs; + + if (memcmp(mac, ar->arBssid, ETH_ALEN) != 0) + return -ENOENT; + + if (down_interruptible(&ar->arSem)) + return -EBUSY; + + ar->statsUpdatePending = true; + + ret = wmi_get_stats_cmd(ar->arWmi); + + if (ret != 0) { + up(&ar->arSem); + return -EIO; + } + + left = wait_event_interruptible_timeout(arEvent, + ar->statsUpdatePending == false, + wmitimeout * HZ); + + up(&ar->arSem); + + if (left == 0) + return -ETIMEDOUT; + else if (left < 0) + return left; + + if (ar->arTargetStats.rx_bytes) { + sinfo->rx_bytes = ar->arTargetStats.rx_bytes; + sinfo->filled |= STATION_INFO_RX_BYTES; + sinfo->rx_packets = ar->arTargetStats.rx_packets; + sinfo->filled |= STATION_INFO_RX_PACKETS; + } + + if (ar->arTargetStats.tx_bytes) { + sinfo->tx_bytes = ar->arTargetStats.tx_bytes; + sinfo->filled |= STATION_INFO_TX_BYTES; + sinfo->tx_packets = ar->arTargetStats.tx_packets; + sinfo->filled |= STATION_INFO_TX_PACKETS; + } + + sinfo->signal = ar->arTargetStats.cs_rssi; + sinfo->filled |= STATION_INFO_SIGNAL; + + rate = ar->arTargetStats.tx_unicast_rate; + + if (is_rate_legacy(rate)) { + sinfo->txrate.legacy = rate / 100; + } else if (is_rate_ht20(rate, &mcs, &sgi)) { + if (sgi) { + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + sinfo->txrate.mcs = mcs - 1; + } else { + sinfo->txrate.mcs = mcs; + } + + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + } else if (is_rate_ht40(rate, &mcs, &sgi)) { + if (sgi) { + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + sinfo->txrate.mcs = mcs - 1; + } else { + sinfo->txrate.mcs = mcs; + } + + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + } else { + WARN(1, "invalid rate: %d", rate); + return 0; + } + + sinfo->filled |= STATION_INFO_TX_BITRATE; + + return 0; +} + +static int ar6k_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct ar6_softc *ar = ar6k_priv(netdev); + return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, true); +} + +static int ar6k_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + struct ar6_softc *ar = ar6k_priv(netdev); + return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, false); +} + +static int ar6k_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) +{ + struct ar6_softc *ar = ar6k_priv(netdev); + if (ar->arConnected) + return wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, false); + return 0; +} + +static struct +cfg80211_ops ar6k_cfg80211_ops = { + .change_virtual_intf = ar6k_cfg80211_change_iface, + .add_virtual_intf = ar6k_cfg80211_add_virtual_intf, + .del_virtual_intf = ar6k_cfg80211_del_virtual_intf, + .scan = ar6k_cfg80211_scan, + .connect = ar6k_cfg80211_connect, + .disconnect = ar6k_cfg80211_disconnect, + .add_key = ar6k_cfg80211_add_key, + .get_key = ar6k_cfg80211_get_key, + .del_key = ar6k_cfg80211_del_key, + .set_default_key = ar6k_cfg80211_set_default_key, + .set_default_mgmt_key = ar6k_cfg80211_set_default_mgmt_key, + .set_wiphy_params = ar6k_cfg80211_set_wiphy_params, + .set_bitrate_mask = ar6k_cfg80211_set_bitrate_mask, + .set_tx_power = ar6k_cfg80211_set_txpower, + .get_tx_power = ar6k_cfg80211_get_txpower, + .set_power_mgmt = ar6k_cfg80211_set_power_mgmt, + .join_ibss = ar6k_cfg80211_join_ibss, + .leave_ibss = ar6k_cfg80211_leave_ibss, + .get_station = ar6k_get_station, + .set_pmksa = ar6k_set_pmksa, + .del_pmksa = ar6k_del_pmksa, + .flush_pmksa = ar6k_flush_pmksa, + CFG80211_TESTMODE_CMD(ar6k_testmode_cmd) +}; + +struct wireless_dev * +ar6k_cfg80211_init(struct device *dev) +{ + int ret = 0; + struct wireless_dev *wdev; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if(!wdev) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Couldn't allocate wireless device\n", __func__)); + return ERR_PTR(-ENOMEM); + } + + /* create a new wiphy for use with cfg80211 */ + wdev->wiphy = wiphy_new(&ar6k_cfg80211_ops, sizeof(struct ar6_softc)); + if(!wdev->wiphy) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Couldn't allocate wiphy device\n", __func__)); + kfree(wdev); + return ERR_PTR(-ENOMEM); + } + + /* set device pointer for wiphy */ + set_wiphy_dev(wdev->wiphy, dev); + + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + /* max num of ssids that can be probed during scanning */ + wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar6k_band_2ghz; + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar6k_band_5ghz; + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + wdev->wiphy->cipher_suites = cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + + ret = wiphy_register(wdev->wiphy); + if(ret < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: Couldn't register wiphy device\n", __func__)); + wiphy_free(wdev->wiphy); + return ERR_PTR(ret); + } + + return wdev; +} + +void +ar6k_cfg80211_deinit(struct ar6_softc *ar) +{ + struct wireless_dev *wdev = ar->wdev; + + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); + + if(ar->scan_request) { + cfg80211_scan_done(ar->scan_request, true); + ar->scan_request = NULL; + } + + if(!wdev) + return; + + wiphy_unregister(wdev->wiphy); + wiphy_free(wdev->wiphy); + kfree(wdev); +} + + + + + + + diff --git a/trunk/drivers/staging/ath6kl/os/linux/export_hci_transport.c b/trunk/drivers/staging/ath6kl/os/linux/export_hci_transport.c new file mode 100644 index 000000000000..430998edacc4 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/export_hci_transport.c @@ -0,0 +1,124 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HCI bridge implementation +// +// Author(s): ="Atheros" +//============================================================================== +#include +#include +#include "a_osapi.h" +#include "htc_api.h" +#include "a_drv.h" +#include "hif.h" +#include "common_drv.h" +#include "a_debug.h" +#include "hci_transport_api.h" + +#include "AR6002/hw4.0/hw/apb_athr_wlan_map.h" +#include "AR6002/hw4.0/hw/uart_reg.h" +#include "AR6002/hw4.0/hw/rtc_wlan_reg.h" + +HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo); +void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans); +int (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue); +int (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous); +void (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans); +int (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans); +int (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); +int (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, + struct htc_packet *pPacket, + int MaxPollMS); +int (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud); +int (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); + +extern struct hci_transport_callbacks ar6kHciTransCallbacks; + +int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks) +{ + ar6kHciTransCallbacks = *hciTransCallbacks; + + _HCI_TransportAttach = HCI_TransportAttach; + _HCI_TransportDetach = HCI_TransportDetach; + _HCI_TransportAddReceivePkts = HCI_TransportAddReceivePkts; + _HCI_TransportSendPkt = HCI_TransportSendPkt; + _HCI_TransportStop = HCI_TransportStop; + _HCI_TransportStart = HCI_TransportStart; + _HCI_TransportEnableDisableAsyncRecv = HCI_TransportEnableDisableAsyncRecv; + _HCI_TransportRecvHCIEventSync = HCI_TransportRecvHCIEventSync; + _HCI_TransportSetBaudRate = HCI_TransportSetBaudRate; + _HCI_TransportEnablePowerMgmt = HCI_TransportEnablePowerMgmt; + + return 0; +} + +int +ar6000_get_hif_dev(struct hif_device *device, void *config) +{ + int status; + + status = HIFConfigureDevice(device, + HIF_DEVICE_GET_OS_DEVICE, + (struct hif_device_os_device_info *)config, + sizeof(struct hif_device_os_device_info)); + return status; +} + +int ar6000_set_uart_config(struct hif_device *hifDevice, + u32 scale, + u32 step) +{ + u32 regAddress; + u32 regVal; + int status; + + regAddress = WLAN_UART_BASE_ADDRESS | UART_CLKDIV_ADDRESS; + regVal = ((u32)scale << 16) | step; + /* change the HCI UART scale/step values through the diagnostic window */ + status = ar6000_WriteRegDiag(hifDevice, ®Address, ®Val); + + return status; +} + +int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data) +{ + u32 regAddress; + int status; + + regAddress = WLAN_RTC_BASE_ADDRESS | WLAN_CPU_CLOCK_ADDRESS; + /* read CPU clock settings*/ + status = ar6000_ReadRegDiag(hifDevice, ®Address, data); + + return status; +} + +EXPORT_SYMBOL(ar6000_register_hci_transport); +EXPORT_SYMBOL(ar6000_get_hif_dev); +EXPORT_SYMBOL(ar6000_set_uart_config); +EXPORT_SYMBOL(ar6000_get_core_clock_config); +EXPORT_SYMBOL(_HCI_TransportAttach); +EXPORT_SYMBOL(_HCI_TransportDetach); +EXPORT_SYMBOL(_HCI_TransportAddReceivePkts); +EXPORT_SYMBOL(_HCI_TransportSendPkt); +EXPORT_SYMBOL(_HCI_TransportStop); +EXPORT_SYMBOL(_HCI_TransportStart); +EXPORT_SYMBOL(_HCI_TransportEnableDisableAsyncRecv); +EXPORT_SYMBOL(_HCI_TransportRecvHCIEventSync); +EXPORT_SYMBOL(_HCI_TransportSetBaudRate); +EXPORT_SYMBOL(_HCI_TransportEnablePowerMgmt); diff --git a/trunk/drivers/staging/ath6kl/os/linux/hci_bridge.c b/trunk/drivers/staging/ath6kl/os/linux/hci_bridge.c new file mode 100644 index 000000000000..6087edcb1d6a --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/hci_bridge.c @@ -0,0 +1,1141 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HCI bridge implementation +// +// Author(s): ="Atheros" +//============================================================================== + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +#include +#include +#include +#include "a_osapi.h" +#include "htc_api.h" +#include "wmi.h" +#include "a_drv.h" +#include "hif.h" +#include "common_drv.h" +#include "a_debug.h" +#define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) +#define ATH_DEBUG_HCI_RECV ATH_DEBUG_MAKE_MODULE_MASK(7) +#define ATH_DEBUG_HCI_SEND ATH_DEBUG_MAKE_MODULE_MASK(8) +#define ATH_DEBUG_HCI_DUMP ATH_DEBUG_MAKE_MODULE_MASK(9) +#else +#include "ar6000_drv.h" +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ + +#ifdef ATH_AR6K_ENABLE_GMBOX +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +#include "export_hci_transport.h" +#else +#include "hci_transport_api.h" +#endif +#include "epping_test.h" +#include "gmboxif.h" +#include "ar3kconfig.h" +#include +#include + + /* only build on newer kernels which have BT configured */ +#if defined(CONFIG_BT_MODULE) || defined(CONFIG_BT) +#define CONFIG_BLUEZ_HCI_BRIDGE +#endif + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +unsigned int ar3khcibaud = 0; +unsigned int hciuartscale = 0; +unsigned int hciuartstep = 0; + +module_param(ar3khcibaud, int, 0644); +module_param(hciuartscale, int, 0644); +module_param(hciuartstep, int, 0644); +#else +extern unsigned int ar3khcibaud; +extern unsigned int hciuartscale; +extern unsigned int hciuartstep; +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ + +struct ar6k_hci_bridge_info { + void *pHCIDev; /* HCI bridge device */ + struct hci_transport_properties HCIProps; /* HCI bridge props */ + struct hci_dev *pBtStackHCIDev; /* BT Stack HCI dev */ + bool HciNormalMode; /* Actual HCI mode enabled (non-TEST)*/ + bool HciRegistered; /* HCI device registered with stack */ + struct htc_packet_queue HTCPacketStructHead; + u8 *pHTCStructAlloc; + spinlock_t BridgeLock; +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + struct hci_transport_misc_handles HCITransHdl; +#else + struct ar6_softc *ar; +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ +}; + +#define MAX_ACL_RECV_BUFS 16 +#define MAX_EVT_RECV_BUFS 8 +#define MAX_HCI_WRITE_QUEUE_DEPTH 32 +#define MAX_ACL_RECV_LENGTH 1200 +#define MAX_EVT_RECV_LENGTH 257 +#define TX_PACKET_RSV_OFFSET 32 +#define NUM_HTC_PACKET_STRUCTS ((MAX_ACL_RECV_BUFS + MAX_EVT_RECV_BUFS + MAX_HCI_WRITE_QUEUE_DEPTH) * 2) + +#define HCI_GET_OP_CODE(p) (((u16)((p)[1])) << 8) | ((u16)((p)[0])) + +extern unsigned int setupbtdev; +struct ar3k_config_info ar3kconfig; + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +struct ar6k_hci_bridge_info *g_pHcidevInfo; +#endif + +static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo); +static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo); +static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo); +static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo, + HCI_TRANSPORT_PACKET_TYPE Type, + struct sk_buff *skb); +static struct sk_buff *bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length); +static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb); + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int ar6000_setup_hci(void *ar); +void ar6000_cleanup_hci(void *ar); +int hci_test_send(void *ar, struct sk_buff *skb); +#else +int ar6000_setup_hci(struct ar6_softc *ar); +void ar6000_cleanup_hci(struct ar6_softc *ar); +/* HCI bridge testing */ +int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb); +#endif /* EXPORT_HCI_BRIDGE_INTERFACE */ + +#define LOCK_BRIDGE(dev) spin_lock_bh(&(dev)->BridgeLock) +#define UNLOCK_BRIDGE(dev) spin_unlock_bh(&(dev)->BridgeLock) + +static inline void FreeBtOsBuf(struct ar6k_hci_bridge_info *pHcidevInfo, void *osbuf) +{ + if (pHcidevInfo->HciNormalMode) { + bt_free_buffer(pHcidevInfo, (struct sk_buff *)osbuf); + } else { + /* in test mode, these are just ordinary netbuf allocations */ + A_NETBUF_FREE(osbuf); + } +} + +static void FreeHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo, struct htc_packet *pPacket) +{ + LOCK_BRIDGE(pHcidevInfo); + HTC_PACKET_ENQUEUE(&pHcidevInfo->HTCPacketStructHead,pPacket); + UNLOCK_BRIDGE(pHcidevInfo); +} + +static struct htc_packet * AllocHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + struct htc_packet *pPacket = NULL; + LOCK_BRIDGE(pHcidevInfo); + pPacket = HTC_PACKET_DEQUEUE(&pHcidevInfo->HTCPacketStructHead); + UNLOCK_BRIDGE(pHcidevInfo); + return pPacket; +} + +#define BLOCK_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1)) + +static void RefillRecvBuffers(struct ar6k_hci_bridge_info *pHcidevInfo, + HCI_TRANSPORT_PACKET_TYPE Type, + int NumBuffers) +{ + int length, i; + void *osBuf = NULL; + struct htc_packet_queue queue; + struct htc_packet *pPacket; + + INIT_HTC_PACKET_QUEUE(&queue); + + if (Type == HCI_ACL_TYPE) { + if (pHcidevInfo->HciNormalMode) { + length = HCI_MAX_FRAME_SIZE; + } else { + length = MAX_ACL_RECV_LENGTH; + } + } else { + length = MAX_EVT_RECV_LENGTH; + } + + /* add on transport head and tail room */ + length += pHcidevInfo->HCIProps.HeadRoom + pHcidevInfo->HCIProps.TailRoom; + /* round up to the required I/O padding */ + length = BLOCK_ROUND_UP_PWR2(length,pHcidevInfo->HCIProps.IOBlockPad); + + for (i = 0; i < NumBuffers; i++) { + + if (pHcidevInfo->HciNormalMode) { + osBuf = bt_alloc_buffer(pHcidevInfo,length); + } else { + osBuf = A_NETBUF_ALLOC(length); + } + + if (NULL == osBuf) { + break; + } + + pPacket = AllocHTCStruct(pHcidevInfo); + if (NULL == pPacket) { + FreeBtOsBuf(pHcidevInfo,osBuf); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); + break; + } + + SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),length,Type); + /* add to queue */ + HTC_PACKET_ENQUEUE(&queue,pPacket); + } + + if (i > 0) { + HCI_TransportAddReceivePkts(pHcidevInfo->pHCIDev, &queue); + } +} + +#define HOST_INTEREST_ITEM_ADDRESS(ar, item) \ + (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \ + (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0)) +static int ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE HCIHandle, + struct hci_transport_properties *pProps, + void *pContext) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + int status; + u32 address, hci_uart_pwr_mgmt_params; +// struct ar3k_config_info ar3kconfig; + + pHcidevInfo->pHCIDev = HCIHandle; + + memcpy(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps)); + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n", + (unsigned long)HCIHandle, + pHcidevInfo->HCIProps.HeadRoom, + pHcidevInfo->HCIProps.TailRoom, + pHcidevInfo->HCIProps.IOBlockPad)); + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)->hard_header_len); +#else + A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= pHcidevInfo->ar->arNetDev->hard_header_len); +#endif + + /* provide buffers */ + RefillRecvBuffers(pHcidevInfo, HCI_ACL_TYPE, MAX_ACL_RECV_BUFS); + RefillRecvBuffers(pHcidevInfo, HCI_EVENT_TYPE, MAX_EVT_RECV_BUFS); + + do { + /* start transport */ + status = HCI_TransportStart(pHcidevInfo->pHCIDev); + + if (status) { + break; + } + + if (!pHcidevInfo->HciNormalMode) { + /* in test mode, no need to go any further */ + break; + } + + // The delay is required when AR6K is driving the BT reset line + // where time is needed after the BT chip is out of reset (HCI_TransportStart) + // and before the first HCI command is issued (AR3KConfigure) + // FIXME + // The delay should be configurable and be only applied when AR6K driving the BT + // reset line. This could be done by some module parameter or based on some HW config + // info. For now apply 100ms delay blindly + A_MDELAY(100); + + A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig)); + ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev; + ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps; +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + ar3kconfig.pHIFDevice = (struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice); +#else + ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice; +#endif + ar3kconfig.pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev; + + if (ar3khcibaud != 0) { + /* user wants ar3k baud rate change */ + ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD; + ar3kconfig.Flags |= AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY; + ar3kconfig.AR3KBaudRate = ar3khcibaud; + } + + if ((hciuartscale != 0) || (hciuartstep != 0)) { + /* user wants to tune HCI bridge UART scale/step values */ + ar3kconfig.AR6KScale = (u16)hciuartscale; + ar3kconfig.AR6KStep = (u16)hciuartstep; + ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP; + } + + /* Fetch the address of the hi_hci_uart_pwr_mgmt_params instance in the host interest area */ + address = TARG_VTOP(pHcidevInfo->ar->arTargetType, + HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar, hi_hci_uart_pwr_mgmt_params)); + status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params); + if (0 == status) { + ar3kconfig.PwrMgmtEnabled = (hci_uart_pwr_mgmt_params & 0x1); + ar3kconfig.IdleTimeout = (hci_uart_pwr_mgmt_params & 0xFFFF0000) >> 16; + ar3kconfig.WakeupTimeout = (hci_uart_pwr_mgmt_params & 0xFF00) >> 8; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to read hci_uart_pwr_mgmt_params! \n")); + } + /* configure the AR3K device */ + memcpy(ar3kconfig.bdaddr,pHcidevInfo->ar->bdaddr,6); + status = AR3KConfigure(&ar3kconfig); + if (status) { + break; + } + + /* Make sure both AR6K and AR3K have power management enabled */ + if (ar3kconfig.PwrMgmtEnabled) { + status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, true); + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n")); + } + } + + status = bt_register_hci(pHcidevInfo); + + } while (false); + + return status; +} + +static void ar6000_hci_transport_failure(void *pContext, int Status) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: transport failure! \n")); + + if (pHcidevInfo->HciNormalMode) { + /* TODO .. */ + } +} + +static void ar6000_hci_transport_removed(void *pContext) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: transport removed. \n")); + + A_ASSERT(pHcidevInfo->pHCIDev != NULL); + + HCI_TransportDetach(pHcidevInfo->pHCIDev); + bt_cleanup_hci(pHcidevInfo); + pHcidevInfo->pHCIDev = NULL; +} + +static void ar6000_hci_send_complete(void *pContext, struct htc_packet *pPacket) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + void *osbuf = pPacket->pPktContext; + A_ASSERT(osbuf != NULL); + A_ASSERT(pHcidevInfo != NULL); + + if (pPacket->Status) { + if ((pPacket->Status != A_ECANCELED) && (pPacket->Status != A_NO_RESOURCE)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Send Packet Failed: %d \n",pPacket->Status)); + } + } + + FreeHTCStruct(pHcidevInfo,pPacket); + FreeBtOsBuf(pHcidevInfo,osbuf); + +} + +static void ar6000_hci_pkt_recv(void *pContext, struct htc_packet *pPacket) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + struct sk_buff *skb; + + A_ASSERT(pHcidevInfo != NULL); + skb = (struct sk_buff *)pPacket->pPktContext; + A_ASSERT(skb != NULL); + + do { + + if (pPacket->Status) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, + ("HCI Bridge, packet received type : %d len:%d \n", + HCI_GET_PACKET_TYPE(pPacket),pPacket->ActualLength)); + + /* set the actual buffer position in the os buffer, HTC recv buffers posted to HCI are set + * to fill the front of the buffer */ + A_NETBUF_PUT(skb,pPacket->ActualLength + pHcidevInfo->HCIProps.HeadRoom); + A_NETBUF_PULL(skb,pHcidevInfo->HCIProps.HeadRoom); + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("<<< Recv HCI %s packet len:%d \n", + (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) ? "EVENT" : "ACL", + skb->len)); + AR_DEBUG_PRINTBUF(skb->data, skb->len,"BT HCI RECV Packet Dump"); + } + + if (pHcidevInfo->HciNormalMode) { + /* indicate the packet */ + if (bt_indicate_recv(pHcidevInfo,HCI_GET_PACKET_TYPE(pPacket),skb)) { + /* bt stack accepted the packet */ + skb = NULL; + } + break; + } + + /* for testing, indicate packet to the network stack */ +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + skb->dev = (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice); + if ((((struct net_device *)pHcidevInfo->HCITransHdl.netDevice)->flags & IFF_UP) == IFF_UP) { + skb->protocol = eth_type_trans(skb, (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)); +#else + skb->dev = pHcidevInfo->ar->arNetDev; + if ((pHcidevInfo->ar->arNetDev->flags & IFF_UP) == IFF_UP) { + skb->protocol = eth_type_trans(skb, pHcidevInfo->ar->arNetDev); +#endif + netif_rx(skb); + skb = NULL; + } + + } while (false); + + FreeHTCStruct(pHcidevInfo,pPacket); + + if (skb != NULL) { + /* packet was not accepted, free it */ + FreeBtOsBuf(pHcidevInfo,skb); + } + +} + +static void ar6000_hci_pkt_refill(void *pContext, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + int refillCount; + + if (Type == HCI_ACL_TYPE) { + refillCount = MAX_ACL_RECV_BUFS - BuffersAvailable; + } else { + refillCount = MAX_EVT_RECV_BUFS - BuffersAvailable; + } + + if (refillCount > 0) { + RefillRecvBuffers(pHcidevInfo,Type,refillCount); + } + +} + +static HCI_SEND_FULL_ACTION ar6000_hci_pkt_send_full(void *pContext, struct htc_packet *pPacket) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; + HCI_SEND_FULL_ACTION action = HCI_SEND_FULL_KEEP; + + if (!pHcidevInfo->HciNormalMode) { + /* for epping testing, check packet tag, some epping packets are + * special and cannot be dropped */ + if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_DATA_PKT_TAG) { + action = HCI_SEND_FULL_DROP; + } + } + + return action; +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int ar6000_setup_hci(void *ar) +#else +int ar6000_setup_hci(struct ar6_softc *ar) +#endif +{ + struct hci_transport_config_info config; + int status = 0; + int i; + struct htc_packet *pPacket; + struct ar6k_hci_bridge_info *pHcidevInfo; + + + do { + + pHcidevInfo = (struct ar6k_hci_bridge_info *)A_MALLOC(sizeof(struct ar6k_hci_bridge_info)); + + if (NULL == pHcidevInfo) { + status = A_NO_MEMORY; + break; + } + + A_MEMZERO(pHcidevInfo, sizeof(struct ar6k_hci_bridge_info)); +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + g_pHcidevInfo = pHcidevInfo; + pHcidevInfo->HCITransHdl = *(struct hci_transport_misc_handles *)ar; +#else + ar->hcidev_info = pHcidevInfo; + pHcidevInfo->ar = ar; +#endif + spin_lock_init(&pHcidevInfo->BridgeLock); + INIT_HTC_PACKET_QUEUE(&pHcidevInfo->HTCPacketStructHead); + + ar->exitCallback = AR3KConfigureExit; + + status = bt_setup_hci(pHcidevInfo); + if (status) { + break; + } + + if (pHcidevInfo->HciNormalMode) { + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in normal mode... \n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in test mode... \n")); + } + + pHcidevInfo->pHTCStructAlloc = (u8 *)A_MALLOC((sizeof(struct htc_packet)) * NUM_HTC_PACKET_STRUCTS); + + if (NULL == pHcidevInfo->pHTCStructAlloc) { + status = A_NO_MEMORY; + break; + } + + pPacket = (struct htc_packet *)pHcidevInfo->pHTCStructAlloc; + for (i = 0; i < NUM_HTC_PACKET_STRUCTS; i++,pPacket++) { + FreeHTCStruct(pHcidevInfo,pPacket); + } + + A_MEMZERO(&config,sizeof(struct hci_transport_config_info)); + config.ACLRecvBufferWaterMark = MAX_ACL_RECV_BUFS / 2; + config.EventRecvBufferWaterMark = MAX_EVT_RECV_BUFS / 2; + config.MaxSendQueueDepth = MAX_HCI_WRITE_QUEUE_DEPTH; + config.pContext = pHcidevInfo; + config.TransportFailure = ar6000_hci_transport_failure; + config.TransportReady = ar6000_hci_transport_ready; + config.TransportRemoved = ar6000_hci_transport_removed; + config.pHCISendComplete = ar6000_hci_send_complete; + config.pHCIPktRecv = ar6000_hci_pkt_recv; + config.pHCIPktRecvRefill = ar6000_hci_pkt_refill; + config.pHCISendFull = ar6000_hci_pkt_send_full; + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + pHcidevInfo->pHCIDev = HCI_TransportAttach(pHcidevInfo->HCITransHdl.htcHandle, &config); +#else + pHcidevInfo->pHCIDev = HCI_TransportAttach(ar->arHtcTarget, &config); +#endif + + if (NULL == pHcidevInfo->pHCIDev) { + status = A_ERROR; + } + + } while (false); + + if (status) { + if (pHcidevInfo != NULL) { + if (NULL == pHcidevInfo->pHCIDev) { + /* GMBOX may not be present in older chips */ + /* just return success */ + status = 0; + } + } + ar6000_cleanup_hci(ar); + } + + return status; +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +void ar6000_cleanup_hci(void *ar) +#else +void ar6000_cleanup_hci(struct ar6_softc *ar) +#endif +{ +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo; +#else + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info; +#endif + + if (pHcidevInfo != NULL) { + bt_cleanup_hci(pHcidevInfo); + + if (pHcidevInfo->pHCIDev != NULL) { + HCI_TransportStop(pHcidevInfo->pHCIDev); + HCI_TransportDetach(pHcidevInfo->pHCIDev); + pHcidevInfo->pHCIDev = NULL; + } + + if (pHcidevInfo->pHTCStructAlloc != NULL) { + kfree(pHcidevInfo->pHTCStructAlloc); + pHcidevInfo->pHTCStructAlloc = NULL; + } + + kfree(pHcidevInfo); +#ifndef EXPORT_HCI_BRIDGE_INTERFACE + ar->hcidev_info = NULL; +#endif + } + + +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int hci_test_send(void *ar, struct sk_buff *skb) +#else +int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb) +#endif +{ + int status = 0; + int length; + EPPING_HEADER *pHeader; + struct htc_packet *pPacket; + HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo; +#else + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info; +#endif + + do { + + if (NULL == pHcidevInfo) { + status = A_ERROR; + break; + } + + if (NULL == pHcidevInfo->pHCIDev) { + status = A_ERROR; + break; + } + + if (pHcidevInfo->HciNormalMode) { + /* this interface cannot run when normal WMI is running */ + status = A_ERROR; + break; + } + + pHeader = (EPPING_HEADER *)A_NETBUF_DATA(skb); + + if (!IS_EPPING_PACKET(pHeader)) { + status = A_EINVAL; + break; + } + + if (IS_EPING_PACKET_NO_DROP(pHeader)) { + htc_tag = AR6K_CONTROL_PKT_TAG; + } + + length = sizeof(EPPING_HEADER) + pHeader->DataLength; + + pPacket = AllocHTCStruct(pHcidevInfo); + if (NULL == pPacket) { + status = A_NO_MEMORY; + break; + } + + SET_HTC_PACKET_INFO_TX(pPacket, + skb, + A_NETBUF_DATA(skb), + length, + HCI_ACL_TYPE, /* send every thing out as ACL */ + htc_tag); + + HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false); + pPacket = NULL; + + } while (false); + + return status; +} + +void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig) +{ + struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info; + struct ar3k_config_info *config = (struct ar3k_config_info *)ar3kconfig; + + config->pHCIDev = pHcidevInfo->pHCIDev; + config->pHCIProps = &pHcidevInfo->HCIProps; + config->pHIFDevice = ar->arHifDevice; + config->pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev; + config->Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD; + config->AR3KBaudRate = 115200; +} + +#ifdef CONFIG_BLUEZ_HCI_BRIDGE +/*** BT Stack Entrypoints *******/ + +/* + * bt_open - open a handle to the device +*/ +static int bt_open(struct hci_dev *hdev) +{ + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_open - enter - x\n")); + set_bit(HCI_RUNNING, &hdev->flags); + set_bit(HCI_UP, &hdev->flags); + set_bit(HCI_INIT, &hdev->flags); + return 0; +} + +/* + * bt_close - close handle to the device +*/ +static int bt_close(struct hci_dev *hdev) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_close - enter\n")); + clear_bit(HCI_RUNNING, &hdev->flags); + return 0; +} + +/* + * bt_send_frame - send data frames +*/ +static int bt_send_frame(struct sk_buff *skb) +{ + struct hci_dev *hdev = (struct hci_dev *)skb->dev; + HCI_TRANSPORT_PACKET_TYPE type; + struct ar6k_hci_bridge_info *pHcidevInfo; + struct htc_packet *pPacket; + int status = 0; + struct sk_buff *txSkb = NULL; + + if (!hdev) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_send_frame - no device\n")); + return -ENODEV; + } + + if (!test_bit(HCI_RUNNING, &hdev->flags)) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_send_frame - not open\n")); + return -EBUSY; + } + + pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data; + A_ASSERT(pHcidevInfo != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("+bt_send_frame type: %d \n",bt_cb(skb)->pkt_type)); + type = HCI_COMMAND_TYPE; + + switch (bt_cb(skb)->pkt_type) { + case HCI_COMMAND_PKT: + type = HCI_COMMAND_TYPE; + hdev->stat.cmd_tx++; + break; + + case HCI_ACLDATA_PKT: + type = HCI_ACL_TYPE; + hdev->stat.acl_tx++; + break; + + case HCI_SCODATA_PKT: + /* we don't support SCO over the bridge */ + kfree_skb(skb); + return 0; + default: + A_ASSERT(false); + kfree_skb(skb); + return 0; + } + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(">>> Send HCI %s packet len: %d\n", + (type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL", + skb->len)); + if (type == HCI_COMMAND_TYPE) { + u16 opcode = HCI_GET_OP_CODE(skb->data); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" HCI Command: OGF:0x%X OCF:0x%X \r\n", + opcode >> 10, opcode & 0x3FF)); + } + AR_DEBUG_PRINTBUF(skb->data,skb->len,"BT HCI SEND Packet Dump"); + } + + do { + + txSkb = bt_skb_alloc(TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom + + pHcidevInfo->HCIProps.TailRoom + skb->len, + GFP_ATOMIC); + + if (txSkb == NULL) { + status = A_NO_MEMORY; + break; + } + + bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type; + txSkb->dev = (void *)pHcidevInfo->pBtStackHCIDev; + skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom); + memcpy(txSkb->data, skb->data, skb->len); + skb_put(txSkb,skb->len); + + pPacket = AllocHTCStruct(pHcidevInfo); + if (NULL == pPacket) { + status = A_NO_MEMORY; + break; + } + + /* HCI packet length here doesn't include the 1-byte transport header which + * will be handled by the HCI transport layer. Enough headroom has already + * been reserved above for the transport header + */ + SET_HTC_PACKET_INFO_TX(pPacket, + txSkb, + txSkb->data, + txSkb->len, + type, + AR6K_CONTROL_PKT_TAG); /* HCI packets cannot be dropped */ + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: bt_send_frame skb:0x%lX \n",(unsigned long)txSkb)); + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: type:%d, Total Length:%d Bytes \n", + type, txSkb->len)); + + status = HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false); + pPacket = NULL; + txSkb = NULL; + + } while (false); + + if (txSkb != NULL) { + kfree_skb(txSkb); + } + + kfree_skb(skb); + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("-bt_send_frame \n")); + return 0; +} + +/* + * bt_ioctl - ioctl processing +*/ +static int bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_ioctl - enter\n")); + return -ENOIOCTLCMD; +} + +/* + * bt_flush - flush outstandingbpackets +*/ +static int bt_flush(struct hci_dev *hdev) +{ + struct ar6k_hci_bridge_info *pHcidevInfo; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_flush - enter\n")); + + pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data; + + /* TODO??? */ + + return 0; +} + + +/* + * bt_destruct - +*/ +static void bt_destruct(struct hci_dev *hdev) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_destruct - enter\n")); + /* nothing to do here */ +} + +static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + int status = 0; + struct hci_dev *pHciDev = NULL; + struct hif_device_os_device_info osDevInfo; + + if (!setupbtdev) { + return 0; + } + + do { + + A_MEMZERO(&osDevInfo,sizeof(osDevInfo)); + /* get the underlying OS device */ +#ifdef EXPORT_HCI_BRIDGE_INTERFACE + status = ar6000_get_hif_dev((struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice), + &osDevInfo); +#else + status = HIFConfigureDevice(pHcidevInfo->ar->arHifDevice, + HIF_DEVICE_GET_OS_DEVICE, + &osDevInfo, + sizeof(osDevInfo)); +#endif + + if (status) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to OS device info from HIF\n")); + break; + } + + /* allocate a BT HCI struct for this device */ + pHciDev = hci_alloc_dev(); + if (NULL == pHciDev) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge - failed to allocate bt struct \n")); + status = A_NO_MEMORY; + break; + } + /* save the device, we'll register this later */ + pHcidevInfo->pBtStackHCIDev = pHciDev; + SET_HCIDEV_DEV(pHciDev,osDevInfo.pOSDevice); + SET_HCI_BUS_TYPE(pHciDev, HCI_VIRTUAL, HCI_BREDR); + pHciDev->driver_data = pHcidevInfo; + pHciDev->open = bt_open; + pHciDev->close = bt_close; + pHciDev->send = bt_send_frame; + pHciDev->ioctl = bt_ioctl; + pHciDev->flush = bt_flush; + pHciDev->destruct = bt_destruct; + pHciDev->owner = THIS_MODULE; + /* driver is running in normal BT mode */ + pHcidevInfo->HciNormalMode = true; + + } while (false); + + if (status) { + bt_cleanup_hci(pHcidevInfo); + } + + return status; +} + +static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + int err; + + if (pHcidevInfo->HciRegistered) { + pHcidevInfo->HciRegistered = false; + clear_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags); + clear_bit(HCI_UP, &pHcidevInfo->pBtStackHCIDev->flags); + clear_bit(HCI_INIT, &pHcidevInfo->pBtStackHCIDev->flags); + A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL); + /* unregister */ + if ((err = hci_unregister_dev(pHcidevInfo->pBtStackHCIDev)) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to unregister with bluetooth %d\n",err)); + } + } + + kfree(pHcidevInfo->pBtStackHCIDev); + pHcidevInfo->pBtStackHCIDev = NULL; +} + +static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + int err; + int status = 0; + + do { + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: registering HCI... \n")); + A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL); + /* mark that we are registered */ + pHcidevInfo->HciRegistered = true; + if ((err = hci_register_dev(pHcidevInfo->pBtStackHCIDev)) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to register with bluetooth %d\n",err)); + pHcidevInfo->HciRegistered = false; + status = A_ERROR; + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: HCI registered \n")); + + } while (false); + + return status; +} + +static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo, + HCI_TRANSPORT_PACKET_TYPE Type, + struct sk_buff *skb) +{ + u8 btType; + int len; + bool success = false; + BT_HCI_EVENT_HEADER *pEvent; + + do { + + if (!test_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags)) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_indicate_recv - not running\n")); + break; + } + + switch (Type) { + case HCI_ACL_TYPE: + btType = HCI_ACLDATA_PKT; + break; + case HCI_EVENT_TYPE: + btType = HCI_EVENT_PKT; + break; + default: + btType = 0; + A_ASSERT(false); + break; + } + + if (0 == btType) { + break; + } + + /* set the final type */ + bt_cb(skb)->pkt_type = btType; + /* set dev */ + skb->dev = (void *)pHcidevInfo->pBtStackHCIDev; + len = skb->len; + + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_RECV)) { + if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) { + pEvent = (BT_HCI_EVENT_HEADER *)skb->data; + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, ("BT HCI EventCode: %d, len:%d \n", + pEvent->EventCode, pEvent->ParamLength)); + } + } + + /* pass receive packet up the stack */ + if (hci_recv_frame(skb) != 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: hci_recv_frame failed \n")); + break; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, + ("HCI Bridge: Indicated RCV of type:%d, Length:%d \n",btType,len)); + } + + success = true; + + } while (false); + + return success; +} + +static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) +{ + struct sk_buff *skb; + /* in normal HCI mode we need to alloc from the bt core APIs */ + skb = bt_skb_alloc(Length, GFP_ATOMIC); + if (NULL == skb) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc bt sk_buff \n")); + } + return skb; +} + +static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb) +{ + kfree_skb(skb); +} + +#else // { CONFIG_BLUEZ_HCI_BRIDGE + + /* stubs when we only want to test the HCI bridging Interface without the HT stack */ +static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + return 0; +} +static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + +} +static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo) +{ + A_ASSERT(false); + return A_ERROR; +} + +static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo, + HCI_TRANSPORT_PACKET_TYPE Type, + struct sk_buff *skb) +{ + A_ASSERT(false); + return false; +} + +static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) +{ + A_ASSERT(false); + return NULL; +} +static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb) +{ + A_ASSERT(false); +} + +#endif // } CONFIG_BLUEZ_HCI_BRIDGE + +#else // { ATH_AR6K_ENABLE_GMBOX + + /* stubs when GMBOX support is not needed */ + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int ar6000_setup_hci(void *ar) +#else +int ar6000_setup_hci(struct ar6_softc *ar) +#endif +{ + return 0; +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +void ar6000_cleanup_hci(void *ar) +#else +void ar6000_cleanup_hci(struct ar6_softc *ar) +#endif +{ + return; +} + +#ifndef EXPORT_HCI_BRIDGE_INTERFACE +void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig) +{ + return; +} +#endif + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +int hci_test_send(void *ar, struct sk_buff *skb) +#else +int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb) +#endif +{ + return -EOPNOTSUPP; +} + +#endif // } ATH_AR6K_ENABLE_GMBOX + + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +static int __init +hcibridge_init_module(void) +{ + int status; + struct hci_transport_callbacks hciTransCallbacks; + + hciTransCallbacks.setupTransport = ar6000_setup_hci; + hciTransCallbacks.cleanupTransport = ar6000_cleanup_hci; + + status = ar6000_register_hci_transport(&hciTransCallbacks); + if (status) + return -ENODEV; + + return 0; +} + +static void __exit +hcibridge_cleanup_module(void) +{ +} + +module_init(hcibridge_init_module); +module_exit(hcibridge_cleanup_module); +MODULE_LICENSE("Dual BSD/GPL"); +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h b/trunk/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h new file mode 100644 index 000000000000..80cef77738fb --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h @@ -0,0 +1,776 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _AR6000_H_ +#define _AR6000_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "a_osapi.h" +#include "htc_api.h" +#include "wmi.h" +#include "a_drv.h" +#include "bmi.h" +#include +#include +#include +#include +#include "pkt_log.h" +#include "aggr_recv_api.h" +#include +#include +#include +#include "ar6000_api.h" +#ifdef CONFIG_HOST_TCMD_SUPPORT +#include +#endif +#include + +#include "targaddrs.h" +#include "dbglog_api.h" +#include "ar6000_diag.h" +#include "common_drv.h" +#include "roaming.h" +#include "hci_transport_api.h" +#define ATH_MODULE_NAME driver +#include "a_debug.h" +#include "hw/apb_map.h" +#include "hw/rtc_reg.h" +#include "hw/mbox_reg.h" +#include "gpio_reg.h" + +#define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0) +#define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1) +#define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2) +#define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3) +#define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4) +#define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5) +#define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) +#define ATH_DEBUG_HCI_RECV ATH_DEBUG_MAKE_MODULE_MASK(7) +#define ATH_DEBUG_HCI_SEND ATH_DEBUG_MAKE_MODULE_MASK(8) +#define ATH_DEBUG_HCI_DUMP ATH_DEBUG_MAKE_MODULE_MASK(9) + +#ifndef __dev_put +#define __dev_put(dev) dev_put(dev) +#endif + + +#define USER_SAVEDKEYS_STAT_INIT 0 +#define USER_SAVEDKEYS_STAT_RUN 1 + +// TODO this needs to move into the AR_SOFTC struct +struct USER_SAVEDKEYS { + struct ieee80211req_key ucast_ik; + struct ieee80211req_key bcast_ik; + CRYPTO_TYPE keyType; + bool keyOk; +}; + +#define DBG_INFO 0x00000001 +#define DBG_ERROR 0x00000002 +#define DBG_WARNING 0x00000004 +#define DBG_SDIO 0x00000008 +#define DBG_HIF 0x00000010 +#define DBG_HTC 0x00000020 +#define DBG_WMI 0x00000040 +#define DBG_WMI2 0x00000080 +#define DBG_DRIVER 0x00000100 + +#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING) + + +int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); +int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_AR6000 1 +#define AR6000_MAX_RX_BUFFERS 16 +#define AR6000_BUFFER_SIZE 1664 +#define AR6000_MAX_AMSDU_RX_BUFFERS 4 +#define AR6000_AMSDU_REFILL_THRESHOLD 3 +#define AR6000_AMSDU_BUFFER_SIZE (WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH + 128) +#define AR6000_MAX_RX_MESSAGE_SIZE (max(WMI_MAX_NORMAL_RX_DATA_FRAME_LENGTH,WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH)) + +#define AR6000_TX_TIMEOUT 10 +#define AR6000_ETH_ADDR_LEN 6 +#define AR6000_MAX_ENDPOINTS 4 +#define MAX_NODE_NUM 15 +/* MAX_HI_COOKIE_NUM are reserved for high priority traffic */ +#define MAX_DEF_COOKIE_NUM 180 +#define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */ +#define MAX_COOKIE_NUM (MAX_DEF_COOKIE_NUM + MAX_HI_COOKIE_NUM) + +/* MAX_DEFAULT_SEND_QUEUE_DEPTH is used to set the default queue depth for the + * WMM send queues. If a queue exceeds this depth htc will query back to the + * OS specific layer by calling EpSendFull(). This gives the OS layer the + * opportunity to drop the packet if desired. Therefore changing + * MAX_DEFAULT_SEND_QUEUE_DEPTH does not affect resource utilization but + * does impact the threshold used to identify if a packet should be + * dropped. */ +#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC) + +#define AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT 1 +#define AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT 1 +#define A_DISCONNECT_TIMER_INTERVAL 10 * 1000 +#define A_DEFAULT_LISTEN_INTERVAL 100 +#define A_MAX_WOW_LISTEN_INTERVAL 1000 + +enum { + DRV_HB_CHALLENGE = 0, + APP_HB_CHALLENGE +}; + +enum { + WLAN_INIT_MODE_NONE = 0, + WLAN_INIT_MODE_USR, + WLAN_INIT_MODE_UDEV, + WLAN_INIT_MODE_DRV +}; + +/* Suspend - configuration */ +enum { + WLAN_SUSPEND_CUT_PWR = 0, + WLAN_SUSPEND_DEEP_SLEEP, + WLAN_SUSPEND_WOW, + WLAN_SUSPEND_CUT_PWR_IF_BT_OFF +}; + +/* WiFi OFF - configuration */ +enum { + WLAN_OFF_CUT_PWR = 0, + WLAN_OFF_DEEP_SLEEP, +}; + +/* WLAN low power state */ +enum { + WLAN_POWER_STATE_ON = 0, + WLAN_POWER_STATE_CUT_PWR = 1, + WLAN_POWER_STATE_DEEP_SLEEP, + WLAN_POWER_STATE_WOW +}; + +/* WLAN WoW State */ +enum { + WLAN_WOW_STATE_NONE = 0, + WLAN_WOW_STATE_SUSPENDED, + WLAN_WOW_STATE_SUSPENDING +}; + + +typedef enum _AR6K_BIN_FILE { + AR6K_OTP_FILE, + AR6K_FIRMWARE_FILE, + AR6K_PATCH_FILE, + AR6K_BOARD_DATA_FILE, +} AR6K_BIN_FILE; + +#ifdef SETUPHCI_ENABLED +#define SETUPHCI_DEFAULT 1 +#else +#define SETUPHCI_DEFAULT 0 +#endif /* SETUPHCI_ENABLED */ + +#ifdef SETUPBTDEV_ENABLED +#define SETUPBTDEV_DEFAULT 1 +#else +#define SETUPBTDEV_DEFAULT 0 +#endif /* SETUPBTDEV_ENABLED */ + +#ifdef ENABLEUARTPRINT_SET +#define ENABLEUARTPRINT_DEFAULT 1 +#else +#define ENABLEUARTPRINT_DEFAULT 0 +#endif /* ENABLEARTPRINT_SET */ + +#ifdef ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER +#define NOHIFSCATTERSUPPORT_DEFAULT 1 +#else /* ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER */ +#define NOHIFSCATTERSUPPORT_DEFAULT 0 +#endif /* ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER */ + + +#if defined(CONFIG_ATH6KL_ENABLE_COEXISTENCE) + +#ifdef CONFIG_AR600x_BT_QCOM +#define ATH6KL_BT_DEV 1 +#elif defined(CONFIG_AR600x_BT_CSR) +#define ATH6KL_BT_DEV 2 +#else +#define ATH6KL_BT_DEV 3 +#endif + +#ifdef CONFIG_AR600x_DUAL_ANTENNA +#define ATH6KL_BT_ANTENNA 2 +#else +#define ATH6KL_BT_ANTENNA 1 +#endif + +#endif /* CONFIG_ATH6KL_ENABLE_COEXISTENCE */ + +#ifdef AR600x_BT_AR3001 +#define AR3KHCIBAUD_DEFAULT 3000000 +#define HCIUARTSCALE_DEFAULT 1 +#define HCIUARTSTEP_DEFAULT 8937 +#else +#define AR3KHCIBAUD_DEFAULT 0 +#define HCIUARTSCALE_DEFAULT 0 +#define HCIUARTSTEP_DEFAULT 0 +#endif /* AR600x_BT_AR3001 */ + +#define WLAN_INIT_MODE_DEFAULT WLAN_INIT_MODE_DRV + +#define AR6K_PATCH_DOWNLOAD_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV1_VERSION) { \ + (_param) = AR6003_REV1_PATCH_DOWNLOAD_ADDRESS; \ + } else if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_PATCH_DOWNLOAD_ADDRESS; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +#define AR6K_DATA_DOWNLOAD_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV1_VERSION) { \ + (_param) = AR6003_REV1_DATA_DOWNLOAD_ADDRESS; \ + } else if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_DATA_DOWNLOAD_ADDRESS; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +#define AR6K_DATASET_PATCH_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_DATASET_PATCH_ADDRESS; \ + } else if ((_ver) == AR6003_REV3_VERSION) { \ + (_param) = AR6003_REV3_DATASET_PATCH_ADDRESS; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +#define AR6K_APP_LOAD_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_APP_LOAD_ADDRESS; \ + } else if ((_ver) == AR6003_REV3_VERSION) { \ + (_param) = AR6003_REV3_APP_LOAD_ADDRESS; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +#define AR6K_APP_START_OVERRIDE_ADDRESS(_param, _ver) do { \ + if ((_ver) == AR6003_REV2_VERSION) { \ + (_param) = AR6003_REV2_APP_START_OVERRIDE; \ + } else if ((_ver) == AR6003_REV3_VERSION) { \ + (_param) = AR6003_REV3_APP_START_OVERRIDE; \ + } else { \ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ + A_ASSERT(0); \ + } \ +} while (0) + +/* AR6003 1.0 definitions */ +#define AR6003_REV1_VERSION 0x300002ba +#define AR6003_REV1_DATA_DOWNLOAD_ADDRESS AR6003_REV1_OTP_DATA_ADDRESS +#define AR6003_REV1_PATCH_DOWNLOAD_ADDRESS 0x57ea6c +#define AR6003_REV1_OTP_FILE "ath6k/AR6003/hw1.0/otp.bin.z77" +#define AR6003_REV1_FIRMWARE_FILE "ath6k/AR6003/hw1.0/athwlan.bin.z77" +#define AR6003_REV1_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw1.0/athtcmd_ram.bin" +#define AR6003_REV1_ART_FIRMWARE_FILE "ath6k/AR6003/hw1.0/device.bin" +#define AR6003_REV1_PATCH_FILE "ath6k/AR6003/hw1.0/data.patch.bin" +#define AR6003_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw1.0/endpointping.bin" +#ifdef CONFIG_AR600x_SD31_XXX +#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.SD31.bin" +#elif defined(CONFIG_AR600x_SD32_XXX) +#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.SD32.bin" +#elif defined(CONFIG_AR600x_WB31_XXX) +#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.WB31.bin" +#else +#define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.CUSTOM.bin" +#endif /* Board Data File */ + +/* AR6003 2.0 definitions */ +#define AR6003_REV2_VERSION 0x30000384 +#define AR6003_REV2_DATA_DOWNLOAD_ADDRESS AR6003_REV2_OTP_DATA_ADDRESS +#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910 +#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" +#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" +#define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" +#define AR6003_REV2_ART_FIRMWARE_FILE "ath6k/AR6003/hw2.0/device.bin" +#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" +#define AR6003_REV2_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw2.0/endpointping.bin" +#ifdef CONFIG_AR600x_SD31_XXX +#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin" +#elif defined(CONFIG_AR600x_SD32_XXX) +#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD32.bin" +#elif defined(CONFIG_AR600x_WB31_XXX) +#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.WB31.bin" +#else +#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.CUSTOM.bin" +#endif /* Board Data File */ + +/* AR6003 3.0 definitions */ +#define AR6003_REV3_VERSION 0x30000582 +#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" +#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" +#define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" +#define AR6003_REV3_ART_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/device.bin" +#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" +#define AR6003_REV3_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/endpointping.bin" +#ifdef CONFIG_AR600x_SD31_XXX +#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" +#elif defined(CONFIG_AR600x_SD32_XXX) +#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.SD32.bin" +#elif defined(CONFIG_AR600x_WB31_XXX) +#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.WB31.bin" +#else +#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.CUSTOM.bin" +#endif /* Board Data File */ + + +/* Power states */ +enum { + WLAN_PWR_CTRL_UP = 0, + WLAN_PWR_CTRL_CUT_PWR, + WLAN_PWR_CTRL_DEEP_SLEEP, + WLAN_PWR_CTRL_WOW, + WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED +}; + +/* HTC RAW streams */ +typedef enum _HTC_RAW_STREAM_ID { + HTC_RAW_STREAM_NOT_MAPPED = -1, + HTC_RAW_STREAM_0 = 0, + HTC_RAW_STREAM_1 = 1, + HTC_RAW_STREAM_2 = 2, + HTC_RAW_STREAM_3 = 3, + HTC_RAW_STREAM_NUM_MAX +} HTC_RAW_STREAM_ID; + +#define RAW_HTC_READ_BUFFERS_NUM 4 +#define RAW_HTC_WRITE_BUFFERS_NUM 4 + +#define HTC_RAW_BUFFER_SIZE 1664 + +typedef struct { + int currPtr; + int length; + unsigned char data[HTC_RAW_BUFFER_SIZE]; + struct htc_packet HTCPacket; +} raw_htc_buffer; + +#ifdef CONFIG_HOST_TCMD_SUPPORT +/* + * add TCMD_MODE besides wmi and bypasswmi + * in TCMD_MODE, only few TCMD releated wmi commands + * counld be hanlder + */ +enum { + AR6000_WMI_MODE = 0, + AR6000_BYPASS_MODE, + AR6000_TCMD_MODE, + AR6000_WLAN_MODE +}; +#endif /* CONFIG_HOST_TCMD_SUPPORT */ + +struct ar_wep_key { + u8 arKeyIndex; + u8 arKeyLen; + u8 arKey[64]; +} ; + +struct ar_key { + u8 key[WLAN_MAX_KEY_LEN]; + u8 key_len; + u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; + u8 seq_len; + u32 cipher; +}; + +enum { + SME_DISCONNECTED, + SME_CONNECTING, + SME_CONNECTED +}; + +struct ar_node_mapping { + u8 macAddress[6]; + u8 epId; + u8 txPending; +}; + +struct ar_cookie { + unsigned long arc_bp[2]; /* Must be first field */ + struct htc_packet HtcPkt; /* HTC packet wrapper */ + struct ar_cookie *arc_list_next; +}; + +struct ar_hb_chlng_resp { + A_TIMER timer; + u32 frequency; + u32 seqNum; + bool outstanding; + u8 missCnt; + u8 missThres; +}; + +/* Per STA data, used in AP mode */ +/*TODO: All this should move to OS independent dir */ + +#define STA_PWR_MGMT_MASK 0x1 +#define STA_PWR_MGMT_SHIFT 0x0 +#define STA_PWR_MGMT_AWAKE 0x0 +#define STA_PWR_MGMT_SLEEP 0x1 + +#define STA_SET_PWR_SLEEP(sta) (sta->flags |= (STA_PWR_MGMT_MASK << STA_PWR_MGMT_SHIFT)) +#define STA_CLR_PWR_SLEEP(sta) (sta->flags &= ~(STA_PWR_MGMT_MASK << STA_PWR_MGMT_SHIFT)) +#define STA_IS_PWR_SLEEP(sta) ((sta->flags >> STA_PWR_MGMT_SHIFT) & STA_PWR_MGMT_MASK) + +#define STA_PS_POLLED_MASK 0x1 +#define STA_PS_POLLED_SHIFT 0x1 +#define STA_SET_PS_POLLED(sta) (sta->flags |= (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT)) +#define STA_CLR_PS_POLLED(sta) (sta->flags &= ~(STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT)) +#define STA_IS_PS_POLLED(sta) (sta->flags & (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT)) + +typedef struct { + u16 flags; + u8 mac[ATH_MAC_LEN]; + u8 aid; + u8 keymgmt; + u8 ucipher; + u8 auth; + u8 wpa_ie[IEEE80211_MAX_IE]; + A_NETBUF_QUEUE_T psq; /* power save q */ + A_MUTEX_T psqLock; +} sta_t; + +typedef struct ar6_raw_htc { + HTC_ENDPOINT_ID arRaw2EpMapping[HTC_RAW_STREAM_NUM_MAX]; + HTC_RAW_STREAM_ID arEp2RawMapping[ENDPOINT_MAX]; + struct semaphore raw_htc_read_sem[HTC_RAW_STREAM_NUM_MAX]; + struct semaphore raw_htc_write_sem[HTC_RAW_STREAM_NUM_MAX]; + wait_queue_head_t raw_htc_read_queue[HTC_RAW_STREAM_NUM_MAX]; + wait_queue_head_t raw_htc_write_queue[HTC_RAW_STREAM_NUM_MAX]; + raw_htc_buffer raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM]; + raw_htc_buffer raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM]; + bool write_buffer_available[HTC_RAW_STREAM_NUM_MAX]; + bool read_buffer_available[HTC_RAW_STREAM_NUM_MAX]; +} AR_RAW_HTC_T; + +struct ar6_softc { + struct net_device *arNetDev; /* net_device pointer */ + void *arWmi; + int arTxPending[ENDPOINT_MAX]; + int arTotalTxDataPending; + u8 arNumDataEndPts; + bool arWmiEnabled; + bool arWmiReady; + bool arConnected; + HTC_HANDLE arHtcTarget; + void *arHifDevice; + spinlock_t arLock; + struct semaphore arSem; + int arSsidLen; + u_char arSsid[32]; + u8 arNextMode; + u8 arNetworkType; + u8 arDot11AuthMode; + u8 arAuthMode; + u8 arPairwiseCrypto; + u8 arPairwiseCryptoLen; + u8 arGroupCrypto; + u8 arGroupCryptoLen; + u8 arDefTxKeyIndex; + struct ar_wep_key arWepKeyList[WMI_MAX_KEY_INDEX + 1]; + u8 arBssid[6]; + u8 arReqBssid[6]; + u16 arChannelHint; + u16 arBssChannel; + u16 arListenIntervalB; + u16 arListenIntervalT; + struct ar6000_version arVersion; + u32 arTargetType; + s8 arRssi; + u8 arTxPwr; + bool arTxPwrSet; + s32 arBitRate; + struct net_device_stats arNetStats; + struct iw_statistics arIwStats; + s8 arNumChannels; + u16 arChannelList[32]; + u32 arRegCode; + bool statsUpdatePending; + TARGET_STATS arTargetStats; + s8 arMaxRetries; + u8 arPhyCapability; +#ifdef CONFIG_HOST_TCMD_SUPPORT + u32 arTargetMode; + void *tcmd_rx_report; + int tcmd_rx_report_len; +#endif + AR6000_WLAN_STATE arWlanState; + struct ar_node_mapping arNodeMap[MAX_NODE_NUM]; + u8 arIbssPsEnable; + u8 arNodeNum; + u8 arNexEpId; + struct ar_cookie *arCookieList; + u32 arCookieCount; + u32 arRateMask; + u8 arSkipScan; + u16 arBeaconInterval; + bool arConnectPending; + bool arWmmEnabled; + struct ar_hb_chlng_resp arHBChallengeResp; + u8 arKeepaliveConfigured; + u32 arMgmtFilter; + HTC_ENDPOINT_ID arAc2EpMapping[WMM_NUM_AC]; + bool arAcStreamActive[WMM_NUM_AC]; + u8 arAcStreamPriMap[WMM_NUM_AC]; + u8 arHiAcStreamActivePri; + u8 arEp2AcMapping[ENDPOINT_MAX]; + HTC_ENDPOINT_ID arControlEp; +#ifdef HTC_RAW_INTERFACE + AR_RAW_HTC_T *arRawHtc; +#endif + bool arNetQueueStopped; + bool arRawIfInit; + int arDeviceIndex; + struct common_credit_state_info arCreditStateInfo; + bool arWMIControlEpFull; + bool dbgLogFetchInProgress; + u8 log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE]; + u32 log_cnt; + u32 dbglog_init_done; + u32 arConnectCtrlFlags; + s32 user_savedkeys_stat; + u32 user_key_ctrl; + struct USER_SAVEDKEYS user_saved_keys; + USER_RSSI_THOLD rssi_map[12]; + u8 arUserBssFilter; + u16 ap_profile_flag; /* AP mode */ + WMI_AP_ACL g_acl; /* AP mode */ + sta_t sta_list[AP_MAX_NUM_STA]; /* AP mode */ + u8 sta_list_index; /* AP mode */ + struct ieee80211req_key ap_mode_bkey; /* AP mode */ + A_NETBUF_QUEUE_T mcastpsq; /* power save q for Mcast frames */ + A_MUTEX_T mcastpsqLock; + bool DTIMExpired; /* flag to indicate DTIM expired */ + u8 intra_bss; /* enable/disable intra bss data forward */ + void *aggr_cntxt; +#ifndef EXPORT_HCI_BRIDGE_INTERFACE + void *hcidev_info; +#endif + WMI_AP_MODE_STAT arAPStats; + u8 ap_hidden_ssid; + u8 ap_country_code[3]; + u8 ap_wmode; + u8 ap_dtim_period; + u16 ap_beacon_interval; + u16 arRTS; + u16 arACS; /* AP mode - Auto Channel Selection */ + struct htc_packet_queue amsdu_rx_buffer_queue; + bool bIsDestroyProgress; /* flag to indicate ar6k destroy is in progress */ + A_TIMER disconnect_timer; + u8 rxMetaVersion; +#ifdef WAPI_ENABLE + u8 arWapiEnable; +#endif + WMI_BTCOEX_CONFIG_EVENT arBtcoexConfig; + WMI_BTCOEX_STATS_EVENT arBtcoexStats; + s32 (*exitCallback)(void *config); /* generic callback at AR6K exit */ + struct hif_device_os_device_info osDevInfo; + struct wireless_dev *wdev; + struct cfg80211_scan_request *scan_request; + struct ar_key keys[WMI_MAX_KEY_INDEX + 1]; + u32 smeState; + u16 arWlanPowerState; + bool arWlanOff; +#ifdef CONFIG_PM + u16 arWowState; + bool arBTOff; + bool arBTSharing; + u16 arSuspendConfig; + u16 arWlanOffConfig; + u16 arWow2Config; +#endif + u8 scan_triggered; + WMI_SCAN_PARAMS_CMD scParams; +#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 + u8 mcast_filters[MAC_MAX_FILTERS_PER_LIST][AR_MCAST_FILTER_MAC_ADDR_SIZE]; + u8 bdaddr[6]; + bool scanSpecificSsid; +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT + void *arApDev; +#endif + u8 arAutoAuthStage; + + u8 *fw_otp; + size_t fw_otp_len; + u8 *fw; + size_t fw_len; + u8 *fw_patch; + size_t fw_patch_len; + u8 *fw_data; + size_t fw_data_len; +}; + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT +struct ar_virtual_interface { + struct net_device *arNetDev; /* net_device pointer */ + struct ar6_softc *arDev; /* ar device pointer */ + struct net_device *arStaNetDev; /* net_device pointer */ +}; +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + +static inline void *ar6k_priv(struct net_device *dev) +{ + return (wdev_priv(dev->ieee80211_ptr)); +} + +#define SET_HCI_BUS_TYPE(pHciDev, __bus, __type) do { \ + (pHciDev)->bus = (__bus); \ + (pHciDev)->dev_type = (__type); \ +} while(0) + +#define GET_INODE_FROM_FILEP(filp) \ + (filp)->f_path.dentry->d_inode + +#define arAc2EndpointID(ar,ac) (ar)->arAc2EpMapping[(ac)] +#define arSetAc2EndpointIDMap(ar,ac,ep) \ +{ (ar)->arAc2EpMapping[(ac)] = (ep); \ + (ar)->arEp2AcMapping[(ep)] = (ac); } +#define arEndpoint2Ac(ar,ep) (ar)->arEp2AcMapping[(ep)] + +#define arRawIfEnabled(ar) (ar)->arRawIfInit +#define arRawStream2EndpointID(ar,raw) (ar)->arRawHtc->arRaw2EpMapping[(raw)] +#define arSetRawStream2EndpointIDMap(ar,raw,ep) \ +{ (ar)->arRawHtc->arRaw2EpMapping[(raw)] = (ep); \ + (ar)->arRawHtc->arEp2RawMapping[(ep)] = (raw); } +#define arEndpoint2RawStreamID(ar,ep) (ar)->arRawHtc->arEp2RawMapping[(ep)] + +struct ar_giwscan_param { + char *current_ev; + char *end_buf; + u32 bytes_needed; + struct iw_request_info *info; +}; + +#define AR6000_STAT_INC(ar, stat) (ar->arNetStats.stat++) + +#define AR6000_SPIN_LOCK(lock, param) do { \ + if (irqs_disabled()) { \ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("IRQs disabled:AR6000_LOCK\n")); \ + } \ + spin_lock_bh(lock); \ +} while (0) + +#define AR6000_SPIN_UNLOCK(lock, param) do { \ + if (irqs_disabled()) { \ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("IRQs disabled: AR6000_UNLOCK\n")); \ + } \ + spin_unlock_bh(lock); \ +} while (0) + +void ar6000_init_profile_info(struct ar6_softc *ar); +void ar6000_install_static_wep_keys(struct ar6_softc *ar); +int ar6000_init(struct net_device *dev); +int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar); +void ar6000_TxDataCleanup(struct ar6_softc *ar); +int ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev); +void ar6000_restart_endpoint(struct net_device *dev); +void ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs); + +#ifdef HTC_RAW_INTERFACE + +#ifndef __user +#define __user +#endif + +int ar6000_htc_raw_open(struct ar6_softc *ar); +int ar6000_htc_raw_close(struct ar6_softc *ar); +ssize_t ar6000_htc_raw_read(struct ar6_softc *ar, + HTC_RAW_STREAM_ID StreamID, + char __user *buffer, size_t count); +ssize_t ar6000_htc_raw_write(struct ar6_softc *ar, + HTC_RAW_STREAM_ID StreamID, + char __user *buffer, size_t count); + +#endif /* HTC_RAW_INTERFACE */ + +/* AP mode */ +/*TODO: These routines should be moved to a file that is common across OS */ +sta_t * +ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr); + +sta_t * +ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid); + +u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason); + +/* HCI support */ + +#ifndef EXPORT_HCI_BRIDGE_INTERFACE +int ar6000_setup_hci(struct ar6_softc *ar); +void ar6000_cleanup_hci(struct ar6_softc *ar); +void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig); + +/* HCI bridge testing */ +int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb); +#endif + +ATH_DEBUG_DECLARE_EXTERN(htc); +ATH_DEBUG_DECLARE_EXTERN(wmi); +ATH_DEBUG_DECLARE_EXTERN(bmi); +ATH_DEBUG_DECLARE_EXTERN(hif); +ATH_DEBUG_DECLARE_EXTERN(wlan); +ATH_DEBUG_DECLARE_EXTERN(misc); + +extern u8 bcast_mac[]; +extern u8 null_mac[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _AR6000_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h b/trunk/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h new file mode 100644 index 000000000000..39e0873aff24 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// The software source and binaries included in this development package are +// licensed, not sold. You, or your company, received the package under one +// or more license agreements. The rights granted to you are specifically +// listed in these license agreement(s). All other rights remain with Atheros +// Communications, Inc., its subsidiaries, or the respective owner including +// those listed on the included copyright notices. Distribution of any +// portion of this package must be in strict compliance with the license +// agreement(s) terms. +// +// +// +// PAL driver for AR6003 +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _AR6K_PAL_H_ +#define _AR6K_PAL_H_ +#define HCI_GET_OP_CODE(p) (((u16)((p)[1])) << 8) | ((u16)((p)[0])) + +/* transmit packet reserve offset */ +#define TX_PACKET_RSV_OFFSET 32 +/* pal specific config structure */ +typedef bool (*ar6k_pal_recv_pkt_t)(void *pHciPalInfo, void *skb); +typedef struct ar6k_pal_config_s +{ + ar6k_pal_recv_pkt_t fpar6k_pal_recv_pkt; +}ar6k_pal_config_t; + +void register_pal_cb(ar6k_pal_config_t *palConfig_p); +#endif /* _AR6K_PAL_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h new file mode 100644 index 000000000000..184dbdb50495 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h @@ -0,0 +1,190 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _AR6XAPI_LINUX_H +#define _AR6XAPI_LINUX_H +#ifdef __cplusplus +extern "C" { +#endif + +struct ar6_softc; + +void ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, + u32 sw_ver, u32 abi_ver); +int ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid); +void ar6000_connect_event(struct ar6_softc *ar, u16 channel, + u8 *bssid, u16 listenInterval, + u16 beaconInterval, NETWORK_TYPE networkType, + u8 beaconIeLen, u8 assocReqLen, + u8 assocRespLen,u8 *assocInfo); +void ar6000_disconnect_event(struct ar6_softc *ar, u8 reason, + u8 *bssid, u8 assocRespLen, + u8 *assocInfo, u16 protocolReasonStatus); +void ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, + bool ismcast); +void ar6000_bitrate_rx(void *devt, s32 rateKbps); +void ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList); +void ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode); +void ar6000_txPwr_rx(void *devt, u8 txPwr); +void ar6000_keepalive_rx(void *devt, u8 configured); +void ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, + WMI_NEIGHBOR_INFO *info); +void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num); +void ar6000_scanComplete_event(struct ar6_softc *ar, int status); +void ar6000_targetStats_event(struct ar6_softc *ar, u8 *ptr, u32 len); +void ar6000_rssiThreshold_event(struct ar6_softc *ar, + WMI_RSSI_THRESHOLD_VAL newThreshold, + s16 rssi); +void ar6000_reportError_event(struct ar6_softc *, WMI_TARGET_ERROR_VAL errorVal); +void ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cac_indication, + u8 statusCode, u8 *tspecSuggestion); +void ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel, u16 newChannel); +void ar6000_hbChallengeResp_event(struct ar6_softc *, u32 cookie, u32 source); +void +ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl); + +void +ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p); + +void +ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters, + WMI_GET_WOW_LIST_REPLY *wow_reply); + +void ar6000_pmkid_list_event(void *devt, u8 numPMKID, + WMI_PMKID *pmkidList, u8 *bssidList); + +void ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values); +void ar6000_gpio_data_rx(u32 reg_id, u32 value); +void ar6000_gpio_ack_rx(void); + +s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt); +s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi); +s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above); + +void ar6000_dbglog_init_done(struct ar6_softc *ar); + +#ifdef CONFIG_HOST_TCMD_SUPPORT +void ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len); +#endif + +void ar6000_tx_retry_err_event(void *devt); + +void ar6000_snrThresholdEvent_rx(void *devt, + WMI_SNR_THRESHOLD_VAL newThreshold, + u8 snr); + +void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, u8 lqVal); + + +void ar6000_ratemask_rx(void *devt, u32 ratemask); + +int ar6000_get_driver_cfg(struct net_device *dev, + u16 cfgParam, + void *result); +void ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *data, int len); + +void ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped, + s8 *buffer, u32 length); + +int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar); + +void ar6000_peer_event(void *devt, u8 eventCode, u8 *bssid); + +void ar6000_indicate_tx_activity(void *devt, u8 trafficClass, bool Active); +HTC_ENDPOINT_ID ar6000_ac2_endpoint_id ( void * devt, u8 ac); +u8 ar6000_endpoint_id2_ac (void * devt, HTC_ENDPOINT_ID ep ); + +void ar6000_btcoex_config_event(struct ar6_softc *ar, u8 *ptr, u32 len); + +void ar6000_btcoex_stats_event(struct ar6_softc *ar, u8 *ptr, u32 len) ; + +void ar6000_dset_open_req(void *devt, + u32 id, + u32 targ_handle, + u32 targ_reply_fn, + u32 targ_reply_arg); +void ar6000_dset_close(void *devt, u32 access_cookie); +void ar6000_dset_data_req(void *devt, + u32 access_cookie, + u32 offset, + u32 length, + u32 targ_buf, + u32 targ_reply_fn, + u32 targ_reply_arg); + + +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +void prof_count_rx(unsigned int addr, unsigned int count); +#endif + +u32 ar6000_getnodeAge (void); + +u32 ar6000_getclkfreq (void); + +int ar6000_ap_mode_profile_commit(struct ar6_softc *ar); + +struct ieee80211req_wpaie; +int +ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie); + +int is_iwioctl_allowed(u8 mode, u16 cmd); + +int is_xioctl_allowed(u8 mode, int cmd); + +void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid); + +void ar6000_dtimexpiry_event(struct ar6_softc *ar); + +void ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *cmd); +void ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *cmd); +void ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *cmd); +void ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd); + +#ifdef WAPI_ENABLE +int ap_set_wapi_key(struct ar6_softc *ar, void *ik); +void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac); +#endif + +int ar6000_connect_to_ap(struct ar6_softc *ar); +int ar6000_disconnect(struct ar6_softc *ar); +int ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool suspending); +int ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state); +int ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 state); + +#ifdef CONFIG_PM +int ar6000_suspend_ev(void *context); +int ar6000_resume_ev(void *context); +int ar6000_power_change_ev(void *context, u32 config); +void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent); +#endif + +#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT +int ar6000_add_ap_interface(struct ar6_softc *ar, char *ifname); +int ar6000_remove_ap_interface(struct ar6_softc *ar); +#endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h new file mode 100644 index 000000000000..3d5f01da543f --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h @@ -0,0 +1,1217 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _ATHDRV_LINUX_H +#define _ATHDRV_LINUX_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * There are two types of ioctl's here: Standard ioctls and + * eXtended ioctls. All extended ioctls (XIOCTL) are multiplexed + * off of the single ioctl command, AR6000_IOCTL_EXTENDED. The + * arguments for every XIOCTL starts with a 32-bit command word + * that is used to select which extended ioctl is in use. After + * the command word are command-specific arguments. + */ + +/* Linux standard Wireless Extensions, private ioctl interfaces */ +#define IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) +#define IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+1) +#define IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+2) +#define IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+3) +#define IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+4) +#define IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+5) +//#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+6) +//#define IEEE80211_IOCTL_SETWMMPARAMS (SIOCIWFIRSTPRIV+7) +//#define IEEE80211_IOCTL_GETWMMPARAMS (SIOCIWFIRSTPRIV+8) +//#define IEEE80211_IOCTL_GETOPTIE (SIOCIWFIRSTPRIV+9) +//#define IEEE80211_IOCTL_SETAUTHALG (SIOCIWFIRSTPRIV+10) +#define IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+10) + + + +/* ====WMI Ioctls==== */ +/* + * + * Many ioctls simply provide WMI services to application code: + * an application makes such an ioctl call with a set of arguments + * that are packaged into the corresponding WMI message, and sent + * to the Target. + */ + +#define AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+11) +/* + * arguments: + * ar6000_version *revision + */ + +#define AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+12) +/* + * arguments: + * WMI_POWER_MODE_CMD pwrModeCmd (see include/wmi.h) + * uses: WMI_SET_POWER_MODE_CMDID + */ + +#define AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+13) +/* + * arguments: + * WMI_SCAN_PARAMS_CMD scanParams (see include/wmi.h) + * uses: WMI_SET_SCAN_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+14) +/* + * arguments: + * UINT32 listenInterval + * uses: WMI_SET_LISTEN_INT_CMDID + */ + +#define AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+15) +/* + * arguments: + * WMI_BSS_FILTER filter (see include/wmi.h) + * uses: WMI_SET_BSS_FILTER_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16) +/* + * arguments: + * WMI_CHANNEL_PARAMS_CMD chParams + * uses: WMI_SET_CHANNEL_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17) +/* + * arguments: + * WMI_PROBED_SSID_CMD probedSsids (see include/wmi.h) + * uses: WMI_SETPROBED_SSID_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18) +/* + * arguments: + * WMI_POWER_PARAMS_CMD powerParams (see include/wmi.h) + * uses: WMI_SET_POWER_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19) +/* + * arguments: + * WMI_ADD_BAD_AP_CMD badAPs (see include/wmi.h) + * uses: WMI_ADD_BAD_AP_CMDID + */ + +#define AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20) +/* + * arguments: + * ar6000_queuereq queueRequest (see below) + */ + +#define AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21) +/* + * arguments: + * WMI_CREATE_PSTREAM createPstreamCmd (see include/wmi.h) + * uses: WMI_CREATE_PSTREAM_CMDID + */ + +#define AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22) +/* + * arguments: + * WMI_DELETE_PSTREAM_CMD deletePstreamCmd (see include/wmi.h) + * uses: WMI_DELETE_PSTREAM_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23) +/* + * arguments: + * WMI_SNR_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) + * uses: WMI_SNR_THRESHOLD_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24) +/* + * arguments: + * WMI_TARGET_ERROR_REPORT_BITMASK errorReportBitMask (see include/wmi.h) + * uses: WMI_TARGET_ERROR_REPORT_BITMASK_CMDID + */ + +#define AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25) +/* + * arguments: + * TARGET_STATS *targetStats (see below) + * uses: WMI_GET_STATISTICS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26) +/* + * arguments: + * WMI_SET_ASSOC_INFO_CMD setAssocInfoCmd + * uses: WMI_SET_ASSOC_INFO_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27) +/* + * arguments: + * WMI_SET_ACCESS_PARAMS_CMD setAccessParams (see include/wmi.h) + * uses: WMI_SET_ACCESS_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28) +/* + * arguments: + * UINT32 beaconMissTime + * uses: WMI_SET_BMISS_TIME_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29) +/* + * arguments: + * WMI_DISC_TIMEOUT_CMD disconnectTimeoutCmd (see include/wmi.h) + * uses: WMI_SET_DISC_TIMEOUT_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30) +/* + * arguments: + * WMI_IBSS_PM_CAPS_CMD ibssPowerMgmtCapsCmd + * uses: WMI_SET_IBSS_PM_CAPS_CMDID + */ + +/* + * There is a very small space available for driver-private + * wireless ioctls. In order to circumvent this limitation, + * we multiplex a bunch of ioctls (XIOCTLs) on top of a + * single AR6000_IOCTL_EXTENDED ioctl. + */ +#define AR6000_IOCTL_EXTENDED (SIOCIWFIRSTPRIV+31) + + +/* ====BMI Extended Ioctls==== */ + +#define AR6000_XIOCTL_BMI_DONE 1 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_DONE) + * uses: BMI_DONE + */ + +#define AR6000_XIOCTL_BMI_READ_MEMORY 2 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_MEMORY) + * UINT32 address + * UINT32 length + * } + * char results[length] + * } + * uses: BMI_READ_MEMORY + */ + +#define AR6000_XIOCTL_BMI_WRITE_MEMORY 3 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_MEMORY) + * UINT32 address + * UINT32 length + * char data[length] + * uses: BMI_WRITE_MEMORY + */ + +#define AR6000_XIOCTL_BMI_EXECUTE 4 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_EXECUTE) + * UINT32 TargetAddress + * UINT32 parameter + * uses: BMI_EXECUTE + */ + +#define AR6000_XIOCTL_BMI_SET_APP_START 5 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_SET_APP_START) + * UINT32 TargetAddress + * uses: BMI_SET_APP_START + */ + +#define AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_SOC_REGISTER) + * UINT32 TargetAddress, 32-bit aligned + * } + * UINT32 result + * } + * uses: BMI_READ_SOC_REGISTER + */ + +#define AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER) + * UINT32 TargetAddress, 32-bit aligned + * UINT32 newValue + * } + * uses: BMI_WRITE_SOC_REGISTER + */ + +#define AR6000_XIOCTL_BMI_TEST 8 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_TEST) + * UINT32 address + * UINT32 length + * UINT32 count + */ + + + +/* Historical Host-side DataSet support */ +#define AR6000_XIOCTL_UNUSED9 9 +#define AR6000_XIOCTL_UNUSED10 10 +#define AR6000_XIOCTL_UNUSED11 11 + +/* ====Misc Extended Ioctls==== */ + +#define AR6000_XIOCTL_FORCE_TARGET_RESET 12 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_FORCE_TARGET_RESET) + */ + + +#ifdef HTC_RAW_INTERFACE +/* HTC Raw Interface Ioctls */ +#define AR6000_XIOCTL_HTC_RAW_OPEN 13 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_OPEN) + */ + +#define AR6000_XIOCTL_HTC_RAW_CLOSE 14 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_CLOSE) + */ + +#define AR6000_XIOCTL_HTC_RAW_READ 15 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_READ) + * UINT32 mailboxID + * UINT32 length + * } + * results[length] + * } + */ + +#define AR6000_XIOCTL_HTC_RAW_WRITE 16 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_WRITE) + * UINT32 mailboxID + * UINT32 length + * char buffer[length] + */ +#endif /* HTC_RAW_INTERFACE */ + +#define AR6000_XIOCTL_CHECK_TARGET_READY 17 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_CHECK_TARGET_READY) + */ + + + +/* ====GPIO (General Purpose I/O) Extended Ioctls==== */ + +#define AR6000_XIOCTL_GPIO_OUTPUT_SET 18 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_OUTPUT_SET) + * ar6000_gpio_output_set_cmd_s (see below) + * uses: WMIX_GPIO_OUTPUT_SET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_INPUT_GET 19 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_INPUT_GET) + * uses: WMIX_GPIO_INPUT_GET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_REGISTER_SET 20 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_SET) + * ar6000_gpio_register_cmd_s (see below) + * uses: WMIX_GPIO_REGISTER_SET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_REGISTER_GET 21 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_GET) + * ar6000_gpio_register_cmd_s (see below) + * uses: WMIX_GPIO_REGISTER_GET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_INTR_ACK 22 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_ACK) + * ar6000_cpio_intr_ack_cmd_s (see below) + * uses: WMIX_GPIO_INTR_ACK_CMDID + */ + +#define AR6000_XIOCTL_GPIO_INTR_WAIT 23 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_WAIT) + */ + + + +/* ====more wireless commands==== */ + +#define AR6000_XIOCTL_SET_ADHOC_BSSID 24 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BSSID) + * WMI_SET_ADHOC_BSSID_CMD setAdHocBssidCmd (see include/wmi.h) + */ + +#define AR6000_XIOCTL_SET_OPT_MODE 25 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_OPT_MODE) + * WMI_SET_OPT_MODE_CMD setOptModeCmd (see include/wmi.h) + * uses: WMI_SET_OPT_MODE_CMDID + */ + +#define AR6000_XIOCTL_OPT_SEND_FRAME 26 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_OPT_SEND_FRAME) + * WMI_OPT_TX_FRAME_CMD optTxFrameCmd (see include/wmi.h) + * uses: WMI_OPT_TX_FRAME_CMDID + */ + +#define AR6000_XIOCTL_SET_BEACON_INTVAL 27 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_BEACON_INTVAL) + * WMI_BEACON_INT_CMD beaconIntCmd (see include/wmi.h) + * uses: WMI_SET_BEACON_INT_CMDID + */ + + +#define IEEE80211_IOCTL_SETAUTHALG 28 + + +#define AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_VOICE_PKT_SIZE) + * WMI_SET_VOICE_PKT_SIZE_CMD setVoicePktSizeCmd (see include/wmi.h) + * uses: WMI_SET_VOICE_PKT_SIZE_CMDID + */ + + +#define AR6000_XIOCTL_SET_MAX_SP 30 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_MAX_SP) + * WMI_SET_MAX_SP_LEN_CMD maxSPLen(see include/wmi.h) + * uses: WMI_SET_MAX_SP_LEN_CMDID + */ + +#define AR6000_XIOCTL_WMI_GET_ROAM_TBL 31 + +#define AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32 + +#define AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33 + + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS) + * WMI_SET_POWERSAVE_TIMERS_CMD powerSaveTimers(see include/wmi.h) + * WMI_SET_POWERSAVE_TIMERS_CMDID + */ + +#define AR6000_XIOCTRL_WMI_GET_POWER_MODE 34 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTRL_WMI_GET_POWER_MODE) + */ + +#define AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35 +typedef enum { + WLAN_DISABLED, + WLAN_ENABLED +} AR6000_WLAN_STATE; +/* + * arguments: + * enable/disable + */ + +#define AR6000_XIOCTL_WMI_GET_ROAM_DATA 36 + +#define AR6000_XIOCTL_WMI_SETRETRYLIMITS 37 +/* + * arguments: + * WMI_SET_RETRY_LIMITS_CMD ibssSetRetryLimitsCmd + * uses: WMI_SET_RETRY_LIMITS_CMDID + */ + +#ifdef CONFIG_HOST_TCMD_SUPPORT +/* ====extended commands for radio test ==== */ + +#define AR6000_XIOCTL_TCMD_CONT_TX 38 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_TX) + * WMI_TCMD_CONT_TX_CMD contTxCmd (see include/wmi.h) + * uses: WMI_TCMD_CONT_TX_CMDID + */ + +#define AR6000_XIOCTL_TCMD_CONT_RX 39 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_RX) + * WMI_TCMD_CONT_RX_CMD rxCmd (see include/wmi.h) + * uses: WMI_TCMD_CONT_RX_CMDID + */ + +#define AR6000_XIOCTL_TCMD_PM 40 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_TCMD_PM) + * WMI_TCMD_PM_CMD pmCmd (see include/wmi.h) + * uses: WMI_TCMD_PM_CMDID + */ + +#endif /* CONFIG_HOST_TCMD_SUPPORT */ + +#define AR6000_XIOCTL_WMI_STARTSCAN 41 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_STARTSCAN) + * UINT8 scanType + * UINT8 scanConnected + * u32 forceFgScan + * uses: WMI_START_SCAN_CMDID + */ + +#define AR6000_XIOCTL_WMI_SETFIXRATES 42 + +#define AR6000_XIOCTL_WMI_GETFIXRATES 43 + + +#define AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44 +/* + * arguments: + * WMI_RSSI_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) + * uses: WMI_RSSI_THRESHOLD_PARAMS_CMDID + */ + +#define AR6000_XIOCTL_WMI_CLR_RSSISNR 45 +/* + * arguments: + * WMI_CLR_RSSISNR_CMD thresholdParams (see include/wmi.h) + * uses: WMI_CLR_RSSISNR_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46 +/* + * arguments: + * WMI_LQ_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) + * uses: WMI_LQ_THRESHOLD_PARAMS_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_RTS 47 +/* + * arguments: + * WMI_SET_RTS_MODE_CMD (see include/wmi.h) + * uses: WMI_SET_RTS_MODE_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_LPREAMBLE 48 + +#define AR6000_XIOCTL_WMI_SET_AUTHMODE 49 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_AUTHMODE) + * UINT8 mode + * uses: WMI_SET_RECONNECT_AUTH_MODE_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_REASSOCMODE 50 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_WMM) + * UINT8 mode + * uses: WMI_SET_WMM_CMDID + */ +#define AR6000_XIOCTL_WMI_SET_WMM 51 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS) + * UINT32 frequency + * UINT8 threshold + */ +#define AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP) + * UINT32 cookie + */ +#define AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_GET_RD) + * UINT32 regDomain + */ +#define AR6000_XIOCTL_WMI_GET_RD 54 + +#define AR6000_XIOCTL_DIAG_READ 55 + +#define AR6000_XIOCTL_DIAG_WRITE 56 + +/* + * arguments cmd (AR6000_XIOCTL_SET_TXOP) + * WMI_TXOP_CFG txopEnable + */ +#define AR6000_XIOCTL_WMI_SET_TXOP 57 + +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_USER_SETKEYS) + * UINT32 keyOpCtrl + * uses struct ar6000_user_setkeys_info + */ +#define AR6000_XIOCTL_USER_SETKEYS 58 + +#define AR6000_XIOCTL_WMI_SET_KEEPALIVE 59 +/* + * arguments: + * UINT8 cmd (AR6000_XIOCTL_WMI_SET_KEEPALIVE) + * UINT8 keepaliveInterval + * uses: WMI_SET_KEEPALIVE_CMDID + */ + +#define AR6000_XIOCTL_WMI_GET_KEEPALIVE 60 +/* + * arguments: + * UINT8 cmd (AR6000_XIOCTL_WMI_GET_KEEPALIVE) + * UINT8 keepaliveInterval + * u32 configured + * uses: WMI_GET_KEEPALIVE_CMDID + */ + +/* ====ROM Patching Extended Ioctls==== */ + +#define AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_INSTALL) + * UINT32 ROM Address + * UINT32 RAM Address + * UINT32 number of bytes + * UINT32 activate? (0 or 1) + * } + * u32 resulting rompatch ID + * } + * uses: BMI_ROMPATCH_INSTALL + */ + +#define AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL) + * UINT32 rompatch ID + * } + * uses: BMI_ROMPATCH_UNINSTALL + */ + +#define AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) + * UINT32 rompatch count + * UINT32 rompatch IDs[rompatch count] + * } + * uses: BMI_ROMPATCH_ACTIVATE + */ + +#define AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE) + * UINT32 rompatch count + * UINT32 rompatch IDs[rompatch count] + * } + * uses: BMI_ROMPATCH_DEACTIVATE + */ + +#define AR6000_XIOCTL_WMI_SET_APPIE 65 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_APPIE) + * UINT32 app_frmtype; + * UINT32 app_buflen; + * UINT8 app_buf[]; + * } + */ +#define AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66 +/* + * arguments: + * u32 filter_type; + */ + +#define AR6000_XIOCTL_DBGLOG_CFG_MODULE 67 + +#define AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68 + +#define AR6000_XIOCTL_WMI_SET_WSC_STATUS 70 +/* + * arguments: + * u32 wsc_status; + * (WSC_REG_INACTIVE or WSC_REG_ACTIVE) + */ + +/* + * arguments: + * struct { + * u8 streamType; + * u8 status; + * } + * uses: WMI_SET_BT_STATUS_CMDID + */ +#define AR6000_XIOCTL_WMI_SET_BT_STATUS 71 + +/* + * arguments: + * struct { + * u8 paramType; + * union { + * u8 noSCOPkts; + * BT_PARAMS_A2DP a2dpParams; + * BT_COEX_REGS regs; + * }; + * } + * uses: WMI_SET_BT_PARAM_CMDID + */ +#define AR6000_XIOCTL_WMI_SET_BT_PARAMS 72 + +#define AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73 +#define AR6000_XIOCTL_WMI_SET_WOW_MODE 74 +#define AR6000_XIOCTL_WMI_GET_WOW_LIST 75 +#define AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76 +#define AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77 + + + +#define AR6000_XIOCTL_TARGET_INFO 78 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_TARGET_INFO) + * u32 TargetVersion (returned) + * u32 TargetType (returned) + * (See also bmi_msg.h target_ver and target_type) + */ + +#define AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79 +/* + * arguments: + * none + */ + +#define AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80 +/* + * This ioctl is used to emulate traffic activity + * timeouts. Activity/inactivity will trigger the driver + * to re-balance credits. + * + * arguments: + * ar6000_traffic_activity_change + */ + +#define AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81 +/* + * This ioctl is used to set the connect control flags + * + * arguments: + * u32 connectCtrlFlags + */ + +#define AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82 +/* + * This IOCTL sets any Authentication,Key Management and Protection + * related parameters. This is used along with the information set in + * Connect Command. + * Currently this enables Multiple PMKIDs to an AP. + * + * arguments: + * struct { + * u32 akmpInfo; + * } + * uses: WMI_SET_AKMP_PARAMS_CMD + */ + +#define AR6000_XIOCTL_WMI_GET_PMKID_LIST 83 + +#define AR6000_XIOCTL_WMI_SET_PMKID_LIST 84 +/* + * This IOCTL is used to set a list of PMKIDs. This list of + * PMKIDs is used in the [Re]AssocReq Frame. This list is used + * only if the MultiPMKID option is enabled via the + * AR6000_XIOCTL_WMI_SET_AKMP_PARAMS IOCTL. + * + * arguments: + * struct { + * u32 numPMKID; + * WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE]; + * } + * uses: WMI_SET_PMKIDLIST_CMD + */ + +#define AR6000_XIOCTL_WMI_SET_PARAMS 85 +#define AR6000_XIOCTL_WMI_SET_MCAST_FILTER 86 +#define AR6000_XIOCTL_WMI_DEL_MCAST_FILTER 87 + + +/* Historical DSETPATCH support for INI patches */ +#define AR6000_XIOCTL_UNUSED90 90 + + +/* Support LZ-compressed firmware download */ +#define AR6000_XIOCTL_BMI_LZ_STREAM_START 91 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_LZ_STREAM_START) + * UINT32 address + * uses: BMI_LZ_STREAM_START + */ + +#define AR6000_XIOCTL_BMI_LZ_DATA 92 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_LZ_DATA) + * UINT32 length + * char data[length] + * uses: BMI_LZ_DATA + */ + +#define AR6000_XIOCTL_PROF_CFG 93 +/* + * arguments: + * u32 period + * u32 nbins + */ + +#define AR6000_XIOCTL_PROF_ADDR_SET 94 +/* + * arguments: + * u32 Target address + */ + +#define AR6000_XIOCTL_PROF_START 95 + +#define AR6000_XIOCTL_PROF_STOP 96 + +#define AR6000_XIOCTL_PROF_COUNT_GET 97 + +#define AR6000_XIOCTL_WMI_ABORT_SCAN 98 + +/* + * AP mode + */ +#define AR6000_XIOCTL_AP_GET_STA_LIST 99 + +#define AR6000_XIOCTL_AP_HIDDEN_SSID 100 + +#define AR6000_XIOCTL_AP_SET_NUM_STA 101 + +#define AR6000_XIOCTL_AP_SET_ACL_MAC 102 + +#define AR6000_XIOCTL_AP_GET_ACL_LIST 103 + +#define AR6000_XIOCTL_AP_COMMIT_CONFIG 104 + +#define IEEE80211_IOCTL_GETWPAIE 105 + +#define AR6000_XIOCTL_AP_CONN_INACT_TIME 106 + +#define AR6000_XIOCTL_AP_PROT_SCAN_TIME 107 + +#define AR6000_XIOCTL_AP_SET_COUNTRY 108 + +#define AR6000_XIOCTL_AP_SET_DTIM 109 + + + + +#define AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT 110 + +#define AR6000_XIOCTL_SET_IP 111 + +#define AR6000_XIOCTL_AP_SET_ACL_POLICY 112 + +#define AR6000_XIOCTL_AP_INTRA_BSS_COMM 113 + +#define AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO 114 + +#define AR6000_XIOCTL_MODULE_DEBUG_SET_MASK 115 + +#define AR6000_XIOCTL_MODULE_DEBUG_GET_MASK 116 + +#define AR6000_XIOCTL_DUMP_RCV_AGGR_STATS 117 + +#define AR6000_XIOCTL_SET_HT_CAP 118 + +#define AR6000_XIOCTL_SET_HT_OP 119 + +#define AR6000_XIOCTL_AP_GET_STAT 120 + +#define AR6000_XIOCTL_SET_TX_SELECT_RATES 121 + +#define AR6000_XIOCTL_SETUP_AGGR 122 + +#define AR6000_XIOCTL_ALLOW_AGGR 123 + +#define AR6000_XIOCTL_AP_GET_HIDDEN_SSID 124 + +#define AR6000_XIOCTL_AP_GET_COUNTRY 125 + +#define AR6000_XIOCTL_AP_GET_WMODE 126 + +#define AR6000_XIOCTL_AP_GET_DTIM 127 + +#define AR6000_XIOCTL_AP_GET_BINTVL 128 + +#define AR6000_XIOCTL_AP_GET_RTS 129 + +#define AR6000_XIOCTL_DELE_AGGR 130 + +#define AR6000_XIOCTL_FETCH_TARGET_REGS 131 + +#define AR6000_XIOCTL_HCI_CMD 132 + +#define AR6000_XIOCTL_ACL_DATA 133 /* used to be used for PAL */ + +#define AR6000_XIOCTL_WLAN_CONN_PRECEDENCE 134 + +#define AR6000_XIOCTL_AP_SET_11BG_RATESET 135 + +/* + * arguments: + * WMI_AP_PS_CMD apPsCmd + * uses: WMI_AP_PS_CMDID + */ + +#define AR6000_XIOCTL_WMI_SET_AP_PS 136 + +#define AR6000_XIOCTL_WMI_MCAST_FILTER 137 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT 138 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV 139 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG 140 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG 141 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG 142 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG 143 + +#define AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG 144 + +#define AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS 145 + +#define AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG 146 + +#define AR6000_XIOCTL_WMI_GET_BTCOEX_STATS 147 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_QOS_SUPP) + * UINT8 mode + * uses: WMI_SET_QOS_SUPP_CMDID + */ +#define AR6000_XIOCTL_WMI_SET_QOS_SUPP 148 + +#define AR6000_XIOCTL_GET_WLAN_SLEEP_STATE 149 + +#define AR6000_XIOCTL_SET_BT_HW_POWER_STATE 150 + +#define AR6000_XIOCTL_GET_BT_HW_POWER_STATE 151 + +#define AR6000_XIOCTL_ADD_AP_INTERFACE 152 + +#define AR6000_XIOCTL_REMOVE_AP_INTERFACE 153 + +#define AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM 154 + +#define AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES 161 + +/* used by AR6000_IOCTL_WMI_GETREV */ +struct ar6000_version { + u32 host_ver; + u32 target_ver; + u32 wlan_ver; + u32 abi_ver; +}; + +/* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */ +struct ar6000_queuereq { + u8 trafficClass; + u16 activeTsids; +}; + +/* used by AR6000_IOCTL_WMI_GET_TARGET_STATS */ +typedef struct targetStats_t { + u64 tx_packets; + u64 tx_bytes; + u64 tx_unicast_pkts; + u64 tx_unicast_bytes; + u64 tx_multicast_pkts; + u64 tx_multicast_bytes; + u64 tx_broadcast_pkts; + u64 tx_broadcast_bytes; + u64 tx_rts_success_cnt; + u64 tx_packet_per_ac[4]; + + u64 tx_errors; + u64 tx_failed_cnt; + u64 tx_retry_cnt; + u64 tx_mult_retry_cnt; + u64 tx_rts_fail_cnt; + + u64 rx_packets; + u64 rx_bytes; + u64 rx_unicast_pkts; + u64 rx_unicast_bytes; + u64 rx_multicast_pkts; + u64 rx_multicast_bytes; + u64 rx_broadcast_pkts; + u64 rx_broadcast_bytes; + u64 rx_fragment_pkt; + + u64 rx_errors; + u64 rx_crcerr; + u64 rx_key_cache_miss; + u64 rx_decrypt_err; + u64 rx_duplicate_frames; + + u64 tkip_local_mic_failure; + u64 tkip_counter_measures_invoked; + u64 tkip_replays; + u64 tkip_format_errors; + u64 ccmp_format_errors; + u64 ccmp_replays; + + u64 power_save_failure_cnt; + + u64 cs_bmiss_cnt; + u64 cs_lowRssi_cnt; + u64 cs_connect_cnt; + u64 cs_disconnect_cnt; + + s32 tx_unicast_rate; + s32 rx_unicast_rate; + + u32 lq_val; + + u32 wow_num_pkts_dropped; + u16 wow_num_events_discarded; + + s16 noise_floor_calibation; + s16 cs_rssi; + s16 cs_aveBeacon_rssi; + u8 cs_aveBeacon_snr; + u8 cs_lastRoam_msec; + u8 cs_snr; + + u8 wow_num_host_pkt_wakeups; + u8 wow_num_host_event_wakeups; + + u32 arp_received; + u32 arp_matched; + u32 arp_replied; +}TARGET_STATS; + +typedef struct targetStats_cmd_t { + TARGET_STATS targetStats; + int clearStats; +} TARGET_STATS_CMD; + +/* used by AR6000_XIOCTL_USER_SETKEYS */ + +/* + * Setting this bit to 1 doesnot initialize the RSC on the firmware + */ +#define AR6000_XIOCTL_USER_SETKEYS_RSC_CTRL 1 +#define AR6000_USER_SETKEYS_RSC_UNCHANGED 0x00000002 + +struct ar6000_user_setkeys_info { + u32 keyOpCtrl; /* Bit Map of Key Mgmt Ctrl Flags */ +}; /* XXX: unused !? */ + +/* used by AR6000_XIOCTL_GPIO_OUTPUT_SET */ +struct ar6000_gpio_output_set_cmd_s { + u32 set_mask; + u32 clear_mask; + u32 enable_mask; + u32 disable_mask; +}; + +/* + * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET + */ +struct ar6000_gpio_register_cmd_s { + u32 gpioreg_id; + u32 value; +}; + +/* used by AR6000_XIOCTL_GPIO_INTR_ACK */ +struct ar6000_gpio_intr_ack_cmd_s { + u32 ack_mask; +}; + +/* used by AR6000_XIOCTL_GPIO_INTR_WAIT */ +struct ar6000_gpio_intr_wait_cmd_s { + u32 intr_mask; + u32 input_values; +}; + +/* used by the AR6000_XIOCTL_DBGLOG_CFG_MODULE */ +typedef struct ar6000_dbglog_module_config_s { + u32 valid; + u16 mmask; + u16 tsr; + u32 rep; + u16 size; +} DBGLOG_MODULE_CONFIG; + +typedef struct user_rssi_thold_t { + s16 tag; + s16 rssi; +} USER_RSSI_THOLD; + +typedef struct user_rssi_params_t { + u8 weight; + u32 pollTime; + USER_RSSI_THOLD tholds[12]; +} USER_RSSI_PARAMS; + +typedef struct ar6000_get_btcoex_config_cmd_t{ + u32 btProfileType; + u32 linkId; + }AR6000_GET_BTCOEX_CONFIG_CMD; + +typedef struct ar6000_btcoex_config_t { + AR6000_GET_BTCOEX_CONFIG_CMD configCmd; + u32 *configEvent; +} AR6000_BTCOEX_CONFIG; + +typedef struct ar6000_btcoex_stats_t { + u32 *statsEvent; + }AR6000_BTCOEX_STATS; +/* + * Host driver may have some config parameters. Typically, these + * config params are one time config parameters. These could + * correspond to any of the underlying modules. Host driver exposes + * an api for the underlying modules to get this config. + */ +#define AR6000_DRIVER_CFG_BASE 0x8000 + +/* Should driver perform wlan node caching? */ +#define AR6000_DRIVER_CFG_GET_WLANNODECACHING 0x8001 +/*Should we log raw WMI msgs */ +#define AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS 0x8002 + +/* used by AR6000_XIOCTL_DIAG_READ & AR6000_XIOCTL_DIAG_WRITE */ +struct ar6000_diag_window_cmd_s { + unsigned int addr; + unsigned int value; +}; + + +struct ar6000_traffic_activity_change { + u32 StreamID; /* stream ID to indicate activity change */ + u32 Active; /* active (1) or inactive (0) */ +}; + +/* Used with AR6000_XIOCTL_PROF_COUNT_GET */ +struct prof_count_s { + u32 addr; /* bin start address */ + u32 count; /* hit count */ +}; + + +/* used by AR6000_XIOCTL_MODULE_DEBUG_SET_MASK */ +/* AR6000_XIOCTL_MODULE_DEBUG_GET_MASK */ +/* AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO */ +struct drv_debug_module_s { + char modulename[128]; /* name of module */ + u32 mask; /* new mask to set .. or .. current mask */ +}; + + +/* All HCI related rx events are sent up to the host app + * via a wmi event id. It can contain ACL data or HCI event, + * based on which it will be de-multiplexed. + */ +typedef enum { + PAL_HCI_EVENT = 0, + PAL_HCI_RX_DATA, +} WMI_PAL_EVENT_INFO; + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/cfg80211.h b/trunk/drivers/staging/ath6kl/os/linux/include/cfg80211.h new file mode 100644 index 000000000000..d5253207b198 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/cfg80211.h @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _AR6K_CFG80211_H_ +#define _AR6K_CFG80211_H_ + +struct wireless_dev *ar6k_cfg80211_init(struct device *dev); +void ar6k_cfg80211_deinit(struct ar6_softc *ar); + +void ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status); + +void ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel, + u8 *bssid, u16 listenInterval, + u16 beaconInterval,NETWORK_TYPE networkType, + u8 beaconIeLen, u8 assocReqLen, + u8 assocRespLen, u8 *assocInfo); + +void ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason, + u8 *bssid, u8 assocRespLen, + u8 *assocInfo, u16 protocolReasonStatus); + +void ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast); + +#ifdef CONFIG_NL80211_TESTMODE +void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf, + int buf_len); +#else +static inline void ar6000_testmode_rx_report_event(struct ar6_softc *ar, + void *buf, int buf_len) +{ +} +#endif + + +#endif /* _AR6K_CFG80211_H_ */ + + + + + + diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/config_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/config_linux.h new file mode 100644 index 000000000000..dbbe1a00b92c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/config_linux.h @@ -0,0 +1,51 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _CONFIG_LINUX_H_ +#define _CONFIG_LINUX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Host side Test Command support + */ +#define CONFIG_HOST_TCMD_SUPPORT + +#define USE_4BYTE_REGISTER_ACCESS + +/* Host-side support for Target-side profiling */ +#undef CONFIG_TARGET_PROFILE_SUPPORT + +/* IP/TCP checksum offload */ +/* Checksum offload is currently not supported for 64 bit platforms */ +#ifndef __LP64__ +#define CONFIG_CHECKSUM_OFFLOAD +#endif /* __LP64__ */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/debug_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/debug_linux.h new file mode 100644 index 000000000000..b8dba52badce --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/debug_linux.h @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _DEBUG_LINUX_H_ +#define _DEBUG_LINUX_H_ + + /* macro to remove parens */ +#define ATH_PRINTX_ARG(arg...) arg + +#ifdef DEBUG + /* NOTE: the AR_DEBUG_PRINTF macro is defined here to handle special handling of variable arg macros + * which may be compiler dependent. */ +#define AR_DEBUG_PRINTF(mask, args) do { \ + if (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (mask)) { \ + A_LOGGER(mask, ATH_MODULE_NAME, ATH_PRINTX_ARG args); \ + } \ +} while (0) +#else + /* on non-debug builds, keep in error and warning messages in the driver, all other + * message tracing will get compiled out */ +#define AR_DEBUG_PRINTF(mask, args) \ + if ((mask) & (ATH_DEBUG_ERR | ATH_DEBUG_WARN)) { A_PRINTF(ATH_PRINTX_ARG args); } + +#endif + + /* compile specific macro to get the function name string */ +#define _A_FUNCNAME_ __func__ + + +#endif /* _DEBUG_LINUX_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h b/trunk/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h new file mode 100644 index 000000000000..74f986183347 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// HCI bridge implementation +// +// Author(s): ="Atheros" +//============================================================================== + +#include "hci_transport_api.h" +#include "common_drv.h" + +extern HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo); +extern void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans); +extern int (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue); +extern int (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous); +extern void (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans); +extern int (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans); +extern int (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); +extern int (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, + struct htc_packet *pPacket, + int MaxPollMS); +extern int (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud); +extern int (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); + + +#define HCI_TransportAttach(HTCHandle, pInfo) \ + _HCI_TransportAttach((HTCHandle), (pInfo)) +#define HCI_TransportDetach(HciTrans) \ + _HCI_TransportDetach(HciTrans) +#define HCI_TransportAddReceivePkts(HciTrans, pQueue) \ + _HCI_TransportAddReceivePkts((HciTrans), (pQueue)) +#define HCI_TransportSendPkt(HciTrans, pPacket, Synchronous) \ + _HCI_TransportSendPkt((HciTrans), (pPacket), (Synchronous)) +#define HCI_TransportStop(HciTrans) \ + _HCI_TransportStop((HciTrans)) +#define HCI_TransportStart(HciTrans) \ + _HCI_TransportStart((HciTrans)) +#define HCI_TransportEnableDisableAsyncRecv(HciTrans, Enable) \ + _HCI_TransportEnableDisableAsyncRecv((HciTrans), (Enable)) +#define HCI_TransportRecvHCIEventSync(HciTrans, pPacket, MaxPollMS) \ + _HCI_TransportRecvHCIEventSync((HciTrans), (pPacket), (MaxPollMS)) +#define HCI_TransportSetBaudRate(HciTrans, Baud) \ + _HCI_TransportSetBaudRate((HciTrans), (Baud)) +#define HCI_TransportEnablePowerMgmt(HciTrans, Enable) \ + _HCI_TransportEnablePowerMgmt((HciTrans), (Enable)) + + +extern int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks); + +extern int ar6000_get_hif_dev(struct hif_device *device, void *config); + +extern int ar6000_set_uart_config(struct hif_device *hifDevice, u32 scale, u32 step); + +/* get core clock register settings + * data: 0 - 40/44MHz + * 1 - 80/88MHz + * where (5G band/2.4G band) + * assume 2.4G band for now + */ +extern int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data); diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h b/trunk/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h new file mode 100644 index 000000000000..e6e96de3fc6b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h @@ -0,0 +1,177 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _IEEE80211_IOCTL_H_ +#define _IEEE80211_IOCTL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Extracted from the MADWIFI net80211/ieee80211_ioctl.h + */ + +/* + * WPA/RSN get/set key request. Specify the key/cipher + * type and whether the key is to be used for sending and/or + * receiving. The key index should be set only when working + * with global keys (use IEEE80211_KEYIX_NONE for ``no index''). + * Otherwise a unicast/pairwise key is specified by the bssid + * (on a station) or mac address (on an ap). They key length + * must include any MIC key data; otherwise it should be no + more than IEEE80211_KEYBUF_SIZE. + */ +struct ieee80211req_key { + u_int8_t ik_type; /* key/cipher type */ + u_int8_t ik_pad; + u_int16_t ik_keyix; /* key index */ + u_int8_t ik_keylen; /* key length in bytes */ + u_int8_t ik_flags; +#define IEEE80211_KEY_XMIT 0x01 +#define IEEE80211_KEY_RECV 0x02 +#define IEEE80211_KEY_DEFAULT 0x80 /* default xmit key */ + u_int8_t ik_macaddr[IEEE80211_ADDR_LEN]; + u_int64_t ik_keyrsc; /* key receive sequence counter */ + u_int64_t ik_keytsc; /* key transmit sequence counter */ + u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE]; +}; +/* + * Delete a key either by index or address. Set the index + * to IEEE80211_KEYIX_NONE when deleting a unicast key. + */ +struct ieee80211req_del_key { + u_int8_t idk_keyix; /* key index */ + u_int8_t idk_macaddr[IEEE80211_ADDR_LEN]; +}; +/* + * MLME state manipulation request. IEEE80211_MLME_ASSOC + * only makes sense when operating as a station. The other + * requests can be used when operating as a station or an + * ap (to effect a station). + */ +struct ieee80211req_mlme { + u_int8_t im_op; /* operation to perform */ +#define IEEE80211_MLME_ASSOC 1 /* associate station */ +#define IEEE80211_MLME_DISASSOC 2 /* disassociate station */ +#define IEEE80211_MLME_DEAUTH 3 /* deauthenticate station */ +#define IEEE80211_MLME_AUTHORIZE 4 /* authorize station */ +#define IEEE80211_MLME_UNAUTHORIZE 5 /* unauthorize station */ + u_int16_t im_reason; /* 802.11 reason code */ + u_int8_t im_macaddr[IEEE80211_ADDR_LEN]; +}; + +struct ieee80211req_addpmkid { + u_int8_t pi_bssid[IEEE80211_ADDR_LEN]; + u_int8_t pi_enable; + u_int8_t pi_pmkid[16]; +}; + +#define AUTH_ALG_OPEN_SYSTEM 0x01 +#define AUTH_ALG_SHARED_KEY 0x02 +#define AUTH_ALG_LEAP 0x04 + +struct ieee80211req_authalg { + u_int8_t auth_alg; +}; + +/* + * Request to add an IE to a Management Frame + */ +enum{ + IEEE80211_APPIE_FRAME_BEACON = 0, + IEEE80211_APPIE_FRAME_PROBE_REQ = 1, + IEEE80211_APPIE_FRAME_PROBE_RESP = 2, + IEEE80211_APPIE_FRAME_ASSOC_REQ = 3, + IEEE80211_APPIE_FRAME_ASSOC_RESP = 4, + IEEE80211_APPIE_NUM_OF_FRAME = 5 +}; + +/* + * The Maximum length of the IE that can be added to a Management frame + */ +#define IEEE80211_APPIE_FRAME_MAX_LEN 200 + +struct ieee80211req_getset_appiebuf { + u_int32_t app_frmtype; /* management frame type for which buffer is added */ + u_int32_t app_buflen; /*application supplied buffer length */ + u_int8_t app_buf[]; +}; + +/* + * The following definitions are used by an application to set filter + * for receiving management frames + */ +enum { + IEEE80211_FILTER_TYPE_BEACON = 0x1, + IEEE80211_FILTER_TYPE_PROBE_REQ = 0x2, + IEEE80211_FILTER_TYPE_PROBE_RESP = 0x4, + IEEE80211_FILTER_TYPE_ASSOC_REQ = 0x8, + IEEE80211_FILTER_TYPE_ASSOC_RESP = 0x10, + IEEE80211_FILTER_TYPE_AUTH = 0x20, + IEEE80211_FILTER_TYPE_DEAUTH = 0x40, + IEEE80211_FILTER_TYPE_DISASSOC = 0x80, + IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */ +}; + +struct ieee80211req_set_filter { + u_int32_t app_filterype; /* management frame filter type */ +}; + +enum { + IEEE80211_PARAM_AUTHMODE = 3, /* Authentication Mode */ + IEEE80211_PARAM_MCASTCIPHER = 5, + IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */ + IEEE80211_PARAM_UCASTCIPHER = 8, + IEEE80211_PARAM_UCASTKEYLEN = 9, /* unicast key length */ + IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */ + IEEE80211_PARAM_ROAMING = 12, /* roaming mode */ + IEEE80211_PARAM_PRIVACY = 13, /* privacy invoked */ + IEEE80211_PARAM_COUNTERMEASURES = 14, /* WPA/TKIP countermeasures */ + IEEE80211_PARAM_DROPUNENCRYPTED = 15, /* discard unencrypted frames */ + IEEE80211_PARAM_WAPI = 16, /* WAPI policy from wapid */ +}; + +/* + * Values for IEEE80211_PARAM_WPA + */ +#define WPA_MODE_WPA1 1 +#define WPA_MODE_WPA2 2 +#define WPA_MODE_AUTO 3 +#define WPA_MODE_NONE 4 + +struct ieee80211req_wpaie { + u_int8_t wpa_macaddr[IEEE80211_ADDR_LEN]; + u_int8_t wpa_ie[IEEE80211_MAX_IE]; + u_int8_t rsn_ie[IEEE80211_MAX_IE]; +}; + +#ifndef IW_ENCODE_ALG_PMK +#define IW_ENCODE_ALG_PMK 4 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _IEEE80211_IOCTL_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/osapi_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/osapi_linux.h new file mode 100644 index 000000000000..41f437307727 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/osapi_linux.h @@ -0,0 +1,339 @@ +//------------------------------------------------------------------------------ +// This file contains the definitions of the basic atheros data types. +// It is used to map the data types in atheros files to a platform specific +// type. +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _OSAPI_LINUX_H_ +#define _OSAPI_LINUX_H_ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#define __ATTRIB_PACK __attribute__ ((packed)) +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) +#define __ATTRIB_NORETURN __attribute__ ((noreturn)) +#ifndef INLINE +#define INLINE __inline__ +#endif +#else /* Not GCC */ +#define __ATTRIB_PACK +#define __ATTRIB_PRINTF +#define __ATTRIB_NORETURN +#ifndef INLINE +#define INLINE __inline +#endif +#endif /* End __GNUC__ */ + +#define PREPACK +#define POSTPACK __ATTRIB_PACK + +/* + * Endianes macros + */ +#define A_BE2CPU8(x) ntohb(x) +#define A_BE2CPU16(x) ntohs(x) +#define A_BE2CPU32(x) ntohl(x) + +#define A_LE2CPU8(x) (x) +#define A_LE2CPU16(x) (x) +#define A_LE2CPU32(x) (x) + +#define A_CPU2BE8(x) htonb(x) +#define A_CPU2BE16(x) htons(x) +#define A_CPU2BE32(x) htonl(x) + +#define A_MEMZERO(addr, len) memset(addr, 0, len) +#define A_MALLOC(size) kmalloc((size), GFP_KERNEL) +#define A_MALLOC_NOWAIT(size) kmalloc((size), GFP_ATOMIC) + +#define A_LOGGER(mask, mod, args...) printk(KERN_ALERT args) +#define A_PRINTF(args...) printk(KERN_ALERT args) + +#define A_PRINTF_LOG(args...) printk(args) +#define A_SPRINTF(buf, args...) sprintf (buf, args) + +/* Mutual Exclusion */ +typedef spinlock_t A_MUTEX_T; +#define A_MUTEX_INIT(mutex) spin_lock_init(mutex) +#define A_MUTEX_LOCK(mutex) spin_lock_bh(mutex) +#define A_MUTEX_UNLOCK(mutex) spin_unlock_bh(mutex) +#define A_IS_MUTEX_VALID(mutex) true /* okay to return true, since A_MUTEX_DELETE does nothing */ +#define A_MUTEX_DELETE(mutex) /* spin locks are not kernel resources so nothing to free.. */ + +/* Get current time in ms adding a constant offset (in ms) */ +#define A_GET_MS(offset) \ + (((jiffies / HZ) * 1000) + (offset)) + +/* + * Timer Functions + */ +#define A_MDELAY(msecs) mdelay(msecs) +typedef struct timer_list A_TIMER; + +#define A_INIT_TIMER(pTimer, pFunction, pArg) do { \ + init_timer(pTimer); \ + (pTimer)->function = (pFunction); \ + (pTimer)->data = (unsigned long)(pArg); \ +} while (0) + +/* + * Start a Timer that elapses after 'periodMSec' milli-seconds + * Support is provided for a one-shot timer. The 'repeatFlag' is + * ignored. + */ +#define A_TIMEOUT_MS(pTimer, periodMSec, repeatFlag) do { \ + if (repeatFlag) { \ + printk("\n" __FILE__ ":%d: Timer Repeat requested\n",__LINE__); \ + panic("Timer Repeat"); \ + } \ + mod_timer((pTimer), jiffies + HZ * (periodMSec) / 1000); \ +} while (0) + +/* + * Cancel the Timer. + */ +#define A_UNTIMEOUT(pTimer) do { \ + del_timer((pTimer)); \ +} while (0) + +#define A_DELETE_TIMER(pTimer) do { \ +} while (0) + +/* + * Wait Queue related functions + */ +typedef wait_queue_head_t A_WAITQUEUE_HEAD; +#define A_INIT_WAITQUEUE_HEAD(head) init_waitqueue_head(head) +#ifndef wait_event_interruptible_timeout +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) +#endif /* wait_event_interruptible_timeout */ + +#define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \ + wait_event_interruptible_timeout(head, condition, timeout); \ +} while (0) + +#define A_WAKE_UP(head) wake_up(head) + +#ifdef DEBUG +extern unsigned int panic_on_assert; +#define A_ASSERT(expr) \ + if (!(expr)) { \ + printk(KERN_ALERT"Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#expr); \ + if (panic_on_assert) panic(#expr); \ + } +#else +#define A_ASSERT(expr) +#endif /* DEBUG */ + +#define A_REQUEST_FIRMWARE(_ppf, _pfile, _dev) request_firmware(_ppf, _pfile, _dev) +#define A_RELEASE_FIRMWARE(_pf) release_firmware(_pf) + +/* + * Initialization of the network buffer subsystem + */ +#define A_NETBUF_INIT() + +/* + * Network buffer queue support + */ +typedef struct sk_buff_head A_NETBUF_QUEUE_T; + +#define A_NETBUF_QUEUE_INIT(q) \ + a_netbuf_queue_init(q) + +#define A_NETBUF_ENQUEUE(q, pkt) \ + a_netbuf_enqueue((q), (pkt)) +#define A_NETBUF_PREQUEUE(q, pkt) \ + a_netbuf_prequeue((q), (pkt)) +#define A_NETBUF_DEQUEUE(q) \ + (a_netbuf_dequeue(q)) +#define A_NETBUF_QUEUE_SIZE(q) \ + a_netbuf_queue_size(q) +#define A_NETBUF_QUEUE_EMPTY(q) \ + (a_netbuf_queue_empty(q) ? true : false) + +/* + * Network buffer support + */ +#define A_NETBUF_ALLOC(size) \ + a_netbuf_alloc(size) +#define A_NETBUF_ALLOC_RAW(size) \ + a_netbuf_alloc_raw(size) +#define A_NETBUF_FREE(bufPtr) \ + a_netbuf_free(bufPtr) +#define A_NETBUF_DATA(bufPtr) \ + a_netbuf_to_data(bufPtr) +#define A_NETBUF_LEN(bufPtr) \ + a_netbuf_to_len(bufPtr) +#define A_NETBUF_PUSH(bufPtr, len) \ + a_netbuf_push(bufPtr, len) +#define A_NETBUF_PUT(bufPtr, len) \ + a_netbuf_put(bufPtr, len) +#define A_NETBUF_TRIM(bufPtr,len) \ + a_netbuf_trim(bufPtr, len) +#define A_NETBUF_PULL(bufPtr, len) \ + a_netbuf_pull(bufPtr, len) +#define A_NETBUF_HEADROOM(bufPtr)\ + a_netbuf_headroom(bufPtr) +#define A_NETBUF_SETLEN(bufPtr,len) \ + a_netbuf_setlen(bufPtr, len) + +/* Add data to end of a buffer */ +#define A_NETBUF_PUT_DATA(bufPtr, srcPtr, len) \ + a_netbuf_put_data(bufPtr, srcPtr, len) + +/* Add data to start of the buffer */ +#define A_NETBUF_PUSH_DATA(bufPtr, srcPtr, len) \ + a_netbuf_push_data(bufPtr, srcPtr, len) + +/* Remove data at start of the buffer */ +#define A_NETBUF_PULL_DATA(bufPtr, dstPtr, len) \ + a_netbuf_pull_data(bufPtr, dstPtr, len) + +/* Remove data from the end of the buffer */ +#define A_NETBUF_TRIM_DATA(bufPtr, dstPtr, len) \ + a_netbuf_trim_data(bufPtr, dstPtr, len) + +/* View data as "size" contiguous bytes of type "t" */ +#define A_NETBUF_VIEW_DATA(bufPtr, t, size) \ + (t )( ((struct skbuf *)(bufPtr))->data) + +/* return the beginning of the headroom for the buffer */ +#define A_NETBUF_HEAD(bufPtr) \ + ((((struct sk_buff *)(bufPtr))->head)) + +/* + * OS specific network buffer access routines + */ +void *a_netbuf_alloc(int size); +void *a_netbuf_alloc_raw(int size); +void a_netbuf_free(void *bufPtr); +void *a_netbuf_to_data(void *bufPtr); +u32 a_netbuf_to_len(void *bufPtr); +int a_netbuf_push(void *bufPtr, s32 len); +int a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len); +int a_netbuf_put(void *bufPtr, s32 len); +int a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len); +int a_netbuf_pull(void *bufPtr, s32 len); +int a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len); +int a_netbuf_trim(void *bufPtr, s32 len); +int a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len); +int a_netbuf_setlen(void *bufPtr, s32 len); +s32 a_netbuf_headroom(void *bufPtr); +void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt); +void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt); +void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q); +int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q); +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); +void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q); + +/* + * Kernel v.s User space functions + */ +u32 a_copy_to_user(void *to, const void *from, u32 n); +u32 a_copy_from_user(void *to, const void *from, u32 n); + +/* In linux, WLAN Rx and Tx run in different contexts, so no need to check + * for any commands/data queued for WLAN */ +#define A_CHECK_DRV_TX() + +#define A_GET_CACHE_LINE_BYTES() L1_CACHE_BYTES + +#define A_CACHE_LINE_PAD 128 + +static inline void *A_ALIGN_TO_CACHE_LINE(void *ptr) { + return (void *)L1_CACHE_ALIGN((unsigned long)ptr); +} + +#else /* __KERNEL__ */ + +#ifdef __GNUC__ +#define __ATTRIB_PACK __attribute__ ((packed)) +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) +#define __ATTRIB_NORETURN __attribute__ ((noreturn)) +#ifndef INLINE +#define INLINE __inline__ +#endif +#else /* Not GCC */ +#define __ATTRIB_PACK +#define __ATTRIB_PRINTF +#define __ATTRIB_NORETURN +#ifndef INLINE +#define INLINE __inline +#endif +#endif /* End __GNUC__ */ + +#define PREPACK +#define POSTPACK __ATTRIB_PACK + +#define A_MEMZERO(addr, len) memset((addr), 0, (len)) +#define A_MALLOC(size) malloc(size) + +#include + +#endif /* __KERNEL__ */ + +#endif /* _OSAPI_LINUX_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/wlan_config.h b/trunk/drivers/staging/ath6kl/os/linux/include/wlan_config.h new file mode 100644 index 000000000000..c1fe0c6e4fa1 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/wlan_config.h @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains the tunable configuration items for the WLAN module +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _HOST_WLAN_CONFIG_H_ +#define _HOST_WLAN_CONFIG_H_ + +/* Include definitions here that can be used to tune the WLAN module behavior. + * Different customers can tune the behavior as per their needs, here. + */ + +/* This configuration item when defined will consider the barker preamble + * mentioned in the ERP IE of the beacons from the AP to determine the short + * preamble support sent in the (Re)Assoc request frames. + */ +#define WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP 0 + +/* This config item when defined will not send the power module state transition + * failure events that happen during scan, to the host. + */ +#define WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN 0 + +/* + * This configuration item enable/disable keepalive support. + * Keepalive support: In the absence of any data traffic to AP, null + * frames will be sent to the AP at periodic interval, to keep the association + * active. This configuration item defines the periodic interval. + * Use value of zero to disable keepalive support + * Default: 60 seconds + */ +#define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60 + +/* + * This configuration item sets the value of disconnect timeout + * Firmware delays sending the disconnec event to the host for this + * timeout after is gets disconnected from the current AP. + * If the firmware successly roams within the disconnect timeout + * it sends a new connect event + */ +#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10 + +/* + * This configuration item disables 11n support. + * 0 - Enable + * 1 - Disable + */ +#define WLAN_CONFIG_DISABLE_11N 0 + +/* + * This configuration item enable BT clock sharing support + * 1 - Enable + * 0 - Disable (Default) + */ +#define WLAN_CONFIG_BT_SHARING 0 + +/* + * This configuration item sets WIFI OFF policy + * 0 - CUT_POWER + * 1 - DEEP_SLEEP (Default) + */ +#define WLAN_CONFIG_WLAN_OFF 1 + +/* + * This configuration item sets suspend policy + * 0 - CUT_POWER (Default) + * 1 - DEEP_SLEEP + * 2 - WoW + * 3 - CUT_POWER if BT OFF (clock sharing designs only) + */ +#define WLAN_CONFIG_PM_SUSPEND 0 + +/* + * This configuration item sets suspend policy to use if PM_SUSPEND is + * set to WoW and device is not connected at the time of suspend + * 0 - CUT_POWER (Default) + * 1 - DEEP_SLEEP + * 2 - WoW + * 3 - CUT_POWER if BT OFF (clock sharing designs only) + */ +#define WLAN_CONFIG_PM_WOW2 0 + +/* + * This configuration item enables/disables transmit bursting + * 0 - Enable tx Bursting (default) + * 1 - Disable tx bursting + */ +#define WLAN_CONFIG_DISABLE_TX_BURSTING 0 + +#endif /* _HOST_WLAN_CONFIG_H_ */ diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h new file mode 100644 index 000000000000..1eb6f822d64e --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h @@ -0,0 +1,300 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ + +#ifndef _WMI_FILTER_LINUX_H_ +#define _WMI_FILTER_LINUX_H_ + +/* + * sioctl_filter - Standard ioctl + * pioctl_filter - Priv ioctl + * xioctl_filter - eXtended ioctl + * + * ---- Possible values for the WMI filter --------------- + * (0) - Block this cmd always (or) not implemented + * (INFRA_NETWORK) - Allow this cmd only in STA mode + * (ADHOC_NETWORK) - Allow this cmd only in IBSS mode + * (AP_NETWORK) - Allow this cmd only in AP mode + * (INFRA_NETWORK | ADHOC_NETWORK) - Block this cmd in AP mode + * (ADHOC_NETWORK | AP_NETWORK) - Block this cmd in STA mode + * (INFRA_NETWORK | AP_NETWORK) - Block this cmd in IBSS mode + * (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK)- allow only when mode is set + * (0xFF) - Allow this cmd always irrespective of mode + */ + +u8 sioctl_filter[] = { +(AP_NETWORK), /* SIOCSIWCOMMIT 0x8B00 */ +(0xFF), /* SIOCGIWNAME 0x8B01 */ +(0), /* SIOCSIWNWID 0x8B02 */ +(0), /* SIOCGIWNWID 0x8B03 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWFREQ 0x8B04 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWFREQ 0x8B05 */ +(0xFF), /* SIOCSIWMODE 0x8B06 */ +(0xFF), /* SIOCGIWMODE 0x8B07 */ +(0), /* SIOCSIWSENS 0x8B08 */ +(0), /* SIOCGIWSENS 0x8B09 */ +(0), /* SIOCSIWRANGE 0x8B0A */ +(0xFF), /* SIOCGIWRANGE 0x8B0B */ +(0), /* SIOCSIWPRIV 0x8B0C */ +(0), /* SIOCGIWPRIV 0x8B0D */ +(0), /* SIOCSIWSTATS 0x8B0E */ +(0), /* SIOCGIWSTATS 0x8B0F */ +(0), /* SIOCSIWSPY 0x8B10 */ +(0), /* SIOCGIWSPY 0x8B11 */ +(0), /* SIOCSIWTHRSPY 0x8B12 */ +(0), /* SIOCGIWTHRSPY 0x8B13 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWAP 0x8B14 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWAP 0x8B15 */ +#if (WIRELESS_EXT >= 18) +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWMLME 0X8B16 */ +#else +(0), /* Dummy 0 */ +#endif /* WIRELESS_EXT */ +(0), /* SIOCGIWAPLIST 0x8B17 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWSCAN 0x8B18 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCGIWSCAN 0x8B19 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWESSID 0x8B1A */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWESSID 0x8B1B */ +(0), /* SIOCSIWNICKN 0x8B1C */ +(0), /* SIOCGIWNICKN 0x8B1D */ +(0), /* Dummy 0 */ +(0), /* Dummy 0 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWRATE 0x8B20 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWRATE 0x8B21 */ +(0), /* SIOCSIWRTS 0x8B22 */ +(0), /* SIOCGIWRTS 0x8B23 */ +(0), /* SIOCSIWFRAG 0x8B24 */ +(0), /* SIOCGIWFRAG 0x8B25 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWTXPOW 0x8B26 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWTXPOW 0x8B27 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWRETRY 0x8B28 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* SIOCGIWRETRY 0x8B29 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWENCODE 0x8B2A */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWENCODE 0x8B2B */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWPOWER 0x8B2C */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWPOWER 0x8B2D */ +}; + + + +u8 pioctl_filter[] = { +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+1) */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+2) */ +(AP_NETWORK), /* IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+3) */ +(INFRA_NETWORK), /* IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+4) */ +(0), /* IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+5) */ +(0), /* (SIOCIWFIRSTPRIV+6) */ +(0), /* (SIOCIWFIRSTPRIV+7) */ +(0), /* (SIOCIWFIRSTPRIV+8) */ +(0), /* (SIOCIWFIRSTPRIV+9) */ +(0), /* IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+10) */ +(0xFF), /* AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+11) */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+12) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+13) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+14) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+15) */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18) */ +(INFRA_NETWORK), /* AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24)*/ +(0xFF), /* AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28) */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29) */ +(ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30) */ +}; + + + +u8 xioctl_filter[] = { +(0xFF), /* Dummy 0 */ +(0xFF), /* AR6000_XIOCTL_BMI_DONE 1 */ +(0xFF), /* AR6000_XIOCTL_BMI_READ_MEMORY 2 */ +(0xFF), /* AR6000_XIOCTL_BMI_WRITE_MEMORY 3 */ +(0xFF), /* AR6000_XIOCTL_BMI_EXECUTE 4 */ +(0xFF), /* AR6000_XIOCTL_BMI_SET_APP_START 5 */ +(0xFF), /* AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6 */ +(0xFF), /* AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7 */ +(0xFF), /* AR6000_XIOCTL_BMI_TEST 8 */ +(0xFF), /* AR6000_XIOCTL_UNUSED9 9 */ +(0xFF), /* AR6000_XIOCTL_UNUSED10 10 */ +(0xFF), /* AR6000_XIOCTL_UNUSED11 11 */ +(0xFF), /* AR6000_XIOCTL_FORCE_TARGET_RESET 12 */ +(0xFF), /* AR6000_XIOCTL_HTC_RAW_OPEN 13 */ +(0xFF), /* AR6000_XIOCTL_HTC_RAW_CLOSE 14 */ +(0xFF), /* AR6000_XIOCTL_HTC_RAW_READ 15 */ +(0xFF), /* AR6000_XIOCTL_HTC_RAW_WRITE 16 */ +(0xFF), /* AR6000_XIOCTL_CHECK_TARGET_READY 17 */ +(0xFF), /* AR6000_XIOCTL_GPIO_OUTPUT_SET 18 */ +(0xFF), /* AR6000_XIOCTL_GPIO_INPUT_GET 19 */ +(0xFF), /* AR6000_XIOCTL_GPIO_REGISTER_SET 20 */ +(0xFF), /* AR6000_XIOCTL_GPIO_REGISTER_GET 21 */ +(0xFF), /* AR6000_XIOCTL_GPIO_INTR_ACK 22 */ +(0xFF), /* AR6000_XIOCTL_GPIO_INTR_WAIT 23 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_ADHOC_BSSID 24 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_OPT_MODE 25 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_OPT_SEND_FRAME 26 */ +(ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_SET_BEACON_INTVAL 27 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETAUTHALG 28 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_MAX_SP 30 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_ROAM_TBL 31 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTRL_WMI_GET_POWER_MODE 34 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_ROAM_DATA 36 */ +(0xFF), /* AR6000_XIOCTL_WMI_SETRETRYLIMITS 37 */ +(0xFF), /* AR6000_XIOCTL_TCMD_CONT_TX 38 */ +(0xFF), /* AR6000_XIOCTL_TCMD_CONT_RX 39 */ +(0xFF), /* AR6000_XIOCTL_TCMD_PM 40 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_STARTSCAN 41 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SETFIXRATES 42 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_GETFIXRATES 43 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_CLR_RSSISNR 45 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_RTS 47 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_LPREAMBLE 48 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_AUTHMODE 49 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_REASSOCMODE 50 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WMM 51 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53 */ +(INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_GET_RD 54 */ +(0xFF), /* AR6000_XIOCTL_DIAG_READ 55 */ +(0xFF), /* AR6000_XIOCTL_DIAG_WRITE 56 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_TXOP 57 */ +(INFRA_NETWORK), /* AR6000_XIOCTL_USER_SETKEYS 58 */ +(INFRA_NETWORK), /* AR6000_XIOCTL_WMI_SET_KEEPALIVE 59 */ +(INFRA_NETWORK), /* AR6000_XIOCTL_WMI_GET_KEEPALIVE 60 */ +(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61 */ +(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62 */ +(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63 */ +(0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_APPIE 65 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66 */ +(0xFF), /* AR6000_XIOCTL_DBGLOG_CFG_MODULE 67 */ +(0xFF), /* AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68 */ +(0xFF), /* Dummy 69 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_WSC_STATUS 70 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_STATUS 71 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_PARAMS 72 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WOW_MODE 74 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_WOW_LIST 75 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77 */ +(0xFF), /* AR6000_XIOCTL_TARGET_INFO 78 */ +(0xFF), /* AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79 */ +(0xFF), /* AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_PMKID_LIST 83 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_PMKID_LIST 84 */ +(0xFF), /* Dummy 85 */ +(0xFF), /* Dummy 86 */ +(0xFF), /* Dummy 87 */ +(0xFF), /* Dummy 88 */ +(0xFF), /* Dummy 89 */ +(0xFF), /* AR6000_XIOCTL_UNUSED90 90 */ +(0xFF), /* AR6000_XIOCTL_BMI_LZ_STREAM_START 91 */ +(0xFF), /* AR6000_XIOCTL_BMI_LZ_DATA 92 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_CFG 93 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_ADDR_SET 94 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_START 95 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_STOP 96 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_COUNT_GET 97 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_ABORT_SCAN 98 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_STA_LIST 99 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_HIDDEN_SSID 100 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_NUM_STA 101 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_ACL_MAC 102 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_ACL_LIST 103 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_COMMIT_CONFIG 104 */ +(AP_NETWORK), /* IEEE80211_IOCTL_GETWPAIE 105 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_CONN_INACT_TIME 106 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_PROT_SCAN_TIME 107 */ +(AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_COUNTRY 108 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_DTIM 109 */ +(0xFF), /* AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT 110 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_IP 111 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_ACL_POLICY 112 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_INTRA_BSS_COMM 113 */ +(0xFF), /* AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO 114 */ +(0xFF), /* AR6000_XIOCTL_MODULE_DEBUG_SET_MASK 115 */ +(0xFF), /* AR6000_XIOCTL_MODULE_DEBUG_GET_MASK 116 */ +(0xFF), /* AR6000_XIOCTL_DUMP_RCV_AGGR_STATS 117 */ +(0xFF), /* AR6000_XIOCTL_SET_HT_CAP 118 */ +(0xFF), /* AR6000_XIOCTL_SET_HT_OP 119 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_STAT 120 */ +(0xFF), /* AR6000_XIOCTL_SET_TX_SELECT_RATES 121 */ +(0xFF), /* AR6000_XIOCTL_SETUP_AGGR 122 */ +(0xFF), /* AR6000_XIOCTL_ALLOW_AGGR 123 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_HIDDEN_SSID 124 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_COUNTRY 125 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_WMODE 126 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_GET_DTIM 127 */ +(AP_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_AP_GET_BINTVL 128 */ +(0xFF), /* AR6000_XIOCTL_AP_GET_RTS 129 */ +(0xFF), /* AR6000_XIOCTL_DELE_AGGR 130 */ +(0xFF), /* AR6000_XIOCTL_FETCH_TARGET_REGS 131 */ +(0xFF), /* AR6000_XIOCTL_HCI_CMD 132 */ +(0xFF), /* AR6000_XIOCTL_ACL_DATA(used to be used for PAL) 133 */ +(0xFF), /* AR6000_XIOCTL_WLAN_CONN_PRECEDENCE 134 */ +(AP_NETWORK), /* AR6000_XIOCTL_AP_SET_11BG_RATESET 135 */ +(0xFF), +(0xFF), +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT 138 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV 139 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG 140 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG 141 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG 142 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG 143 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG 144 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS 145 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG 146 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_BTCOEX_GET_STATS 147 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_QOS_SUPP 148 */ +(0xFF), /* AR6000_XIOCTL_GET_WLAN_SLEEP_STATE 149 */ +(0xFF), /* AR6000_XIOCTL_SET_BT_HW_POWER_STATE 150 */ +(0xFF), /* AR6000_XIOCTL_GET_BT_HW_POWER_STATE 151 */ +(0xFF), /* AR6000_XIOCTL_ADD_AP_INTERFACE 152 */ +(0xFF), /* AR6000_XIOCTL_REMOVE_AP_INTERFACE 153 */ +(0xFF), /* AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM 154 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WPA_OFFLOAD_STATE 155 */ +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_PASSPHRASE 156 */ +(0xFF), +(0xFF), +(0xFF), +(0xFF), +(INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES 161 */ +}; + +#endif /*_WMI_FILTER_LINUX_H_*/ diff --git a/trunk/drivers/staging/ath6kl/os/linux/netbuf.c b/trunk/drivers/staging/ath6kl/os/linux/netbuf.c new file mode 100644 index 000000000000..963a2fb76a92 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/os/linux/netbuf.c @@ -0,0 +1,231 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Communications Inc. +// All rights reserved. +// +// +// +// Permission to use, copy, modify, and/or 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. +// +// +// +// Author(s): ="Atheros" +//------------------------------------------------------------------------------ +#include +#include "athdefs.h" +#include "a_osapi.h" +#include "htc_packet.h" + +#define AR6000_DATA_OFFSET 64 + +void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt) +{ + skb_queue_tail((struct sk_buff_head *) q, (struct sk_buff *) pkt); +} + +void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt) +{ + skb_queue_head((struct sk_buff_head *) q, (struct sk_buff *) pkt); +} + +void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q) +{ + return((void *) skb_dequeue((struct sk_buff_head *) q)); +} + +int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q) +{ + return(skb_queue_len((struct sk_buff_head *) q)); +} + +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q) +{ + return(skb_queue_empty((struct sk_buff_head *) q)); +} + +void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q) +{ + skb_queue_head_init((struct sk_buff_head *) q); +} + +void * +a_netbuf_alloc(int size) +{ + struct sk_buff *skb; + size += 2 * (A_GET_CACHE_LINE_BYTES()); /* add some cacheline space at front and back of buffer */ + skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(struct htc_packet) + size); + skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(struct htc_packet) + A_GET_CACHE_LINE_BYTES()); + return ((void *)skb); +} + +/* + * Allocate an SKB w.o. any encapsulation requirement. + */ +void * +a_netbuf_alloc_raw(int size) +{ + struct sk_buff *skb; + + skb = dev_alloc_skb(size); + + return ((void *)skb); +} + +void +a_netbuf_free(void *bufPtr) +{ + struct sk_buff *skb = (struct sk_buff *)bufPtr; + + dev_kfree_skb(skb); +} + +u32 a_netbuf_to_len(void *bufPtr) +{ + return (((struct sk_buff *)bufPtr)->len); +} + +void * +a_netbuf_to_data(void *bufPtr) +{ + return (((struct sk_buff *)bufPtr)->data); +} + +/* + * Add len # of bytes to the beginning of the network buffer + * pointed to by bufPtr + */ +int +a_netbuf_push(void *bufPtr, s32 len) +{ + skb_push((struct sk_buff *)bufPtr, len); + + return 0; +} + +/* + * Add len # of bytes to the beginning of the network buffer + * pointed to by bufPtr and also fill with data + */ +int +a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len) +{ + skb_push((struct sk_buff *) bufPtr, len); + memcpy(((struct sk_buff *)bufPtr)->data, srcPtr, len); + + return 0; +} + +/* + * Add len # of bytes to the end of the network buffer + * pointed to by bufPtr + */ +int +a_netbuf_put(void *bufPtr, s32 len) +{ + skb_put((struct sk_buff *)bufPtr, len); + + return 0; +} + +/* + * Add len # of bytes to the end of the network buffer + * pointed to by bufPtr and also fill with data + */ +int +a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len) +{ + char *start = (char*)(((struct sk_buff *)bufPtr)->data + + ((struct sk_buff *)bufPtr)->len); + skb_put((struct sk_buff *)bufPtr, len); + memcpy(start, srcPtr, len); + + return 0; +} + + +/* + * Trim the network buffer pointed to by bufPtr to len # of bytes + */ +int +a_netbuf_setlen(void *bufPtr, s32 len) +{ + skb_trim((struct sk_buff *)bufPtr, len); + + return 0; +} + +/* + * Chop of len # of bytes from the end of the buffer. + */ +int +a_netbuf_trim(void *bufPtr, s32 len) +{ + skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len); + + return 0; +} + +/* + * Chop of len # of bytes from the end of the buffer and return the data. + */ +int +a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len) +{ + char *start = (char*)(((struct sk_buff *)bufPtr)->data + + (((struct sk_buff *)bufPtr)->len - len)); + + memcpy(dstPtr, start, len); + skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len); + + return 0; +} + + +/* + * Returns the number of bytes available to a a_netbuf_push() + */ +s32 a_netbuf_headroom(void *bufPtr) +{ + return (skb_headroom((struct sk_buff *)bufPtr)); +} + +/* + * Removes specified number of bytes from the beginning of the buffer + */ +int +a_netbuf_pull(void *bufPtr, s32 len) +{ + skb_pull((struct sk_buff *)bufPtr, len); + + return 0; +} + +/* + * Removes specified number of bytes from the beginning of the buffer + * and return the data + */ +int +a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len) +{ + memcpy(dstPtr, ((struct sk_buff *)bufPtr)->data, len); + skb_pull((struct sk_buff *)bufPtr, len); + + return 0; +} + +#ifdef EXPORT_HCI_BRIDGE_INTERFACE +EXPORT_SYMBOL(a_netbuf_to_data); +EXPORT_SYMBOL(a_netbuf_put); +EXPORT_SYMBOL(a_netbuf_pull); +EXPORT_SYMBOL(a_netbuf_alloc); +EXPORT_SYMBOL(a_netbuf_free); +#endif diff --git a/trunk/drivers/staging/ath6kl/reorder/aggr_rx_internal.h b/trunk/drivers/staging/ath6kl/reorder/aggr_rx_internal.h new file mode 100644 index 000000000000..11125967d53d --- /dev/null +++ b/trunk/drivers/staging/ath6kl/reorder/aggr_rx_internal.h @@ -0,0 +1,117 @@ +/* + * + * Copyright (c) 2004-2010 Atheros Communications Inc. + * All rights reserved. + * + * +// +// Permission to use, copy, modify, and/or 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. +// +// + * + */ + +#ifndef __AGGR_RX_INTERNAL_H__ +#define __AGGR_RX_INTERNAL_H__ + +#include "a_osapi.h" +#include "aggr_recv_api.h" + +#define AGGR_WIN_IDX(x, y) ((x) % (y)) +#define AGGR_INCR_IDX(x, y) AGGR_WIN_IDX(((x)+1), (y)) +#define AGGR_DCRM_IDX(x, y) AGGR_WIN_IDX(((x)-1), (y)) +#define IEEE80211_MAX_SEQ_NO 0xFFF +#define IEEE80211_NEXT_SEQ_NO(x) (((x) + 1) & IEEE80211_MAX_SEQ_NO) + + +#define NUM_OF_TIDS 8 +#define AGGR_SZ_DEFAULT 8 + +#define AGGR_WIN_SZ_MIN 2 +#define AGGR_WIN_SZ_MAX 8 +/* TID Window sz is double of what is negotiated. Derive TID_WINDOW_SZ from win_sz, per tid */ +#define TID_WINDOW_SZ(_x) ((_x) << 1) + +#define AGGR_NUM_OF_FREE_NETBUFS 16 + +#define AGGR_GET_RXTID_STATS(_p, _x) (&(_p->stat[(_x)])) +#define AGGR_GET_RXTID(_p, _x) (&(_p->RxTid[(_x)])) + +/* Hold q is a function of win_sz, which is negotiated per tid */ +#define HOLD_Q_SZ(_x) (TID_WINDOW_SZ((_x))*sizeof(struct osbuf_hold_q)) +/* AGGR_RX_TIMEOUT value is important as a (too) small value can cause frames to be + * delivered out of order and a (too) large value can cause undesirable latency in + * certain situations. */ +#define AGGR_RX_TIMEOUT 400 /* Timeout(in ms) for delivery of frames, if they are stuck */ + +typedef enum { + ALL_SEQNO = 0, + CONTIGUOUS_SEQNO = 1, +}DELIVERY_ORDER; + +struct osbuf_hold_q { + void *osbuf; + bool is_amsdu; + u16 seq_no; +}; + + +#if 0 +/* XXX: unused ? */ +struct window_snapshot { + u16 seqno_st; + u16 seqno_end; +}; +#endif + +struct rxtid { + bool aggr; /* is it ON or OFF */ + bool progress; /* true when frames have arrived after a timer start */ + bool timerMon; /* true if the timer started for the sake of this TID */ + u16 win_sz; /* negotiated window size */ + u16 seq_next; /* Next seq no, in current window */ + u32 hold_q_sz; /* Num of frames that can be held in hold q */ + struct osbuf_hold_q *hold_q; /* Hold q for re-order */ +#if 0 + struct window_snapshot old_win; /* Sliding window snapshot - for timeout */ +#endif + A_NETBUF_QUEUE_T q; /* q head for enqueuing frames for dispatch */ + A_MUTEX_T lock; +}; + +struct rxtid_stats { + u32 num_into_aggr; /* hitting at the input of this module */ + u32 num_dups; /* duplicate */ + u32 num_oow; /* out of window */ + u32 num_mpdu; /* single payload 802.3/802.11 frame */ + u32 num_amsdu; /* AMSDU */ + u32 num_delivered; /* frames delivered to IP stack */ + u32 num_timeouts; /* num of timeouts, during which frames delivered */ + u32 num_hole; /* frame not present, when window moved over */ + u32 num_bar; /* num of resets of seq_num, via BAR */ +}; + +struct aggr_info { + u8 aggr_sz; /* config value of aggregation size */ + u8 timerScheduled; + A_TIMER timer; /* timer for returning held up pkts in re-order que */ + void *dev; /* dev handle */ + RX_CALLBACK rx_fn; /* callback function to return frames; to upper layer */ + struct rxtid RxTid[NUM_OF_TIDS]; /* Per tid window */ + ALLOC_NETBUFS netbuf_allocator; /* OS netbuf alloc fn */ + A_NETBUF_QUEUE_T freeQ; /* pre-allocated buffers - for A_MSDU slicing */ + struct rxtid_stats stat[NUM_OF_TIDS]; /* Tid based statistics */ + PACKET_LOG pkt_log; /* Log info of the packets */ +}; + +#endif /* __AGGR_RX_INTERNAL_H__ */ diff --git a/trunk/drivers/staging/ath6kl/reorder/rcv_aggr.c b/trunk/drivers/staging/ath6kl/reorder/rcv_aggr.c new file mode 100644 index 000000000000..9b1509ec5a7b --- /dev/null +++ b/trunk/drivers/staging/ath6kl/reorder/rcv_aggr.c @@ -0,0 +1,661 @@ +/* + * + * Copyright (c) 2010 Atheros Communications Inc. + * All rights reserved. + * + * +// +// Permission to use, copy, modify, and/or 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 "pkt_log.h" +#include "aggr_recv_api.h" +#include "aggr_rx_internal.h" +#include "wmi.h" + +extern int +wmi_dot3_2_dix(void *osbuf); + +static void +aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf); + +static void +aggr_timeout(unsigned long arg); + +static void +aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order); + +static void +aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q); + +static void * +aggr_get_osbuf(struct aggr_info *p_aggr); + +void * +aggr_init(ALLOC_NETBUFS netbuf_allocator) +{ + struct aggr_info *p_aggr = NULL; + struct rxtid *rxtid; + u8 i; + int status = 0; + + A_PRINTF("In aggr_init..\n"); + + do { + p_aggr = A_MALLOC(sizeof(struct aggr_info)); + if(!p_aggr) { + A_PRINTF("Failed to allocate memory for aggr_node\n"); + status = A_ERROR; + break; + } + + /* Init timer and data structures */ + A_MEMZERO(p_aggr, sizeof(struct aggr_info)); + p_aggr->aggr_sz = AGGR_SZ_DEFAULT; + A_INIT_TIMER(&p_aggr->timer, aggr_timeout, p_aggr); + p_aggr->timerScheduled = false; + A_NETBUF_QUEUE_INIT(&p_aggr->freeQ); + + p_aggr->netbuf_allocator = netbuf_allocator; + p_aggr->netbuf_allocator(&p_aggr->freeQ, AGGR_NUM_OF_FREE_NETBUFS); + + for(i = 0; i < NUM_OF_TIDS; i++) { + rxtid = AGGR_GET_RXTID(p_aggr, i); + rxtid->aggr = false; + rxtid->progress = false; + rxtid->timerMon = false; + A_NETBUF_QUEUE_INIT(&rxtid->q); + A_MUTEX_INIT(&rxtid->lock); + } + }while(false); + + A_PRINTF("going out of aggr_init..status %s\n", + (status == 0) ? "OK":"Error"); + + if (status) { + /* Cleanup */ + aggr_module_destroy(p_aggr); + } + return ((status == 0) ? p_aggr : NULL); +} + +/* utility function to clear rx hold_q for a tid */ +static void +aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid) +{ + struct rxtid *rxtid; + struct rxtid_stats *stats; + + A_ASSERT(tid < NUM_OF_TIDS && p_aggr); + + rxtid = AGGR_GET_RXTID(p_aggr, tid); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + + if(rxtid->aggr) { + aggr_deque_frms(p_aggr, tid, 0, ALL_SEQNO); + } + + rxtid->aggr = false; + rxtid->progress = false; + rxtid->timerMon = false; + rxtid->win_sz = 0; + rxtid->seq_next = 0; + rxtid->hold_q_sz = 0; + + if(rxtid->hold_q) { + kfree(rxtid->hold_q); + rxtid->hold_q = NULL; + } + + A_MEMZERO(stats, sizeof(struct rxtid_stats)); +} + +void +aggr_module_destroy(void *cntxt) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + u8 i, k; + A_PRINTF("%s(): aggr = %p\n",_A_FUNCNAME_, p_aggr); + A_ASSERT(p_aggr); + + if(p_aggr) { + if(p_aggr->timerScheduled) { + A_UNTIMEOUT(&p_aggr->timer); + p_aggr->timerScheduled = false; + } + + for(i = 0; i < NUM_OF_TIDS; i++) { + rxtid = AGGR_GET_RXTID(p_aggr, i); + /* Free the hold q contents and hold_q*/ + if(rxtid->hold_q) { + for(k = 0; k< rxtid->hold_q_sz; k++) { + if(rxtid->hold_q[k].osbuf) { + A_NETBUF_FREE(rxtid->hold_q[k].osbuf); + } + } + kfree(rxtid->hold_q); + } + /* Free the dispatch q contents*/ + while(A_NETBUF_QUEUE_SIZE(&rxtid->q)) { + A_NETBUF_FREE(A_NETBUF_DEQUEUE(&rxtid->q)); + } + if (A_IS_MUTEX_VALID(&rxtid->lock)) { + A_MUTEX_DELETE(&rxtid->lock); + } + } + /* free the freeQ and its contents*/ + while(A_NETBUF_QUEUE_SIZE(&p_aggr->freeQ)) { + A_NETBUF_FREE(A_NETBUF_DEQUEUE(&p_aggr->freeQ)); + } + kfree(p_aggr); + } + A_PRINTF("out aggr_module_destroy\n"); +} + + +void +aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + + A_ASSERT(p_aggr && fn && dev); + + p_aggr->rx_fn = fn; + p_aggr->dev = dev; +} + + +void +aggr_process_bar(void *cntxt, u8 tid, u16 seq_no) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid_stats *stats; + + A_ASSERT(p_aggr); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + stats->num_bar++; + + aggr_deque_frms(p_aggr, tid, seq_no, ALL_SEQNO); +} + + +void +aggr_recv_addba_req_evt(void *cntxt, u8 tid, u16 seq_no, u8 win_sz) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + struct rxtid_stats *stats; + + A_ASSERT(p_aggr); + rxtid = AGGR_GET_RXTID(p_aggr, tid); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + + A_PRINTF("%s(): win_sz = %d aggr %d\n", _A_FUNCNAME_, win_sz, rxtid->aggr); + if(win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) { + A_PRINTF("win_sz %d, tid %d\n", win_sz, tid); + } + + if(rxtid->aggr) { + /* Just go and deliver all the frames up from this + * queue, as if we got DELBA and re-initialize the queue + */ + aggr_delete_tid_state(p_aggr, tid); + } + + rxtid->seq_next = seq_no; + /* create these queues, only upon receiving of ADDBA for a + * tid, reducing memory requirement + */ + rxtid->hold_q = A_MALLOC(HOLD_Q_SZ(win_sz)); + if((rxtid->hold_q == NULL)) { + A_PRINTF("Failed to allocate memory, tid = %d\n", tid); + A_ASSERT(0); + } + A_MEMZERO(rxtid->hold_q, HOLD_Q_SZ(win_sz)); + + /* Update rxtid for the window sz */ + rxtid->win_sz = win_sz; + /* hold_q_sz inicates the depth of holding q - which is + * a factor of win_sz. Compute once, as it will be used often + */ + rxtid->hold_q_sz = TID_WINDOW_SZ(win_sz); + /* There should be no frames on q - even when second ADDBA comes in. + * If aggr was previously ON on this tid, we would have cleaned up + * the q + */ + if(A_NETBUF_QUEUE_SIZE(&rxtid->q) != 0) { + A_PRINTF("ERROR: Frames still on queue ?\n"); + A_ASSERT(0); + } + + rxtid->aggr = true; +} + +void +aggr_recv_delba_req_evt(void *cntxt, u8 tid) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + + A_ASSERT(p_aggr); + A_PRINTF("%s(): tid %d\n", _A_FUNCNAME_, tid); + + rxtid = AGGR_GET_RXTID(p_aggr, tid); + + if(rxtid->aggr) { + aggr_delete_tid_state(p_aggr, tid); + } +} + +static void +aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order) +{ + struct rxtid *rxtid; + struct osbuf_hold_q *node; + u16 idx, idx_end, seq_end; + struct rxtid_stats *stats; + + A_ASSERT(p_aggr); + rxtid = AGGR_GET_RXTID(p_aggr, tid); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + + /* idx is absolute location for first frame */ + idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); + + /* idx_end is typically the last possible frame in the window, + * but changes to 'the' seq_no, when BAR comes. If seq_no + * is non-zero, we will go up to that and stop. + * Note: last seq no in current window will occupy the same + * index position as index that is just previous to start. + * An imp point : if win_sz is 7, for seq_no space of 4095, + * then, there would be holes when sequence wrap around occurs. + * Target should judiciously choose the win_sz, based on + * this condition. For 4095, (TID_WINDOW_SZ = 2 x win_sz + * 2, 4, 8, 16 win_sz works fine). + * We must deque from "idx" to "idx_end", including both. + */ + seq_end = (seq_no) ? seq_no : rxtid->seq_next; + idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz); + + /* Critical section begins */ + A_MUTEX_LOCK(&rxtid->lock); + do { + + node = &rxtid->hold_q[idx]; + + if((order == CONTIGUOUS_SEQNO) && (!node->osbuf)) + break; + + /* chain frames and deliver frames bcos: + * 1. either the frames are in order and window is contiguous, OR + * 2. we need to deque frames, irrespective of holes + */ + if(node->osbuf) { + if(node->is_amsdu) { + aggr_slice_amsdu(p_aggr, rxtid, &node->osbuf); + } else { + A_NETBUF_ENQUEUE(&rxtid->q, node->osbuf); + } + node->osbuf = NULL; + } else { + stats->num_hole++; + } + + /* window is moving */ + rxtid->seq_next = IEEE80211_NEXT_SEQ_NO(rxtid->seq_next); + idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); + } while(idx != idx_end); + /* Critical section ends */ + A_MUTEX_UNLOCK(&rxtid->lock); + + stats->num_delivered += A_NETBUF_QUEUE_SIZE(&rxtid->q); + aggr_dispatch_frames(p_aggr, &rxtid->q); +} + +static void * +aggr_get_osbuf(struct aggr_info *p_aggr) +{ + void *buf = NULL; + + /* Starving for buffers? get more from OS + * check for low netbuffers( < 1/4 AGGR_NUM_OF_FREE_NETBUFS) : + * re-allocate bufs if so + * allocate a free buf from freeQ + */ + if (A_NETBUF_QUEUE_SIZE(&p_aggr->freeQ) < (AGGR_NUM_OF_FREE_NETBUFS >> 2)) { + p_aggr->netbuf_allocator(&p_aggr->freeQ, AGGR_NUM_OF_FREE_NETBUFS); + } + + if (A_NETBUF_QUEUE_SIZE(&p_aggr->freeQ)) { + buf = A_NETBUF_DEQUEUE(&p_aggr->freeQ); + } + + return buf; +} + + +static void +aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf) +{ + void *new_buf; + u16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len; + u8 *framep; + + /* Frame format at this point: + * [DIX hdr | 802.3 | 802.3 | ... | 802.3] + * + * Strip the DIX header. + * Iterate through the osbuf and do: + * grab a free netbuf from freeQ + * find the start and end of a frame + * copy it to netbuf(Vista can do better here) + * convert all msdu's(802.3) frames to upper layer format - os routine + * -for now lets convert from 802.3 to dix + * enque this to dispatch q of tid + * repeat + * free the osbuf - to OS. It's been sliced. + */ + + mac_hdr_len = sizeof(ATH_MAC_HDR); + framep = A_NETBUF_DATA(*osbuf) + mac_hdr_len; + amsdu_len = A_NETBUF_LEN(*osbuf) - mac_hdr_len; + + while(amsdu_len > mac_hdr_len) { + /* Begin of a 802.3 frame */ + payload_8023_len = A_BE2CPU16(((ATH_MAC_HDR *)framep)->typeOrLen); +#define MAX_MSDU_SUBFRAME_PAYLOAD_LEN 1508 +#define MIN_MSDU_SUBFRAME_PAYLOAD_LEN 46 + if(payload_8023_len < MIN_MSDU_SUBFRAME_PAYLOAD_LEN || payload_8023_len > MAX_MSDU_SUBFRAME_PAYLOAD_LEN) { + A_PRINTF("802.3 AMSDU frame bound check failed. len %d\n", payload_8023_len); + break; + } + frame_8023_len = payload_8023_len + mac_hdr_len; + new_buf = aggr_get_osbuf(p_aggr); + if(new_buf == NULL) { + A_PRINTF("No buffer available \n"); + break; + } + + memcpy(A_NETBUF_DATA(new_buf), framep, frame_8023_len); + A_NETBUF_PUT(new_buf, frame_8023_len); + if (wmi_dot3_2_dix(new_buf) != 0) { + A_PRINTF("dot3_2_dix err..\n"); + A_NETBUF_FREE(new_buf); + break; + } + + A_NETBUF_ENQUEUE(&rxtid->q, new_buf); + + /* Is this the last subframe within this aggregate ? */ + if ((amsdu_len - frame_8023_len) == 0) { + break; + } + + /* Add the length of A-MSDU subframe padding bytes - + * Round to nearest word. + */ + frame_8023_len = ((frame_8023_len + 3) & ~3); + + framep += frame_8023_len; + amsdu_len -= frame_8023_len; + } + + A_NETBUF_FREE(*osbuf); + *osbuf = NULL; +} + +void +aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + struct rxtid_stats *stats; + u16 idx, st, cur, end; + u16 *log_idx; + struct osbuf_hold_q *node; + PACKET_LOG *log; + + A_ASSERT(p_aggr); + A_ASSERT(tid < NUM_OF_TIDS); + + rxtid = AGGR_GET_RXTID(p_aggr, tid); + stats = AGGR_GET_RXTID_STATS(p_aggr, tid); + + stats->num_into_aggr++; + + if(!rxtid->aggr) { + if(is_amsdu) { + aggr_slice_amsdu(p_aggr, rxtid, osbuf); + stats->num_amsdu++; + aggr_dispatch_frames(p_aggr, &rxtid->q); + } + return; + } + + /* Check the incoming sequence no, if it's in the window */ + st = rxtid->seq_next; + cur = seq_no; + end = (st + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO; + /* Log the pkt info for future analysis */ + log = &p_aggr->pkt_log; + log_idx = &log->last_idx; + log->info[*log_idx].cur = cur; + log->info[*log_idx].st = st; + log->info[*log_idx].end = end; + *log_idx = IEEE80211_NEXT_SEQ_NO(*log_idx); + + if(((st < end) && (cur < st || cur > end)) || + ((st > end) && (cur > end) && (cur < st))) { + /* the cur frame is outside the window. Since we know + * our target would not do this without reason it must + * be assumed that the window has moved for some valid reason. + * Therefore, we dequeue all frames and start fresh. + */ + u16 extended_end; + + extended_end = (end + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO; + + if(((end < extended_end) && (cur < end || cur > extended_end)) || + ((end > extended_end) && (cur > extended_end) && (cur < end))) { + // dequeue all frames in queue and shift window to new frame + aggr_deque_frms(p_aggr, tid, 0, ALL_SEQNO); + //set window start so that new frame is last frame in window + if(cur >= rxtid->hold_q_sz-1) { + rxtid->seq_next = cur - (rxtid->hold_q_sz-1); + }else{ + rxtid->seq_next = IEEE80211_MAX_SEQ_NO - (rxtid->hold_q_sz-2 - cur); + } + } else { + // dequeue only those frames that are outside the new shifted window + if(cur >= rxtid->hold_q_sz-1) { + st = cur - (rxtid->hold_q_sz-1); + }else{ + st = IEEE80211_MAX_SEQ_NO - (rxtid->hold_q_sz-2 - cur); + } + + aggr_deque_frms(p_aggr, tid, st, ALL_SEQNO); + } + + stats->num_oow++; + } + + idx = AGGR_WIN_IDX(seq_no, rxtid->hold_q_sz); + + /*enque the frame, in hold_q */ + node = &rxtid->hold_q[idx]; + + A_MUTEX_LOCK(&rxtid->lock); + if(node->osbuf) { + /* Is the cur frame duplicate or something beyond our + * window(hold_q -> which is 2x, already)? + * 1. Duplicate is easy - drop incoming frame. + * 2. Not falling in current sliding window. + * 2a. is the frame_seq_no preceding current tid_seq_no? + * -> drop the frame. perhaps sender did not get our ACK. + * this is taken care of above. + * 2b. is the frame_seq_no beyond window(st, TID_WINDOW_SZ); + * -> Taken care of it above, by moving window forward. + * + */ + A_NETBUF_FREE(node->osbuf); + stats->num_dups++; + } + + node->osbuf = *osbuf; + node->is_amsdu = is_amsdu; + node->seq_no = seq_no; + if(node->is_amsdu) { + stats->num_amsdu++; + } else { + stats->num_mpdu++; + } + A_MUTEX_UNLOCK(&rxtid->lock); + + *osbuf = NULL; + aggr_deque_frms(p_aggr, tid, 0, CONTIGUOUS_SEQNO); + + if(p_aggr->timerScheduled) { + rxtid->progress = true; + }else{ + for(idx=0 ; idxhold_q_sz ; idx++) { + if(rxtid->hold_q[idx].osbuf) { + /* there is a frame in the queue and no timer so + * start a timer to ensure that the frame doesn't remain + * stuck forever. */ + p_aggr->timerScheduled = true; + A_TIMEOUT_MS(&p_aggr->timer, AGGR_RX_TIMEOUT, 0); + rxtid->progress = false; + rxtid->timerMon = true; + break; + } + } + } +} + +/* + * aggr_reset_state -- Called when it is deemed necessary to clear the aggregate + * hold Q state. Examples include when a Connect event or disconnect event is + * received. + */ +void +aggr_reset_state(void *cntxt) +{ + u8 tid; + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + + A_ASSERT(p_aggr); + + for(tid=0 ; tidaggr == false || + rxtid->timerMon == false || + rxtid->progress == true) { + continue; + } + // dequeue all frames in for this tid + stats->num_timeouts++; + A_PRINTF("TO: st %d end %d\n", rxtid->seq_next, ((rxtid->seq_next + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO)); + aggr_deque_frms(p_aggr, i, 0, ALL_SEQNO); + } + + p_aggr->timerScheduled = false; + // determine whether a new timer should be started. + for(i = 0; i < NUM_OF_TIDS; i++) { + rxtid = AGGR_GET_RXTID(p_aggr, i); + + if(rxtid->aggr == true && rxtid->hold_q) { + for(j = 0 ; j < rxtid->hold_q_sz ; j++) + { + if(rxtid->hold_q[j].osbuf) + { + p_aggr->timerScheduled = true; + rxtid->timerMon = true; + rxtid->progress = false; + break; + } + } + + if(j >= rxtid->hold_q_sz) { + rxtid->timerMon = false; + } + } + } + + if(p_aggr->timerScheduled) { + /* Rearm the timer*/ + A_TIMEOUT_MS(&p_aggr->timer, AGGR_RX_TIMEOUT, 0); + } + +} + +static void +aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q) +{ + void *osbuf; + + while((osbuf = A_NETBUF_DEQUEUE(q))) { + p_aggr->rx_fn(p_aggr->dev, osbuf); + } +} + +void +aggr_dump_stats(void *cntxt, PACKET_LOG **log_buf) +{ + struct aggr_info *p_aggr = (struct aggr_info *)cntxt; + struct rxtid *rxtid; + struct rxtid_stats *stats; + u8 i; + + *log_buf = &p_aggr->pkt_log; + A_PRINTF("\n\n================================================\n"); + A_PRINTF("tid: num_into_aggr, dups, oow, mpdu, amsdu, delivered, timeouts, holes, bar, seq_next\n"); + for(i = 0; i < NUM_OF_TIDS; i++) { + stats = AGGR_GET_RXTID_STATS(p_aggr, i); + rxtid = AGGR_GET_RXTID(p_aggr, i); + A_PRINTF("%d: %d %d %d %d %d %d %d %d %d : %d\n", i, stats->num_into_aggr, stats->num_dups, + stats->num_oow, stats->num_mpdu, + stats->num_amsdu, stats->num_delivered, stats->num_timeouts, + stats->num_hole, stats->num_bar, + rxtid->seq_next); + } + A_PRINTF("================================================\n\n"); + +} diff --git a/trunk/drivers/staging/ath6kl/wlan/include/ieee80211.h b/trunk/drivers/staging/ath6kl/wlan/include/ieee80211.h new file mode 100644 index 000000000000..cf47d0657e70 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/include/ieee80211.h @@ -0,0 +1,397 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _NET80211_IEEE80211_H_ +#define _NET80211_IEEE80211_H_ + +/* + * 802.11 protocol definitions. + */ +#define IEEE80211_WEP_KEYLEN 5 /* 40bit */ +#define IEEE80211_WEP_IVLEN 3 /* 24bit */ +#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */ +#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */ +#define IEEE80211_WEP_NKID 4 /* number of key ids */ + +/* + * 802.11i defines an extended IV for use with non-WEP ciphers. + * When the EXTIV bit is set in the key id byte an additional + * 4 bytes immediately follow the IV for TKIP. For CCMP the + * EXTIV bit is likewise set but the 8 bytes represent the + * CCMP header rather than IV+extended-IV. + */ +#define IEEE80211_WEP_EXTIV 0x20 +#define IEEE80211_WEP_EXTIVLEN 4 /* extended IV length */ +#define IEEE80211_WEP_MICLEN 8 /* trailing MIC */ + +#define IEEE80211_CRC_LEN 4 + +#ifdef WAPI_ENABLE +#define IEEE80211_WAPI_EXTIVLEN 10 /* extended IV length */ +#endif /* WAPI ENABLE */ + + +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ +/* is 802.11 address multicast/broadcast? */ +#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01) +#define IEEE80211_IS_BROADCAST(_a) (*(_a) == 0xFF) +#define WEP_HEADER (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN) +#define WEP_TRAILER IEEE80211_WEP_CRCLEN +#define CCMP_HEADER (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + \ + IEEE80211_WEP_EXTIVLEN) +#define CCMP_TRAILER IEEE80211_WEP_MICLEN +#define TKIP_HEADER (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + \ + IEEE80211_WEP_EXTIVLEN) +#define TKIP_TRAILER IEEE80211_WEP_CRCLEN +#define TKIP_MICLEN IEEE80211_WEP_MICLEN + + +#define IEEE80211_ADDR_EQ(addr1, addr2) \ + (memcmp(addr1, addr2, IEEE80211_ADDR_LEN) == 0) + +#define IEEE80211_ADDR_COPY(dst,src) memcpy(dst,src,IEEE80211_ADDR_LEN) + +#define IEEE80211_KEYBUF_SIZE 16 +#define IEEE80211_MICBUF_SIZE (8+8) /* space for both tx and rx */ + +/* + * NB: these values are ordered carefully; there are lots of + * of implications in any reordering. In particular beware + * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY. + */ +#define IEEE80211_CIPHER_WEP 0 +#define IEEE80211_CIPHER_TKIP 1 +#define IEEE80211_CIPHER_AES_OCB 2 +#define IEEE80211_CIPHER_AES_CCM 3 +#define IEEE80211_CIPHER_CKIP 5 +#define IEEE80211_CIPHER_CCKM_KRK 6 +#define IEEE80211_CIPHER_NONE 7 /* pseudo value */ + +#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1) + +#define IEEE80211_IS_VALID_WEP_CIPHER_LEN(len) \ + (((len) == 5) || ((len) == 13) || ((len) == 16)) + + + +/* + * generic definitions for IEEE 802.11 frames + */ +PREPACK struct ieee80211_frame { + u8 i_fc[2]; + u8 i_dur[2]; + u8 i_addr1[IEEE80211_ADDR_LEN]; + u8 i_addr2[IEEE80211_ADDR_LEN]; + u8 i_addr3[IEEE80211_ADDR_LEN]; + u8 i_seq[2]; + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ + /* see below */ +} POSTPACK; + +PREPACK struct ieee80211_qosframe { + u8 i_fc[2]; + u8 i_dur[2]; + u8 i_addr1[IEEE80211_ADDR_LEN]; + u8 i_addr2[IEEE80211_ADDR_LEN]; + u8 i_addr3[IEEE80211_ADDR_LEN]; + u8 i_seq[2]; + u8 i_qos[2]; +} POSTPACK; + +#define IEEE80211_FC0_VERSION_MASK 0x03 +#define IEEE80211_FC0_VERSION_SHIFT 0 +#define IEEE80211_FC0_VERSION_0 0x00 +#define IEEE80211_FC0_TYPE_MASK 0x0c +#define IEEE80211_FC0_TYPE_SHIFT 2 +#define IEEE80211_FC0_TYPE_MGT 0x00 +#define IEEE80211_FC0_TYPE_CTL 0x04 +#define IEEE80211_FC0_TYPE_DATA 0x08 + +#define IEEE80211_FC0_SUBTYPE_MASK 0xf0 +#define IEEE80211_FC0_SUBTYPE_SHIFT 4 +/* for TYPE_MGT */ +#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00 +#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10 +#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20 +#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30 +#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40 +#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50 +#define IEEE80211_FC0_SUBTYPE_BEACON 0x80 +#define IEEE80211_FC0_SUBTYPE_ATIM 0x90 +#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0 +#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0 +#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0 +/* for TYPE_CTL */ +#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0 +#define IEEE80211_FC0_SUBTYPE_RTS 0xb0 +#define IEEE80211_FC0_SUBTYPE_CTS 0xc0 +#define IEEE80211_FC0_SUBTYPE_ACK 0xd0 +#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0 +#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0 +/* for TYPE_DATA (bit combination) */ +#define IEEE80211_FC0_SUBTYPE_DATA 0x00 +#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10 +#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20 +#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30 +#define IEEE80211_FC0_SUBTYPE_NODATA 0x40 +#define IEEE80211_FC0_SUBTYPE_CFACK 0x50 +#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60 +#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70 +#define IEEE80211_FC0_SUBTYPE_QOS 0x80 +#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0 + +#define IEEE80211_FC1_DIR_MASK 0x03 +#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */ +#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */ +#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */ +#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */ + +#define IEEE80211_FC1_MORE_FRAG 0x04 +#define IEEE80211_FC1_RETRY 0x08 +#define IEEE80211_FC1_PWR_MGT 0x10 +#define IEEE80211_FC1_MORE_DATA 0x20 +#define IEEE80211_FC1_WEP 0x40 +#define IEEE80211_FC1_ORDER 0x80 + +#define IEEE80211_SEQ_FRAG_MASK 0x000f +#define IEEE80211_SEQ_FRAG_SHIFT 0 +#define IEEE80211_SEQ_SEQ_MASK 0xfff0 +#define IEEE80211_SEQ_SEQ_SHIFT 4 + +#define IEEE80211_NWID_LEN 32 + +/* + * 802.11 rate set. + */ +#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */ +#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */ + +#define WMM_NUM_AC 4 /* 4 AC categories */ + +#define WMM_PARAM_ACI_M 0x60 /* Mask for ACI field */ +#define WMM_PARAM_ACI_S 5 /* Shift for ACI field */ +#define WMM_PARAM_ACM_M 0x10 /* Mask for ACM bit */ +#define WMM_PARAM_ACM_S 4 /* Shift for ACM bit */ +#define WMM_PARAM_AIFSN_M 0x0f /* Mask for aifsn field */ +#define WMM_PARAM_LOGCWMIN_M 0x0f /* Mask for CwMin field (in log) */ +#define WMM_PARAM_LOGCWMAX_M 0xf0 /* Mask for CwMax field (in log) */ +#define WMM_PARAM_LOGCWMAX_S 4 /* Shift for CwMax field */ + +#define WMM_AC_TO_TID(_ac) ( \ + ((_ac) == WMM_AC_VO) ? 6 : \ + ((_ac) == WMM_AC_VI) ? 5 : \ + ((_ac) == WMM_AC_BK) ? 1 : \ + 0) + +#define TID_TO_WMM_AC(_tid) ( \ + ((_tid) < 1) ? WMM_AC_BE : \ + ((_tid) < 3) ? WMM_AC_BK : \ + ((_tid) < 6) ? WMM_AC_VI : \ + WMM_AC_VO) +/* + * Management information element payloads. + */ + +enum { + IEEE80211_ELEMID_SSID = 0, + IEEE80211_ELEMID_RATES = 1, + IEEE80211_ELEMID_FHPARMS = 2, + IEEE80211_ELEMID_DSPARMS = 3, + IEEE80211_ELEMID_CFPARMS = 4, + IEEE80211_ELEMID_TIM = 5, + IEEE80211_ELEMID_IBSSPARMS = 6, + IEEE80211_ELEMID_COUNTRY = 7, + IEEE80211_ELEMID_CHALLENGE = 16, + /* 17-31 reserved for challenge text extension */ + IEEE80211_ELEMID_PWRCNSTR = 32, + IEEE80211_ELEMID_PWRCAP = 33, + IEEE80211_ELEMID_TPCREQ = 34, + IEEE80211_ELEMID_TPCREP = 35, + IEEE80211_ELEMID_SUPPCHAN = 36, + IEEE80211_ELEMID_CHANSWITCH = 37, + IEEE80211_ELEMID_MEASREQ = 38, + IEEE80211_ELEMID_MEASREP = 39, + IEEE80211_ELEMID_QUIET = 40, + IEEE80211_ELEMID_IBSSDFS = 41, + IEEE80211_ELEMID_ERP = 42, + IEEE80211_ELEMID_HTCAP_ANA = 45, /* Address ANA, and non-ANA story, for interop. CL#171733 */ + IEEE80211_ELEMID_RSN = 48, + IEEE80211_ELEMID_XRATES = 50, + IEEE80211_ELEMID_HTINFO_ANA = 61, +#ifdef WAPI_ENABLE + IEEE80211_ELEMID_WAPI = 68, +#endif + IEEE80211_ELEMID_TPC = 150, + IEEE80211_ELEMID_CCKM = 156, + IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ +}; + +#define ATH_OUI 0x7f0300 /* Atheros OUI */ +#define ATH_OUI_TYPE 0x01 +#define ATH_OUI_SUBTYPE 0x01 +#define ATH_OUI_VERSION 0x00 + +#define WPA_OUI 0xf25000 +#define WPA_OUI_TYPE 0x01 +#define WPA_VERSION 1 /* current supported version */ + +#define WPA_CSE_NULL 0x00 +#define WPA_CSE_WEP40 0x01 +#define WPA_CSE_TKIP 0x02 +#define WPA_CSE_CCMP 0x04 +#define WPA_CSE_WEP104 0x05 + +#define WPA_ASE_NONE 0x00 +#define WPA_ASE_8021X_UNSPEC 0x01 +#define WPA_ASE_8021X_PSK 0x02 + +#define RSN_OUI 0xac0f00 +#define RSN_VERSION 1 /* current supported version */ + +#define RSN_CSE_NULL 0x00 +#define RSN_CSE_WEP40 0x01 +#define RSN_CSE_TKIP 0x02 +#define RSN_CSE_WRAP 0x03 +#define RSN_CSE_CCMP 0x04 +#define RSN_CSE_WEP104 0x05 + +#define RSN_ASE_NONE 0x00 +#define RSN_ASE_8021X_UNSPEC 0x01 +#define RSN_ASE_8021X_PSK 0x02 + +#define RSN_CAP_PREAUTH 0x01 + +#define WMM_OUI 0xf25000 +#define WMM_OUI_TYPE 0x02 +#define WMM_INFO_OUI_SUBTYPE 0x00 +#define WMM_PARAM_OUI_SUBTYPE 0x01 +#define WMM_VERSION 1 + +/* WMM stream classes */ +#define WMM_NUM_AC 4 +#define WMM_AC_BE 0 /* best effort */ +#define WMM_AC_BK 1 /* background */ +#define WMM_AC_VI 2 /* video */ +#define WMM_AC_VO 3 /* voice */ + +/* TSPEC related */ +#define ACTION_CATEGORY_CODE_TSPEC 17 +#define ACTION_CODE_TSPEC_ADDTS 0 +#define ACTION_CODE_TSPEC_ADDTS_RESP 1 +#define ACTION_CODE_TSPEC_DELTS 2 + +typedef enum { + TSPEC_STATUS_CODE_ADMISSION_ACCEPTED = 0, + TSPEC_STATUS_CODE_ADDTS_INVALID_PARAMS = 0x1, + TSPEC_STATUS_CODE_ADDTS_REQUEST_REFUSED = 0x3, + TSPEC_STATUS_CODE_UNSPECIFIED_QOS_RELATED_FAILURE = 0xC8, + TSPEC_STATUS_CODE_REQUESTED_REFUSED_POLICY_CONFIGURATION = 0xC9, + TSPEC_STATUS_CODE_INSUFFCIENT_BANDWIDTH = 0xCA, + TSPEC_STATUS_CODE_INVALID_PARAMS = 0xCB, + TSPEC_STATUS_CODE_DELTS_SENT = 0x30, + TSPEC_STATUS_CODE_DELTS_RECV = 0x31, +} TSPEC_STATUS_CODE; + +#define TSPEC_TSID_MASK 0xF +#define TSPEC_TSID_S 1 + +/* + * WMM/802.11e Tspec Element + */ +typedef PREPACK struct wmm_tspec_ie_t { + u8 elementId; + u8 len; + u8 oui[3]; + u8 ouiType; + u8 ouiSubType; + u8 version; + u16 tsInfo_info; + u8 tsInfo_reserved; + u16 nominalMSDU; + u16 maxMSDU; + u32 minServiceInt; + u32 maxServiceInt; + u32 inactivityInt; + u32 suspensionInt; + u32 serviceStartTime; + u32 minDataRate; + u32 meanDataRate; + u32 peakDataRate; + u32 maxBurstSize; + u32 delayBound; + u32 minPhyRate; + u16 sba; + u16 mediumTime; +} POSTPACK WMM_TSPEC_IE; + + +/* + * BEACON management packets + * + * octet timestamp[8] + * octet beacon interval[2] + * octet capability information[2] + * information element + * octet elemid + * octet length + * octet information[length] + */ + +#define IEEE80211_BEACON_INTERVAL(beacon) \ + ((beacon)[8] | ((beacon)[9] << 8)) +#define IEEE80211_BEACON_CAPABILITY(beacon) \ + ((beacon)[10] | ((beacon)[11] << 8)) + +#define IEEE80211_CAPINFO_ESS 0x0001 +#define IEEE80211_CAPINFO_IBSS 0x0002 +#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004 +#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008 +#define IEEE80211_CAPINFO_PRIVACY 0x0010 +#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020 +#define IEEE80211_CAPINFO_PBCC 0x0040 +#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080 +/* bits 8-9 are reserved */ +#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400 +#define IEEE80211_CAPINFO_APSD 0x0800 +/* bit 12 is reserved */ +#define IEEE80211_CAPINFO_DSSSOFDM 0x2000 +/* bits 14-15 are reserved */ + +/* + * Authentication Modes + */ + +enum ieee80211_authmode { + IEEE80211_AUTH_NONE = 0, + IEEE80211_AUTH_OPEN = 1, + IEEE80211_AUTH_SHARED = 2, + IEEE80211_AUTH_8021X = 3, + IEEE80211_AUTH_AUTO = 4, /* auto-select/accept */ + /* NB: these are used only for ioctls */ + IEEE80211_AUTH_WPA = 5, /* WPA/RSN w/ 802.1x */ + IEEE80211_AUTH_WPA_PSK = 6, /* WPA/RSN w/ PSK */ + IEEE80211_AUTH_WPA_CCKM = 7, /* WPA/RSN IE w/ CCKM */ +}; + +#define IEEE80211_PS_MAX_QUEUE 50 /*Maximum no of buffers that can be queues for PS*/ + +#endif /* _NET80211_IEEE80211_H_ */ diff --git a/trunk/drivers/staging/ath6kl/wlan/include/ieee80211_node.h b/trunk/drivers/staging/ath6kl/wlan/include/ieee80211_node.h new file mode 100644 index 000000000000..1cb01671c0d3 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/include/ieee80211_node.h @@ -0,0 +1,93 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// Author(s): ="Atheros" +//============================================================================== +#ifndef _IEEE80211_NODE_H_ +#define _IEEE80211_NODE_H_ + +/* + * Node locking definitions. + */ +#define IEEE80211_NODE_LOCK_INIT(_nt) A_MUTEX_INIT(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_DESTROY(_nt) if (A_IS_MUTEX_VALID(&(_nt)->nt_nodelock)) { \ + A_MUTEX_DELETE(&(_nt)->nt_nodelock); } + +#define IEEE80211_NODE_LOCK(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_UNLOCK(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_BH(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_UNLOCK_BH(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_ASSERT(_nt) + +/* + * Node reference counting definitions. + * + * ieee80211_node_initref initialize the reference count to 1 + * ieee80211_node_incref add a reference + * ieee80211_node_decref remove a reference + * ieee80211_node_dectestref remove a reference and return 1 if this + * is the last reference, otherwise 0 + * ieee80211_node_refcnt reference count for printing (only) + */ +#define ieee80211_node_initref(_ni) ((_ni)->ni_refcnt = 1) +#define ieee80211_node_incref(_ni) ((_ni)->ni_refcnt++) +#define ieee80211_node_decref(_ni) ((_ni)->ni_refcnt--) +#define ieee80211_node_dectestref(_ni) (((_ni)->ni_refcnt--) == 1) +#define ieee80211_node_refcnt(_ni) ((_ni)->ni_refcnt) + +#define IEEE80211_NODE_HASHSIZE 32 +/* simple hash is enough for variation of macaddr */ +#define IEEE80211_NODE_HASH(addr) \ + (((const u8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \ + IEEE80211_NODE_HASHSIZE) + +/* + * Table of ieee80211_node instances. Each ieee80211com + * has at least one for holding the scan candidates. + * When operating as an access point or in ibss mode there + * is a second table for associated stations or neighbors. + */ +struct ieee80211_node_table { + void *nt_wmip; /* back reference */ + A_MUTEX_T nt_nodelock; /* on node table */ + struct bss *nt_node_first; /* information of all nodes */ + struct bss *nt_node_last; /* information of all nodes */ + struct bss *nt_hash[IEEE80211_NODE_HASHSIZE]; + const char *nt_name; /* for debugging */ + u32 nt_scangen; /* gen# for timeout scan */ +#ifdef THREAD_X + A_TIMER nt_inact_timer; + u8 isTimerArmed; /* is the node timer armed */ +#endif + u32 nt_nodeAge; /* node aging time */ +#ifdef OS_ROAM_MANAGEMENT + u32 nt_si_gen; /* gen# for scan indication*/ +#endif +}; + +#ifdef THREAD_X +#define WLAN_NODE_INACT_TIMEOUT_MSEC 20000 +#else +#define WLAN_NODE_INACT_TIMEOUT_MSEC 120000 +#endif + +#define WLAN_NODE_INACT_CNT 4 + +#endif /* _IEEE80211_NODE_H_ */ diff --git a/trunk/drivers/staging/ath6kl/wlan/src/wlan_node.c b/trunk/drivers/staging/ath6kl/wlan/src/wlan_node.c new file mode 100644 index 000000000000..0fe5f4b1346c --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/src/wlan_node.c @@ -0,0 +1,636 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// IEEE 802.11 node handling support. +// +// Author(s): ="Atheros" +//============================================================================== +#include +#include +#include +#define ATH_MODULE_NAME wlan +#include +#include "htc.h" +#include "htc_api.h" +#include +#include +#include +#include +#include + +#define ATH_DEBUG_WLAN ATH_DEBUG_MAKE_MODULE_MASK(0) + +#ifdef ATH_DEBUG_MODULE + +static struct ath_debug_mask_description wlan_debug_desc[] = { + { ATH_DEBUG_WLAN , "General WLAN Node Tracing"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(wlan, + "wlan", + "WLAN Node Management", + ATH_DEBUG_MASK_DEFAULTS, + ATH_DEBUG_DESCRIPTION_COUNT(wlan_debug_desc), + wlan_debug_desc); + +#endif + +#ifdef THREAD_X +static void wlan_node_timeout(unsigned long arg); +#endif + +static bss_t * _ieee80211_find_node (struct ieee80211_node_table *nt, + const u8 *macaddr); + +bss_t * +wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size) +{ + bss_t *ni; + + ni = A_MALLOC_NOWAIT(sizeof(bss_t)); + + if (ni != NULL) { + if (wh_size) + { + ni->ni_buf = A_MALLOC_NOWAIT(wh_size); + if (ni->ni_buf == NULL) { + kfree(ni); + ni = NULL; + return ni; + } + } + } else { + return ni; + } + + /* Make sure our lists are clean */ + ni->ni_list_next = NULL; + ni->ni_list_prev = NULL; + ni->ni_hash_next = NULL; + ni->ni_hash_prev = NULL; + + // + // ni_scangen never initialized before and during suspend/resume of winmobile, + // that some junk has been stored in this, due to this scan list didn't properly updated + // + ni->ni_scangen = 0; + +#ifdef OS_ROAM_MANAGEMENT + ni->ni_si_gen = 0; +#endif + + return ni; +} + +void +wlan_node_free(bss_t *ni) +{ + if (ni->ni_buf != NULL) { + kfree(ni->ni_buf); + } + kfree(ni); +} + +void +wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni, + const u8 *macaddr) +{ + int hash; + u32 timeoutValue = 0; + + memcpy(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN); + hash = IEEE80211_NODE_HASH (macaddr); + ieee80211_node_initref (ni); /* mark referenced */ + + timeoutValue = nt->nt_nodeAge; + + ni->ni_tstamp = A_GET_MS (0); + ni->ni_actcnt = WLAN_NODE_INACT_CNT; + + IEEE80211_NODE_LOCK_BH(nt); + + /* Insert at the end of the node list */ + ni->ni_list_next = NULL; + ni->ni_list_prev = nt->nt_node_last; + if(nt->nt_node_last != NULL) + { + nt->nt_node_last->ni_list_next = ni; + } + nt->nt_node_last = ni; + if(nt->nt_node_first == NULL) + { + nt->nt_node_first = ni; + } + + /* Insert into the hash list i.e. the bucket */ + if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL) + { + nt->nt_hash[hash]->ni_hash_prev = ni; + } + ni->ni_hash_prev = NULL; + nt->nt_hash[hash] = ni; + +#ifdef THREAD_X + if (!nt->isTimerArmed) { + A_TIMEOUT_MS(&nt->nt_inact_timer, timeoutValue, 0); + nt->isTimerArmed = true; + } +#endif + + IEEE80211_NODE_UNLOCK_BH(nt); +} + +static bss_t * +_ieee80211_find_node(struct ieee80211_node_table *nt, + const u8 *macaddr) +{ + bss_t *ni; + int hash; + + IEEE80211_NODE_LOCK_ASSERT(nt); + + hash = IEEE80211_NODE_HASH(macaddr); + for(ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) { + if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) { + ieee80211_node_incref(ni); /* mark referenced */ + return ni; + } + } + return NULL; +} + +bss_t * +wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr) +{ + bss_t *ni; + + IEEE80211_NODE_LOCK(nt); + ni = _ieee80211_find_node(nt, macaddr); + IEEE80211_NODE_UNLOCK(nt); + return ni; +} + +/* + * Reclaim a node. If this is the last reference count then + * do the normal free work. Otherwise remove it from the node + * table and mark it gone by clearing the back-reference. + */ +void +wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni) +{ + IEEE80211_NODE_LOCK(nt); + + if(ni->ni_list_prev == NULL) + { + /* First in list so fix the list head */ + nt->nt_node_first = ni->ni_list_next; + } + else + { + ni->ni_list_prev->ni_list_next = ni->ni_list_next; + } + + if(ni->ni_list_next == NULL) + { + /* Last in list so fix list tail */ + nt->nt_node_last = ni->ni_list_prev; + } + else + { + ni->ni_list_next->ni_list_prev = ni->ni_list_prev; + } + + if(ni->ni_hash_prev == NULL) + { + /* First in list so fix the list head */ + int hash; + hash = IEEE80211_NODE_HASH(ni->ni_macaddr); + nt->nt_hash[hash] = ni->ni_hash_next; + } + else + { + ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; + } + + if(ni->ni_hash_next != NULL) + { + ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; + } + wlan_node_free(ni); + + IEEE80211_NODE_UNLOCK(nt); +} + +static void +wlan_node_dec_free(bss_t *ni) +{ + if (ieee80211_node_dectestref(ni)) { + wlan_node_free(ni); + } +} + +void +wlan_free_allnodes(struct ieee80211_node_table *nt) +{ + bss_t *ni; + + while ((ni = nt->nt_node_first) != NULL) { + wlan_node_reclaim(nt, ni); + } +} + +void +wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f, + void *arg) +{ + bss_t *ni; + u32 gen; + + gen = ++nt->nt_scangen; + + IEEE80211_NODE_LOCK(nt); + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + if (ni->ni_scangen != gen) { + ni->ni_scangen = gen; + (void) ieee80211_node_incref(ni); + (*f)(arg, ni); + wlan_node_dec_free(ni); + } + } + IEEE80211_NODE_UNLOCK(nt); +} + +/* + * Node table support. + */ +void +wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt) +{ + int i; + + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN, ("node table = 0x%lx\n", (unsigned long)nt)); + IEEE80211_NODE_LOCK_INIT(nt); + + A_REGISTER_MODULE_DEBUG_INFO(wlan); + + nt->nt_node_first = nt->nt_node_last = NULL; + for(i = 0; i < IEEE80211_NODE_HASHSIZE; i++) + { + nt->nt_hash[i] = NULL; + } + +#ifdef THREAD_X + A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt); + nt->isTimerArmed = false; +#endif + nt->nt_wmip = wmip; + nt->nt_nodeAge = WLAN_NODE_INACT_TIMEOUT_MSEC; + + // + // nt_scangen never initialized before and during suspend/resume of winmobile, + // that some junk has been stored in this, due to this scan list didn't properly updated + // + nt->nt_scangen = 0; + +#ifdef OS_ROAM_MANAGEMENT + nt->nt_si_gen = 0; +#endif +} + +void +wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge) +{ + nt->nt_nodeAge = nodeAge; + return; +} +void +wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt) +{ +#ifdef THREAD_X + bss_t *bss, *nextBss; + u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false; + + wmi_get_current_bssid(nt->nt_wmip, myBssid); + + bss = nt->nt_node_first; + while (bss != NULL) + { + nextBss = bss->ni_list_next; + if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) + { + /* + * free up all but the current bss - if set + */ + wlan_node_reclaim(nt, bss); + + } + bss = nextBss; + } +#else + bss_t *bss, *nextBss; + u8 myBssid[IEEE80211_ADDR_LEN]; + u32 timeoutValue = 0; + u32 now = A_GET_MS(0); + timeoutValue = nt->nt_nodeAge; + + wmi_get_current_bssid(nt->nt_wmip, myBssid); + + bss = nt->nt_node_first; + while (bss != NULL) + { + nextBss = bss->ni_list_next; + if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) + { + + if (((now - bss->ni_tstamp) > timeoutValue) || --bss->ni_actcnt == 0) + { + /* + * free up all but the current bss - if set + */ + wlan_node_reclaim(nt, bss); + } + } + bss = nextBss; + } +#endif +} + +#ifdef THREAD_X +static void +wlan_node_timeout (unsigned long arg) +{ + struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg; + bss_t *bss, *nextBss; + u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false; + u32 timeoutValue = 0; + u32 now = A_GET_MS(0); + + timeoutValue = nt->nt_nodeAge; + + wmi_get_current_bssid(nt->nt_wmip, myBssid); + + bss = nt->nt_node_first; + while (bss != NULL) + { + nextBss = bss->ni_list_next; + if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) + { + + if ((now - bss->ni_tstamp) > timeoutValue) + { + /* + * free up all but the current bss - if set + */ + wlan_node_reclaim(nt, bss); + } + else + { + /* + * Re-arm timer, only when we have a bss other than + * current bss AND it is not aged-out. + */ + reArmTimer = true; + } + } + bss = nextBss; + } + + if (reArmTimer) + A_TIMEOUT_MS (&nt->nt_inact_timer, timeoutValue, 0); + + nt->isTimerArmed = reArmTimer; +} +#endif + +void +wlan_node_table_cleanup(struct ieee80211_node_table *nt) +{ +#ifdef THREAD_X + A_UNTIMEOUT(&nt->nt_inact_timer); + A_DELETE_TIMER(&nt->nt_inact_timer); +#endif + wlan_free_allnodes(nt); + IEEE80211_NODE_LOCK_DESTROY(nt); +} + +bss_t * +wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid, + u32 ssidLength, bool bIsWPA2, bool bMatchSSID) +{ + bss_t *ni = NULL; + u8 *pIESsid = NULL; + + IEEE80211_NODE_LOCK (nt); + + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + pIESsid = ni->ni_cie.ie_ssid; + if (pIESsid[1] <= 32) { + + // Step 1 : Check SSID + if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) { + + // + // Step 2.1 : Check MatchSSID is true, if so, return Matched SSID + // Profile, otherwise check whether WPA2 or WPA + // + if (true == bMatchSSID) { + ieee80211_node_incref (ni); /* mark referenced */ + IEEE80211_NODE_UNLOCK (nt); + return ni; + } + + // Step 2 : if SSID matches, check WPA or WPA2 + if (true == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) { + ieee80211_node_incref (ni); /* mark referenced */ + IEEE80211_NODE_UNLOCK (nt); + return ni; + } + if (false == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) { + ieee80211_node_incref(ni); /* mark referenced */ + IEEE80211_NODE_UNLOCK (nt); + return ni; + } + } + } + } + + IEEE80211_NODE_UNLOCK (nt); + + return NULL; +} + +void +wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni) +{ + IEEE80211_NODE_LOCK (nt); + wlan_node_dec_free (ni); + IEEE80211_NODE_UNLOCK (nt); +} + +void +wlan_node_remove_core (struct ieee80211_node_table *nt, bss_t *ni) +{ + if(ni->ni_list_prev == NULL) + { + /* First in list so fix the list head */ + nt->nt_node_first = ni->ni_list_next; + } + else + { + ni->ni_list_prev->ni_list_next = ni->ni_list_next; + } + + if(ni->ni_list_next == NULL) + { + /* Last in list so fix list tail */ + nt->nt_node_last = ni->ni_list_prev; + } + else + { + ni->ni_list_next->ni_list_prev = ni->ni_list_prev; + } + + if(ni->ni_hash_prev == NULL) + { + /* First in list so fix the list head */ + int hash; + hash = IEEE80211_NODE_HASH(ni->ni_macaddr); + nt->nt_hash[hash] = ni->ni_hash_next; + } + else + { + ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; + } + + if(ni->ni_hash_next != NULL) + { + ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; + } +} + +bss_t * +wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid) +{ + bss_t *bss, *nextBss; + + IEEE80211_NODE_LOCK(nt); + + bss = nt->nt_node_first; + + while (bss != NULL) + { + nextBss = bss->ni_list_next; + + if (memcmp(bssid, bss->ni_macaddr, 6) == 0) + { + wlan_node_remove_core (nt, bss); + IEEE80211_NODE_UNLOCK(nt); + return bss; + } + + bss = nextBss; + } + + IEEE80211_NODE_UNLOCK(nt); + return NULL; +} + +bss_t * +wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid, + u32 ssidLength, u32 dot11AuthMode, u32 authMode, + u32 pairwiseCryptoType, u32 grpwiseCryptoTyp) +{ + bss_t *ni = NULL; + bss_t *best_ni = NULL; + u8 *pIESsid = NULL; + + IEEE80211_NODE_LOCK (nt); + + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + pIESsid = ni->ni_cie.ie_ssid; + if (pIESsid[1] <= 32) { + + // Step 1 : Check SSID + if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) { + + if (ni->ni_cie.ie_capInfo & 0x10) + { + + if ((NULL != ni->ni_cie.ie_rsn) && (WPA2_PSK_AUTH == authMode)) + { + /* WPA2 */ + if (NULL == best_ni) + { + best_ni = ni; + } + else if (ni->ni_rssi > best_ni->ni_rssi) + { + best_ni = ni; + } + } + else if ((NULL != ni->ni_cie.ie_wpa) && (WPA_PSK_AUTH == authMode)) + { + /* WPA */ + if (NULL == best_ni) + { + best_ni = ni; + } + else if (ni->ni_rssi > best_ni->ni_rssi) + { + best_ni = ni; + } + } + else if (WEP_CRYPT == pairwiseCryptoType) + { + /* WEP */ + if (NULL == best_ni) + { + best_ni = ni; + } + else if (ni->ni_rssi > best_ni->ni_rssi) + { + best_ni = ni; + } + } + } + else + { + /* open AP */ + if ((OPEN_AUTH == authMode) && (NONE_CRYPT == pairwiseCryptoType)) + { + if (NULL == best_ni) + { + best_ni = ni; + } + else if (ni->ni_rssi > best_ni->ni_rssi) + { + best_ni = ni; + } + } + } + } + } + } + + IEEE80211_NODE_UNLOCK (nt); + + return best_ni; +} + diff --git a/trunk/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c b/trunk/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c new file mode 100644 index 000000000000..07b8313b16e8 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c @@ -0,0 +1,199 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// IEEE 802.11 input handling. +// +// Author(s): ="Atheros" +//============================================================================== + +#include "a_config.h" +#include "athdefs.h" +#include "a_osapi.h" +#include +#include +#include + +#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \ + if ((_len) < (_minlen)) { \ + return A_EINVAL; \ + } \ +} while (0) + +#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \ + if ((__elem) == NULL) { \ + return A_EINVAL; \ + } \ + if ((__elem)[1] > (__maxlen)) { \ + return A_EINVAL; \ + } \ +} while (0) + + +/* unaligned little endian access */ +#define LE_READ_2(p) \ + ((u16) \ + ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8))) + +#define LE_READ_4(p) \ + ((u32) \ + ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \ + (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24))) + + +static int __inline +iswpaoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI); +} + +static int __inline +iswmmoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI); +} + +/* unused functions for now */ +#if 0 +static int __inline +iswmmparam(const u8 *frm) +{ + return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE; +} + +static int __inline +iswmminfo(const u8 *frm) +{ + return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE; +} +#endif + +static int __inline +isatherosoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI); +} + +static int __inline +iswscoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI); +} + +int +wlan_parse_beacon(u8 *buf, int framelen, struct ieee80211_common_ie *cie) +{ + u8 *frm, *efrm; + u8 elemid_ssid = false; + + frm = buf; + efrm = (u8 *) (frm + framelen); + + /* + * beacon/probe response frame format + * [8] time stamp + * [2] beacon interval + * [2] capability information + * [tlv] ssid + * [tlv] supported rates + * [tlv] country information + * [tlv] parameter set (FH/DS) + * [tlv] erp information + * [tlv] extended supported rates + * [tlv] WMM + * [tlv] WPA or RSN + * [tlv] Atheros Advanced Capabilities + */ + IEEE80211_VERIFY_LENGTH(efrm - frm, 12); + A_MEMZERO(cie, sizeof(*cie)); + + cie->ie_tstamp = frm; frm += 8; + cie->ie_beaconInt = A_LE2CPU16(*(u16 *)frm); frm += 2; + cie->ie_capInfo = A_LE2CPU16(*(u16 *)frm); frm += 2; + cie->ie_chan = 0; + + while (frm < efrm) { + switch (*frm) { + case IEEE80211_ELEMID_SSID: + if (!elemid_ssid) { + cie->ie_ssid = frm; + elemid_ssid = true; + } + break; + case IEEE80211_ELEMID_RATES: + cie->ie_rates = frm; + break; + case IEEE80211_ELEMID_COUNTRY: + cie->ie_country = frm; + break; + case IEEE80211_ELEMID_FHPARMS: + break; + case IEEE80211_ELEMID_DSPARMS: + cie->ie_chan = frm[2]; + break; + case IEEE80211_ELEMID_TIM: + cie->ie_tim = frm; + break; + case IEEE80211_ELEMID_IBSSPARMS: + break; + case IEEE80211_ELEMID_XRATES: + cie->ie_xrates = frm; + break; + case IEEE80211_ELEMID_ERP: + if (frm[1] != 1) { + //A_PRINTF("Discarding ERP Element - Bad Len\n"); + return A_EINVAL; + } + cie->ie_erp = frm[2]; + break; + case IEEE80211_ELEMID_RSN: + cie->ie_rsn = frm; + break; + case IEEE80211_ELEMID_HTCAP_ANA: + cie->ie_htcap = frm; + break; + case IEEE80211_ELEMID_HTINFO_ANA: + cie->ie_htop = frm; + break; +#ifdef WAPI_ENABLE + case IEEE80211_ELEMID_WAPI: + cie->ie_wapi = frm; + break; +#endif + case IEEE80211_ELEMID_VENDOR: + if (iswpaoui(frm)) { + cie->ie_wpa = frm; + } else if (iswmmoui(frm)) { + cie->ie_wmm = frm; + } else if (isatherosoui(frm)) { + cie->ie_ath = frm; + } else if(iswscoui(frm)) { + cie->ie_wsc = frm; + } + break; + default: + break; + } + frm += frm[1] + 2; + } + IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE); + IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN); + + return 0; +} diff --git a/trunk/drivers/staging/ath6kl/wlan/src/wlan_utils.c b/trunk/drivers/staging/ath6kl/wlan/src/wlan_utils.c new file mode 100644 index 000000000000..bc91599d9bf6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wlan/src/wlan_utils.c @@ -0,0 +1,58 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This module implements frequently used wlan utilies +// +// Author(s): ="Atheros" +//============================================================================== +#include +#include +#include + +/* + * converts ieee channel number to frequency + */ +u16 wlan_ieee2freq(int chan) +{ + if (chan == 14) { + return 2484; + } + if (chan < 14) { /* 0-13 */ + return (2407 + (chan*5)); + } + if (chan < 27) { /* 15-26 */ + return (2512 + ((chan-15)*20)); + } + return (5000 + (chan*5)); +} + +/* + * Converts MHz frequency to IEEE channel number. + */ +u32 wlan_freq2ieee(u16 freq) +{ + if (freq == 2484) + return 14; + if (freq < 2484) + return (freq - 2407) / 5; + if (freq < 5000) + return 15 + ((freq - 2512) / 20); + return (freq - 5000) / 5; +} diff --git a/trunk/drivers/staging/ath6kl/wmi/wmi.c b/trunk/drivers/staging/ath6kl/wmi/wmi.c new file mode 100644 index 000000000000..c7b5e5cf9df7 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wmi/wmi.c @@ -0,0 +1,6444 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This module implements the hardware independent layer of the +// Wireless Module Interface (WMI) protocol. +// +// Author(s): ="Atheros" +//============================================================================== + +#include +#include +#include +#include "htc.h" +#include "htc_api.h" +#include "wmi.h" +#include +#include +#include +#include +#include "dset_api.h" +#include "wmi_host.h" +#include "a_drv.h" +#include "a_drv_api.h" +#define ATH_MODULE_NAME wmi +#include "a_debug.h" +#include "dbglog_api.h" +#include "roaming.h" +#include "cfg80211.h" + +#define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0) + +#ifdef ATH_DEBUG_MODULE + +static struct ath_debug_mask_description wmi_debug_desc[] = { + { ATH_DEBUG_WMI , "General WMI Tracing"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(wmi, + "wmi", + "Wireless Module Interface", + ATH_DEBUG_MASK_DEFAULTS, + ATH_DEBUG_DESCRIPTION_COUNT(wmi_debug_desc), + wmi_debug_desc); + +#endif + +#ifndef REXOS +#define DBGARG _A_FUNCNAME_ +#define DBGFMT "%s() : " +#define DBG_WMI ATH_DEBUG_WMI +#define DBG_ERROR ATH_DEBUG_ERR +#define DBG_WMI2 ATH_DEBUG_WMI +#define A_DPRINTF AR_DEBUG_PRINTF +#endif + +static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, + int len); + +static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_sync_point(struct wmi_t *wmip); + +static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, + int len); + +static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, + int len); +#ifdef CONFIG_HOST_DSET_SUPPORT +static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, + int len); +#endif /* CONFIG_HOST_DSET_SUPPORT */ + + +static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len); + +static int +wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len); + + +#ifdef CONFIG_HOST_TCMD_SUPPORT +static int +wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len); +#endif + +static int +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len); + +static bool +wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex); + +static int +wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int +wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len); + +static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len); + +int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId, + WMI_SYNC_FLAG syncflag); + +u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size); +u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size); + +void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); +void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); +static int wmi_send_rssi_threshold_params(struct wmi_t *wmip, + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); +static int wmi_send_snr_threshold_params(struct wmi_t *wmip, + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +static int +wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len); +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ + +static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap, + int len); + +static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap, + int len); +static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int); +static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int); +static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int); +static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len); +static int wmi_hci_event_rx(struct wmi_t *, u8 *, int); + +#ifdef WAPI_ENABLE +static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap, + int len); +#endif + +#if defined(UNDER_CE) +#if defined(NDIS51_MINIPORT) +unsigned int processDot11Hdr = 0; +#else +unsigned int processDot11Hdr = 1; +#endif +#else +extern unsigned int processDot11Hdr; +#endif + +int wps_enable; +static const s32 wmi_rateTable[][2] = { + //{W/O SGI, with SGI} + {1000, 1000}, + {2000, 2000}, + {5500, 5500}, + {11000, 11000}, + {6000, 6000}, + {9000, 9000}, + {12000, 12000}, + {18000, 18000}, + {24000, 24000}, + {36000, 36000}, + {48000, 48000}, + {54000, 54000}, + {6500, 7200}, + {13000, 14400}, + {19500, 21700}, + {26000, 28900}, + {39000, 43300}, + {52000, 57800}, + {58500, 65000}, + {65000, 72200}, + {13500, 15000}, + {27000, 30000}, + {40500, 45000}, + {54000, 60000}, + {81000, 90000}, + {108000, 120000}, + {121500, 135000}, + {135000, 150000}, + {0, 0}}; + +#define MODE_A_SUPPORT_RATE_START ((s32) 4) +#define MODE_A_SUPPORT_RATE_STOP ((s32) 11) + +#define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START +#define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP + +#define MODE_B_SUPPORT_RATE_START ((s32) 0) +#define MODE_B_SUPPORT_RATE_STOP ((s32) 3) + +#define MODE_G_SUPPORT_RATE_START ((s32) 0) +#define MODE_G_SUPPORT_RATE_STOP ((s32) 11) + +#define MODE_GHT20_SUPPORT_RATE_START ((s32) 0) +#define MODE_GHT20_SUPPORT_RATE_STOP ((s32) 19) + +#define MAX_NUMBER_OF_SUPPORT_RATES (MODE_GHT20_SUPPORT_RATE_STOP + 1) + +/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ +const u8 up_to_ac[]= { + WMM_AC_BE, + WMM_AC_BK, + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VI, + WMM_AC_VO, + WMM_AC_VO, + }; + +/* This stuff is used when we want a simple layer-3 visibility */ +typedef PREPACK struct _iphdr { + u8 ip_ver_hdrlen; /* version and hdr length */ + u8 ip_tos; /* type of service */ + u16 ip_len; /* total length */ + u16 ip_id; /* identification */ + s16 ip_off; /* fragment offset field */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u8 ip_ttl; /* time to live */ + u8 ip_p; /* protocol */ + u16 ip_sum; /* checksum */ + u8 ip_src[4]; /* source and dest address */ + u8 ip_dst[4]; +} POSTPACK iphdr; + +static s16 rssi_event_value = 0; +static s16 snr_event_value = 0; + +bool is_probe_ssid = false; + +void * +wmi_init(void *devt) +{ + struct wmi_t *wmip; + + A_REGISTER_MODULE_DEBUG_INFO(wmi); + + wmip = A_MALLOC (sizeof(struct wmi_t)); + if (wmip == NULL) { + return (NULL); + } + A_MEMZERO(wmip, sizeof(struct wmi_t )); +#ifdef THREAD_X + INIT_WMI_LOCK(wmip); +#else + A_MUTEX_INIT(&wmip->wmi_lock); +#endif + wmip->wmi_devt = devt; + wlan_node_table_init(wmip, &wmip->wmi_scan_table); + wmi_qos_state_init(wmip); + + wmip->wmi_powerMode = REC_POWER; + wmip->wmi_phyMode = WMI_11G_MODE; + + wmip->wmi_pair_crypto_type = NONE_CRYPT; + wmip->wmi_grp_crypto_type = NONE_CRYPT; + + wmip->wmi_ht_allowed[A_BAND_24GHZ] = 1; + wmip->wmi_ht_allowed[A_BAND_5GHZ] = 1; + + return (wmip); +} + +void +wmi_qos_state_init(struct wmi_t *wmip) +{ + u8 i; + + if (wmip == NULL) { + return; + } + LOCK_WMI(wmip); + + /* Initialize QoS States */ + wmip->wmi_numQoSStream = 0; + + wmip->wmi_fatPipeExists = 0; + + for (i=0; i < WMM_NUM_AC; i++) { + wmip->wmi_streamExistsForAC[i]=0; + } + + UNLOCK_WMI(wmip); + + A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1); +} + +void +wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid) +{ + A_ASSERT( eid != ENDPOINT_UNUSED); + wmip->wmi_endpoint_id = eid; +} + +HTC_ENDPOINT_ID +wmi_get_control_ep(struct wmi_t * wmip) +{ + return(wmip->wmi_endpoint_id); +} + +void +wmi_shutdown(struct wmi_t *wmip) +{ + if (wmip != NULL) { + wlan_node_table_cleanup(&wmip->wmi_scan_table); + if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) { +#ifdef THREAD_X + DELETE_WMI_LOCK(&wmip); +#else + A_MUTEX_DELETE(&wmip->wmi_lock); +#endif + } + kfree(wmip); + } +} + +/* + * performs DIX to 802.3 encapsulation for transmit packets. + * uses passed in buffer. Returns buffer or NULL if failed. + * Assumes the entire DIX header is contigous and that there is + * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers. + */ +int +wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf) +{ + u8 *datap; + u16 typeorlen; + ATH_MAC_HDR macHdr; + ATH_LLC_SNAP_HDR *llcHdr; + + A_ASSERT(osbuf != NULL); + + if (A_NETBUF_HEADROOM(osbuf) < + (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR))) + { + return A_NO_MEMORY; + } + + datap = A_NETBUF_DATA(osbuf); + + typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN); + + if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) { + /* + * packet is already in 802.3 format - return success + */ + A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG)); + return (0); + } + + /* + * Save mac fields and length to be inserted later + */ + memcpy(macHdr.dstMac, datap, ATH_MAC_LEN); + memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN); + macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) + + sizeof(ATH_LLC_SNAP_HDR)); + + /* + * Make room for LLC+SNAP headers + */ + if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) { + return A_NO_MEMORY; + } + datap = A_NETBUF_DATA(osbuf); + + memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR)); + + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); + llcHdr->dsap = 0xAA; + llcHdr->ssap = 0xAA; + llcHdr->cntl = 0x03; + llcHdr->orgCode[0] = 0x0; + llcHdr->orgCode[1] = 0x0; + llcHdr->orgCode[2] = 0x0; + llcHdr->etherType = typeorlen; + + return (0); +} + +int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS) +{ + switch(*pVersion){ + case 0: + return (0); + case WMI_META_VERSION_1: + { + WMI_TX_META_V1 *pV1= NULL; + A_ASSERT(osbuf != NULL); + if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) { + return A_NO_MEMORY; + } + + pV1 = (WMI_TX_META_V1 *)A_NETBUF_DATA(osbuf); + /* the pktID is used in conjunction with txComplete messages + * allowing the target to notify which tx requests have been + * completed and how. */ + pV1->pktID = 0; + /* the ratePolicyID allows the host to specify which rate policy + * to use for transmitting this packet. 0 means use default behavior. */ + pV1->ratePolicyID = 0; + A_ASSERT(pVersion != NULL); + /* the version must be used to populate the meta field of the WMI_DATA_HDR */ + *pVersion = WMI_META_VERSION_1; + return (0); + } + case WMI_META_VERSION_2: + { + WMI_TX_META_V2 *pV2 ; + A_ASSERT(osbuf != NULL); + if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) { + return A_NO_MEMORY; + } + pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf); + memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2)); + return (0); + } + default: + return (0); + } +} + +/* Adds a WMI data header */ +int +wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData, + WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS) +{ + WMI_DATA_HDR *dtHdr; +// u8 metaVersion = 0; + int status; + + A_ASSERT(osbuf != NULL); + + /* adds the meta data field after the wmi data hdr. If metaVersion + * is returns 0 then no meta field was added. */ + if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) { + return status; + } + + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) { + return A_NO_MEMORY; + } + + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); + A_MEMZERO(dtHdr, sizeof(WMI_DATA_HDR)); + + WMI_DATA_HDR_SET_MSG_TYPE(dtHdr, msgType); + WMI_DATA_HDR_SET_DATA_TYPE(dtHdr, data_type); + + if (bMoreData) { + WMI_DATA_HDR_SET_MORE_BIT(dtHdr); + } + + WMI_DATA_HDR_SET_META(dtHdr, metaVersion); + + dtHdr->info3 = 0; + + return (0); +} + + +u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled) +{ + u8 *datap; + u8 trafficClass = WMM_AC_BE; + u16 ipType = IP_ETHERTYPE; + WMI_DATA_HDR *dtHdr; + u8 streamExists = 0; + u8 userPriority; + u32 hdrsize, metasize; + ATH_LLC_SNAP_HDR *llcHdr; + + WMI_CREATE_PSTREAM_CMD cmd; + + A_ASSERT(osbuf != NULL); + + // + // Initialize header size + // + hdrsize = 0; + + datap = A_NETBUF_DATA(osbuf); + dtHdr = (WMI_DATA_HDR *)datap; + metasize = (WMI_DATA_HDR_GET_META(dtHdr))? WMI_MAX_TX_META_SZ : 0; + + if (!wmmEnabled) + { + /* If WMM is disabled all traffic goes as BE traffic */ + userPriority = 0; + } + else + { + if (processDot11Hdr) + { + hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32)); + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize + + hdrsize); + + + } + else + { + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize + + sizeof(ATH_MAC_HDR)); + } + + if (llcHdr->etherType == A_CPU2BE16(ipType)) + { + /* Extract the endpoint info from the TOS field in the IP header */ + + userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority); + } + else + { + userPriority = layer2Priority & 0x7; + } + } + + + /* workaround for WMM S5 */ + if ((WMM_AC_VI == wmip->wmi_traffic_class) && ((5 == userPriority) || (4 == userPriority))) + { + userPriority = 1; + } + + trafficClass = convert_userPriority_to_trafficClass(userPriority); + + WMI_DATA_HDR_SET_UP(dtHdr, userPriority); + /* lower 3-bits are 802.1d priority */ + //dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT; + + LOCK_WMI(wmip); + streamExists = wmip->wmi_fatPipeExists; + UNLOCK_WMI(wmip); + + if (!(streamExists & (1 << trafficClass))) + { + + A_MEMZERO(&cmd, sizeof(cmd)); + cmd.trafficClass = trafficClass; + cmd.userPriority = userPriority; + cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT; + /* Implicit streams are created with TSID 0xFF */ + + cmd.tsid = WMI_IMPLICIT_PSTREAM; + wmi_create_pstream_cmd(wmip, &cmd); + } + + return trafficClass; +} + +int +wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode) +{ + u8 *datap; + u16 typeorlen; + ATH_MAC_HDR macHdr; + ATH_LLC_SNAP_HDR *llcHdr; + struct ieee80211_frame *wh; + u32 hdrsize; + + A_ASSERT(osbuf != NULL); + + if (A_NETBUF_HEADROOM(osbuf) < + (sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR))) + { + return A_NO_MEMORY; + } + + datap = A_NETBUF_DATA(osbuf); + + typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN); + + if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) { +/* + * packet is already in 802.3 format - return success + */ + A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG)); + goto AddDot11Hdr; + } + + /* + * Save mac fields and length to be inserted later + */ + memcpy(macHdr.dstMac, datap, ATH_MAC_LEN); + memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN); + macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) + + sizeof(ATH_LLC_SNAP_HDR)); + + // Remove the Ethernet hdr + A_NETBUF_PULL(osbuf, sizeof(ATH_MAC_HDR)); + /* + * Make room for LLC+SNAP headers + */ + if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) { + return A_NO_MEMORY; + } + datap = A_NETBUF_DATA(osbuf); + + llcHdr = (ATH_LLC_SNAP_HDR *)(datap); + llcHdr->dsap = 0xAA; + llcHdr->ssap = 0xAA; + llcHdr->cntl = 0x03; + llcHdr->orgCode[0] = 0x0; + llcHdr->orgCode[1] = 0x0; + llcHdr->orgCode[2] = 0x0; + llcHdr->etherType = typeorlen; + +AddDot11Hdr: + /* Make room for 802.11 hdr */ + if (wmip->wmi_is_wmm_enabled) + { + hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32)); + if (A_NETBUF_PUSH(osbuf, hdrsize) != 0) + { + return A_NO_MEMORY; + } + wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf); + wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_QOS; + } + else + { + hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32)); + if (A_NETBUF_PUSH(osbuf, hdrsize) != 0) + { + return A_NO_MEMORY; + } + wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf); + wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_DATA; + } + /* Setup the SA & DA */ + IEEE80211_ADDR_COPY(wh->i_addr2, macHdr.srcMac); + + if (mode == INFRA_NETWORK) { + IEEE80211_ADDR_COPY(wh->i_addr3, macHdr.dstMac); + } + else if (mode == ADHOC_NETWORK) { + IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac); + } + + return (0); +} + +int +wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf) +{ + u8 *datap; + struct ieee80211_frame *pwh,wh; + u8 type,subtype; + ATH_LLC_SNAP_HDR *llcHdr; + ATH_MAC_HDR macHdr; + u32 hdrsize; + + A_ASSERT(osbuf != NULL); + datap = A_NETBUF_DATA(osbuf); + + pwh = (struct ieee80211_frame *)datap; + type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + + memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame)); + + /* strip off the 802.11 hdr*/ + if (subtype == IEEE80211_FC0_SUBTYPE_QOS) { + hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32)); + A_NETBUF_PULL(osbuf, hdrsize); + } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) { + A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame)); + } + + datap = A_NETBUF_DATA(osbuf); + llcHdr = (ATH_LLC_SNAP_HDR *)(datap); + + macHdr.typeOrLen = llcHdr->etherType; + A_MEMZERO(macHdr.dstMac, sizeof(macHdr.dstMac)); + A_MEMZERO(macHdr.srcMac, sizeof(macHdr.srcMac)); + + switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { + case IEEE80211_FC1_DIR_NODS: + IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1); + IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2); + break; + case IEEE80211_FC1_DIR_TODS: + IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr3); + IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2); + break; + case IEEE80211_FC1_DIR_FROMDS: + IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1); + IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr3); + break; + case IEEE80211_FC1_DIR_DSTODS: + break; + } + + // Remove the LLC Hdr. + A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)); + + // Insert the ATH MAC hdr. + + A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR)); + datap = A_NETBUF_DATA(osbuf); + + memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR)); + + return 0; +} + +/* + * performs 802.3 to DIX encapsulation for received packets. + * Assumes the entire 802.3 header is contigous. + */ +int +wmi_dot3_2_dix(void *osbuf) +{ + u8 *datap; + ATH_MAC_HDR macHdr; + ATH_LLC_SNAP_HDR *llcHdr; + + A_ASSERT(osbuf != NULL); + datap = A_NETBUF_DATA(osbuf); + + memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR)); + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); + macHdr.typeOrLen = llcHdr->etherType; + + if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) { + return A_NO_MEMORY; + } + + datap = A_NETBUF_DATA(osbuf); + + memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR)); + + return (0); +} + +/* + * Removes a WMI data header + */ +int +wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf) +{ + A_ASSERT(osbuf != NULL); + + return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR))); +} + +void +wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg) +{ + wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg); +} + +/* + * WMI Extended Event received from Target. + */ +int +wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf) +{ + WMIX_CMD_HDR *cmd; + u16 id; + u8 *datap; + u32 len; + int status = 0; + + if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) { + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + return A_ERROR; + } + + cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); + id = cmd->commandId; + + if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) { + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + return A_ERROR; + } + + datap = A_NETBUF_DATA(osbuf); + len = A_NETBUF_LEN(osbuf); + + switch (id) { + case (WMIX_DSETOPENREQ_EVENTID): + status = wmi_dset_open_req_rx(wmip, datap, len); + break; +#ifdef CONFIG_HOST_DSET_SUPPORT + case (WMIX_DSETCLOSE_EVENTID): + status = wmi_dset_close_rx(wmip, datap, len); + break; + case (WMIX_DSETDATAREQ_EVENTID): + status = wmi_dset_data_req_rx(wmip, datap, len); + break; +#endif /* CONFIG_HOST_DSET_SUPPORT */ + case (WMIX_HB_CHALLENGE_RESP_EVENTID): + wmi_hbChallengeResp_rx(wmip, datap, len); + break; + case (WMIX_DBGLOG_EVENTID): + wmi_dbglog_event_rx(wmip, datap, len); + break; +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) + case (WMIX_PROF_COUNT_EVENTID): + wmi_prof_count_rx(wmip, datap, len); + break; +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ + default: + A_DPRINTF(DBG_WMI|DBG_ERROR, + (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); + wmip->wmi_stats.cmd_id_err++; + status = A_ERROR; + break; + } + + return status; +} + +/* + * Control Path + */ +u32 cmdRecvNum; + +int +wmi_control_rx(struct wmi_t *wmip, void *osbuf) +{ + WMI_CMD_HDR *cmd; + u16 id; + u8 *datap; + u32 len, i, loggingReq; + int status = 0; + + A_ASSERT(osbuf != NULL); + if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) { + A_NETBUF_FREE(osbuf); + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + return A_ERROR; + } + + cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); + id = cmd->commandId; + + if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) { + A_NETBUF_FREE(osbuf); + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + return A_ERROR; + } + + datap = A_NETBUF_DATA(osbuf); + len = A_NETBUF_LEN(osbuf); + + loggingReq = 0; + + ar6000_get_driver_cfg(wmip->wmi_devt, + AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS, + &loggingReq); + + if(loggingReq) { + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id)); + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum)); + for(i = 0; i < len; i++) + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i])); + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n")); + } + + LOCK_WMI(wmip); + cmdRecvNum++; + UNLOCK_WMI(wmip); + + switch (id) { + case (WMI_GET_BITRATE_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG)); + status = wmi_bitrate_reply_rx(wmip, datap, len); + break; + case (WMI_GET_CHANNEL_LIST_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG)); + status = wmi_channelList_reply_rx(wmip, datap, len); + break; + case (WMI_GET_TX_PWR_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG)); + status = wmi_txPwr_reply_rx(wmip, datap, len); + break; + case (WMI_READY_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG)); + status = wmi_ready_event_rx(wmip, datap, len); + A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt); + break; + case (WMI_CONNECT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG)); + status = wmi_connect_event_rx(wmip, datap, len); + break; + case (WMI_DISCONNECT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG)); + status = wmi_disconnect_event_rx(wmip, datap, len); + break; + case (WMI_PEER_NODE_EVENTID): + A_DPRINTF (DBG_WMI, (DBGFMT "WMI_PEER_NODE_EVENTID\n", DBGARG)); + status = wmi_peer_node_event_rx(wmip, datap, len); + break; + case (WMI_TKIP_MICERR_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG)); + status = wmi_tkip_micerr_event_rx(wmip, datap, len); + break; + case (WMI_BSSINFO_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG)); + { + /* + * convert WMI_BSS_INFO_HDR2 to WMI_BSS_INFO_HDR + * Take a local copy of the WMI_BSS_INFO_HDR2 from the wmi buffer + * and reconstruct the WMI_BSS_INFO_HDR in its place + */ + WMI_BSS_INFO_HDR2 bih2; + WMI_BSS_INFO_HDR *bih; + memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2)); + + A_NETBUF_PUSH(osbuf, 4); + datap = A_NETBUF_DATA(osbuf); + len = A_NETBUF_LEN(osbuf); + bih = (WMI_BSS_INFO_HDR *)datap; + + bih->channel = bih2.channel; + bih->frameType = bih2.frameType; + bih->snr = bih2.snr; + bih->rssi = bih2.snr - 95; + bih->ieMask = bih2.ieMask; + memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN); + + status = wmi_bssInfo_event_rx(wmip, datap, len); + } + break; + case (WMI_REGDOMAIN_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG)); + status = wmi_regDomain_event_rx(wmip, datap, len); + break; + case (WMI_PSTREAM_TIMEOUT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG)); + status = wmi_pstream_timeout_event_rx(wmip, datap, len); + break; + case (WMI_NEIGHBOR_REPORT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG)); + status = wmi_neighborReport_event_rx(wmip, datap, len); + break; + case (WMI_SCAN_COMPLETE_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG)); + status = wmi_scanComplete_rx(wmip, datap, len); + break; + case (WMI_CMDERROR_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG)); + status = wmi_errorEvent_rx(wmip, datap, len); + break; + case (WMI_REPORT_STATISTICS_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG)); + status = wmi_statsEvent_rx(wmip, datap, len); + break; + case (WMI_RSSI_THRESHOLD_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG)); + status = wmi_rssiThresholdEvent_rx(wmip, datap, len); + break; + case (WMI_ERROR_REPORT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG)); + status = wmi_reportErrorEvent_rx(wmip, datap, len); + break; + case (WMI_OPT_RX_FRAME_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG)); + status = wmi_opt_frame_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_ROAM_TBL_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG)); + status = wmi_roam_tbl_event_rx(wmip, datap, len); + break; + case (WMI_EXTENSION_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG)); + status = wmi_control_rx_xtnd(wmip, osbuf); + break; + case (WMI_CAC_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG)); + status = wmi_cac_event_rx(wmip, datap, len); + break; + case (WMI_CHANNEL_CHANGE_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CHANNEL_CHANGE_EVENTID\n", DBGARG)); + status = wmi_channel_change_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_ROAM_DATA_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG)); + status = wmi_roam_data_event_rx(wmip, datap, len); + break; +#ifdef CONFIG_HOST_TCMD_SUPPORT + case (WMI_TEST_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG)); + status = wmi_tcmd_test_report_rx(wmip, datap, len); + break; +#endif + case (WMI_GET_FIXRATES_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG)); + status = wmi_ratemask_reply_rx(wmip, datap, len); + break; + case (WMI_TX_RETRY_ERR_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG)); + status = wmi_txRetryErrEvent_rx(wmip, datap, len); + break; + case (WMI_SNR_THRESHOLD_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG)); + status = wmi_snrThresholdEvent_rx(wmip, datap, len); + break; + case (WMI_LQ_THRESHOLD_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG)); + status = wmi_lqThresholdEvent_rx(wmip, datap, len); + break; + case (WMI_APLIST_EVENTID): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n")); + status = wmi_aplistEvent_rx(wmip, datap, len); + break; + case (WMI_GET_KEEPALIVE_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG)); + status = wmi_keepalive_reply_rx(wmip, datap, len); + break; + case (WMI_GET_WOW_LIST_EVENTID): + status = wmi_get_wow_list_event_rx(wmip, datap, len); + break; + case (WMI_GET_PMKID_LIST_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG)); + status = wmi_get_pmkid_list_event_rx(wmip, datap, len); + break; + case (WMI_PSPOLL_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSPOLL_EVENT\n", DBGARG)); + status = wmi_pspoll_event_rx(wmip, datap, len); + break; + case (WMI_DTIMEXPIRY_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DTIMEXPIRY_EVENT\n", DBGARG)); + status = wmi_dtimexpiry_event_rx(wmip, datap, len); + break; + case (WMI_SET_PARAMS_REPLY_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG)); + status = wmi_set_params_event_rx(wmip, datap, len); + break; + case (WMI_ADDBA_REQ_EVENTID): + status = wmi_addba_req_event_rx(wmip, datap, len); + break; + case (WMI_ADDBA_RESP_EVENTID): + status = wmi_addba_resp_event_rx(wmip, datap, len); + break; + case (WMI_DELBA_REQ_EVENTID): + status = wmi_delba_req_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_BTCOEX_CONFIG_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_CONFIG_EVENTID", DBGARG)); + status = wmi_btcoex_config_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_BTCOEX_STATS_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_STATS_EVENTID", DBGARG)); + status = wmi_btcoex_stats_event_rx(wmip, datap, len); + break; + case (WMI_TX_COMPLETE_EVENTID): + { + int index; + TX_COMPLETE_MSG_V1 *pV1; + WMI_TX_COMPLETE_EVENT *pEv = (WMI_TX_COMPLETE_EVENT *)datap; + A_PRINTF("comp: %d %d %d\n", pEv->numMessages, pEv->msgLen, pEv->msgType); + + for(index = 0 ; index < pEv->numMessages ; index++) { + pV1 = (TX_COMPLETE_MSG_V1 *)(datap + sizeof(WMI_TX_COMPLETE_EVENT) + index*sizeof(TX_COMPLETE_MSG_V1)); + A_PRINTF("msg: %d %d %d %d\n", pV1->status, pV1->pktID, pV1->rateIdx, pV1->ackFailures); + } + } + break; + case (WMI_HCI_EVENT_EVENTID): + status = wmi_hci_event_rx(wmip, datap, len); + break; +#ifdef WAPI_ENABLE + case (WMI_WAPI_REKEY_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_WAPI_REKEY_EVENTID", DBGARG)); + status = wmi_wapi_rekey_event_rx(wmip, datap, len); + break; +#endif + default: + A_DPRINTF(DBG_WMI|DBG_ERROR, + (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); + wmip->wmi_stats.cmd_id_err++; + status = A_ERROR; + break; + } + + A_NETBUF_FREE(osbuf); + + return status; +} + +/* Send a "simple" wmi command -- one with no arguments */ +static int +wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG)); +} + +/* Send a "simple" extended wmi command -- one with no arguments. + Enabling this command only if GPIO or profiling support is enabled. + This is to suppress warnings on some platforms */ +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +static int +wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send_xtnd(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG)); +} +#endif + +static int +wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap; + + if (len < sizeof(WMI_READY_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + wmip->wmi_ready = true; + A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability, + ev->sw_version, ev->abi_version); + + return 0; +} + +#define LE_READ_4(p) \ + ((u32) \ + ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \ + (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24))) + +static int __inline +iswmmoui(const u8 *frm) +{ + return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI); +} + +static int __inline +iswmmparam(const u8 *frm) +{ + return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE; +} + + +static int +wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CONNECT_EVENT *ev; + u8 *pie,*peie; + + if (len < sizeof(WMI_CONNECT_EVENT)) + { + return A_EINVAL; + } + ev = (WMI_CONNECT_EVENT *)datap; + + A_DPRINTF(DBG_WMI, + (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", + DBGARG, ev->channel, + ev->bssid[0], ev->bssid[1], ev->bssid[2], + ev->bssid[3], ev->bssid[4], ev->bssid[5])); + + memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN); + + /* initialize pointer to start of assoc rsp IEs */ + pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + + sizeof(u16) + /* capinfo*/ + sizeof(u16) + /* status Code */ + sizeof(u16) ; /* associd */ + + /* initialize pointer to end of assoc rsp IEs */ + peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen; + + while (pie < peie) + { + switch (*pie) + { + case IEEE80211_ELEMID_VENDOR: + if (iswmmoui(pie)) + { + if(iswmmparam (pie)) + { + wmip->wmi_is_wmm_enabled = true; + } + } + break; + } + + if (wmip->wmi_is_wmm_enabled) + { + break; + } + pie += pie[1] + 2; + } + + A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid, + ev->listenInterval, ev->beaconInterval, + (NETWORK_TYPE) ev->networkType, ev->beaconIeLen, + ev->assocReqLen, ev->assocRespLen, + ev->assocInfo); + + return 0; +} + +static int +wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_REG_DOMAIN_EVENT *ev; + + if (len < sizeof(*ev)) { + return A_EINVAL; + } + ev = (WMI_REG_DOMAIN_EVENT *)datap; + + A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain); + + return 0; +} + +static int +wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_NEIGHBOR_REPORT_EVENT *ev; + int numAps; + + if (len < sizeof(*ev)) { + return A_EINVAL; + } + ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap; + numAps = ev->numberOfAps; + + if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) { + return A_EINVAL; + } + + A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor); + + return 0; +} + +static int +wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_DISCONNECT_EVENT *ev; + wmip->wmi_traffic_class = 100; + + if (len < sizeof(WMI_DISCONNECT_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + ev = (WMI_DISCONNECT_EVENT *)datap; + + A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid)); + + wmip->wmi_is_wmm_enabled = false; + wmip->wmi_pair_crypto_type = NONE_CRYPT; + wmip->wmi_grp_crypto_type = NONE_CRYPT; + + A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid, + ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus); + + return 0; +} + +static int +wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_PEER_NODE_EVENT *ev; + + if (len < sizeof(WMI_PEER_NODE_EVENT)) { + return A_EINVAL; + } + ev = (WMI_PEER_NODE_EVENT *)datap; + if (ev->eventCode == PEER_NODE_JOIN_EVENT) { + A_DPRINTF (DBG_WMI, (DBGFMT "Joined node with Macaddr: ", DBGARG)); + } else if(ev->eventCode == PEER_NODE_LEAVE_EVENT) { + A_DPRINTF (DBG_WMI, (DBGFMT "left node with Macaddr: ", DBGARG)); + } + + A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr); + + return 0; +} + +static int +wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TKIP_MICERR_EVENT *ev; + + if (len < sizeof(*ev)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + ev = (WMI_TKIP_MICERR_EVENT *)datap; + A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast); + + return 0; +} + +static int +wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + bss_t *bss = NULL; + WMI_BSS_INFO_HDR *bih; + u8 *buf; + u32 nodeCachingAllowed = 1; + u8 cached_ssid_len = 0; + u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0}; + u8 beacon_ssid_len = 0; + + if (len <= sizeof(WMI_BSS_INFO_HDR)) { + return A_EINVAL; + } + + bih = (WMI_BSS_INFO_HDR *)datap; + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); + + if (bih->rssi > 0) { + if (NULL == bss) + return 0; //no node found in the table, just drop the node with incorrect RSSI + else + bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX + } + + A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len); + /* What is driver config for wlan node caching? */ + if(ar6000_get_driver_cfg(wmip->wmi_devt, + AR6000_DRIVER_CFG_GET_WLANNODECACHING, + &nodeCachingAllowed) != 0) { + wmi_node_return(wmip, bss); + return A_EINVAL; + } + + if(!nodeCachingAllowed) { + wmi_node_return(wmip, bss); + return 0; + } + + buf = datap + sizeof(WMI_BSS_INFO_HDR); + len -= sizeof(WMI_BSS_INFO_HDR); + + A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, " + "bssid \"%pM\"\n", DBGARG, bih->channel, + (unsigned char) bih->rssi, bih->bssid)); + + if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) { + wmi_node_return(wmip, bss); + return 0; + } + + if (bss != NULL) { + /* + * Free up the node. Not the most efficient process given + * we are about to allocate a new node but it is simple and should be + * adequate. + */ + + /* In case of hidden AP, beacon will not have ssid, + * but a directed probe response will have it, + * so cache the probe-resp-ssid if already present. */ + if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType)) + { + u8 *ie_ssid; + + ie_ssid = bss->ni_cie.ie_ssid; + if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0)) + { + cached_ssid_len = ie_ssid[1]; + memcpy(cached_ssid_buf, ie_ssid + 2, cached_ssid_len); + } + } + + /* + * Use the current average rssi of associated AP base on assumpiton + * 1. Most os with GUI will update RSSI by wmi_get_stats_cmd() periodically + * 2. wmi_get_stats_cmd(..) will be called when calling wmi_startscan_cmd(...) + * The average value of RSSI give end-user better feeling for instance value of scan result + * It also sync up RSSI info in GUI between scan result and RSSI signal icon + */ + if (IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) { + bih->rssi = bss->ni_rssi; + bih->snr = bss->ni_snr; + } + + wlan_node_reclaim(&wmip->wmi_scan_table, bss); + } + + /* beacon/probe response frame format + * [8] time stamp + * [2] beacon interval + * [2] capability information + * [tlv] ssid */ + beacon_ssid_len = buf[SSID_IE_LEN_INDEX]; + + /* If ssid is cached for this hidden AP, then change buffer len accordingly. */ + if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) && + (0 != cached_ssid_len) && + (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1]))) + { + len += (cached_ssid_len - beacon_ssid_len); + } + + bss = wlan_node_alloc(&wmip->wmi_scan_table, len); + if (bss == NULL) { + return A_NO_MEMORY; + } + + bss->ni_snr = bih->snr; + bss->ni_rssi = bih->rssi; + A_ASSERT(bss->ni_buf != NULL); + + /* In case of hidden AP, beacon will not have ssid, + * but a directed probe response will have it, + * so place the cached-ssid(probe-resp) in the bssinfo. */ + if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) && + (0 != cached_ssid_len) && + (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1]))) + { + u8 *ni_buf = bss->ni_buf; + int buf_len = len; + + /* copy the first 14 bytes such as + * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */ + memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1); + + ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len; + ni_buf += (SSID_IE_LEN_INDEX + 1); + + buf += (SSID_IE_LEN_INDEX + 1); + buf_len -= (SSID_IE_LEN_INDEX + 1); + + /* copy the cached ssid */ + memcpy(ni_buf, cached_ssid_buf, cached_ssid_len); + ni_buf += cached_ssid_len; + + buf += beacon_ssid_len; + buf_len -= beacon_ssid_len; + + if (cached_ssid_len > beacon_ssid_len) + buf_len -= (cached_ssid_len - beacon_ssid_len); + + /* now copy the rest of bytes */ + memcpy(ni_buf, buf, buf_len); + } + else + memcpy(bss->ni_buf, buf, len); + + bss->ni_framelen = len; + if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) { + wlan_node_free(bss); + return A_EINVAL; + } + + /* + * Update the frequency in ie_chan, overwriting of channel number + * which is done in wlan_parse_beacon + */ + bss->ni_cie.ie_chan = bih->channel; + wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); + + return 0; +} + +static int +wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + bss_t *bss; + WMI_OPT_RX_INFO_HDR *bih; + u8 *buf; + + if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) { + return A_EINVAL; + } + + bih = (WMI_OPT_RX_INFO_HDR *)datap; + buf = datap + sizeof(WMI_OPT_RX_INFO_HDR); + len -= sizeof(WMI_OPT_RX_INFO_HDR); + + A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG, + bih->bssid[4], bih->bssid[5])); + + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); + if (bss != NULL) { + /* + * Free up the node. Not the most efficient process given + * we are about to allocate a new node but it is simple and should be + * adequate. + */ + wlan_node_reclaim(&wmip->wmi_scan_table, bss); + } + + bss = wlan_node_alloc(&wmip->wmi_scan_table, len); + if (bss == NULL) { + return A_NO_MEMORY; + } + + bss->ni_snr = bih->snr; + bss->ni_cie.ie_chan = bih->channel; + A_ASSERT(bss->ni_buf != NULL); + memcpy(bss->ni_buf, buf, len); + wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); + + return 0; +} + + /* This event indicates inactivity timeout of a fatpipe(pstream) + * at the target + */ +static int +wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_PSTREAM_TIMEOUT_EVENT *ev; + + if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) { + return A_EINVAL; + } + + A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG)); + + ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap; + + /* When the pstream (fat pipe == AC) timesout, it means there were no + * thinStreams within this pstream & it got implicitly created due to + * data flow on this AC. We start the inactivity timer only for + * implicitly created pstream. Just reset the host state. + */ + /* Set the activeTsids for this AC to 0 */ + LOCK_WMI(wmip); + wmip->wmi_streamExistsForAC[ev->trafficClass]=0; + wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass); + UNLOCK_WMI(wmip); + + /*Indicate inactivity to driver layer for this fatpipe (pstream)*/ + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass); + + return 0; +} + +static int +wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_BIT_RATE_REPLY *reply; + s32 rate; + u32 sgi,index; + /* 54149: + * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY. + * since there is difference in the length and to avoid returning + * error value. + */ + if (len < sizeof(WMI_BIT_RATE_REPLY)) { + return A_EINVAL; + } + reply = (WMI_BIT_RATE_REPLY *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex)); + + if (reply->rateIndex == (s8) RATE_AUTO) { + rate = RATE_AUTO; + } else { + // the SGI state is stored as the MSb of the rateIndex + index = reply->rateIndex & 0x7f; + sgi = (reply->rateIndex & 0x80)? 1:0; + rate = wmi_rateTable[index][sgi]; + } + + A_WMI_BITRATE_RX(wmip->wmi_devt, rate); + return 0; +} + +static int +wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_FIX_RATES_REPLY *reply; + + if (len < sizeof(WMI_FIX_RATES_REPLY)) { + return A_EINVAL; + } + reply = (WMI_FIX_RATES_REPLY *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask)); + + A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask); + + return 0; +} + +static int +wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CHANNEL_LIST_REPLY *reply; + + if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) { + return A_EINVAL; + } + reply = (WMI_CHANNEL_LIST_REPLY *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels, + reply->channelList); + + return 0; +} + +static int +wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TX_PWR_REPLY *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TX_PWR_REPLY *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM); + + return 0; +} +static int +wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_GET_KEEPALIVE_CMD *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_GET_KEEPALIVE_CMD *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured); + + return 0; +} + + +static int +wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_DSETOPENREQ_EVENT *dsetopenreq; + + if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) { + return A_EINVAL; + } + dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id)); + A_WMI_DSET_OPEN_REQ(wmip->wmi_devt, + dsetopenreq->dset_id, + dsetopenreq->targ_dset_handle, + dsetopenreq->targ_reply_fn, + dsetopenreq->targ_reply_arg); + + return 0; +} + +#ifdef CONFIG_HOST_DSET_SUPPORT +static int +wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_DSETCLOSE_EVENT *dsetclose; + + if (len < sizeof(WMIX_DSETCLOSE_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + dsetclose = (WMIX_DSETCLOSE_EVENT *)datap; + A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie); + + return 0; +} + +static int +wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_DSETDATAREQ_EVENT *dsetdatareq; + + if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap; + A_WMI_DSET_DATA_REQ(wmip->wmi_devt, + dsetdatareq->access_cookie, + dsetdatareq->offset, + dsetdatareq->length, + dsetdatareq->targ_buf, + dsetdatareq->targ_reply_fn, + dsetdatareq->targ_reply_arg); + + return 0; +} +#endif /* CONFIG_HOST_DSET_SUPPORT */ + +static int +wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_SCAN_COMPLETE_EVENT *ev; + + ev = (WMI_SCAN_COMPLETE_EVENT *)datap; + if ((int)ev->status == 0) { + wlan_refresh_inactive_nodes(&wmip->wmi_scan_table); + } + A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status); + is_probe_ssid = false; + + return 0; +} + +/* + * Target is reporting a programming error. This is for + * developer aid only. Target only checks a few common violations + * and it is responsibility of host to do all error checking. + * Behavior of target after wmi error event is undefined. + * A reset is recommended. + */ +static int +wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CMD_ERROR_EVENT *ev; + + ev = (WMI_CMD_ERROR_EVENT *)datap; + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId)); + switch (ev->errorCode) { + case (INVALID_PARAM): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n")); + break; + case (ILLEGAL_STATE): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n")); + break; + case (INTERNAL_ERROR): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n")); + break; + } + + return 0; +} + + +static int +wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len); + + return 0; +} + +static int +wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_RSSI_THRESHOLD_EVENT *reply; + WMI_RSSI_THRESHOLD_VAL newThreshold; + WMI_RSSI_THRESHOLD_PARAMS_CMD cmd; + SQ_THRESHOLD_PARAMS *sq_thresh = + &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI]; + u8 upper_rssi_threshold, lower_rssi_threshold; + s16 rssi; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_RSSI_THRESHOLD_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + newThreshold = (WMI_RSSI_THRESHOLD_VAL) reply->range; + rssi = reply->rssi; + + /* + * Identify the threshold breached and communicate that to the app. After + * that install a new set of thresholds based on the signal quality + * reported by the target + */ + if (newThreshold) { + /* Upper threshold breached */ + if (rssi < sq_thresh->upper_threshold[0]) { + A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper RSSI threshold event: " + " %d\n", DBGARG, rssi)); + } else if ((rssi < sq_thresh->upper_threshold[1]) && + (rssi >= sq_thresh->upper_threshold[0])) + { + newThreshold = WMI_RSSI_THRESHOLD1_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[2]) && + (rssi >= sq_thresh->upper_threshold[1])) + { + newThreshold = WMI_RSSI_THRESHOLD2_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[3]) && + (rssi >= sq_thresh->upper_threshold[2])) + { + newThreshold = WMI_RSSI_THRESHOLD3_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[4]) && + (rssi >= sq_thresh->upper_threshold[3])) + { + newThreshold = WMI_RSSI_THRESHOLD4_ABOVE; + } else if ((rssi < sq_thresh->upper_threshold[5]) && + (rssi >= sq_thresh->upper_threshold[4])) + { + newThreshold = WMI_RSSI_THRESHOLD5_ABOVE; + } else if (rssi >= sq_thresh->upper_threshold[5]) { + newThreshold = WMI_RSSI_THRESHOLD6_ABOVE; + } + } else { + /* Lower threshold breached */ + if (rssi > sq_thresh->lower_threshold[0]) { + A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower RSSI threshold event: " + "%d %d\n", DBGARG, rssi, sq_thresh->lower_threshold[0])); + } else if ((rssi > sq_thresh->lower_threshold[1]) && + (rssi <= sq_thresh->lower_threshold[0])) + { + newThreshold = WMI_RSSI_THRESHOLD6_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[2]) && + (rssi <= sq_thresh->lower_threshold[1])) + { + newThreshold = WMI_RSSI_THRESHOLD5_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[3]) && + (rssi <= sq_thresh->lower_threshold[2])) + { + newThreshold = WMI_RSSI_THRESHOLD4_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[4]) && + (rssi <= sq_thresh->lower_threshold[3])) + { + newThreshold = WMI_RSSI_THRESHOLD3_BELOW; + } else if ((rssi > sq_thresh->lower_threshold[5]) && + (rssi <= sq_thresh->lower_threshold[4])) + { + newThreshold = WMI_RSSI_THRESHOLD2_BELOW; + } else if (rssi <= sq_thresh->lower_threshold[5]) { + newThreshold = WMI_RSSI_THRESHOLD1_BELOW; + } + } + /* Calculate and install the next set of thresholds */ + lower_rssi_threshold = ar6000_get_lower_threshold(rssi, sq_thresh, + sq_thresh->lower_threshold_valid_count); + upper_rssi_threshold = ar6000_get_upper_threshold(rssi, sq_thresh, + sq_thresh->upper_threshold_valid_count); + /* Issue a wmi command to install the thresholds */ + cmd.thresholdAbove1_Val = upper_rssi_threshold; + cmd.thresholdBelow1_Val = lower_rssi_threshold; + cmd.weight = sq_thresh->weight; + cmd.pollTime = sq_thresh->polling_interval; + + rssi_event_value = rssi; + + if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) { + A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n", + DBGARG)); + } + + A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi); + + return 0; +} + + +static int +wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TARGET_ERROR_REPORT_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal); + + return 0; +} + +static int +wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CAC_EVENT *reply; + WMM_TSPEC_IE *tspec_ie; + u16 activeTsids; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_CAC_EVENT *)datap; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) && + (reply->statusCode != TSPEC_STATUS_CODE_ADMISSION_ACCEPTED)) { + tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion); + + wmi_delete_pstream_cmd(wmip, reply->ac, + (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK); + } + else if (reply->cac_indication == CAC_INDICATION_NO_RESP) { + u8 i; + + /* following assumes that there is only one outstanding ADDTS request + when this event is received */ + LOCK_WMI(wmip); + activeTsids = wmip->wmi_streamExistsForAC[reply->ac]; + UNLOCK_WMI(wmip); + + for (i = 0; i < sizeof(activeTsids) * 8; i++) { + if ((activeTsids >> i) & 1) { + break; + } + } + if (i < (sizeof(activeTsids) * 8)) { + wmi_delete_pstream_cmd(wmip, reply->ac, i); + } + } + /* + * Ev#72990: Clear active tsids and Add missing handling + * for delete qos stream from AP + */ + else if (reply->cac_indication == CAC_INDICATION_DELETE) { + u8 tsid = 0; + + tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion); + tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK); + LOCK_WMI(wmip); + wmip->wmi_streamExistsForAC[reply->ac] &= ~(1<wmi_streamExistsForAC[reply->ac]; + UNLOCK_WMI(wmip); + + + /* Indicate stream inactivity to driver layer only if all tsids + * within this AC are deleted. + */ + if (!activeTsids) { + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, reply->ac); + wmip->wmi_fatPipeExists &= ~(1 << reply->ac); + } + } + + A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac, + reply->cac_indication, reply->statusCode, + reply->tspecSuggestion); + + return 0; +} + +static int +wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_CHANNEL_CHANGE_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_CHANNEL_CHANGE_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel, + reply->newChannel); + + return 0; +} + +static int +wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_HB_CHALLENGE_RESP_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG)); + + A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source); + + return 0; +} + +static int +wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TARGET_ROAM_TBL *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_ROAM_TBL *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply); + + return 0; +} + +static int +wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_TARGET_ROAM_DATA *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_ROAM_DATA *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply); + + return 0; +} + +static int +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt); + + return 0; +} + +static int +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_SNR_THRESHOLD_EVENT *reply; + SQ_THRESHOLD_PARAMS *sq_thresh = + &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR]; + WMI_SNR_THRESHOLD_VAL newThreshold; + WMI_SNR_THRESHOLD_PARAMS_CMD cmd; + u8 upper_snr_threshold, lower_snr_threshold; + s16 snr; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_SNR_THRESHOLD_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + newThreshold = (WMI_SNR_THRESHOLD_VAL) reply->range; + snr = reply->snr; + /* + * Identify the threshold breached and communicate that to the app. After + * that install a new set of thresholds based on the signal quality + * reported by the target + */ + if (newThreshold) { + /* Upper threshold breached */ + if (snr < sq_thresh->upper_threshold[0]) { + A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper SNR threshold event: " + "%d\n", DBGARG, snr)); + } else if ((snr < sq_thresh->upper_threshold[1]) && + (snr >= sq_thresh->upper_threshold[0])) + { + newThreshold = WMI_SNR_THRESHOLD1_ABOVE; + } else if ((snr < sq_thresh->upper_threshold[2]) && + (snr >= sq_thresh->upper_threshold[1])) + { + newThreshold = WMI_SNR_THRESHOLD2_ABOVE; + } else if ((snr < sq_thresh->upper_threshold[3]) && + (snr >= sq_thresh->upper_threshold[2])) + { + newThreshold = WMI_SNR_THRESHOLD3_ABOVE; + } else if (snr >= sq_thresh->upper_threshold[3]) { + newThreshold = WMI_SNR_THRESHOLD4_ABOVE; + } + } else { + /* Lower threshold breached */ + if (snr > sq_thresh->lower_threshold[0]) { + A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower SNR threshold event: " + "%d %d\n", DBGARG, snr, sq_thresh->lower_threshold[0])); + } else if ((snr > sq_thresh->lower_threshold[1]) && + (snr <= sq_thresh->lower_threshold[0])) + { + newThreshold = WMI_SNR_THRESHOLD4_BELOW; + } else if ((snr > sq_thresh->lower_threshold[2]) && + (snr <= sq_thresh->lower_threshold[1])) + { + newThreshold = WMI_SNR_THRESHOLD3_BELOW; + } else if ((snr > sq_thresh->lower_threshold[3]) && + (snr <= sq_thresh->lower_threshold[2])) + { + newThreshold = WMI_SNR_THRESHOLD2_BELOW; + } else if (snr <= sq_thresh->lower_threshold[3]) { + newThreshold = WMI_SNR_THRESHOLD1_BELOW; + } + } + + /* Calculate and install the next set of thresholds */ + lower_snr_threshold = ar6000_get_lower_threshold(snr, sq_thresh, + sq_thresh->lower_threshold_valid_count); + upper_snr_threshold = ar6000_get_upper_threshold(snr, sq_thresh, + sq_thresh->upper_threshold_valid_count); + + /* Issue a wmi command to install the thresholds */ + cmd.thresholdAbove1_Val = upper_snr_threshold; + cmd.thresholdBelow1_Val = lower_snr_threshold; + cmd.weight = sq_thresh->weight; + cmd.pollTime = sq_thresh->polling_interval; + + A_DPRINTF(DBG_WMI, (DBGFMT "snr: %d, threshold: %d, lower: %d, upper: %d\n" + ,DBGARG, snr, newThreshold, lower_snr_threshold, + upper_snr_threshold)); + + snr_event_value = snr; + + if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) { + A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n", + DBGARG)); + } + A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr); + + return 0; +} + +static int +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_LQ_THRESHOLD_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_LQ_THRESHOLD_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt, + (WMI_LQ_THRESHOLD_VAL) reply->range, + reply->lq); + + return 0; +} + +static int +wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + u16 ap_info_entry_size; + WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap; + WMI_AP_INFO_V1 *ap_info_v1; + u8 i; + + if (len < sizeof(WMI_APLIST_EVENT)) { + return A_EINVAL; + } + + if (ev->apListVer == APLIST_VER1) { + ap_info_entry_size = sizeof(WMI_AP_INFO_V1); + ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList; + } else { + return A_EINVAL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP)); + if (len < (int)(sizeof(WMI_APLIST_EVENT) + + (ev->numAP - 1) * ap_info_entry_size)) + { + return A_EINVAL; + } + + /* + * AP List Ver1 Contents + */ + for (i = 0; i < ev->numAP; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\ + "Channel %d\n", i, + ap_info_v1->bssid[0], ap_info_v1->bssid[1], + ap_info_v1->bssid[2], ap_info_v1->bssid[3], + ap_info_v1->bssid[4], ap_info_v1->bssid[5], + ap_info_v1->channel)); + ap_info_v1++; + } + return 0; +} + +static int +wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + u32 dropped; + + dropped = *((u32 *)datap); + datap += sizeof(dropped); + len -= sizeof(dropped); + A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len); + return 0; +} + +/* + * Called to send a wmi command. Command specific data is already built + * on osbuf and current osbuf->data points to it. + */ +int +wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, + WMI_SYNC_FLAG syncflag) +{ + int status; +#define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID)) + WMI_CMD_HDR *cHdr; + HTC_ENDPOINT_ID eid = wmip->wmi_endpoint_id; + + A_ASSERT(osbuf != NULL); + + if (syncflag >= END_WMIFLAG) { + A_NETBUF_FREE(osbuf); + return A_EINVAL; + } + + if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { + /* + * We want to make sure all data currently queued is transmitted before + * the cmd execution. Establish a new sync point. + */ + wmi_sync_point(wmip); + } + + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) { + A_NETBUF_FREE(osbuf); + return A_NO_MEMORY; + } + + cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); + cHdr->commandId = (u16) cmdId; + cHdr->info1 = 0; // added for virtual interface + + /* + * Only for OPT_TX_CMD, use BE endpoint. + */ + if (IS_OPT_TX_CMD(cmdId)) { + if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) { + A_NETBUF_FREE(osbuf); + return status; + } + eid = A_WMI_Ac2EndpointID(wmip->wmi_devt, WMM_AC_BE); + } + A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid); + + if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { + /* + * We want to make sure all new data queued waits for the command to + * execute. Establish a new sync point. + */ + wmi_sync_point(wmip); + } + return (0); +#undef IS_OPT_TX_CMD +} + +int +wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId, + WMI_SYNC_FLAG syncflag) +{ + WMIX_CMD_HDR *cHdr; + + if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) { + A_NETBUF_FREE(osbuf); + return A_NO_MEMORY; + } + + cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); + cHdr->commandId = (u32) cmdId; + + return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag); +} + +int +wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType, + DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode, + CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen, + CRYPTO_TYPE groupCrypto, u8 groupCryptoLen, + int ssidLength, u8 *ssid, + u8 *bssid, u16 channel, u32 ctrl_flags) +{ + void *osbuf; + WMI_CONNECT_CMD *cc; + wmip->wmi_traffic_class = 100; + + if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) { + return A_EINVAL; + } + if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD)); + + cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cc, sizeof(*cc)); + + if (ssidLength) + { + memcpy(cc->ssid, ssid, ssidLength); + } + + cc->ssidLength = ssidLength; + cc->networkType = netType; + cc->dot11AuthMode = dot11AuthMode; + cc->authMode = authMode; + cc->pairwiseCryptoType = pairwiseCrypto; + cc->pairwiseCryptoLen = pairwiseCryptoLen; + cc->groupCryptoType = groupCrypto; + cc->groupCryptoLen = groupCryptoLen; + cc->channel = channel; + cc->ctrl_flags = ctrl_flags; + + if (bssid != NULL) { + memcpy(cc->bssid, bssid, ATH_MAC_LEN); + } + + wmip->wmi_pair_crypto_type = pairwiseCrypto; + wmip->wmi_grp_crypto_type = groupCrypto; + + return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel) +{ + void *osbuf; + WMI_RECONNECT_CMD *cc; + wmip->wmi_traffic_class = 100; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD)); + + cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cc, sizeof(*cc)); + + cc->channel = channel; + + if (bssid != NULL) { + memcpy(cc->bssid, bssid, ATH_MAC_LEN); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_disconnect_cmd(struct wmi_t *wmip) +{ + int status; + wmip->wmi_traffic_class = 100; + + /* Bug fix for 24817(elevator bug) - the disconnect command does not + need to do a SYNC before.*/ + status = wmi_simple_cmd(wmip, WMI_DISCONNECT_CMDID); + + return status; +} + +int +wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType, + u32 forceFgScan, u32 isLegacy, + u32 homeDwellTime, u32 forceScanInterval, + s8 numChan, u16 *channelList) +{ + void *osbuf; + WMI_START_SCAN_CMD *sc; + s8 size; + + size = sizeof (*sc); + + if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) { + return A_EINVAL; + } + + if (numChan) { + if (numChan > WMI_MAX_CHANNELS) { + return A_EINVAL; + } + size += sizeof(u16) * (numChan - 1); + } + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf)); + sc->scanType = scanType; + sc->forceFgScan = forceFgScan; + sc->isLegacy = isLegacy; + sc->homeDwellTime = homeDwellTime; + sc->forceScanInterval = forceScanInterval; + sc->numChannels = numChan; + if (numChan) { + memcpy(sc->channelList, channelList, numChan * sizeof(u16)); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec, + u16 fg_end_sec, u16 bg_sec, + u16 minact_chdw_msec, u16 maxact_chdw_msec, + u16 pas_chdw_msec, + u8 shScanRatio, u8 scanCtrlFlags, + u32 max_dfsch_act_time, u16 maxact_scan_per_ssid) +{ + void *osbuf; + WMI_SCAN_PARAMS_CMD *sc; + + osbuf = A_NETBUF_ALLOC(sizeof(*sc)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*sc)); + + sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(sc, sizeof(*sc)); + sc->fg_start_period = fg_start_sec; + sc->fg_end_period = fg_end_sec; + sc->bg_period = bg_sec; + sc->minact_chdwell_time = minact_chdw_msec; + sc->maxact_chdwell_time = maxact_chdw_msec; + sc->pas_chdwell_time = pas_chdw_msec; + sc->shortScanRatio = shScanRatio; + sc->scanCtrlFlags = scanCtrlFlags; + sc->max_dfsch_act_time = max_dfsch_act_time; + sc->maxact_scan_per_ssid = maxact_scan_per_ssid; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask) +{ + void *osbuf; + WMI_BSS_FILTER_CMD *cmd; + + if (filter >= LAST_BSS_FILTER) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->bssFilter = filter; + cmd->ieMask = ieMask; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag, + u8 ssidLength, u8 *ssid) +{ + void *osbuf; + WMI_PROBED_SSID_CMD *cmd; + + if (index > MAX_PROBED_SSID_INDEX) { + return A_EINVAL; + } + if (ssidLength > sizeof(cmd->ssid)) { + return A_EINVAL; + } + if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) { + return A_EINVAL; + } + if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) { + return A_EINVAL; + } + + if (flag & SPECIFIC_SSID_FLAG) { + is_probe_ssid = true; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->entryIndex = index; + cmd->flag = flag; + cmd->ssidLength = ssidLength; + memcpy(cmd->ssid, ssid, ssidLength); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons) +{ + void *osbuf; + WMI_LISTEN_INT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->listenInterval = listenInterval; + cmd->numBeacons = listenBeacons; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons) +{ + void *osbuf; + WMI_BMISS_TIME_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->bmissTime = bmissTime; + cmd->numBeacons = bmissBeacons; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType, + u8 ieLen, u8 *ieInfo) +{ + void *osbuf; + WMI_SET_ASSOC_INFO_CMD *cmd; + u16 cmdLen; + + cmdLen = sizeof(*cmd) + ieLen - 1; + osbuf = A_NETBUF_ALLOC(cmdLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, cmdLen); + + cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, cmdLen); + cmd->ieType = ieType; + cmd->bufferSize = ieLen; + memcpy(cmd->assocInfo, ieInfo, ieLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode) +{ + void *osbuf; + WMI_POWER_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->powerMode = powerMode; + wmip->wmi_powerMode = powerMode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl, + u16 atim_windows, u16 timeout_value) +{ + void *osbuf; + WMI_IBSS_PM_CAPS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->power_saving = pmEnable; + cmd->ttl = ttl; + cmd->atim_windows = atim_windows; + cmd->timeout_value = timeout_value; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time, + u32 ps_period, u8 sleep_period) +{ + void *osbuf; + WMI_AP_PS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_AP_PS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->psType = psType; + cmd->idle_time = idle_time; + cmd->ps_period = ps_period; + cmd->sleep_period = sleep_period; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AP_PS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod, + u16 psPollNum, u16 dtimPolicy, + u16 tx_wakeup_policy, u16 num_tx_to_wakeup, + u16 ps_fail_event_policy) +{ + void *osbuf; + WMI_POWER_PARAMS_CMD *pm; + + osbuf = A_NETBUF_ALLOC(sizeof(*pm)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*pm)); + + pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(pm, sizeof(*pm)); + pm->idle_period = idlePeriod; + pm->pspoll_number = psPollNum; + pm->dtim_policy = dtimPolicy; + pm->tx_wakeup_policy = tx_wakeup_policy; + pm->num_tx_to_wakeup = num_tx_to_wakeup; + pm->ps_fail_event_policy = ps_fail_event_policy; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout) +{ + void *osbuf; + WMI_DISC_TIMEOUT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->disconnectTimeout = timeout; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType, + u8 keyUsage, u8 keyLength, u8 *keyRSC, + u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr, + WMI_SYNC_FLAG sync_flag) +{ + void *osbuf; + WMI_ADD_CIPHER_KEY_CMD *cmd; + + if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) || + (keyMaterial == NULL)) + { + return A_EINVAL; + } + + if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->keyIndex = keyIndex; + cmd->keyType = keyType; + cmd->keyUsage = keyUsage; + cmd->keyLength = keyLength; + memcpy(cmd->key, keyMaterial, keyLength); +#ifdef WAPI_ENABLE + if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) { +#else + if (NULL != keyRSC) { +#endif // WAPI_ENABLE + memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC)); + } + cmd->key_op_ctrl = key_op_ctrl; + + if(macAddr) { + memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag)); +} + +int +wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk) +{ + void *osbuf; + WMI_ADD_KRK_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + memcpy(cmd->krk, krk, WMI_KRK_LEN); + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_delete_krk_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID); +} + +int +wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex) +{ + void *osbuf; + WMI_DELETE_CIPHER_KEY_CMD *cmd; + + if (keyIndex > WMI_MAX_KEY_INDEX) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->keyIndex = keyIndex; + + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId, + bool set) +{ + void *osbuf; + WMI_SET_PMKID_CMD *cmd; + + if (bssid == NULL) { + return A_EINVAL; + } + + if ((set == true) && (pmkId == NULL)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf)); + memcpy(cmd->bssid, bssid, sizeof(cmd->bssid)); + if (set == true) { + memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid)); + cmd->enable = PMKID_ENABLE; + } else { + A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid)); + cmd->enable = PMKID_DISABLE; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en) +{ + void *osbuf; + WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_akmp_params_cmd(struct wmi_t *wmip, + WMI_SET_AKMP_PARAMS_CMD *akmpParams) +{ + void *osbuf; + WMI_SET_AKMP_PARAMS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->akmpInfo = akmpParams->akmpInfo; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_pmkid_list_cmd(struct wmi_t *wmip, + WMI_SET_PMKID_LIST_CMD *pmkInfo) +{ + void *osbuf; + WMI_SET_PMKID_LIST_CMD *cmd; + u16 cmdLen; + u8 i; + + cmdLen = sizeof(pmkInfo->numPMKID) + + pmkInfo->numPMKID * sizeof(WMI_PMKID); + + osbuf = A_NETBUF_ALLOC(cmdLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, cmdLen); + cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->numPMKID = pmkInfo->numPMKID; + + for (i = 0; i < cmd->numPMKID; i++) { + memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i], + WMI_PMKID_LEN); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_get_pmkid_list_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID); +} + +int +wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid) +{ + WMI_DATA_HDR *dtHdr; + + A_ASSERT( eid != wmip->wmi_endpoint_id); + A_ASSERT(osbuf != NULL); + + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) { + return A_NO_MEMORY; + } + + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); + dtHdr->info = + (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT; + + dtHdr->info3 = 0; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - eid %d\n", DBGARG, eid)); + + return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid)); +} + +typedef struct _WMI_DATA_SYNC_BUFS { + u8 trafficClass; + void *osbuf; +}WMI_DATA_SYNC_BUFS; + +static int +wmi_sync_point(struct wmi_t *wmip) +{ + void *cmd_osbuf; + WMI_SYNC_CMD *cmd; + WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC]; + u8 i,numPriStreams=0; + int status = 0; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + memset(dataSyncBufs,0,sizeof(dataSyncBufs)); + + /* lock out while we walk through the priority list and assemble our local array */ + LOCK_WMI(wmip); + + for (i=0; i < WMM_NUM_AC ; i++) { + if (wmip->wmi_fatPipeExists & (1 << i)) { + numPriStreams++; + dataSyncBufs[numPriStreams-1].trafficClass = i; + } + } + + UNLOCK_WMI(wmip); + + /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */ + + do { + /* + * We allocate all network buffers needed so we will be able to + * send all required frames. + */ + cmd_osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (cmd_osbuf == NULL) { + status = A_NO_MEMORY; + break; + } + + A_NETBUF_PUT(cmd_osbuf, sizeof(*cmd)); + + cmd = (WMI_SYNC_CMD *)(A_NETBUF_DATA(cmd_osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + /* In the SYNC cmd sent on the control Ep, send a bitmap of the data + * eps on which the Data Sync will be sent + */ + cmd->dataSyncMap = wmip->wmi_fatPipeExists; + + for (i=0; i < numPriStreams ; i++) { + dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0); + if (dataSyncBufs[i].osbuf == NULL) { + status = A_NO_MEMORY; + break; + } + } //end for + + /* if Buffer allocation for any of the dataSync fails, then do not + * send the Synchronize cmd on the control ep + */ + if (status) { + break; + } + + /* + * Send sync cmd followed by sync data messages on all endpoints being + * used + */ + status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID, + NO_SYNC_WMIFLAG); + + if (status) { + break; + } + /* cmd buffer sent, we no longer own it */ + cmd_osbuf = NULL; + + for(i=0; i < numPriStreams; i++) { + A_ASSERT(dataSyncBufs[i].osbuf != NULL); + status = wmi_dataSync_send(wmip, + dataSyncBufs[i].osbuf, + A_WMI_Ac2EndpointID(wmip->wmi_devt, + dataSyncBufs[i]. + trafficClass) + ); + + if (status) { + break; + } + /* we don't own this buffer anymore, NULL it out of the array so it + * won't get cleaned up */ + dataSyncBufs[i].osbuf = NULL; + } //end for + + } while(false); + + /* free up any resources left over (possibly due to an error) */ + + if (cmd_osbuf != NULL) { + A_NETBUF_FREE(cmd_osbuf); + } + + for (i = 0; i < numPriStreams; i++) { + if (dataSyncBufs[i].osbuf != NULL) { + A_NETBUF_FREE(dataSyncBufs[i].osbuf); + } + } + + return (status); +} + +int +wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params) +{ + void *osbuf; + WMI_CREATE_PSTREAM_CMD *cmd; + u8 fatPipeExistsForAC=0; + s32 minimalPHY = 0; + s32 nominalPHY = 0; + + /* Validate all the parameters. */ + if( !((params->userPriority < 8) && + (params->userPriority <= 0x7) && + (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) && + (params->trafficDirection == UPLINK_TRAFFIC || + params->trafficDirection == DNLINK_TRAFFIC || + params->trafficDirection == BIDIR_TRAFFIC) && + (params->trafficType == TRAFFIC_TYPE_APERIODIC || + params->trafficType == TRAFFIC_TYPE_PERIODIC ) && + (params->voicePSCapability == DISABLE_FOR_THIS_AC || + params->voicePSCapability == ENABLE_FOR_THIS_AC || + params->voicePSCapability == ENABLE_FOR_ALL_AC) && + (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) ) + { + return A_EINVAL; + } + + // + // check nominal PHY rate is >= minimalPHY, so that DUT + // can allow TSRS IE + // + + // get the physical rate + minimalPHY = ((params->minPhyRate / 1000)/1000); // unit of bps + + // check minimal phy < nominal phy rate + // + if (params->nominalPHY >= minimalPHY) + { + nominalPHY = (params->nominalPHY * 1000)/500; // unit of 500 kbps + A_DPRINTF(DBG_WMI, + (DBGFMT "TSRS IE Enabled::MinPhy %x->NominalPhy ===> %x\n", DBGARG, + minimalPHY, nominalPHY)); + + params->nominalPHY = nominalPHY; + } + else + { + params->nominalPHY = 0; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + A_DPRINTF(DBG_WMI, + (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG, + params->trafficClass, params->tsid)); + + cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + memcpy(cmd, params, sizeof(*cmd)); + + /* this is an implicitly created Fat pipe */ + if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) { + LOCK_WMI(wmip); + fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); + wmip->wmi_fatPipeExists |= (1<trafficClass); + UNLOCK_WMI(wmip); + } else { + /* this is an explicitly created thin stream within a fat pipe */ + LOCK_WMI(wmip); + fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); + wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<tsid); + /* if a thinstream becomes active, the fat pipe automatically + * becomes active + */ + wmip->wmi_fatPipeExists |= (1<trafficClass); + UNLOCK_WMI(wmip); + } + + /* Indicate activty change to driver layer only if this is the + * first TSID to get created in this AC explicitly or an implicit + * fat pipe is getting created. + */ + if (!fatPipeExistsForAC) { + A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass); + } + + /* mike: should be SYNC_BEFORE_WMIFLAG */ + return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid) +{ + void *osbuf; + WMI_DELETE_PSTREAM_CMD *cmd; + int status; + u16 activeTsids=0; + + /* validate the parameters */ + if (trafficClass > 3) { + A_DPRINTF(DBG_WMI, (DBGFMT "Invalid trafficClass: %d\n", DBGARG, trafficClass)); + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->trafficClass = trafficClass; + cmd->tsid = tsid; + + LOCK_WMI(wmip); + activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; + UNLOCK_WMI(wmip); + + /* Check if the tsid was created & exists */ + if (!(activeTsids & (1<wmi_streamExistsForAC[trafficClass] &= ~(1<wmi_streamExistsForAC[trafficClass]; + UNLOCK_WMI(wmip); + + + /* Indicate stream inactivity to driver layer only if all tsids + * within this AC are deleted. + */ + if(!activeTsids) { + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass); + wmip->wmi_fatPipeExists &= ~(1< 15)){ + + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + frameType = (u8)((subType << 4) | type); + + cmd->bEnableMask = bEnable; + cmd->frameType = frameType; + cmd->frameRateMask = rateMask; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_FRAMERATES_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * used to set the bit rate. rate is in Kbps. If rate == -1 + * then auto selection is used. + */ +int +wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate) +{ + void *osbuf; + WMI_BIT_RATE_CMD *cmd; + s8 drix, mrix, crix, ret_val; + + if (dataRate != -1) { + ret_val = wmi_validate_bitrate(wmip, dataRate, &drix); + if(ret_val == A_EINVAL){ + return A_EINVAL; + } + } else { + drix = -1; + } + + if (mgmtRate != -1) { + ret_val = wmi_validate_bitrate(wmip, mgmtRate, &mrix); + if(ret_val == A_EINVAL){ + return A_EINVAL; + } + } else { + mrix = -1; + } + if (ctlRate != -1) { + ret_val = wmi_validate_bitrate(wmip, ctlRate, &crix); + if(ret_val == A_EINVAL){ + return A_EINVAL; + } + } else { + crix = -1; + } + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->rateIndex = drix; + cmd->mgmtRateIndex = mrix; + cmd->ctlRateIndex = crix; + + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_get_bitrate_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID); +} + +/* + * Returns true iff the given rate index is legal in the current PHY mode. + */ +bool +wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex) +{ + WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode; + bool isValid = true; + switch(phyMode) { + case WMI_11A_MODE: + if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){ + if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { + isValid = false; + } + } else { + if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) { + isValid = false; + } + } + break; + + case WMI_11B_MODE: + if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) { + isValid = false; + } + break; + + case WMI_11GONLY_MODE: + if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){ + if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { + isValid = false; + } + } else { + if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) { + isValid = false; + } + } + break; + + case WMI_11G_MODE: + case WMI_11AG_MODE: + if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){ + if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { + isValid = false; + } + } else { + if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) { + isValid = false; + } + } + break; + default: + A_ASSERT(false); + break; + } + + return isValid; +} + +s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx) +{ + s8 i; + + for (i=0;;i++) + { + if (wmi_rateTable[(u32) i][0] == 0) { + return A_EINVAL; + } + if (wmi_rateTable[(u32) i][0] == rate) { + break; + } + } + + if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) { + return A_EINVAL; + } + + *rate_idx = i; + return 0; +} + +int +wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask) +{ + void *osbuf; + WMI_FIX_RATES_CMD *cmd; +#if 0 + s32 rateIndex; +/* This check does not work for AR6003 as the HT modes are enabled only when + * the STA is connected to a HT_BSS and is not based only on channel. It is + * safe to skip this check however because rate control will only use rates + * that are permitted by the valid rate mask and the fix rate mask. Meaning + * the fix rate mask is not sufficient by itself to cause an invalid rate + * to be used. */ + /* Make sure all rates in the mask are valid in the current PHY mode */ + for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) { + if((1 << rateIndex) & (u32)fixRatesMask) { + if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) { + A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG)); + return A_EINVAL; + } + } + } +#endif + + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->fixRateMask = fixRatesMask; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_get_ratemask_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID); +} + +int +wmi_get_channelList_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID); +} + +/* + * used to generate a wmi sey channel Parameters cmd. + * mode should always be specified and corresponds to the phy mode of the + * wlan. + * numChan should alway sbe specified. If zero indicates that all available + * channels should be used. + * channelList is an array of channel frequencies (in Mhz) which the radio + * should limit its operation to. It should be NULL if numChan == 0. Size of + * array should correspond to numChan entries. + */ +int +wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam, + WMI_PHY_MODE mode, s8 numChan, + u16 *channelList) +{ + void *osbuf; + WMI_CHANNEL_PARAMS_CMD *cmd; + s8 size; + + size = sizeof (*cmd); + + if (numChan) { + if (numChan > WMI_MAX_CHANNELS) { + return A_EINVAL; + } + size += sizeof(u16) * (numChan - 1); + } + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + wmip->wmi_phyMode = mode; + cmd->scanParam = scanParam; + cmd->phyMode = mode; + cmd->numChannels = numChan; + memcpy(cmd->channelList, channelList, numChan * sizeof(u16)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +void +wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) +{ + SQ_THRESHOLD_PARAMS *sq_thresh = + &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI]; + /* + * Parse the command and store the threshold values here. The checks + * for valid values can be put here + */ + sq_thresh->weight = rssiCmd->weight; + sq_thresh->polling_interval = rssiCmd->pollTime; + + sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->upper_threshold_valid_count = 6; + + /* List sorted in descending order */ + sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR; + sq_thresh->lower_threshold_valid_count = 6; + + if (!rssi_event_value) { + /* + * Configuring the thresholds to their extremes allows the host to get an + * event from the target which is used for the configuring the correct + * thresholds + */ + rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0]; + rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0]; + } else { + /* + * In case the user issues multiple times of rssi_threshold_setting, + * we should not use the extreames anymore, the target does not expect that. + */ + rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh, + sq_thresh->upper_threshold_valid_count); + rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh, + sq_thresh->lower_threshold_valid_count); +} +} + +int +wmi_set_rssi_threshold_params(struct wmi_t *wmip, + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) +{ + + /* Check these values are in ascending order */ + if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val || + rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val || + rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val || + rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val || + rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val || + rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val || + rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val || + rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val || + rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val || + rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val) + { + return A_EINVAL; + } + + wmi_cache_configure_rssithreshold(wmip, rssiCmd); + + return (wmi_send_rssi_threshold_params(wmip, rssiCmd)); +} + +int +wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd) +{ + void *osbuf; + WMI_SET_IP_CMD *cmd; + + /* Multicast address are not valid */ + if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) || + (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD)); + cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf)); + memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, + WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd) +{ + void *osbuf; + s8 size; + WMI_SET_HOST_SLEEP_MODE_CMD *cmd; + u16 activeTsids=0; + u8 streamExists=0; + u8 i; + + if( hostModeCmd->awake == hostModeCmd->asleep) { + return A_EINVAL; + } + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD)); + + if(hostModeCmd->asleep) { + /* + * Relinquish credits from all implicitly created pstreams since when we + * go to sleep. If user created explicit thinstreams exists with in a + * fatpipe leave them intact for the user to delete + */ + LOCK_WMI(wmip); + streamExists = wmip->wmi_fatPipeExists; + UNLOCK_WMI(wmip); + + for(i=0;i< WMM_NUM_AC;i++) { + if (streamExists & (1<wmi_streamExistsForAC[i]; + UNLOCK_WMI(wmip); + /* If there are no user created thin streams delete the fatpipe */ + if(!activeTsids) { + streamExists &= ~(1<wmi_devt,i); + } + } + } + + /* Update the fatpipes that exists*/ + LOCK_WMI(wmip); + wmip->wmi_fatPipeExists = streamExists; + UNLOCK_WMI(wmip); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_wow_mode_cmd(struct wmi_t *wmip, + WMI_SET_WOW_MODE_CMD *wowModeCmd) +{ + void *osbuf; + s8 size; + WMI_SET_WOW_MODE_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_get_wow_list_cmd(struct wmi_t *wmip, + WMI_GET_WOW_LIST_CMD *wowListCmd) +{ + void *osbuf; + s8 size; + WMI_GET_WOW_LIST_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID, + NO_SYNC_WMIFLAG)); + +} + +static int +wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_GET_WOW_LIST_REPLY *reply; + + if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) { + return A_EINVAL; + } + reply = (WMI_GET_WOW_LIST_REPLY *)datap; + + A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters, + reply); + + return 0; +} + +int wmi_add_wow_pattern_cmd(struct wmi_t *wmip, + WMI_ADD_WOW_PATTERN_CMD *addWowCmd, + u8 *pattern, u8 *mask, + u8 pattern_size) +{ + void *osbuf; + s8 size; + WMI_ADD_WOW_PATTERN_CMD *cmd; + u8 *filter_mask = NULL; + + size = sizeof (*cmd); + + size += ((2 * addWowCmd->filter_size)* sizeof(u8)); + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->filter_list_id = addWowCmd->filter_list_id; + cmd->filter_offset = addWowCmd->filter_offset; + cmd->filter_size = addWowCmd->filter_size; + + memcpy(cmd->filter, pattern, addWowCmd->filter_size); + + filter_mask = (u8 *)(cmd->filter + cmd->filter_size); + memcpy(filter_mask, mask, addWowCmd->filter_size); + + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_del_wow_pattern_cmd(struct wmi_t *wmip, + WMI_DEL_WOW_PATTERN_CMD *delWowCmd) +{ + void *osbuf; + s8 size; + WMI_DEL_WOW_PATTERN_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID, + NO_SYNC_WMIFLAG)); + +} + +void +wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) +{ + SQ_THRESHOLD_PARAMS *sq_thresh = + &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR]; + /* + * Parse the command and store the threshold values here. The checks + * for valid values can be put here + */ + sq_thresh->weight = snrCmd->weight; + sq_thresh->polling_interval = snrCmd->pollTime; + + sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val; + sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val; + sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val; + sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val; + sq_thresh->upper_threshold_valid_count = 4; + + /* List sorted in descending order */ + sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val; + sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val; + sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val; + sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val; + sq_thresh->lower_threshold_valid_count = 4; + + if (!snr_event_value) { + /* + * Configuring the thresholds to their extremes allows the host to get an + * event from the target which is used for the configuring the correct + * thresholds + */ + snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0]; + snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0]; + } else { + /* + * In case the user issues multiple times of snr_threshold_setting, + * we should not use the extreames anymore, the target does not expect that. + */ + snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh, + sq_thresh->upper_threshold_valid_count); + snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh, + sq_thresh->lower_threshold_valid_count); + } + +} +int +wmi_set_snr_threshold_params(struct wmi_t *wmip, + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) +{ + if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val || + snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val || + snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val || + snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val || + snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val || + snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val) + { + return A_EINVAL; + } + wmi_cache_configure_snrthreshold(wmip, snrCmd); + return (wmi_send_snr_threshold_params(wmip, snrCmd)); +} + +int +wmi_clr_rssi_snr(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(sizeof(int)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_lq_threshold_params(struct wmi_t *wmip, + WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd) +{ + void *osbuf; + s8 size; + WMI_LQ_THRESHOLD_PARAMS_CMD *cmd; + /* These values are in ascending order */ + if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val || + lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val || + lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val || + lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val || + lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val || + lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) { + + return A_EINVAL; + } + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask) +{ + void *osbuf; + s8 size; + WMI_TARGET_ERROR_REPORT_BITMASK *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + cmd->bitmask = mask; + + return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source) +{ + void *osbuf; + WMIX_HB_CHALLENGE_RESP_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->cookie = cookie; + cmd->source = source; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask, + u16 tsr, bool rep, u16 size, + u32 valid) +{ + void *osbuf; + WMIX_DBGLOG_CFG_MODULE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->config.cfgmmask = mmask; + cmd->config.cfgtsr = tsr; + cmd->config.cfgrep = rep; + cmd->config.cfgsize = size; + cmd->config.cfgvalid = valid; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_get_stats_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID); +} + +int +wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid) +{ + void *osbuf; + WMI_ADD_BAD_AP_CMD *cmd; + + if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->badApIndex = apIndex; + memcpy(cmd->bssid, bssid, sizeof(cmd->bssid)); + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG)); +} + +int +wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex) +{ + void *osbuf; + WMI_DELETE_BAD_AP_CMD *cmd; + + if (apIndex > WMI_MAX_BAD_AP_INDEX) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->badApIndex = apIndex; + + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_abort_scan_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID); +} + +int +wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM) +{ + void *osbuf; + WMI_SET_TX_PWR_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->dbM = dbM; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_get_txPwr_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID); +} + +u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass) +{ + u16 activeTsids=0; + + LOCK_WMI(wmip); + activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; + UNLOCK_WMI(wmip); + + return activeTsids; +} + +int +wmi_get_roam_tbl_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID); +} + +int +wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType) +{ + void *osbuf; + u32 size = sizeof(u8); + WMI_TARGET_ROAM_DATA *cmd; + + osbuf = A_NETBUF_ALLOC(size); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf)); + cmd->roamDataType = roamDataType; + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p, + u8 size) +{ + void *osbuf; + WMI_SET_ROAM_CTRL_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + memcpy(cmd, p, size); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_powersave_timers_cmd(struct wmi_t *wmip, + WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd, + u8 size) +{ + void *osbuf; + WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd; + + /* These timers can't be zero */ + if(!pCmd->psPollTimeout || !pCmd->triggerTimeout || + !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD || + pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) || + !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD || + pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD)) + return A_EINVAL; + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + memcpy(cmd, pCmd, size); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, u8 eCWmin, + u8 eCWmax, u8 aifsn) +{ + void *osbuf; + WMI_SET_ACCESS_PARAMS_CMD *cmd; + + if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) || + (aifsn > WMI_MAX_AIFSN_ACPARAM) || (ac >= WMM_NUM_AC)) + { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->txop = txop; + cmd->eCWmin = eCWmin; + cmd->eCWmax = eCWmax; + cmd->aifsn = aifsn; + cmd->ac = ac; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType, + u8 trafficClass, u8 maxRetries, + u8 enableNotify) +{ + void *osbuf; + WMI_SET_RETRY_LIMITS_CMD *cmd; + + if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) && + (frameType != DATA_FRAMETYPE)) + { + return A_EINVAL; + } + + if (maxRetries > WMI_MAX_RETRIES) { + return A_EINVAL; + } + + if (frameType != DATA_FRAMETYPE) { + trafficClass = 0; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->frameType = frameType; + cmd->trafficClass = trafficClass; + cmd->maxRetries = maxRetries; + cmd->enableNotify = enableNotify; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID, + NO_SYNC_WMIFLAG)); +} + +void +wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid) +{ + if (bssid != NULL) { + memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN); + } +} + +int +wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode) +{ + void *osbuf; + WMI_SET_OPT_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->optMode = optMode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID, + SYNC_BOTH_WMIFLAG)); +} + +int +wmi_opt_tx_frame_cmd(struct wmi_t *wmip, + u8 frmType, + u8 *dstMacAddr, + u8 *bssid, + u16 optIEDataLen, + u8 *optIEData) +{ + void *osbuf; + WMI_OPT_TX_FRAME_CMD *cmd; + osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd))); + + cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1)); + + cmd->frmType = frmType; + cmd->optIEDataLen = optIEDataLen; + //cmd->optIEData = (u8 *)((int)cmd + sizeof(*cmd)); + memcpy(cmd->bssid, bssid, sizeof(cmd->bssid)); + memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr)); + memcpy(&cmd->optIEData[0], optIEData, optIEDataLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl) +{ + void *osbuf; + WMI_BEACON_INT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->beaconInterval = intvl; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize) +{ + void *osbuf; + WMI_SET_VOICE_PKT_SIZE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->voicePktSize = voicePktSize; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen) +{ + void *osbuf; + WMI_SET_MAX_SP_LEN_CMD *cmd; + + /* maxSPLen is a two-bit value. If user trys to set anything + * other than this, then its invalid + */ + if(maxSPLen & ~0x03) + return A_EINVAL; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->maxSPLen = maxSPLen; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID, + NO_SYNC_WMIFLAG)); +} + +u8 wmi_determine_userPriority( + u8 *pkt, + u32 layer2Pri) +{ + u8 ipPri; + iphdr *ipHdr = (iphdr *)pkt; + + /* Determine IPTOS priority */ + /* + * IP Tos format : + * (Refer Pg 57 WMM-test-plan-v1.2) + * IP-TOS - 8bits + * : DSCP(6-bits) ECN(2-bits) + * : DSCP - P2 P1 P0 X X X + * where (P2 P1 P0) form 802.1D + */ + ipPri = ipHdr->ip_tos >> 5; + ipPri &= 0x7; + + if ((layer2Pri & 0x7) > ipPri) + return ((u8)layer2Pri & 0x7); + else + return ipPri; +} + +u8 convert_userPriority_to_trafficClass(u8 userPriority) +{ + return (up_to_ac[userPriority & 0x7]); +} + +u8 wmi_get_power_mode_cmd(struct wmi_t *wmip) +{ + return wmip->wmi_powerMode; +} + +int +wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance) +{ + int ret = 0; + +#define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0) +#define TSPEC_SERVICE_START_TIME_ATHEROS_DEF 0 +#define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF 0 +#define TSPEC_DELAY_BOUND_ATHEROS_DEF 0 +#define TSPEC_MEDIUM_TIME_ATHEROS_DEF 0 +#define TSPEC_SBA_ATHEROS_DEF 0x2000 /* factor is 1 */ + + /* Verify TSPEC params for ATHEROS compliance */ + if(tspecCompliance == ATHEROS_COMPLIANCE) { + if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) || + (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) || + (pCmd->minDataRate != pCmd->meanDataRate) || + (pCmd->minDataRate != pCmd->peakDataRate) || + (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) || + (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) || + (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) || + (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) { + + A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG)); + //A_PRINTF("%s: Invalid TSPEC params\n", __func__); + ret = A_EINVAL; + } + } + + return ret; +} + +#ifdef CONFIG_HOST_TCMD_SUPPORT +static int +wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + ar6000_testmode_rx_report_event(wmip->wmi_devt, datap, len); + + return 0; +} + +#endif /* CONFIG_HOST_TCMD_SUPPORT*/ + +int +wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode) +{ + void *osbuf; + WMI_SET_AUTH_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->mode = mode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode) +{ + void *osbuf; + WMI_SET_REASSOC_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->mode = mode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy) +{ + void *osbuf; + WMI_SET_LPREAMBLE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->status = status; + cmd->preamblePolicy = preamblePolicy; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold) +{ + void *osbuf; + WMI_SET_RTS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->threshold = threshold; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status) +{ + void *osbuf; + WMI_SET_WMM_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->status = status; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status) +{ + void *osbuf; + WMI_SET_QOS_SUPP_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->status = status; + return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg) +{ + void *osbuf; + WMI_SET_WMM_TXOP_CMD *cmd; + + if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) ) + return A_EINVAL; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->txopEnable = cfg; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_country(struct wmi_t *wmip, u8 *countryCode) +{ + void *osbuf; + WMI_AP_SET_COUNTRY_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + memcpy(cmd->countryCode,countryCode,3); + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID, + NO_SYNC_WMIFLAG)); +} + +#ifdef CONFIG_HOST_TCMD_SUPPORT +/* WMI layer doesn't need to know the data type of the test cmd. + This would be beneficial for customers like Qualcomm, who might + have different test command requirements from different manufacturers + */ +int +wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len) +{ + void *osbuf; + char *data; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + osbuf= A_NETBUF_ALLOC(len); + if(osbuf == NULL) + { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, len); + data = A_NETBUF_DATA(osbuf); + memcpy(data, buf, len); + + return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID, + NO_SYNC_WMIFLAG)); +} + +#endif + +int +wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status) +{ + void *osbuf; + WMI_SET_BT_STATUS_CMD *cmd; + + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status)); + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->streamType = streamType; + cmd->status = status; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd) +{ + void *osbuf; + WMI_SET_BT_PARAMS_CMD* alloc_cmd; + + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType)); + + if (cmd->paramType == BT_PARAM_SCO) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("sco params %d %d %d %d %d %d %d %d %d %d %d %d\n", cmd->info.scoParams.numScoCyclesForceTrigger, + cmd->info.scoParams.dataResponseTimeout, + cmd->info.scoParams.stompScoRules, + cmd->info.scoParams.scoOptFlags, + cmd->info.scoParams.stompDutyCyleVal, + cmd->info.scoParams.stompDutyCyleMaxVal, + cmd->info.scoParams.psPollLatencyFraction, + cmd->info.scoParams.noSCOSlots, + cmd->info.scoParams.noIdleSlots, + cmd->info.scoParams.scoOptOffRssi, + cmd->info.scoParams.scoOptOnRssi, + cmd->info.scoParams.scoOptRtsCount)); + } + else if (cmd->paramType == BT_PARAM_A2DP) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit, + cmd->info.a2dpParams.a2dpBurstCntMin, + cmd->info.a2dpParams.a2dpDataRespTimeout, + cmd->info.a2dpParams.a2dpOptFlags, + cmd->info.a2dpParams.isCoLocatedBtRoleMaster, + cmd->info.a2dpParams.a2dpOptOffRssi, + cmd->info.a2dpParams.a2dpOptOnRssi, + cmd->info.a2dpParams.a2dpOptRtsCount)); + } + else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType)); + } + else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev)); + } + else if (cmd->paramType == BT_PARAM_ACLCOEX) { + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime, + cmd->info.aclCoexParams.aclBtMediumUsageTime, + cmd->info.aclCoexParams.aclDataRespTimeout)); + } + else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) { + A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG)); + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd, cmd, sizeof(*cmd)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_FE_ANT_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID, + NO_SYNC_WMIFLAG)); + +} + + +int +wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)); + A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID, + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_SCO_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_A2DP_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, + WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_DEBUG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip, + WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd) +{ + void *osbuf; + WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd) +{ + void *osbuf; + WMI_GET_BTCOEX_CONFIG_CMD *alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD)); + return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID , + NO_SYNC_WMIFLAG)); + +} + +int +wmi_get_btcoex_stats_cmd(struct wmi_t *wmip) +{ + + return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID); + +} + +int +wmi_get_keepalive_configured(struct wmi_t *wmip) +{ + void *osbuf; + WMI_GET_KEEPALIVE_CMD *cmd; + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID, + NO_SYNC_WMIFLAG)); +} + +u8 wmi_get_keepalive_cmd(struct wmi_t *wmip) +{ + return wmip->wmi_keepaliveInterval; +} + +int +wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval) +{ + void *osbuf; + WMI_SET_KEEPALIVE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->keepaliveInterval = keepaliveInterval; + wmip->wmi_keepaliveInterval = keepaliveInterval; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer) +{ + void *osbuf; + WMI_SET_PARAMS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd) + length); + + cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->opcode = opcode; + cmd->length = length; + memcpy(cmd->buffer, buffer, length); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4) +{ + void *osbuf; + WMI_SET_MCAST_FILTER_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->multicast_mac[0] = 0x01; + cmd->multicast_mac[1] = 0x00; + cmd->multicast_mac[2] = 0x5e; + cmd->multicast_mac[3] = dot2&0x7F; + cmd->multicast_mac[4] = dot3; + cmd->multicast_mac[5] = dot4; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4) +{ + void *osbuf; + WMI_SET_MCAST_FILTER_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->multicast_mac[0] = 0x01; + cmd->multicast_mac[1] = 0x00; + cmd->multicast_mac[2] = 0x5e; + cmd->multicast_mac[3] = dot2&0x7F; + cmd->multicast_mac[4] = dot3; + cmd->multicast_mac[5] = dot4; + + return (wmi_cmd_send(wmip, osbuf, WMI_DEL_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable) +{ + void *osbuf; + WMI_MCAST_FILTER_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->enable = enable; + + return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen, + u8 *ieInfo) +{ + void *osbuf; + WMI_SET_APPIE_CMD *cmd; + u16 cmdLen; + + cmdLen = sizeof(*cmd) + ieLen - 1; + osbuf = A_NETBUF_ALLOC(cmdLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, cmdLen); + + cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, cmdLen); + + cmd->mgmtFrmType = mgmtFrmType; + cmd->ieLen = ieLen; + memcpy(cmd->ieInfo, ieInfo, ieLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen) +{ + void *osbuf; + u8 *data; + + osbuf = A_NETBUF_ALLOC(dataLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, dataLen); + + data = A_NETBUF_DATA(osbuf); + + memcpy(data, cmd, dataLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG)); +} + +s32 wmi_get_rate(s8 rateindex) +{ + if (rateindex == RATE_AUTO) { + return 0; + } else { + return(wmi_rateTable[(u32) rateindex][0]); + } +} + +void +wmi_node_return (struct wmi_t *wmip, bss_t *bss) +{ + if (NULL != bss) + { + wlan_node_return (&wmip->wmi_scan_table, bss); + } +} + +void +wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge) +{ + wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge); +} + +bss_t * +wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid, + u32 ssidLength, bool bIsWPA2, bool bMatchSSID) +{ + bss_t *node = NULL; + node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid, + ssidLength, bIsWPA2, bMatchSSID); + return node; +} + + +#ifdef THREAD_X +void +wmi_refresh_scan_table (struct wmi_t *wmip) +{ + wlan_refresh_inactive_nodes (&wmip->wmi_scan_table); +} +#endif + +void +wmi_free_allnodes(struct wmi_t *wmip) +{ + wlan_free_allnodes(&wmip->wmi_scan_table); +} + +bss_t * +wmi_find_node(struct wmi_t *wmip, const u8 *macaddr) +{ + bss_t *ni=NULL; + ni=wlan_find_node(&wmip->wmi_scan_table,macaddr); + return ni; +} + +void +wmi_free_node(struct wmi_t *wmip, const u8 *macaddr) +{ + bss_t *ni=NULL; + + ni=wlan_find_node(&wmip->wmi_scan_table,macaddr); + if (ni != NULL) { + wlan_node_reclaim(&wmip->wmi_scan_table, ni); + } + + return; +} + +int +wmi_dset_open_reply(struct wmi_t *wmip, + u32 status, + u32 access_cookie, + u32 dset_size, + u32 dset_version, + u32 targ_handle, + u32 targ_reply_fn, + u32 targ_reply_arg) +{ + void *osbuf; + WMIX_DSETOPEN_REPLY_CMD *open_reply; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%lx\n", DBGARG, (unsigned long)wmip)); + + osbuf = A_NETBUF_ALLOC(sizeof(*open_reply)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*open_reply)); + open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); + + open_reply->status = status; + open_reply->targ_dset_handle = targ_handle; + open_reply->targ_reply_fn = targ_reply_fn; + open_reply->targ_reply_arg = targ_reply_arg; + open_reply->access_cookie = access_cookie; + open_reply->size = dset_size; + open_reply->version = dset_version; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID, + NO_SYNC_WMIFLAG)); +} + +static int +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len) +{ + WMI_PMKID_LIST_REPLY *reply; + u32 expected_len; + + if (len < sizeof(WMI_PMKID_LIST_REPLY)) { + return A_EINVAL; + } + reply = (WMI_PMKID_LIST_REPLY *)datap; + expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN; + + if (len < expected_len) { + return A_EINVAL; + } + + A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID, + reply->pmkidList, reply->bssidList[0]); + + return 0; +} + + +static int +wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len) +{ + WMI_SET_PARAMS_REPLY *reply; + + if (len < sizeof(WMI_SET_PARAMS_REPLY)) { + return A_EINVAL; + } + reply = (WMI_SET_PARAMS_REPLY *)datap; + + if (0 == reply->status) + { + + } + else + { + + } + + return 0; +} + + +#ifdef CONFIG_HOST_DSET_SUPPORT +int +wmi_dset_data_reply(struct wmi_t *wmip, + u32 status, + u8 *user_buf, + u32 length, + u32 targ_buf, + u32 targ_reply_fn, + u32 targ_reply_arg) +{ + void *osbuf; + WMIX_DSETDATA_REPLY_CMD *data_reply; + u32 size; + + size = sizeof(*data_reply) + length; + + if (size <= length) { + return A_ERROR; + } + + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status)); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, size); + data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); + + data_reply->status = status; + data_reply->targ_buf = targ_buf; + data_reply->targ_reply_fn = targ_reply_fn; + data_reply->targ_reply_arg = targ_reply_arg; + data_reply->length = length; + + if (status == 0) { + if (a_copy_from_user(data_reply->buf, user_buf, length)) { + A_NETBUF_FREE(osbuf); + return A_ERROR; + } + } + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID, + NO_SYNC_WMIFLAG)); +} +#endif /* CONFIG_HOST_DSET_SUPPORT */ + +int +wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status) +{ + void *osbuf; + char *cmd; + + wps_enable = status; + + osbuf = a_netbuf_alloc(sizeof(1)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + a_netbuf_put(osbuf, sizeof(1)); + + cmd = (char *)(a_netbuf_to_data(osbuf)); + + A_MEMZERO(cmd, sizeof(*cmd)); + cmd[0] = (status?1:0); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID, + NO_SYNC_WMIFLAG)); +} + +#if defined(CONFIG_TARGET_PROFILE_SUPPORT) +int +wmi_prof_cfg_cmd(struct wmi_t *wmip, + u32 period, + u32 nbins) +{ + void *osbuf; + WMIX_PROF_CFG_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->period = period; + cmd->nbins = nbins; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr) +{ + void *osbuf; + WMIX_PROF_ADDR_SET_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->addr = addr; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_prof_start_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID); +} + +int +wmi_prof_stop_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID); +} + +int +wmi_prof_count_get_cmd(struct wmi_t *wmip) +{ + return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID); +} + +/* Called to handle WMIX_PROF_CONT_EVENTID */ +static int +wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap; + + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG, + prof_data->addr, prof_data->count)); + + A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count); + + return 0; +} +#endif /* CONFIG_TARGET_PROFILE_SUPPORT */ + +#ifdef OS_ROAM_MANAGEMENT + +#define ETHERNET_MAC_ADDRESS_LENGTH 6 + +void +wmi_scan_indication (struct wmi_t *wmip) +{ + struct ieee80211_node_table *nt; + u32 gen; + u32 size; + u32 bsssize; + bss_t *bss; + u32 numbss; + PNDIS_802_11_BSSID_SCAN_INFO psi; + PBYTE pie; + NDIS_802_11_FIXED_IEs *pFixed; + NDIS_802_11_VARIABLE_IEs *pVar; + u32 RateSize; + + struct ar6kScanIndication + { + NDIS_802_11_STATUS_INDICATION ind; + NDIS_802_11_BSSID_SCAN_INFO_LIST slist; + } *pAr6kScanIndEvent; + + nt = &wmip->wmi_scan_table; + + ++nt->nt_si_gen; + + + gen = nt->nt_si_gen; + + size = offsetof(struct ar6kScanIndication, slist) + + offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo); + + numbss = 0; + + IEEE80211_NODE_LOCK(nt); + + //calc size + for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) { + if (bss->ni_si_gen != gen) { + bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs); + bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs); + +#ifdef SUPPORT_WPA2 + if (bss->ni_cie.ie_rsn) { + bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2; + } +#endif + if (bss->ni_cie.ie_wpa) { + bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2; + } + + // bsssize must be a multiple of 4 to maintain alignment. + bsssize = (bsssize + 3) & ~3; + + size += bsssize; + + numbss++; + } + } + + if (0 == numbss) + { +// RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n")); + ar6000_scan_indication (wmip->wmi_devt, NULL, 0); + IEEE80211_NODE_UNLOCK (nt); + return; + } + + pAr6kScanIndEvent = A_MALLOC(size); + + if (NULL == pAr6kScanIndEvent) + { + IEEE80211_NODE_UNLOCK(nt); + return; + } + + A_MEMZERO(pAr6kScanIndEvent, size); + + //copy data + pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList; + pAr6kScanIndEvent->slist.Version = 1; + pAr6kScanIndEvent->slist.NumItems = numbss; + + psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0]; + + for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) { + if (bss->ni_si_gen != gen) { + + bss->ni_si_gen = gen; + + //Set scan time + psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC; + + // Copy data to bssid_ex + bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs); + bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs); + +#ifdef SUPPORT_WPA2 + if (bss->ni_cie.ie_rsn) { + bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2; + } +#endif + if (bss->ni_cie.ie_wpa) { + bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2; + } + + // bsssize must be a multiple of 4 to maintain alignment. + bsssize = (bsssize + 3) & ~3; + + psi->Bssid.Length = bsssize; + + memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH); + + +//if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) || +// ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70))) +// RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5])); + + psi->Bssid.Ssid.SsidLength = 0; + pie = bss->ni_cie.ie_ssid; + + if (pie) { + // Format of SSID IE is: + // Type (1 octet) + // Length (1 octet) + // SSID (Length octets) + // + // Validation of the IE should have occurred within WMI. + // + if (pie[1] <= 32) { + psi->Bssid.Ssid.SsidLength = pie[1]; + memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength); + } + } + psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0; + + //Post the RSSI value relative to the Standard Noise floor value. + psi->Bssid.Rssi = bss->ni_rssi; + + if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) { + + if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) { + psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24; + } + else { + psi->Bssid.NetworkTypeInUse = Ndis802_11DS; + } + } + else { + psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5; + } + + psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration); + psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us) + psi->Bssid.Configuration.ATIMWindow = 0; + psi->Bssid.Configuration.DSConfig = bss->ni_cie.ie_chan * 1000; + psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS; + + RateSize = 0; + pie = bss->ni_cie.ie_rates; + if (pie) { + RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX; + memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize); + } + pie = bss->ni_cie.ie_xrates; + if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) { + memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2], + (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize)); + } + + // Copy the fixed IEs + psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs); + + pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs; + memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp)); + pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt; + pFixed->Capabilities = bss->ni_cie.ie_capInfo; + + // Copy selected variable IEs + + pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs)); + +#ifdef SUPPORT_WPA2 + // Copy the WPAv2 IE + if (bss->ni_cie.ie_rsn) { + pie = bss->ni_cie.ie_rsn; + psi->Bssid.IELength += pie[1] + 2; + memcpy(pVar, pie, pie[1] + 2); + pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2); + } +#endif + // Copy the WPAv1 IE + if (bss->ni_cie.ie_wpa) { + pie = bss->ni_cie.ie_wpa; + psi->Bssid.IELength += pie[1] + 2; + memcpy(pVar, pie, pie[1] + 2); + pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2); + } + + // Advance buffer pointer + psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid)); + } + } + + IEEE80211_NODE_UNLOCK(nt); + +// wmi_free_allnodes(wmip); + +// RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss)); + + ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size); + + kfree(pAr6kScanIndEvent); +} +#endif + +u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, + u32 size) +{ + u32 index; + u8 threshold = (u8)sq_thresh->upper_threshold[size - 1]; + + /* The list is already in sorted order. Get the next lower value */ + for (index = 0; index < size; index ++) { + if (rssi < sq_thresh->upper_threshold[index]) { + threshold = (u8)sq_thresh->upper_threshold[index]; + break; + } + } + + return threshold; +} + +u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, + u32 size) +{ + u32 index; + u8 threshold = (u8)sq_thresh->lower_threshold[size - 1]; + + /* The list is already in sorted order. Get the next lower value */ + for (index = 0; index < size; index ++) { + if (rssi > sq_thresh->lower_threshold[index]) { + threshold = (u8)sq_thresh->lower_threshold[index]; + break; + } + } + + return threshold; +} +static int +wmi_send_rssi_threshold_params(struct wmi_t *wmip, + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) +{ + void *osbuf; + s8 size; + WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} +static int +wmi_send_snr_threshold_params(struct wmi_t *wmip, + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) +{ + void *osbuf; + s8 size; + WMI_SNR_THRESHOLD_PARAMS_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd) +{ + void *osbuf; + WMI_SET_TARGET_EVENT_REPORT_CMD* alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + memcpy(alloc_cmd, cmd, sizeof(*cmd)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID, + NO_SYNC_WMIFLAG)); +} + +bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id) +{ + wmi_get_current_bssid (wmip, id); + return wlan_node_remove (&wmip->wmi_scan_table, id); +} + +int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss) +{ + wlan_setup_node (&wmip->wmi_scan_table, bss, id); + return 0; +} + +static int +wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap; + + A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd); + + return 0; +} + + +static int +wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap; + + A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd); + + return 0; +} + +static int +wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap; + + A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd); + + return 0; +} + +int +wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len); + + return 0; +} + + +int +wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len) +{ + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len); + + return 0; + +} + +static int +wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap; + A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +//// //// +//// AP mode functions //// +//// //// +//////////////////////////////////////////////////////////////////////////////// +/* + * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG + * + * When AR6K in AP mode, This command will be called after + * changing ssid, channel etc. It will pass the profile to + * target with a flag which will indicate which parameter changed, + * also if this flag is 0, there was no change in parametes, so + * commit cmd will not be sent to target. Without calling this IOCTL + * the changes will not take effect. + */ +int +wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p) +{ + void *osbuf; + WMI_CONNECT_CMD *cm; + + osbuf = A_NETBUF_ALLOC(sizeof(*cm)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cm)); + cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cm, sizeof(*cm)); + + memcpy(cm,p,sizeof(*cm)); + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID + * + * This command will be used to enable/disable hidden ssid functioanlity of + * beacon. If it is enabled, ssid will be NULL in beacon. + */ +int +wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid) +{ + void *osbuf; + WMI_AP_HIDDEN_SSID_CMD *hs; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD)); + hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(hs, sizeof(*hs)); + + hs->hidden_ssid = hidden_ssid; + + A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid)); + return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA + * + * This command is used to limit max num of STA that can connect + * with this AP. This value should not exceed AP_MAX_NUM_STA (this + * is max num of STA supported by AP). Value was already validated + * in ioctl.c + */ +int +wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta) +{ + void *osbuf; + WMI_AP_SET_NUM_STA_CMD *ns; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD)); + ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(ns, sizeof(*ns)); + + ns->num_sta = num_sta; + + A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta)); + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC + * + * This command is used to send list of mac of STAs which will + * be allowed to connect with this AP. When this list is empty + * firware will allow all STAs till the count reaches AP_MAX_NUM_STA. + */ +int +wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl) +{ + void *osbuf; + WMI_AP_ACL_MAC_CMD *a; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD)); + a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(a, sizeof(*a)); + memcpy(a,acl,sizeof(*acl)); + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_SET_MLME + * + * This command is used to send list of mac of STAs which will + * be allowed to connect with this AP. When this list is empty + * firware will allow all STAs till the count reaches AP_MAX_NUM_STA. + */ +int +wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason) +{ + void *osbuf; + WMI_AP_SET_MLME_CMD *mlme; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD)); + mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(mlme, sizeof(*mlme)); + + mlme->cmd = cmd; + memcpy(mlme->mac, mac, ATH_MAC_LEN); + mlme->reason = reason; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG)); +} + +static int +wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len) +{ + WMI_PSPOLL_EVENT *ev; + + if (len < sizeof(WMI_PSPOLL_EVENT)) { + return A_EINVAL; + } + ev = (WMI_PSPOLL_EVENT *)datap; + + A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid); + return 0; +} + +static int +wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len) +{ + A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt); + return 0; +} + +#ifdef WAPI_ENABLE +static int +wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len) +{ + u8 *ev; + + if (len < 7) { + return A_EINVAL; + } + ev = (u8 *)datap; + + A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]); + return 0; +} +#endif + +int +wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag) +{ + WMI_AP_SET_PVB_CMD *cmd; + void *osbuf = NULL; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD)); + cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->aid = aid; + cmd->flag = flag; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period) +{ + WMI_AP_CONN_INACT_CMD *cmd; + void *osbuf = NULL; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD)); + cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->period = period; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell) +{ + WMI_AP_PROT_SCAN_TIME_CMD *cmd; + void *osbuf = NULL; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD)); + cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->period_min = period; + cmd->dwell_ms = dwell; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim) +{ + WMI_AP_SET_DTIM_CMD *cmd; + void *osbuf = NULL; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD)); + cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->dtim = dtim; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY + * + * This command is used to set ACL policay. While changing policy, if you + * want to retain the existing MAC addresses in the ACL list, policy should be + * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared. + * If there is no chage in policy, the list will be intact. + */ +int +wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy) +{ + void *osbuf; + WMI_AP_ACL_POLICY_CMD *po; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; +} + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD)); + po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(po, sizeof(*po)); + + po->policy = policy; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset) +{ + void *osbuf; + WMI_AP_SET_11BG_RATESET_CMD *rs; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD)); + rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(rs, sizeof(*rs)); + + rs->rateset = rateset; + + return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd) +{ + void *osbuf; + WMI_SET_HT_CAP_CMD *htCap; + u8 band; + + osbuf = A_NETBUF_ALLOC(sizeof(*htCap)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*htCap)); + + band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ; + wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0; + + htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(htCap, sizeof(*htCap)); + memcpy(htCap, cmd, sizeof(*htCap)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width) +{ + void *osbuf; + WMI_SET_HT_OP_CMD *htInfo; + + osbuf = A_NETBUF_ALLOC(sizeof(*htInfo)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*htInfo)); + + htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(htInfo, sizeof(*htInfo)); + htInfo->sta_chan_width = sta_chan_width; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray) +{ + void *osbuf; + WMI_SET_TX_SELECT_RATES_CMD *pData; + + osbuf = A_NETBUF_ALLOC(sizeof(*pData)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*pData)); + + pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf)); + memcpy(pData, pMaskArray, sizeof(*pData)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID, + NO_SYNC_WMIFLAG)); +} + + +int +wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz) +{ + void *osbuf; + WMI_HCI_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz); + cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf)); + + cmd->cmd_buf_sz = sz; + memcpy(cmd->buf, buf, sz); + return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask) +{ + void *osbuf; + WMI_ALLOW_AGGR_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->tx_allow_aggr = tx_tidmask; + cmd->rx_allow_aggr = rx_tidmask; + + return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid) +{ + void *osbuf; + WMI_ADDBA_REQ_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->tid = tid; + + return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink) +{ + void *osbuf; + WMI_DELBA_REQ_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->tid = tid; + cmd->is_sender_initiator = uplink; /* uplink =1 - uplink direction, 0=downlink direction */ + + /* Delete the local aggr state, on host */ + return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion, + bool rxDot11Hdr, bool defragOnHost) +{ + void *osbuf; + WMI_RX_FRAME_FORMAT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0; + cmd->defragOnHost = (defragOnHost==true)? 1:0; + cmd->metaVersion = rxMetaVersion; /* */ + + /* Delete the local aggr state, on host */ + return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode) +{ + void *osbuf; + WMI_SET_THIN_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->enable = (bThinMode==true)? 1:0; + + /* Delete the local aggr state, on host */ + return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG)); +} + + +int +wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence) +{ + void *osbuf; + WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->precedence = precedence; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID, + NO_SYNC_WMIFLAG)); +} + +int +wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk) +{ + void *osbuf; + WMI_SET_PMK_CMD *p; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD)); + + p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(p, sizeof(*p)); + + memcpy(p->pmk, pmk, WMI_PMK_LEN); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd) +{ + void *osbuf; + WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD)); + + p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf)); + memset(p, 0, sizeof(*p)); + + p->threshold = cmd->threshold; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG)); +} + +int +wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold) +{ + void *osbuf; + WMI_SET_TX_SGI_PARAM_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY ; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_TX_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->sgiMask = sgiMask; + cmd->sgiPERThreshold = sgiPERThreshold; + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID, + NO_SYNC_WMIFLAG)); +} + +bss_t * +wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid, + u32 ssidLength, + u32 dot11AuthMode, u32 authMode, + u32 pairwiseCryptoType, u32 grpwiseCryptoTyp) +{ + bss_t *node = NULL; + node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid, + ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp); + + return node; +} + +u16 wmi_ieee2freq (int chan) +{ + u16 freq = 0; + freq = wlan_ieee2freq (chan); + return freq; + +} + +u32 wmi_freq2ieee (u16 freq) +{ + u16 chan = 0; + chan = wlan_freq2ieee (freq); + return chan; +} diff --git a/trunk/drivers/staging/ath6kl/wmi/wmi_host.h b/trunk/drivers/staging/ath6kl/wmi/wmi_host.h new file mode 100644 index 000000000000..53e4f085dfe6 --- /dev/null +++ b/trunk/drivers/staging/ath6kl/wmi/wmi_host.h @@ -0,0 +1,102 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. +// +// +// Permission to use, copy, modify, and/or 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. +// +// +//------------------------------------------------------------------------------ +//============================================================================== +// This file contains local definitios for the wmi host module. +// +// Author(s): ="Atheros" +//============================================================================== +#ifndef _WMI_HOST_H_ +#define _WMI_HOST_H_ + +#include "roaming.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct wmi_stats { + u32 cmd_len_err; + u32 cmd_id_err; +}; + +#define SSID_IE_LEN_INDEX 13 + +/* Host side link management data structures */ +#define SIGNAL_QUALITY_THRESHOLD_LEVELS 6 +#define SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS +#define SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS +typedef struct sq_threshold_params_s { + s16 upper_threshold[SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS]; + s16 lower_threshold[SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS]; + u32 upper_threshold_valid_count; + u32 lower_threshold_valid_count; + u32 polling_interval; + u8 weight; + u8 last_rssi; //normally you would expect this to be bss specific but we keep only one instance because its only valid when the device is in a connected state. Not sure if it belongs to host or target. + u8 last_rssi_poll_event; //Not sure if it belongs to host or target +} SQ_THRESHOLD_PARAMS; + +/* + * These constants are used with A_WLAN_BAND_SET. + */ +#define A_BAND_24GHZ 0 +#define A_BAND_5GHZ 1 +#define A_NUM_BANDS 2 + +struct wmi_t { + bool wmi_ready; + bool wmi_numQoSStream; + u16 wmi_streamExistsForAC[WMM_NUM_AC]; + u8 wmi_fatPipeExists; + void *wmi_devt; + struct wmi_stats wmi_stats; + struct ieee80211_node_table wmi_scan_table; + u8 wmi_bssid[ATH_MAC_LEN]; + u8 wmi_powerMode; + u8 wmi_phyMode; + u8 wmi_keepaliveInterval; +#ifdef THREAD_X + A_CSECT_T wmi_lock; +#else + A_MUTEX_T wmi_lock; +#endif + HTC_ENDPOINT_ID wmi_endpoint_id; + SQ_THRESHOLD_PARAMS wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_NUM_MAX]; + CRYPTO_TYPE wmi_pair_crypto_type; + CRYPTO_TYPE wmi_grp_crypto_type; + bool wmi_is_wmm_enabled; + u8 wmi_ht_allowed[A_NUM_BANDS]; + u8 wmi_traffic_class; +}; + +#ifdef THREAD_X +#define INIT_WMI_LOCK(w) A_CSECT_INIT(&(w)->wmi_lock) +#define LOCK_WMI(w) A_CSECT_ENTER(&(w)->wmi_lock); +#define UNLOCK_WMI(w) A_CSECT_LEAVE(&(w)->wmi_lock); +#define DELETE_WMI_LOCK(w) A_CSECT_DELETE(&(w)->wmi_lock); +#else +#define LOCK_WMI(w) A_MUTEX_LOCK(&(w)->wmi_lock); +#define UNLOCK_WMI(w) A_MUTEX_UNLOCK(&(w)->wmi_lock); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _WMI_HOST_H_ */ diff --git a/trunk/drivers/staging/bcm/Bcmchar.c b/trunk/drivers/staging/bcm/Bcmchar.c index 6f8a75dc1ef0..867dbf1c9926 100644 --- a/trunk/drivers/staging/bcm/Bcmchar.c +++ b/trunk/drivers/staging/bcm/Bcmchar.c @@ -34,7 +34,7 @@ static int bcm_char_open(struct inode *inode, struct file * filp) /* Store the Adapter structure */ filp->private_data = pTarang; - /* Start Queuing the control response Packets */ + /*Start Queuing the control response Packets*/ atomic_inc(&Adapter->ApplicationRunning); nonseekable_open(inode, filp); @@ -84,7 +84,7 @@ static int bcm_char_release(struct inode *inode, struct file *filp) up(&Adapter->RxAppControlQueuelock); - /* Stop Queuing the control response Packets */ + /*Stop Queuing the control response Packets*/ atomic_dec(&Adapter->ApplicationRunning); kfree(pTarang); @@ -100,8 +100,8 @@ static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, PPER_TARANG_DATA pTarang = filp->private_data; PMINI_ADAPTER Adapter = pTarang->Adapter; struct sk_buff *Packet = NULL; - ssize_t PktLen = 0; - int wait_ret_val = 0; + ssize_t PktLen = 0; + int wait_ret_val = 0; unsigned long ret = 0; wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue, @@ -157,1811 +157,1942 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { PPER_TARANG_DATA pTarang = filp->private_data; void __user *argp = (void __user *)arg; - PMINI_ADAPTER Adapter = pTarang->Adapter; - INT Status = STATUS_FAILURE; + PMINI_ADAPTER Adapter = pTarang->Adapter; + INT Status = STATUS_FAILURE; int timeout = 0; - IOCTL_BUFFER IoBuffer; + IOCTL_BUFFER IoBuffer; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg); - if (_IOC_TYPE(cmd) != BCM_IOCTL) + if(_IOC_TYPE(cmd) != BCM_IOCTL) return -EFAULT; - if (_IOC_DIR(cmd) & _IOC_READ) + if(_IOC_DIR(cmd) & _IOC_READ) Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd)); else if (_IOC_DIR(cmd) & _IOC_WRITE) - Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd)); + Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd)); else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE)) - Status = STATUS_SUCCESS; + Status = STATUS_SUCCESS; - if (Status) + if(Status) return -EFAULT; - if (Adapter->device_removed) + if(Adapter->device_removed) + { return -EFAULT; + } - if (FALSE == Adapter->fw_download_done) { - switch (cmd) { - case IOCTL_MAC_ADDR_REQ: - case IOCTL_LINK_REQ: - case IOCTL_CM_REQUEST: - case IOCTL_SS_INFO_REQ: - case IOCTL_SEND_CONTROL_MESSAGE: - case IOCTL_IDLE_REQ: - case IOCTL_BCM_GPIO_SET_REQUEST: - case IOCTL_BCM_GPIO_STATUS_REQUEST: - return -EACCES; - default: - break; + if(FALSE == Adapter->fw_download_done) + { + switch (cmd) + { + case IOCTL_MAC_ADDR_REQ: + case IOCTL_LINK_REQ: + case IOCTL_CM_REQUEST: + case IOCTL_SS_INFO_REQ: + case IOCTL_SEND_CONTROL_MESSAGE: + case IOCTL_IDLE_REQ: + case IOCTL_BCM_GPIO_SET_REQUEST: + case IOCTL_BCM_GPIO_STATUS_REQUEST: + return -EACCES; + default: + break; } } Status = vendorextnIoctl(Adapter, cmd, arg); - if (Status != CONTINUE_COMMON_PATH) - return Status; - - switch (cmd) { - /* Rdms for Swin Idle... */ - case IOCTL_BCM_REGISTER_READ_PRIVATE: { - RDM_BUFFER sRdmBuffer = {0}; - PCHAR temp_buff; - UINT Bufflen; - - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + if(Status != CONTINUE_COMMON_PATH ) + return Status; - if (IoBuffer.InputLength > sizeof(sRdmBuffer)) - return -EINVAL; + switch(cmd){ + // Rdms for Swin Idle... + case IOCTL_BCM_REGISTER_READ_PRIVATE: + { + RDM_BUFFER sRdmBuffer = {0}; + PCHAR temp_buff; + UINT Bufflen; - if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; + /* Copy Ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - /* FIXME: need to restrict BuffLen */ - Bufflen = IoBuffer.OutputLength + (4 - IoBuffer.OutputLength%4)%4; - temp_buff = kmalloc(Bufflen, GFP_KERNEL); - if (!temp_buff) - return -ENOMEM; + if (IoBuffer.InputLength > sizeof(sRdmBuffer)) + return -EINVAL; - Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register, - (PUINT)temp_buff, Bufflen); - if (Status == STATUS_SUCCESS) { - if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) - Status = -EFAULT; - } + if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; - kfree(temp_buff); - break; - } + /* FIXME: need to restrict BuffLen */ + Bufflen = IoBuffer.OutputLength + (4 - IoBuffer.OutputLength%4)%4; + temp_buff = kmalloc(Bufflen, GFP_KERNEL); + if(!temp_buff) + return -ENOMEM; - case IOCTL_BCM_REGISTER_WRITE_PRIVATE: { - WRM_BUFFER sWrmBuffer = {0}; - UINT uiTempVar = 0; - /* Copy Ioctl Buffer structure */ + Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register, + (PUINT)temp_buff, Bufflen); + if(Status == STATUS_SUCCESS) + { + if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) + Status = -EFAULT; + } - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + kfree(temp_buff); + break; + } + case IOCTL_BCM_REGISTER_WRITE_PRIVATE: + { + WRM_BUFFER sWrmBuffer = {0}; + UINT uiTempVar=0; + /* Copy Ioctl Buffer structure */ - if (IoBuffer.InputLength > sizeof(sWrmBuffer)) - return -EINVAL; + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - /* Get WrmBuffer structure */ - if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; + if (IoBuffer.InputLength > sizeof(sWrmBuffer)) + return -EINVAL; + + /* Get WrmBuffer structure */ + if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; - uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; - if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && - ((uiTempVar == EEPROM_REJECT_REG_1) || + uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; + if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && + ((uiTempVar == EEPROM_REJECT_REG_1)|| (uiTempVar == EEPROM_REJECT_REG_2) || (uiTempVar == EEPROM_REJECT_REG_3) || - (uiTempVar == EEPROM_REJECT_REG_4))) { - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); - return -EFAULT; - } - - Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register, - (PUINT)sWrmBuffer.Data, sizeof(ULONG)); - - if (Status == STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n"); - } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); - Status = -EFAULT; - } - break; - } - - case IOCTL_BCM_REGISTER_READ: - case IOCTL_BCM_EEPROM_REGISTER_READ: { - RDM_BUFFER sRdmBuffer = {0}; - PCHAR temp_buff = NULL; - UINT uiTempVar = 0; - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n"); - return -EACCES; + (uiTempVar == EEPROM_REJECT_REG_4))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); + return -EFAULT; + } + Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register, + (PUINT)sWrmBuffer.Data, sizeof(ULONG)); + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"WRM Done\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); + Status = -EFAULT; + } + break; } - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (IoBuffer.InputLength > sizeof(sRdmBuffer)) - return -EINVAL; + case IOCTL_BCM_REGISTER_READ: + case IOCTL_BCM_EEPROM_REGISTER_READ: + { + RDM_BUFFER sRdmBuffer = {0}; + PCHAR temp_buff = NULL; + UINT uiTempVar = 0; + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n"); + return -EACCES; + } + /* Copy Ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; + if (IoBuffer.InputLength > sizeof(sRdmBuffer)) + return -EINVAL; - /* FIXME: don't trust user supplied length */ - temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL); - if (!temp_buff) - return STATUS_FAILURE; + if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; - if ((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) || - ((ULONG)sRdmBuffer.Register & 0x3)) { + /* FIXME: don't trust user supplied length */ + temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL); + if(!temp_buff) + return STATUS_FAILURE; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n", + if((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) || + ((ULONG)sRdmBuffer.Register & 0x3)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n", (int)sRdmBuffer.Register); + return -EINVAL; + } - kfree(temp_buff); - return -EINVAL; - } - - uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK; - Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength); - - if (Status == STATUS_SUCCESS) - if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) - Status = -EFAULT; + uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK; + Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, + (PUINT)temp_buff, IoBuffer.OutputLength); + if(Status == STATUS_SUCCESS) + if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) + Status = -EFAULT; - kfree(temp_buff); - break; - } - case IOCTL_BCM_REGISTER_WRITE: - case IOCTL_BCM_EEPROM_REGISTER_WRITE: { - WRM_BUFFER sWrmBuffer = {0}; - UINT uiTempVar = 0; - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n"); - return -EACCES; + kfree(temp_buff); + break; } + case IOCTL_BCM_REGISTER_WRITE: + case IOCTL_BCM_EEPROM_REGISTER_WRITE: + { + WRM_BUFFER sWrmBuffer = {0}; + UINT uiTempVar=0; + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n"); + return -EACCES; + } - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (IoBuffer.InputLength > sizeof(sWrmBuffer)) - return -EINVAL; + /* Copy Ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - /* Get WrmBuffer structure */ - if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; + if (IoBuffer.InputLength > sizeof(sWrmBuffer)) + return -EINVAL; - if ((((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) || - ((ULONG)sWrmBuffer.Register & 0x3)) { + /* Get WrmBuffer structure */ + if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)sWrmBuffer.Register); - return -EINVAL; - } + if( (((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) || + ((ULONG)sWrmBuffer.Register & 0x3) ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", + (int)sWrmBuffer.Register); + return -EINVAL; + } - uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; - if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && - ((uiTempVar == EEPROM_REJECT_REG_1) || + uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; + if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && + ((uiTempVar == EEPROM_REJECT_REG_1)|| (uiTempVar == EEPROM_REJECT_REG_2) || (uiTempVar == EEPROM_REJECT_REG_3) || (uiTempVar == EEPROM_REJECT_REG_4)) && - (cmd == IOCTL_BCM_REGISTER_WRITE)) { - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); + (cmd == IOCTL_BCM_REGISTER_WRITE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); return -EFAULT; - } - - Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register, - (PUINT)sWrmBuffer.Data, sWrmBuffer.Length); - - if (Status == STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n"); - } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); - Status = -EFAULT; - } - break; - } - case IOCTL_BCM_GPIO_SET_REQUEST: { - UCHAR ucResetValue[4]; - UINT value = 0; - UINT uiBit = 0; - UINT uiOperation = 0; - - GPIO_INFO gpio_info = {0}; - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode"); - return -EACCES; - } - - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (IoBuffer.InputLength > sizeof(gpio_info)) - return -EINVAL; - - if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; - - uiBit = gpio_info.uiGpioNumber; - uiOperation = gpio_info.uiGpioValue; - value = (1< is not correspond to LED !!!", value); - Status = -EINVAL; + Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register, + (PUINT)sWrmBuffer.Data, sWrmBuffer.Length); + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); + Status = -EFAULT; + } break; } + case IOCTL_BCM_GPIO_SET_REQUEST: + { + UCHAR ucResetValue[4]; + UINT value =0; + UINT uiBit = 0; + UINT uiOperation = 0; + + GPIO_INFO gpio_info = {0}; + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode"); + return -EACCES; + } + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + if (IoBuffer.InputLength > sizeof(gpio_info)) + return -EINVAL; + if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; + uiBit = gpio_info.uiGpioNumber; + uiOperation = gpio_info.uiGpioValue; - /* Set - setting 1 */ - if (uiOperation) { - /* Set the gpio output register */ - Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, (PUINT)(&value), sizeof(UINT)); + value= (1< is not correspond to LED !!!",value); + Status = -EINVAL; break; } - } - Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); - if (STATUS_SUCCESS != Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, - "GPIO_MODE_REGISTER read failed"); - break; - } + if(uiOperation)//Set - setting 1 + { + //Set the gpio output register + Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG , + (PUINT)(&value), sizeof(UINT)); + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to set the %dth GPIO \n",uiBit); + break; + } + } + else//Unset - setting 0 + { + //Set the gpio output register + Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG , + (PUINT)(&value), sizeof(UINT)); + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO bit\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to clear the %dth GPIO \n",uiBit); + break; + } + } - /* Set the gpio mode register to output */ - *(UINT *)ucResetValue |= (1<IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode"); - Status = -EACCES; - break; - } - - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (IoBuffer.InputLength > sizeof(threadReq)) - return -EINVAL; - - if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; - - /* if LED thread is running(Actively or Inactively) set it state to make inactive */ - if (Adapter->LEDInfo.led_thread_running) { - if (threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Activating thread req"); - Adapter->DriverState = LED_THREAD_ACTIVE; - } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DeActivating Thread req....."); - Adapter->DriverState = LED_THREAD_INACTIVE; + if (STATUS_SUCCESS != Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO_MODE_REGISTER read failed"); + break; } - - /* signal thread. */ - wake_up(&Adapter->LEDInfo.notify_led_event); - } - } - break; - - case IOCTL_BCM_GPIO_STATUS_REQUEST: { - ULONG uiBit = 0; - UCHAR ucRead[4]; - GPIO_INFO gpio_info = {0}; - - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) - return -EACCES; - - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (IoBuffer.InputLength > sizeof(gpio_info)) - return -EINVAL; - - if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; - - uiBit = gpio_info.uiGpioNumber; - - /* Set the gpio output register */ - Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, - (PUINT)ucRead, sizeof(UINT)); - - if (Status != STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n"); - return Status; - } - } - break; - - case IOCTL_BCM_GPIO_MULTI_REQUEST: { - UCHAR ucResetValue[4]; - GPIO_MULTI_INFO gpio_multi_info[MAX_IDX]; - PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info; - - memset(pgpio_multi_info, 0, MAX_IDX * sizeof(GPIO_MULTI_INFO)); - - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) - return -EINVAL; - - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (IoBuffer.InputLength > sizeof(gpio_multi_info)) - return -EINVAL; - - if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; - - if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == FALSE) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, - "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!", - pgpio_multi_info[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap); - Status = -EINVAL; - break; + //Set the gpio mode register to output + *(UINT*)ucResetValue |= (1<IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode"); + Status = -EACCES; + break; + } - /* Set the gpio output register */ - if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) & - (pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) { - /* Set 1's in GPIO OUTPUT REGISTER */ - *(UINT *)ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask & - pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & - pgpio_multi_info[WIMAX_IDX].uiGPIOValue; + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - if (*(UINT *) ucResetValue) - Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, - (PUINT)ucResetValue, sizeof(ULONG)); + if (IoBuffer.InputLength > sizeof(threadReq)) + return -EINVAL; - if (Status != STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_SET_REG Failed."); - return Status; - } + if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; - /* Clear to 0's in GPIO OUTPUT REGISTER */ - *(UINT *)ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask & - pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & - (~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue))); + //if LED thread is running(Actively or Inactively) set it state to make inactive + if(Adapter->LEDInfo.led_thread_running) + { + if(threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Activating thread req"); + Adapter->DriverState = LED_THREAD_ACTIVE; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DeActivating Thread req....."); + Adapter->DriverState = LED_THREAD_INACTIVE; + } - if (*(UINT *) ucResetValue) - Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)ucResetValue, sizeof(ULONG)); + //signal thread. + wake_up(&Adapter->LEDInfo.notify_led_event); - if (Status != STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_CLR_REG Failed."); - return Status; } } + break; + case IOCTL_BCM_GPIO_STATUS_REQUEST: + { + ULONG uiBit = 0; + UCHAR ucRead[4]; + GPIO_INFO gpio_info = {0}; + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + return -EACCES; + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + if (IoBuffer.InputLength > sizeof(gpio_info)) + return -EINVAL; + if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; + uiBit = gpio_info.uiGpioNumber; + //Set the gpio output register + Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, + (PUINT)ucRead, sizeof(UINT)); + if(Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n"); + return Status; + } - if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) { - Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); - - if (Status != STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM to GPIO_PIN_STATE_REGISTER Failed."); - return Status; } - - pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue & - pgpio_multi_info[WIMAX_IDX].uiGPIOMask); - } - - Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "Failed while copying Content to IOBufer for user space err:%d", Status); break; - } - } - break; - - case IOCTL_BCM_GPIO_MODE_REQUEST: { - UCHAR ucResetValue[4]; - GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX]; - PGPIO_MULTI_MODE pgpio_multi_mode = (PGPIO_MULTI_MODE)gpio_multi_mode; - - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) - return -EINVAL; - - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (IoBuffer.InputLength > sizeof(gpio_multi_mode)) - return -EINVAL; + case IOCTL_BCM_GPIO_MULTI_REQUEST: + { + UCHAR ucResetValue[4]; + GPIO_MULTI_INFO gpio_multi_info[MAX_IDX]; + PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info; + + memset( pgpio_multi_info, 0, MAX_IDX * sizeof( GPIO_MULTI_INFO)); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + return -EINVAL; + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + if (IoBuffer.InputLength > sizeof(gpio_multi_info)) + return -EINVAL; + if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; - if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; + if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_info[WIMAX_IDX].uiGPIOMask)== FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_info[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap); + Status = -EINVAL; + break; + } - Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); + /* Set the gpio output register */ - if (STATUS_SUCCESS != Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed"); - return Status; - } + if( ( pgpio_multi_info[WIMAX_IDX].uiGPIOMask) & + ( pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) + { + /* Set 1's in GPIO OUTPUT REGISTER */ + *(UINT*) ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask & + pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & + pgpio_multi_info[WIMAX_IDX].uiGPIOValue; - /* Validating the request */ - if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) == FALSE) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, - "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!", - pgpio_multi_mode[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap); - Status = -EINVAL; - break; - } + if( *(UINT*) ucResetValue) + Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_SET_REG , (PUINT) ucResetValue, sizeof(ULONG)); - if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) { - /* write all OUT's (1's) */ - *(UINT *) ucResetValue |= (pgpio_multi_mode[WIMAX_IDX].uiGPIOMode & - pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); - - /* write all IN's (0's) */ - *(UINT *) ucResetValue &= ~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) & - pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); - - /* Currently implemented return the modes of all GPIO's - * else needs to bit AND with mask - */ - pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue; - - Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(ULONG)); - if (Status == STATUS_SUCCESS) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, - "WRM to GPIO_MODE_REGISTER Done"); - } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "WRM to GPIO_MODE_REGISTER Failed"); - Status = -EFAULT; - break; - } - } else { -/* if uiGPIOMask is 0 then return mode register configuration */ - pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue; - } - - Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "Failed while copying Content to IOBufer for user space err:%d", Status); - break; - } - } - break; - - case IOCTL_MAC_ADDR_REQ: - case IOCTL_LINK_REQ: - case IOCTL_CM_REQUEST: - case IOCTL_SS_INFO_REQ: - case IOCTL_SEND_CONTROL_MESSAGE: - case IOCTL_IDLE_REQ: { - PVOID pvBuffer = NULL; - - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + if( Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_SET_REG Failed."); + return Status; + } - /* FIXME: don't accept any length from user */ - pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); - if (!pvBuffer) - return -ENOMEM; + /* Clear to 0's in GPIO OUTPUT REGISTER */ + *(UINT*) ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask & + pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & + ( ~( pgpio_multi_info[WIMAX_IDX].uiGPIOValue))); - if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) { - Status = -EFAULT; - kfree(pvBuffer); - break; - } + if( *(UINT*) ucResetValue) + Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_CLR_REG , (PUINT) ucResetValue, sizeof(ULONG)); - down(&Adapter->LowPowerModeSync); - Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, - !Adapter->bPreparingForLowPowerMode, - (1 * HZ)); - if (Status == -ERESTARTSYS) - goto cntrlEnd; + if( Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_CLR_REG Failed." ); + return Status; + } + } - if (Adapter->bPreparingForLowPowerMode) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, - "Preparing Idle Mode is still True - Hence Rejecting control message\n"); - Status = STATUS_FAILURE; - goto cntrlEnd; - } - Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer); + if( pgpio_multi_info[WIMAX_IDX].uiGPIOMask) + { + Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); -cntrlEnd: - up(&Adapter->LowPowerModeSync); - kfree(pvBuffer); - break; - } + if(Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM to GPIO_PIN_STATE_REGISTER Failed."); + return Status; + } - case IOCTL_BCM_BUFFER_DOWNLOAD_START: { - INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); - if (NVMAccess) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, - "IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); - return -EACCES; - } + pgpio_multi_info[WIMAX_IDX].uiGPIOValue = ( *(UINT*)ucResetValue & + pgpio_multi_info[WIMAX_IDX].uiGPIOMask); + } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "Starting the firmware download PID =0x%x!!!!\n", current->pid); - - if (!down_trylock(&Adapter->fw_download_sema)) { - Adapter->bBinDownloaded = FALSE; - Adapter->fw_download_process_pid = current->pid; - Adapter->bCfgDownloaded = FALSE; - Adapter->fw_download_done = FALSE; - netif_carrier_off(Adapter->dev); - netif_stop_queue(Adapter->dev); - Status = reset_card_proc(Adapter); - if (Status) { - pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name); - up(&Adapter->fw_download_sema); - up(&Adapter->NVMRdmWrmLock); - break; + Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status); + break; + } } - mdelay(10); - } else { - Status = -EBUSY; - } + break; + case IOCTL_BCM_GPIO_MODE_REQUEST: + { + UCHAR ucResetValue[4]; + GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX]; + PGPIO_MULTI_MODE pgpio_multi_mode = ( PGPIO_MULTI_MODE) gpio_multi_mode; - up(&Adapter->NVMRdmWrmLock); - break; - } + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + return -EINVAL; - case IOCTL_BCM_BUFFER_DOWNLOAD: { - FIRMWARE_INFO *psFwInfo = NULL; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); - do { - if (!down_trylock(&Adapter->fw_download_sema)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "Invalid way to download buffer. Use Start and then call this!!!\n"); - Status = -EINVAL; - break; - } - - /* Copy Ioctl Buffer structure */ if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) return -EFAULT; - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "Length for FW DLD is : %lx\n", IoBuffer.InputLength); - - if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) + if (IoBuffer.InputLength > sizeof(gpio_multi_mode)) return -EINVAL; - - psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL); - if (!psFwInfo) - return -ENOMEM; - - if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) + if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength)) return -EFAULT; - if (!psFwInfo->pvMappedFirmwareAddress || - (psFwInfo->u32FirmwareLength == 0)) { + Status = rdmaltWithLock( Adapter, ( UINT) GPIO_MODE_REGISTER, ( PUINT) ucResetValue, sizeof( UINT)); + if( STATUS_SUCCESS != Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Read of GPIO_MODE_REGISTER failed"); + return Status; + } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n", - psFwInfo->u32FirmwareLength); + //Validating the request + if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)== FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_mode[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap); Status = -EINVAL; break; } - Status = bcm_ioctl_fw_download(Adapter, psFwInfo); - - if (Status != STATUS_SUCCESS) { - if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n"); + if( pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) + { + /* write all OUT's (1's) */ + *( UINT*) ucResetValue |= ( pgpio_multi_mode[WIMAX_IDX].uiGPIOMode & + pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); + /* write all IN's (0's) */ + *( UINT*) ucResetValue &= ~( ( ~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) & + pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); + + /* Currently implemented return the modes of all GPIO's + * else needs to bit AND with mask + * */ + pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT*)ucResetValue; + + Status = wrmaltWithLock( Adapter, GPIO_MODE_REGISTER , ( PUINT) ucResetValue, sizeof( ULONG)); + if( Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM to GPIO_MODE_REGISTER Done"); + } else - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n"); - - /* up(&Adapter->fw_download_sema); */ - - if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { - Adapter->DriverState = DRIVER_INIT; - Adapter->LEDInfo.bLedInitDone = FALSE; - wake_up(&Adapter->LEDInfo.notify_led_event); + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to GPIO_MODE_REGISTER Failed"); + Status = -EFAULT; + break; } } - break; - - } while (0); - - if (Status != STATUS_SUCCESS) - up(&Adapter->fw_download_sema); - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n"); - kfree(psFwInfo); - break; - } - - case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: { - INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); - - if (NVMAccess) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "FW download blocked as EEPROM Read/Write is in progress\n"); - up(&Adapter->fw_download_sema); - return -EACCES; - } - - if (down_trylock(&Adapter->fw_download_sema)) { - Adapter->bBinDownloaded = TRUE; - Adapter->bCfgDownloaded = TRUE; - atomic_set(&Adapter->CurrNumFreeTxDesc, 0); - Adapter->CurrNumRecvDescs = 0; - Adapter->downloadDDR = 0; - - /* setting the Mips to Run */ - Status = run_card_proc(Adapter); - - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n"); - up(&Adapter->fw_download_sema); - up(&Adapter->NVMRdmWrmLock); - break; - } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, - DBG_LVL_ALL, "Firm Download Over...\n"); + else /* if uiGPIOMask is 0 then return mode register configuration */ + { + pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *( UINT*) ucResetValue; } - - mdelay(10); - - /* Wait for MailBox Interrupt */ - if (StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter)) - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n"); - - timeout = 5*HZ; - Adapter->waiting_to_fw_download_done = FALSE; - wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue, - Adapter->waiting_to_fw_download_done, timeout); - Adapter->fw_download_process_pid = INVALID_PID; - Adapter->fw_download_done = TRUE; - atomic_set(&Adapter->CurrNumFreeTxDesc, 0); - Adapter->CurrNumRecvDescs = 0; - Adapter->PrevNumRecvDescs = 0; - atomic_set(&Adapter->cntrlpktCnt, 0); - Adapter->LinkUpStatus = 0; - Adapter->LinkStatus = 0; - - if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { - Adapter->DriverState = FW_DOWNLOAD_DONE; - wake_up(&Adapter->LEDInfo.notify_led_event); + Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status); + break; } - - if (!timeout) - Status = -ENODEV; - } else { - Status = -EINVAL; } - - up(&Adapter->fw_download_sema); - up(&Adapter->NVMRdmWrmLock); - break; - } - - case IOCTL_BE_BUCKET_SIZE: - Status = 0; - if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg)) - Status = -EFAULT; - break; - - case IOCTL_RTPS_BUCKET_SIZE: - Status = 0; - if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg)) - Status = -EFAULT; break; - case IOCTL_CHIP_RESET: { - INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); - if (NVMAccess) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); - return -EACCES; - } + case IOCTL_MAC_ADDR_REQ: + case IOCTL_LINK_REQ: + case IOCTL_CM_REQUEST: + case IOCTL_SS_INFO_REQ: + case IOCTL_SEND_CONTROL_MESSAGE: + case IOCTL_IDLE_REQ: + { + PVOID pvBuffer=NULL; - down(&Adapter->RxAppControlQueuelock); - Status = reset_card_proc(Adapter); - flushAllAppQ(); - up(&Adapter->RxAppControlQueuelock); - up(&Adapter->NVMRdmWrmLock); - ResetCounters(Adapter); - break; - } + /* Copy Ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - case IOCTL_QOS_THRESHOLD: { - USHORT uiLoopIndex; + /* FIXME: don't accept any length from user */ + pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); + if(!pvBuffer) + return -ENOMEM; - Status = 0; - for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) { - if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold, - (unsigned long __user *)arg)) { + if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + { Status = -EFAULT; + kfree(pvBuffer); break; } - } - break; - } - - case IOCTL_DUMP_PACKET_INFO: - DumpPackInfo(Adapter); - DumpPhsRules(&Adapter->stBCMPhsContext); - Status = STATUS_SUCCESS; - break; - - case IOCTL_GET_PACK_INFO: - if (copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES)) - return -EFAULT; - Status = STATUS_SUCCESS; - break; - - case IOCTL_BCM_SWITCH_TRANSFER_MODE: { - UINT uiData = 0; - if (copy_from_user(&uiData, argp, sizeof(UINT))) - return -EFAULT; - if (uiData) { - /* Allow All Packets */ - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n"); - Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE; - } else { - /* Allow IP only Packets */ - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n"); - Adapter->TransferMode = IP_PACKET_ONLY_MODE; - } - Status = STATUS_SUCCESS; - break; - } - - case IOCTL_BCM_GET_DRIVER_VERSION: { - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength)) - return -EFAULT; - Status = STATUS_SUCCESS; - break; - } - - case IOCTL_BCM_GET_CURRENT_STATUS: { - LINK_STATE link_state; - - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n"); - Status = -EFAULT; - break; - } - - if (IoBuffer.OutputLength != sizeof(link_state)) { - Status = -EINVAL; + down(&Adapter->LowPowerModeSync); + Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, + !Adapter->bPreparingForLowPowerMode, + (1 * HZ)); + if(Status == -ERESTARTSYS) + goto cntrlEnd; + + if(Adapter->bPreparingForLowPowerMode) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Preparing Idle Mode is still True - Hence Rejecting control message\n"); + Status = STATUS_FAILURE ; + goto cntrlEnd ; + } + Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer); + cntrlEnd: + up(&Adapter->LowPowerModeSync); + kfree(pvBuffer); break; } + case IOCTL_BCM_BUFFER_DOWNLOAD_START: + { + INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock) ; + if(NVMAccess) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); + return -EACCES; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); + if(!down_trylock(&Adapter->fw_download_sema)) + { + Adapter->bBinDownloaded=FALSE; + Adapter->fw_download_process_pid=current->pid; + Adapter->bCfgDownloaded=FALSE; + Adapter->fw_download_done=FALSE; + netif_carrier_off(Adapter->dev); + netif_stop_queue(Adapter->dev); + Status = reset_card_proc(Adapter); + if(Status) + { + pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name); + up(&Adapter->fw_download_sema); + up(&Adapter->NVMRdmWrmLock); + break; + } + mdelay(10); + } + else + { - memset(&link_state, 0, sizeof(link_state)); - link_state.bIdleMode = Adapter->IdleMode; - link_state.bShutdownMode = Adapter->bShutStatus; - link_state.ucLinkStatus = Adapter->LinkStatus; + Status = -EBUSY; - if (copy_to_user(IoBuffer.OutputBuffer, &link_state, min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n"); - Status = -EFAULT; + } + up(&Adapter->NVMRdmWrmLock); break; } - Status = STATUS_SUCCESS; - break; - } - - case IOCTL_BCM_SET_MAC_TRACING: { - UINT tracing_flag; - - /* copy ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + case IOCTL_BCM_BUFFER_DOWNLOAD: + { + FIRMWARE_INFO *psFwInfo = NULL; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); + do{ + if(!down_trylock(&Adapter->fw_download_sema)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid way to download buffer. Use Start and then call this!!!\n"); + Status=-EINVAL; + break; + } - if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT))) - return -EFAULT; + /* Copy Ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - if (tracing_flag) - Adapter->pTarangs->MacTracingEnabled = TRUE; - else - Adapter->pTarangs->MacTracingEnabled = FALSE; - break; - } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length for FW DLD is : %lx\n", + IoBuffer.InputLength); - case IOCTL_BCM_GET_DSX_INDICATION: { - ULONG ulSFId = 0; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) + return -EINVAL; - if (IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "Mismatch req: %lx needed is =0x%zx!!!", - IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt)); - return -EINVAL; - } + psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL); + if(!psFwInfo) + return -ENOMEM; - if (copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId))) - return -EFAULT; + if(copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId); - get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer); - Status = STATUS_SUCCESS; - } - break; + if(!psFwInfo->pvMappedFirmwareAddress || + (psFwInfo->u32FirmwareLength == 0)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n", + psFwInfo->u32FirmwareLength); + Status = -EINVAL; + break; + } + Status = bcm_ioctl_fw_download(Adapter, psFwInfo); + if(Status != STATUS_SUCCESS) + { + if(psFwInfo->u32StartingAddress==CONFIG_BEGIN_ADDR) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n"); + } + //up(&Adapter->fw_download_sema); - case IOCTL_BCM_GET_HOST_MIBS: { - PVOID temp_buff; + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + Adapter->DriverState = DRIVER_INIT; + Adapter->LEDInfo.bLedInitDone = FALSE; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + } + break ; + }while(0); - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + if(Status != STATUS_SUCCESS) + up(&Adapter->fw_download_sema); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n"); + kfree(psFwInfo); + break; + } + case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: + { + INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); + if(NVMAccess) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " FW download blocked as EEPROM Read/Write is in progress\n"); + up(&Adapter->fw_download_sema); + return -EACCES; + } + if(down_trylock(&Adapter->fw_download_sema)) + { + Adapter->bBinDownloaded=TRUE; + Adapter->bCfgDownloaded=TRUE; + atomic_set(&Adapter->CurrNumFreeTxDesc, 0); + + Adapter->CurrNumRecvDescs=0; + Adapter->downloadDDR = 0; + + //setting the Mips to Run + Status = run_card_proc(Adapter); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n"); + up(&Adapter->fw_download_sema); + up(&Adapter->NVMRdmWrmLock); + break; + } + else + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Firm Download Over...\n"); + mdelay(10); + /* Wait for MailBox Interrupt */ + if(StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n"); + } + timeout = 5*HZ; + Adapter->waiting_to_fw_download_done = FALSE; + wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue, + Adapter->waiting_to_fw_download_done, timeout); + Adapter->fw_download_process_pid=INVALID_PID; + Adapter->fw_download_done=TRUE; + atomic_set(&Adapter->CurrNumFreeTxDesc, 0); + Adapter->CurrNumRecvDescs = 0; + Adapter->PrevNumRecvDescs = 0; + atomic_set(&Adapter->cntrlpktCnt,0); + Adapter->LinkUpStatus = 0; + Adapter->LinkStatus = 0; + + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + Adapter->DriverState = FW_DOWNLOAD_DONE; + wake_up(&Adapter->LEDInfo.notify_led_event); + } - if (IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "Length Check failed %lu %zd\n", - IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS)); - return -EINVAL; + if(!timeout) + { + Status = -ENODEV; + } + } + else + { + Status = -EINVAL; + } + up(&Adapter->fw_download_sema); + up(&Adapter->NVMRdmWrmLock); + break; } - - /* FIXME: HOST_STATS are too big for kmalloc (122048)! */ - temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL); - if (!temp_buff) - return STATUS_FAILURE; - - Status = ProcessGetHostMibs(Adapter, temp_buff); - GetDroppedAppCntrlPktMibs(temp_buff, pTarang); - - if (Status != STATUS_FAILURE) - if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS))) + case IOCTL_BE_BUCKET_SIZE: + Status = 0; + if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg)) Status = -EFAULT; - - kfree(temp_buff); - break; - } - - case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE: - if ((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE == Adapter->IdleMode)) { - Adapter->usIdleModePattern = ABORT_IDLE_MODE; - Adapter->bWakeUpDevice = TRUE; - wake_up(&Adapter->process_rx_cntrlpkt); - } - - Status = STATUS_SUCCESS; - break; - - case IOCTL_BCM_BULK_WRM: { - PBULKWRM_BUFFER pBulkBuffer; - UINT uiTempVar = 0; - PCHAR pvBuffer = NULL; - - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { - - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n"); - Status = -EACCES; break; - } - - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - /* FIXME: restrict length */ - pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); - if (!pvBuffer) - return -ENOMEM; - - /* Get WrmBuffer structure */ - if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) { - kfree(pvBuffer); - Status = -EFAULT; + case IOCTL_RTPS_BUCKET_SIZE: + Status = 0; + if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg)) + Status = -EFAULT; break; - } - - pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer; - - if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 || - ((ULONG)pBulkBuffer->Register & 0x3)) { - kfree(pvBuffer); - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)pBulkBuffer->Register); - Status = -EINVAL; + case IOCTL_CHIP_RESET: + { + INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); + if(NVMAccess) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); + return -EACCES; + } + down(&Adapter->RxAppControlQueuelock); + Status = reset_card_proc(Adapter); + flushAllAppQ(); + up(&Adapter->RxAppControlQueuelock); + up(&Adapter->NVMRdmWrmLock); + ResetCounters(Adapter); break; } + case IOCTL_QOS_THRESHOLD: + { + USHORT uiLoopIndex; - uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK; - if (!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) && - ((uiTempVar == EEPROM_REJECT_REG_1) || - (uiTempVar == EEPROM_REJECT_REG_2) || - (uiTempVar == EEPROM_REJECT_REG_3) || - (uiTempVar == EEPROM_REJECT_REG_4)) && - (cmd == IOCTL_BCM_REGISTER_WRITE)) { - - kfree(pvBuffer); - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); - Status = -EFAULT; + Status = 0; + for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) { + if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold, + (unsigned long __user *)arg)) { + Status = -EFAULT; + break; + } + } break; } - if (pBulkBuffer->SwapEndian == FALSE) - Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); - else - Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); - - if (Status != STATUS_SUCCESS) - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n"); - - kfree(pvBuffer); - break; - } - - case IOCTL_BCM_GET_NVM_SIZE: - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + case IOCTL_DUMP_PACKET_INFO: - if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) { - if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT))) - return -EFAULT; - } - - Status = STATUS_SUCCESS; - break; + DumpPackInfo(Adapter); + DumpPhsRules(&Adapter->stBCMPhsContext); + Status = STATUS_SUCCESS; + break; - case IOCTL_BCM_CAL_INIT: { - UINT uiSectorSize = 0 ; - if (Adapter->eNVMType == NVM_FLASH) { - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + case IOCTL_GET_PACK_INFO: + if(copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES)) return -EFAULT; - - if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT))) + Status = STATUS_SUCCESS; + break; + case IOCTL_BCM_SWITCH_TRANSFER_MODE: + { + UINT uiData = 0; + if(copy_from_user(&uiData, argp, sizeof(UINT))) return -EFAULT; - if ((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) { - if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, - sizeof(UINT))) - return -EFAULT; - } else { - if (IsFlash2x(Adapter)) { - if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, sizeof(UINT))) - return -EFAULT; - } else { - if ((TRUE == Adapter->bShutStatus) || (TRUE == Adapter->IdleMode)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is in Idle/Shutdown Mode\n"); - return -EACCES; - } - - Adapter->uiSectorSize = uiSectorSize; - BcmUpdateSectorSize(Adapter, Adapter->uiSectorSize); - } + if(uiData) /* Allow All Packets */ + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n"); + Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE; + } + else /* Allow IP only Packets */ + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n"); + Adapter->TransferMode = IP_PACKET_ONLY_MODE; } Status = STATUS_SUCCESS; - } else { - Status = STATUS_FAILURE; + break; } - } - break; - - case IOCTL_BCM_SET_DEBUG: -#ifdef DEBUG - { - USER_BCM_DBG_STATE sUserDebugState; - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n"); - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE))) - return -EFAULT; - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ", - sUserDebugState.OnOff, sUserDebugState.Type); - /* sUserDebugState.Subtype <<= 1; */ - sUserDebugState.Subtype = 1 << sUserDebugState.Subtype; - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype); - - /* Update new 'DebugState' in the Adapter */ - Adapter->stDebugState.type |= sUserDebugState.Type; - /* Subtype: A bitmap of 32 bits for Subtype per Type. - * Valid indexes in 'subtype' array: 1,2,4,8 - * corresponding to valid Type values. Hence we can use the 'Type' field - * as the index value, ignoring the array entries 0,3,5,6,7 ! - */ - if (sUserDebugState.OnOff) - Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype; - else - Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype; + case IOCTL_BCM_GET_DRIVER_VERSION: + { + /* Copy Ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - BCM_SHOW_DEBUG_BITMAP(Adapter); - } -#endif - break; - - case IOCTL_BCM_NVM_READ: - case IOCTL_BCM_NVM_WRITE: { - NVM_READWRITE stNVMReadWrite; - PUCHAR pReadData = NULL; - ULONG ulDSDMagicNumInUsrBuff = 0; - struct timeval tv0, tv1; - memset(&tv0, 0, sizeof(struct timeval)); - memset(&tv1, 0, sizeof(struct timeval)); - if ((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n"); - Status = -EFAULT; + if(copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength)) + return -EFAULT; + Status = STATUS_SUCCESS; break; } + case IOCTL_BCM_GET_CURRENT_STATUS: + { + LINK_STATE link_state; - if (IsFlash2x(Adapter)) { - if ((Adapter->eActiveDSD != DSD0) && - (Adapter->eActiveDSD != DSD1) && - (Adapter->eActiveDSD != DSD2)) { - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No DSD is active..hence NVM Command is blocked"); - return STATUS_FAILURE ; + /* Copy Ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n"); + Status = -EFAULT; + break; + } + if (IoBuffer.OutputLength != sizeof(link_state)) { + Status = -EINVAL; + break; } - } - - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; - - if (copy_from_user(&stNVMReadWrite, - (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer, - sizeof(NVM_READWRITE))) - return -EFAULT; - /* - * Deny the access if the offset crosses the cal area limit. - */ + memset(&link_state, 0, sizeof(link_state)); + link_state.bIdleMode = Adapter->IdleMode; + link_state.bShutdownMode = Adapter->bShutStatus; + link_state.ucLinkStatus = Adapter->LinkStatus; - if ((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) { - /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); */ - Status = STATUS_FAILURE; + if (copy_to_user(IoBuffer.OutputBuffer, &link_state, + min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n"); + Status = -EFAULT; + break; + } + Status = STATUS_SUCCESS; break; } + case IOCTL_BCM_SET_MAC_TRACING: + { + UINT tracing_flag; + + /* copy ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + if(copy_from_user(&tracing_flag,IoBuffer.InputBuffer,sizeof(UINT))) + return -EFAULT; + + if (tracing_flag) + Adapter->pTarangs->MacTracingEnabled = TRUE; + else + Adapter->pTarangs->MacTracingEnabled = FALSE; + break; + } + case IOCTL_BCM_GET_DSX_INDICATION: + { + ULONG ulSFId=0; + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + if(IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, + "Mismatch req: %lx needed is =0x%zx!!!", + IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt)); + return -EINVAL; + } - pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL); - if (!pReadData) - return -ENOMEM; + if(copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId))) + return -EFAULT; - if (copy_from_user(pReadData, stNVMReadWrite.pBuffer, stNVMReadWrite.uiNumBytes)) { - Status = -EFAULT; - kfree(pReadData); - break; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId ); + get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer); + Status=STATUS_SUCCESS; } + break; + case IOCTL_BCM_GET_HOST_MIBS: + { + PVOID temp_buff; - do_gettimeofday(&tv0); - if (IOCTL_BCM_NVM_READ == cmd) { - down(&Adapter->NVMRdmWrmLock); - - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); - up(&Adapter->NVMRdmWrmLock); - kfree(pReadData); - return -EACCES; + if(IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, + "Length Check failed %lu %zd\n", + IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS)); + return -EINVAL; } - Status = BeceemNVMRead(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); - up(&Adapter->NVMRdmWrmLock); + /* FIXME: HOST_STATS are too big for kmalloc (122048)! */ + temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL); + if(!temp_buff) + return STATUS_FAILURE; - if (Status != STATUS_SUCCESS) { - kfree(pReadData); - return Status; - } + Status = ProcessGetHostMibs(Adapter, temp_buff); + GetDroppedAppCntrlPktMibs(temp_buff, pTarang); - if (copy_to_user(stNVMReadWrite.pBuffer, pReadData, stNVMReadWrite.uiNumBytes)) { - kfree(pReadData); - Status = -EFAULT; - } - } else { - down(&Adapter->NVMRdmWrmLock); + if (Status != STATUS_FAILURE) + if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS))) + Status = -EFAULT; - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { + kfree(temp_buff); + break; + } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); - up(&Adapter->NVMRdmWrmLock); - kfree(pReadData); - return -EACCES; + case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE: + if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE==Adapter->IdleMode)) + { + Adapter->usIdleModePattern = ABORT_IDLE_MODE; + Adapter->bWakeUpDevice = TRUE; + wake_up(&Adapter->process_rx_cntrlpkt); } + Status = STATUS_SUCCESS; + break; - Adapter->bHeaderChangeAllowed = TRUE; - if (IsFlash2x(Adapter)) { - /* - * New Requirement:- - * DSD section updation will be allowed in two case:- - * 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull - * 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is - * corrupted then user space program first modify the DSD header with valid DSD sig so - * that this as well as further write may be worthwhile. - * - * This restriction has been put assuming that if DSD sig is corrupted, DSD - * data won't be considered valid. - */ + case IOCTL_BCM_BULK_WRM: + { + PBULKWRM_BUFFER pBulkBuffer; + UINT uiTempVar=0; + PCHAR pvBuffer = NULL; + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n"); + Status = -EACCES; + break; + } - Status = BcmFlash2xCorruptSig(Adapter, Adapter->eActiveDSD); - if (Status != STATUS_SUCCESS) { - if (((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize) || - (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) { + /* Copy Ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input.."); - up(&Adapter->NVMRdmWrmLock); - kfree(pReadData); - return Status; - } + /* FIXME: restrict length */ + pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); + if(!pvBuffer) + return -ENOMEM; + + /* Get WrmBuffer structure */ + if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + { + kfree(pvBuffer); + Status = -EFAULT; + break; + } - ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE)); - if (ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input.."); - up(&Adapter->NVMRdmWrmLock); - kfree(pReadData); - return Status; - } + pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer; + + if(((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 || + ((ULONG)pBulkBuffer->Register & 0x3)) + { + kfree(pvBuffer); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"WRM Done On invalid Address : %x Access Denied.\n",(int)pBulkBuffer->Register); + Status = -EINVAL; + break; } - } - Status = BeceemNVMWrite(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify); - if (IsFlash2x(Adapter)) - BcmFlash2xWriteSig(Adapter, Adapter->eActiveDSD); - Adapter->bHeaderChangeAllowed = FALSE; + uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK; + if(!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) + && ((uiTempVar == EEPROM_REJECT_REG_1)|| + (uiTempVar == EEPROM_REJECT_REG_2) || + (uiTempVar == EEPROM_REJECT_REG_3) || + (uiTempVar == EEPROM_REJECT_REG_4)) && + (cmd == IOCTL_BCM_REGISTER_WRITE)) + { + kfree(pvBuffer); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"EEPROM Access Denied, not in VSG Mode\n"); + Status = -EFAULT; + break; + } - up(&Adapter->NVMRdmWrmLock); + if(pBulkBuffer->SwapEndian == FALSE) + Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); + else + Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); - if (Status != STATUS_SUCCESS) { - kfree(pReadData); - return Status; + if(Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n"); + } + + kfree(pvBuffer); + break; } - } - do_gettimeofday(&tv1); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n", (tv1.tv_sec - tv0.tv_sec)*1000 + (tv1.tv_usec - tv0.tv_usec)/1000); + case IOCTL_BCM_GET_NVM_SIZE: + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - kfree(pReadData); - Status = STATUS_SUCCESS; - } - break; - - case IOCTL_BCM_FLASH2X_SECTION_READ: { - FLASH2X_READWRITE sFlash2xRead = {0}; - PUCHAR pReadBuff = NULL ; - UINT NOB = 0; - UINT BuffSize = 0; - UINT ReadBytes = 0; - UINT ReadOffset = 0; - void __user *OutPutBuff; - - if (IsFlash2x(Adapter) != TRUE) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); - return -EINVAL; - } + if(Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH ) { + if(copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT))) + return -EFAULT; + } + Status = STATUS_SUCCESS ; + break; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called"); - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + case IOCTL_BCM_CAL_INIT : - /* Reading FLASH 2.x READ structure */ - if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE))) - return -EFAULT; + { + UINT uiSectorSize = 0 ; + if(Adapter->eNVMType == NVM_FLASH) + { + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xRead.Section); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%x", sFlash2xRead.offset); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xRead.numOfBytes); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xRead.bVerify); + if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT))) + return -EFAULT; - /* This was internal to driver for raw read. now it has ben exposed to user space app. */ - if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == FALSE) - return STATUS_FAILURE; + if((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) + { + if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, + sizeof(UINT))) + return -EFAULT; + } + else + { + if(IsFlash2x(Adapter)) + { + if (copy_to_user(IoBuffer.OutputBuffer, + &Adapter->uiSectorSize , + sizeof(UINT))) + return -EFAULT; + } + else + { + if((TRUE == Adapter->bShutStatus) || + (TRUE == Adapter->IdleMode)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle/Shutdown Mode\n"); + return -EACCES; + } + + Adapter->uiSectorSize = uiSectorSize ; + BcmUpdateSectorSize(Adapter,Adapter->uiSectorSize); + } + } + Status = STATUS_SUCCESS ; + } + else + { + Status = STATUS_FAILURE; + } + } + break; + case IOCTL_BCM_SET_DEBUG : +#ifdef DEBUG + { + USER_BCM_DBG_STATE sUserDebugState; - NOB = sFlash2xRead.numOfBytes; - if (NOB > Adapter->uiSectorSize) - BuffSize = Adapter->uiSectorSize; - else - BuffSize = NOB; +// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Entered the ioctl %x \n", IOCTL_BCM_SET_DEBUG ); - ReadOffset = sFlash2xRead.offset ; - OutPutBuff = IoBuffer.OutputBuffer; - pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n"); + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - if (pReadBuff == NULL) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure"); - return -ENOMEM; - } - down(&Adapter->NVMRdmWrmLock); + if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE))) + return -EFAULT; - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); - up(&Adapter->NVMRdmWrmLock); - kfree(pReadBuff); - return -EACCES; - } + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ", + sUserDebugState.OnOff, sUserDebugState.Type); + //sUserDebugState.Subtype <<= 1; + sUserDebugState.Subtype = 1 << sUserDebugState.Subtype; + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype); + + // Update new 'DebugState' in the Adapter + Adapter->stDebugState.type |= sUserDebugState.Type; + /* Subtype: A bitmap of 32 bits for Subtype per Type. + * Valid indexes in 'subtype' array: 1,2,4,8 + * corresponding to valid Type values. Hence we can use the 'Type' field + * as the index value, ignoring the array entries 0,3,5,6,7 ! + */ + if (sUserDebugState.OnOff) + Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype; + else + Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype; - while (NOB) { - if (NOB > Adapter->uiSectorSize) - ReadBytes = Adapter->uiSectorSize; - else - ReadBytes = NOB; + BCM_SHOW_DEBUG_BITMAP(Adapter); - /* Reading the data from Flash 2.x */ - Status = BcmFlash2xBulkRead(Adapter, (PUINT)pReadBuff, sFlash2xRead.Section, ReadOffset, ReadBytes); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Flash 2x read err with Status :%d", Status); - break; } +#endif + break; + case IOCTL_BCM_NVM_READ: + case IOCTL_BCM_NVM_WRITE: + { + NVM_READWRITE stNVMReadWrite; + PUCHAR pReadData = NULL; + ULONG ulDSDMagicNumInUsrBuff = 0; + struct timeval tv0, tv1; + memset(&tv0,0,sizeof(struct timeval)); + memset(&tv1,0,sizeof(struct timeval)); + if((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,"The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n"); + Status = -EFAULT; + break; + } - BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes); - - Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy to use failed with status :%d", Status); - break; - } - NOB = NOB - ReadBytes; - if (NOB) { - ReadOffset = ReadOffset + ReadBytes; - OutPutBuff = OutPutBuff + ReadBytes ; - } - } + if(IsFlash2x(Adapter)) + { + if((Adapter->eActiveDSD != DSD0) && + (Adapter->eActiveDSD != DSD1) && + (Adapter->eActiveDSD != DSD2)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"No DSD is active..hence NVM Command is blocked"); + return STATUS_FAILURE ; + } + } - up(&Adapter->NVMRdmWrmLock); - kfree(pReadBuff); - } - break; - - case IOCTL_BCM_FLASH2X_SECTION_WRITE: { - FLASH2X_READWRITE sFlash2xWrite = {0}; - PUCHAR pWriteBuff; - void __user *InputAddr; - UINT NOB = 0; - UINT BuffSize = 0; - UINT WriteOffset = 0; - UINT WriteBytes = 0; - - if (IsFlash2x(Adapter) != TRUE) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); - return -EINVAL; - } + /* Copy Ioctl Buffer structure */ - /* First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite */ - Adapter->bAllDSDWriteAllow = FALSE; + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called"); + if(copy_from_user(&stNVMReadWrite, + (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer, + sizeof(NVM_READWRITE))) + return -EFAULT; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + // + // Deny the access if the offset crosses the cal area limit. + // + if((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) + { + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset , +// stNVMReadWrite.uiNumBytes); + Status = STATUS_FAILURE; + break; + } - /* Reading FLASH 2.x READ structure */ - if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE))) - return -EFAULT; + pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL); + if(!pReadData) + return -ENOMEM; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%d", sFlash2xWrite.offset); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xWrite.numOfBytes); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xWrite.bVerify); + if(copy_from_user(pReadData, stNVMReadWrite.pBuffer, + stNVMReadWrite.uiNumBytes)) + { + Status = -EFAULT; + kfree(pReadData); + break; + } - if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && (sFlash2xWrite.Section != VSA2)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Only VSA write is allowed"); - return -EINVAL; - } + do_gettimeofday(&tv0); + if(IOCTL_BCM_NVM_READ == cmd) + { + down(&Adapter->NVMRdmWrmLock); - if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == FALSE) - return STATUS_FAILURE; + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + kfree(pReadData); + return -EACCES; + } - InputAddr = sFlash2xWrite.pDataBuff; - WriteOffset = sFlash2xWrite.offset; - NOB = sFlash2xWrite.numOfBytes; + Status = BeceemNVMRead(Adapter, (PUINT)pReadData, + stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); + + up(&Adapter->NVMRdmWrmLock); + + if(Status != STATUS_SUCCESS) + { + kfree(pReadData); + return Status; + } + if(copy_to_user(stNVMReadWrite.pBuffer,pReadData, stNVMReadWrite.uiNumBytes)) + { + kfree(pReadData); + Status = -EFAULT; + } + } + else + { - if (NOB > Adapter->uiSectorSize) - BuffSize = Adapter->uiSectorSize; - else - BuffSize = NOB ; + down(&Adapter->NVMRdmWrmLock); - pWriteBuff = kmalloc(BuffSize, GFP_KERNEL); + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + kfree(pReadData); + return -EACCES; + } - if (pWriteBuff == NULL) - return -ENOMEM; + Adapter->bHeaderChangeAllowed = TRUE ; + if(IsFlash2x(Adapter)) + { + /* + New Requirement:- + DSD section updation will be allowed in two case:- + 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull + 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is + corrupted then user space program first modify the DSD header with valid DSD sig so + that this as well as further write may be worthwhile. + + This restriction has been put assuming that if DSD sig is corrupted, DSD + data won't be considered valid. + + + */ + Status = BcmFlash2xCorruptSig(Adapter,Adapter->eActiveDSD); + if(Status != STATUS_SUCCESS) + { + if(( (stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize ) || + (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input.."); + up(&Adapter->NVMRdmWrmLock); + kfree(pReadData); + return Status; + } + + ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE)); + if(ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input.."); + up(&Adapter->NVMRdmWrmLock); + kfree(pReadData); + return Status; + } + } + } + Status = BeceemNVMWrite(Adapter, (PUINT )pReadData, + stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify); + if(IsFlash2x(Adapter)) + BcmFlash2xWriteSig(Adapter,Adapter->eActiveDSD); - /* extracting the remainder of the given offset. */ - WriteBytes = Adapter->uiSectorSize; - if (WriteOffset % Adapter->uiSectorSize) - WriteBytes = Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize); + Adapter->bHeaderChangeAllowed = FALSE ; - if (NOB < WriteBytes) - WriteBytes = NOB; + up(&Adapter->NVMRdmWrmLock); - down(&Adapter->NVMRdmWrmLock); - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { + if(Status != STATUS_SUCCESS) + { + kfree(pReadData); + return Status; + } + } + do_gettimeofday(&tv1); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n",(tv1.tv_sec - tv0.tv_sec)*1000 +(tv1.tv_usec - tv0.tv_usec)/1000); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); - up(&Adapter->NVMRdmWrmLock); - kfree(pWriteBuff); - return -EACCES; - } - BcmFlash2xCorruptSig(Adapter, sFlash2xWrite.Section); - do { - Status = copy_from_user(pWriteBuff, InputAddr, WriteBytes); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to user failed with status :%d", Status); - break; + kfree(pReadData); + Status = STATUS_SUCCESS; } - BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pWriteBuff, WriteBytes); + break; + case IOCTL_BCM_FLASH2X_SECTION_READ : + { + + FLASH2X_READWRITE sFlash2xRead = {0}; + PUCHAR pReadBuff = NULL ; + UINT NOB = 0; + UINT BuffSize = 0; + UINT ReadBytes = 0; + UINT ReadOffset = 0; + void __user *OutPutBuff; + + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } - /* Writing the data from Flash 2.x */ - Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pWriteBuff, sFlash2xWrite.Section, WriteOffset, WriteBytes, sFlash2xWrite.bVerify); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called"); + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status); - break; - } + //Reading FLASH 2.x READ structure + if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer,sizeof(FLASH2X_READWRITE))) + return -EFAULT; - NOB = NOB - WriteBytes; - if (NOB) { - WriteOffset = WriteOffset + WriteBytes; - InputAddr = InputAddr + WriteBytes; - if (NOB > Adapter->uiSectorSize) - WriteBytes = Adapter->uiSectorSize; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xRead.Section); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%x" ,sFlash2xRead.offset); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xRead.numOfBytes); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xRead.bVerify); + + //This was internal to driver for raw read. now it has ben exposed to user space app. + if(validateFlash2xReadWrite(Adapter,&sFlash2xRead) == FALSE) + return STATUS_FAILURE ; + + NOB = sFlash2xRead.numOfBytes; + if(NOB > Adapter->uiSectorSize ) + BuffSize = Adapter->uiSectorSize; else - WriteBytes = NOB; - } - } while (NOB > 0); + BuffSize = NOB ; - BcmFlash2xWriteSig(Adapter, sFlash2xWrite.Section); - up(&Adapter->NVMRdmWrmLock); - kfree(pWriteBuff); - } - break; + ReadOffset = sFlash2xRead.offset ; + OutPutBuff = IoBuffer.OutputBuffer; - case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP: { - PFLASH2X_BITMAP psFlash2xBitMap; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called"); - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL); + if(pReadBuff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure"); + return -ENOMEM; + } + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + kfree(pReadBuff); + return -EACCES; + } - if (IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP)) - return -EINVAL; + while(NOB) + { - psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL); - if (psFlash2xBitMap == NULL) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory is not available"); - return -ENOMEM; - } + if(NOB > Adapter->uiSectorSize ) + ReadBytes = Adapter->uiSectorSize; + else + ReadBytes = NOB; - /* Reading the Flash Sectio Bit map */ - down(&Adapter->NVMRdmWrmLock); - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { + //Reading the data from Flash 2.x - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); - up(&Adapter->NVMRdmWrmLock); - kfree(psFlash2xBitMap); - return -EACCES; - } + Status = BcmFlash2xBulkRead(Adapter,(PUINT)pReadBuff,sFlash2xRead.Section,ReadOffset,ReadBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Flash 2x read err with Status :%d", Status); + break ; + } - BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap); - up(&Adapter->NVMRdmWrmLock); - if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP))) - Status = -EFAULT; + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff, ReadBytes); + + Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Copy to use failed with status :%d", Status); + break; + } + NOB = NOB - ReadBytes; + if(NOB) + { + ReadOffset = ReadOffset + ReadBytes ; + OutPutBuff = OutPutBuff + ReadBytes ; + } - kfree(psFlash2xBitMap); - } - break; + } + up(&Adapter->NVMRdmWrmLock); + kfree(pReadBuff); + + } + break ; + case IOCTL_BCM_FLASH2X_SECTION_WRITE : + { + FLASH2X_READWRITE sFlash2xWrite = {0}; + PUCHAR pWriteBuff; + void __user *InputAddr; + UINT NOB = 0; + UINT BuffSize = 0; + UINT WriteOffset = 0; + UINT WriteBytes = 0; + + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } - case IOCTL_BCM_SET_ACTIVE_SECTION: { - FLASH2X_SECTION_VAL eFlash2xSectionVal = 0; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called"); + //First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite + Adapter->bAllDSDWriteAllow = FALSE; - if (IsFlash2x(Adapter) != TRUE) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); - return -EINVAL; - } - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); - return Status; - } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_FLASH2X_SECTION_WRITE Called"); + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT)); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); - return Status; - } + //Reading FLASH 2.x READ structure + if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE))) + return -EFAULT; - down(&Adapter->NVMRdmWrmLock); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xWrite.Section); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%d" ,sFlash2xWrite.offset); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xWrite.numOfBytes); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xWrite.bVerify); + if((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && + (sFlash2xWrite.Section != VSA2) ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Only VSA write is allowed"); + return -EINVAL; + } - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { + if(validateFlash2xReadWrite(Adapter,&sFlash2xWrite) == FALSE) + return STATUS_FAILURE ; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); - up(&Adapter->NVMRdmWrmLock); - return -EACCES; - } + InputAddr = sFlash2xWrite.pDataBuff; + WriteOffset = sFlash2xWrite.offset ; + NOB = sFlash2xWrite.numOfBytes; - Status = BcmSetActiveSection(Adapter, eFlash2xSectionVal); - if (Status) - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Failed to make it's priority Highest. Status %d", Status); + if(NOB > Adapter->uiSectorSize ) + BuffSize = Adapter->uiSectorSize; + else + BuffSize = NOB ; - up(&Adapter->NVMRdmWrmLock); - } - break; + pWriteBuff = kmalloc(BuffSize, GFP_KERNEL); + if(pWriteBuff == NULL) + return -ENOMEM; - case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION: { - /* Right Now we are taking care of only DSD */ - Adapter->bAllDSDWriteAllow = FALSE; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called"); - Status = STATUS_SUCCESS; - } - break; - case IOCTL_BCM_COPY_SECTION: { - FLASH2X_COPY_SECTION sCopySectStrut = {0}; - Status = STATUS_SUCCESS; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called"); + //extracting the remainder of the given offset. + WriteBytes = Adapter->uiSectorSize ; + if(WriteOffset % Adapter->uiSectorSize) + WriteBytes =Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize); + if(NOB < WriteBytes) + WriteBytes = NOB; - Adapter->bAllDSDWriteAllow = FALSE; - if (IsFlash2x(Adapter) != TRUE) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); - return -EINVAL; - } + down(&Adapter->NVMRdmWrmLock); - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status); - return Status; - } + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + kfree(pWriteBuff); + return -EACCES; + } - Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION)); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status); - return Status; - } + BcmFlash2xCorruptSig(Adapter,sFlash2xWrite.Section); + do + { + Status = copy_from_user(pWriteBuff,InputAddr,WriteBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to user failed with status :%d", Status); + break ; + } + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pWriteBuff,WriteBytes); + //Writing the data from Flash 2.x + Status = BcmFlash2xBulkWrite(Adapter,(PUINT)pWriteBuff,sFlash2xWrite.Section,WriteOffset,WriteBytes,sFlash2xWrite.bVerify); + + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status); + break ; + } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes); + NOB = NOB - WriteBytes; + if(NOB) + { + WriteOffset = WriteOffset + WriteBytes ; + InputAddr = InputAddr + WriteBytes ; + if(NOB > Adapter->uiSectorSize ) + WriteBytes = Adapter->uiSectorSize; + else + WriteBytes = NOB; + } - if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == FALSE) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection); - return -EINVAL; - } - if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == FALSE) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection); - return -EINVAL; - } + } while(NOB > 0); + BcmFlash2xWriteSig(Adapter,sFlash2xWrite.Section); + up(&Adapter->NVMRdmWrmLock); + kfree(pWriteBuff); + } + break ; + case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP : + { - if (sCopySectStrut.SrcSection == sCopySectStrut.DstSection) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source and Destination section should be different"); - return -EINVAL; - } + PFLASH2X_BITMAP psFlash2xBitMap; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called"); - down(&Adapter->NVMRdmWrmLock); + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { + if(IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP)) + return -EINVAL; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); - up(&Adapter->NVMRdmWrmLock); - return -EACCES; - } + psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL); + if(psFlash2xBitMap == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory is not available"); + return -ENOMEM ; + } + //Reading the Flash Sectio Bit map + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + kfree(psFlash2xBitMap); + return -EACCES; + } - if (sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) { - if (IsNonCDLessDevice(Adapter)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is Non-CDLess hence won't have ISO !!"); - Status = -EINVAL; - } else if (sCopySectStrut.numOfBytes == 0) { - Status = BcmCopyISO(Adapter, sCopySectStrut); - } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Partial Copy of ISO section is not Allowed.."); - Status = STATUS_FAILURE; - } - up(&Adapter->NVMRdmWrmLock); - return Status; - } + BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap); + up(&Adapter->NVMRdmWrmLock); + if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP))) + Status = -EFAULT; + + kfree(psFlash2xBitMap); + } + break ; + case IOCTL_BCM_SET_ACTIVE_SECTION : + { + FLASH2X_SECTION_VAL eFlash2xSectionVal = 0; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called"); + + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } - Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection, - sCopySectStrut.DstSection, sCopySectStrut.offset, sCopySectStrut.numOfBytes); - up(&Adapter->NVMRdmWrmLock); - } - break; + Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + return Status; + } - case IOCTL_BCM_GET_FLASH_CS_INFO: { - Status = STATUS_SUCCESS; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called"); + Status = copy_from_user(&eFlash2xSectionVal,IoBuffer.InputBuffer, sizeof(INT)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); + return Status; + } - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); - break; - } + down(&Adapter->NVMRdmWrmLock); - if (Adapter->eNVMType != NVM_FLASH) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Connected device does not have flash"); - Status = -EINVAL; - break; - } + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + return -EACCES; + } - if (IsFlash2x(Adapter) == TRUE) { - if (IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO)) - return -EINVAL; + Status = BcmSetActiveSection(Adapter,eFlash2xSectionVal); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed to make it's priority Highest. Status %d", Status); + } + up(&Adapter->NVMRdmWrmLock); + } + break ; + case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION : + { + //Right Now we are taking care of only DSD + Adapter->bAllDSDWriteAllow = FALSE ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called"); + + Status = STATUS_SUCCESS ; + } + break ; + case IOCTL_BCM_COPY_SECTION : + { + FLASH2X_COPY_SECTION sCopySectStrut = {0}; + Status = STATUS_SUCCESS; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called"); + + Adapter->bAllDSDWriteAllow = FALSE ; + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } - if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO))) - return -EFAULT; - } else { - if (IoBuffer.OutputLength < sizeof(FLASH_CS_INFO)) - return -EINVAL; + Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status); + return Status; + } - if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO))) - return -EFAULT; - } - } - break; + Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status); + return Status; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes); - case IOCTL_BCM_SELECT_DSD: { - UINT SectOfset = 0; - FLASH2X_SECTION_VAL eFlash2xSectionVal; - eFlash2xSectionVal = NO_SECTION_VAL; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SELECT_DSD Called"); - if (IsFlash2x(Adapter) != TRUE) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); - return -EINVAL; - } + if(IsSectionExistInFlash(Adapter,sCopySectStrut.SrcSection) == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection); + return -EINVAL; + } - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); - return Status; - } - Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT)); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); - return Status; - } + if(IsSectionExistInFlash(Adapter,sCopySectStrut.DstSection) == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection); + return -EINVAL; + } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read Section :%d", eFlash2xSectionVal); - if ((eFlash2xSectionVal != DSD0) && - (eFlash2xSectionVal != DSD1) && - (eFlash2xSectionVal != DSD2)) { + if(sCopySectStrut.SrcSection == sCopySectStrut.DstSection) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Source and Destination section should be different"); + return -EINVAL; + } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Passed section<%x> is not DSD section", eFlash2xSectionVal); - return STATUS_FAILURE; - } + down(&Adapter->NVMRdmWrmLock); - SectOfset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal); - if (SectOfset == INVALID_OFFSET) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal); - return -EINVAL; - } + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + return -EACCES; + } - Adapter->bAllDSDWriteAllow = TRUE; - Adapter->ulFlashCalStart = SectOfset; - Adapter->eActiveDSD = eFlash2xSectionVal; - } - Status = STATUS_SUCCESS; - break; - - case IOCTL_BCM_NVM_RAW_READ: { - NVM_READWRITE stNVMRead; - INT NOB ; - INT BuffSize ; - INT ReadOffset = 0; - UINT ReadBytes = 0 ; - PUCHAR pReadBuff; - void __user *OutPutBuff; - - if (Adapter->eNVMType != NVM_FLASH) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NVM TYPE is not Flash"); - return -EINVAL; - } + if(sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) + { + if(IsNonCDLessDevice(Adapter)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is Non-CDLess hence won't have ISO !!"); + Status = -EINVAL ; + } + else if(sCopySectStrut.numOfBytes == 0) + { + Status = BcmCopyISO(Adapter,sCopySectStrut); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Partial Copy of ISO section is not Allowed.."); + Status = STATUS_FAILURE ; + } + up(&Adapter->NVMRdmWrmLock); + return Status; + } - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n"); - Status = -EFAULT; - break; - } + Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection, + sCopySectStrut.DstSection,sCopySectStrut.offset,sCopySectStrut.numOfBytes); + up(&Adapter->NVMRdmWrmLock); + } + break ; + case IOCTL_BCM_GET_FLASH_CS_INFO : + { + Status = STATUS_SUCCESS; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called"); + + Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + break; + } + if(Adapter->eNVMType != NVM_FLASH) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Connected device does not have flash"); + Status = -EINVAL; + break; + } + if(IsFlash2x(Adapter) == TRUE) + { - if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(NVM_READWRITE))) - return -EFAULT; + if(IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO)) + return -EINVAL; - NOB = stNVMRead.uiNumBytes; - /* In Raw-Read max Buff size : 64MB */ + if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO))) + return -EFAULT; + } + else + { + if(IoBuffer.OutputLength < sizeof(FLASH_CS_INFO)) + return -EINVAL; - if (NOB > DEFAULT_BUFF_SIZE) - BuffSize = DEFAULT_BUFF_SIZE; - else - BuffSize = NOB; + if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO))) + return -EFAULT; - ReadOffset = stNVMRead.uiOffset; - OutPutBuff = stNVMRead.pBuffer; + } + } + break ; + case IOCTL_BCM_SELECT_DSD : + { + UINT SectOfset = 0; + FLASH2X_SECTION_VAL eFlash2xSectionVal; + eFlash2xSectionVal = NO_SECTION_VAL ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_SELECT_DSD Called"); + + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } - pReadBuff = kzalloc(BuffSize , GFP_KERNEL); - if (pReadBuff == NULL) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure"); - Status = -ENOMEM; - break; - } - down(&Adapter->NVMRdmWrmLock); + Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + return Status; + } + Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); + return Status; + } - if ((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus == TRUE) || - (Adapter->bPreparingForLowPowerMode == TRUE)) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", eFlash2xSectionVal); + if((eFlash2xSectionVal != DSD0) && + (eFlash2xSectionVal != DSD1) && + (eFlash2xSectionVal != DSD2) ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Passed section<%x> is not DSD section", eFlash2xSectionVal); + return STATUS_FAILURE ; + } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); - kfree(pReadBuff); - up(&Adapter->NVMRdmWrmLock); - return -EACCES; - } + SectOfset= BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal); + if(SectOfset == INVALID_OFFSET) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal); + return -EINVAL; + } - Adapter->bFlashRawRead = TRUE; + Adapter->bAllDSDWriteAllow = TRUE ; + + Adapter->ulFlashCalStart = SectOfset ; + Adapter->eActiveDSD = eFlash2xSectionVal; + } + Status = STATUS_SUCCESS ; + break; + + case IOCTL_BCM_NVM_RAW_READ : + { + + NVM_READWRITE stNVMRead; + INT NOB ; + INT BuffSize ; + INT ReadOffset = 0; + UINT ReadBytes = 0 ; + PUCHAR pReadBuff; + void __user *OutPutBuff; + + if(Adapter->eNVMType != NVM_FLASH) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"NVM TYPE is not Flash "); + return -EINVAL ; + } - while (NOB) { - if (NOB > DEFAULT_BUFF_SIZE) - ReadBytes = DEFAULT_BUFF_SIZE; - else - ReadBytes = NOB; + /* Copy Ioctl Buffer structure */ + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n"); + Status = -EFAULT; + break; + } - /* Reading the data from Flash 2.x */ - Status = BeceemNVMRead(Adapter, (PUINT)pReadBuff, ReadOffset, ReadBytes); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status); - break; - } + if(copy_from_user(&stNVMRead, IoBuffer.OutputBuffer,sizeof(NVM_READWRITE))) + return -EFAULT; - BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes); + NOB = stNVMRead.uiNumBytes; + //In Raw-Read max Buff size : 64MB - Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to use failed with status :%d", Status); - break; - } - NOB = NOB - ReadBytes; - if (NOB) { - ReadOffset = ReadOffset + ReadBytes; - OutPutBuff = OutPutBuff + ReadBytes; - } - } - Adapter->bFlashRawRead = FALSE; - up(&Adapter->NVMRdmWrmLock); - kfree(pReadBuff); - break; - } + if(NOB > DEFAULT_BUFF_SIZE) + BuffSize = DEFAULT_BUFF_SIZE; + else + BuffSize = NOB ; - case IOCTL_BCM_CNTRLMSG_MASK: { - ULONG RxCntrlMsgBitMask = 0; + ReadOffset = stNVMRead.uiOffset; + OutPutBuff = stNVMRead.pBuffer; - /* Copy Ioctl Buffer structure */ - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space"); - Status = -EFAULT; - break; - } + pReadBuff = kzalloc(BuffSize , GFP_KERNEL); + if(pReadBuff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure"); + Status = -ENOMEM; + break; + } + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + kfree(pReadBuff); + up(&Adapter->NVMRdmWrmLock); + return -EACCES; + } - if (IoBuffer.InputLength != sizeof(unsigned long)) { - Status = -EINVAL; - break; - } + Adapter->bFlashRawRead = TRUE ; + while(NOB) + { + if(NOB > DEFAULT_BUFF_SIZE ) + ReadBytes = DEFAULT_BUFF_SIZE; + else + ReadBytes = NOB; + + //Reading the data from Flash 2.x + Status = BeceemNVMRead(Adapter,(PUINT)pReadBuff,ReadOffset,ReadBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status); + break; + } - Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength); - if (Status) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of control bit mask failed from user space"); - Status = -EFAULT; - break; - } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask); - pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask; - } - break; + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff,ReadBytes); + + Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to use failed with status :%d", Status); + break; + } + NOB = NOB - ReadBytes; + if(NOB) + { + ReadOffset = ReadOffset + ReadBytes ; + OutPutBuff = OutPutBuff + ReadBytes ; + } - case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: { - DEVICE_DRIVER_INFO DevInfo; + } + Adapter->bFlashRawRead = FALSE ; + up(&Adapter->NVMRdmWrmLock); + kfree(pReadBuff); + break ; + } + + case IOCTL_BCM_CNTRLMSG_MASK: + { + ULONG RxCntrlMsgBitMask = 0 ; + + /* Copy Ioctl Buffer structure */ + Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of Ioctl buffer is failed from user space"); + Status = -EFAULT; + break; + } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n"); + if (IoBuffer.InputLength != sizeof(unsigned long)) { + Status = -EINVAL; + break; + } - DevInfo.MaxRDMBufferSize = BUFFER_4K; - DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START; - DevInfo.u32RxAlignmentCorrection = 0; - DevInfo.u32NVMType = Adapter->eNVMType; - DevInfo.u32InterfaceType = BCM_USB; + Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of control bit mask failed from user space"); + Status = -EFAULT; + break; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask); + pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask ; + } + break; + case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: + { + DEVICE_DRIVER_INFO DevInfo; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n"); + + DevInfo.MaxRDMBufferSize = BUFFER_4K; + DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START; + DevInfo.u32RxAlignmentCorrection = 0; + DevInfo.u32NVMType = Adapter->eNVMType; + DevInfo.u32InterfaceType = BCM_USB; + + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + if(IoBuffer.OutputLength < sizeof(DevInfo)) + return -EINVAL; - if (IoBuffer.OutputLength < sizeof(DevInfo)) - return -EINVAL; + if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo))) + return -EFAULT; + } + break ; - if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo))) - return -EFAULT; - } - break; + case IOCTL_BCM_TIME_SINCE_NET_ENTRY: + { + ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0}; - case IOCTL_BCM_TIME_SINCE_NET_ENTRY: { - ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0}; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_TIME_SINCE_NET_ENTRY called"); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_TIME_SINCE_NET_ENTRY called"); + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + if(IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED)) + return -EINVAL; - if (IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED)) - return -EINVAL; + stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry; - stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry; + if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED))) + return -EFAULT; - if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED))) - return -EFAULT; - } - break; + } + break; - case IOCTL_CLOSE_NOTIFICATION: - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_CLOSE_NOTIFICATION"); - break; + case IOCTL_CLOSE_NOTIFICATION: + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_CLOSE_NOTIFICATION"); + break; - default: - pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd); - Status = STATUS_FAILURE; - break; + default: + pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd); + Status = STATUS_FAILURE; + break; } return Status; } @@ -1976,6 +2107,8 @@ static const struct file_operations bcm_fops = { .llseek = no_llseek, }; +extern struct class *bcm_class; + int register_control_device_interface(PMINI_ADAPTER Adapter) { @@ -1989,8 +2122,8 @@ int register_control_device_interface(PMINI_ADAPTER Adapter) } Adapter->pstCreatedClassDevice = device_create(bcm_class, NULL, - MKDEV(Adapter->major, 0), - Adapter, DEV_NAME); + MKDEV(Adapter->major, 0), + Adapter, DEV_NAME); if (IS_ERR(Adapter->pstCreatedClassDevice)) { pr_err(DRV_NAME ": class device create failed\n"); @@ -2008,4 +2141,3 @@ void unregister_control_device_interface(PMINI_ADAPTER Adapter) unregister_chrdev(Adapter->major, DEV_NAME); } } - diff --git a/trunk/drivers/staging/bcm/Macros.h b/trunk/drivers/staging/bcm/Macros.h index 46ed99c53764..916bebb7ed50 100644 --- a/trunk/drivers/staging/bcm/Macros.h +++ b/trunk/drivers/staging/bcm/Macros.h @@ -1,17 +1,17 @@ /************************************* -* Macros.h +* Macros.h **************************************/ -#ifndef __MACROS_H__ +#ifndef __MACROS_H__ #define __MACROS_H__ -#define TX_TIMER_PERIOD 10 /*10 msec*/ +#define TX_TIMER_PERIOD 10 //10 msec #define MAX_CLASSIFIERS 100 -/* #define MAX_CLASSIFIERS_PER_SF 20 */ +//#define MAX_CLASSIFIERS_PER_SF 20 #define MAX_TARGET_DSX_BUFFERS 24 -#define MAX_CNTRL_PKTS 100 -#define MAX_DATA_PKTS 200 -#define MAX_ETH_SIZE 1536 +#define MAX_CNTRL_PKTS 100 +#define MAX_DATA_PKTS 200 +#define MAX_ETH_SIZE 1536 #define MAX_CNTL_PKT_SIZE 2048 #define MTU_SIZE 1400 @@ -20,102 +20,102 @@ #define MAC_ADDR_REGISTER 0xbf60d000 -/* Quality of Service */ -#define NO_OF_QUEUES 17 -#define HiPriority (NO_OF_QUEUES-1) -#define LowPriority 0 -#define BE 2 -#define rtPS 4 -#define ERTPS 5 -#define UGS 6 - -#define BE_BUCKET_SIZE (1024*1024*100) /* 32kb */ -#define rtPS_BUCKET_SIZE (1024*1024*100) /* 8kb */ -#define MAX_ALLOWED_RATE (1024*1024*100) -#define TX_PACKET_THRESHOLD 10 -#define XSECONDS (1*HZ) -#define DSC_ACTIVATE_REQUEST 248 -#define QUEUE_DEPTH_OFFSET 0x1fc01000 -#define MAX_DEVICE_DESC_SIZE 2040 -#define MAX_CTRL_QUEUE_LEN 100 -#define MAX_APP_QUEUE_LEN 200 -#define MAX_LATENCY_ALLOWED 0xFFFFFFFF -#define DEFAULT_UG_INTERVAL 250 -#define DEFAULT_UGI_FACTOR 4 - -#define DEFAULT_PERSFCOUNT 60 -#define MAX_CONNECTIONS 10 -#define MAX_CLASS_NAME_LENGTH 32 - -#define ETH_LENGTH_OF_ADDRESS 6 -#define MAX_MULTICAST_ADDRESSES 32 -#define IP_LENGTH_OF_ADDRESS 4 - -#define IP_PACKET_ONLY_MODE 0 -#define ETH_PACKET_TUNNELING_MODE 1 - -/* Link Request */ -#define SET_MAC_ADDRESS_REQUEST 0 -#define SYNC_UP_REQUEST 1 -#define SYNCED_UP 2 -#define LINK_UP_REQUEST 3 -#define LINK_CONNECTED 4 -#define SYNC_UP_NOTIFICATION 2 -#define LINK_UP_NOTIFICATION 4 +///////////Quality of Service/////////////////////////// +#define NO_OF_QUEUES 17 +#define HiPriority NO_OF_QUEUES-1 +#define LowPriority 0 +#define BE 2 +#define rtPS 4 +#define ERTPS 5 +#define UGS 6 + +#define BE_BUCKET_SIZE 1024*1024*100 //32kb +#define rtPS_BUCKET_SIZE 1024*1024*100 //8kb +#define MAX_ALLOWED_RATE 1024*1024*100 +#define TX_PACKET_THRESHOLD 10 +#define XSECONDS 1*HZ +#define DSC_ACTIVATE_REQUEST 248 +#define QUEUE_DEPTH_OFFSET 0x1fc01000 +#define MAX_DEVICE_DESC_SIZE 2040 +#define MAX_CTRL_QUEUE_LEN 100 +#define MAX_APP_QUEUE_LEN 200 +#define MAX_LATENCY_ALLOWED 0xFFFFFFFF +#define DEFAULT_UG_INTERVAL 250 +#define DEFAULT_UGI_FACTOR 4 + +#define DEFAULT_PERSFCOUNT 60 +#define MAX_CONNECTIONS 10 +#define MAX_CLASS_NAME_LENGTH 32 + +#define ETH_LENGTH_OF_ADDRESS 6 +#define MAX_MULTICAST_ADDRESSES 32 +#define IP_LENGTH_OF_ADDRESS 4 + +#define IP_PACKET_ONLY_MODE 0 +#define ETH_PACKET_TUNNELING_MODE 1 + +////////////Link Request////////////// +#define SET_MAC_ADDRESS_REQUEST 0 +#define SYNC_UP_REQUEST 1 +#define SYNCED_UP 2 +#define LINK_UP_REQUEST 3 +#define LINK_CONNECTED 4 +#define SYNC_UP_NOTIFICATION 2 +#define LINK_UP_NOTIFICATION 4 #define LINK_NET_ENTRY 0x0002 -#define HMC_STATUS 0x0004 +#define HMC_STATUS 0x0004 #define LINK_UP_CONTROL_REQ 0x83 #define STATS_POINTER_REQ_STATUS 0x86 #define NETWORK_ENTRY_REQ_PAYLOAD 198 -#define LINK_DOWN_REQ_PAYLOAD 226 +#define LINK_DOWN_REQ_PAYLOAD 226 #define SYNC_UP_REQ_PAYLOAD 228 -#define STATISTICS_POINTER_REQ 237 +#define STATISTICS_POINTER_REQ 237 #define LINK_UP_REQ_PAYLOAD 245 #define LINK_UP_ACK 246 #define STATS_MSG_SIZE 4 #define INDEX_TO_DATA 4 -#define GO_TO_IDLE_MODE_PAYLOAD 210 -#define COME_UP_FROM_IDLE_MODE_PAYLOAD 211 -#define IDLE_MODE_SF_UPDATE_MSG 187 +#define GO_TO_IDLE_MODE_PAYLOAD 210 +#define COME_UP_FROM_IDLE_MODE_PAYLOAD 211 +#define IDLE_MODE_SF_UPDATE_MSG 187 -#define SKB_RESERVE_ETHERNET_HEADER 16 -#define SKB_RESERVE_PHS_BYTES 32 +#define SKB_RESERVE_ETHERNET_HEADER 16 +#define SKB_RESERVE_PHS_BYTES 32 -#define IP_PACKET_ONLY_MODE 0 -#define ETH_PACKET_TUNNELING_MODE 1 +#define IP_PACKET_ONLY_MODE 0 +#define ETH_PACKET_TUNNELING_MODE 1 -#define ETH_CS_802_3 1 -#define ETH_CS_802_1Q_VLAN 3 -#define IPV4_CS 1 -#define IPV6_CS 2 -#define ETH_CS_MASK 0x3f +#define ETH_CS_802_3 1 +#define ETH_CS_802_1Q_VLAN 3 +#define IPV4_CS 1 +#define IPV6_CS 2 +#define ETH_CS_MASK 0x3f /** \brief Validity bit maps for TLVs in packet classification rule */ -#define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0 -#define PKT_CLASSIFICATION_VLANID_VALID 1 +#define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0 +#define PKT_CLASSIFICATION_VLANID_VALID 1 #ifndef MIN -#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) +#define MIN(_a, _b) ((_a) < (_b)? (_a): (_b)) #endif /*Leader related terms */ -#define LEADER_STATUS 0x00 -#define LEADER_STATUS_TCP_ACK 0x1 -#define LEADER_SIZE sizeof(LEADER) -#define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND) -#define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND) -#define CM_REQUEST_SIZE (LEADER_SIZE + sizeof(stLocalSFChangeRequest)) -#define IDLE_REQ_SIZE sizeof(PACKETTOSEND) +#define LEADER_STATUS 0x00 +#define LEADER_STATUS_TCP_ACK 0x1 +#define LEADER_SIZE sizeof(LEADER) +#define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND) +#define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND) +#define CM_REQUEST_SIZE LEADER_SIZE + sizeof(stLocalSFChangeRequest) +#define IDLE_REQ_SIZE sizeof(PACKETTOSEND) -#define MAX_TRANSFER_CTRL_BYTE_USB (2*1024) +#define MAX_TRANSFER_CTRL_BYTE_USB 2 * 1024 #define GET_MAILBOX1_REG_REQUEST 0x87 #define GET_MAILBOX1_REG_RESPONSE 0x67 @@ -124,40 +124,40 @@ #define TRANSMIT_NETWORK_DATA 0x00 #define RECEIVED_NETWORK_DATA 0x20 -#define CM_RESPONSES 0xA0 -#define STATUS_RSP 0xA1 -#define LINK_CONTROL_RESP 0xA2 -#define IDLE_MODE_STATUS 0xA3 -#define STATS_POINTER_RESP 0xA6 -#define MGMT_MSG_INFO_SW_STATUS 0xA7 -#define AUTH_SS_HOST_MSG 0xA8 - -#define CM_DSA_ACK_PAYLOAD 247 -#define CM_DSC_ACK_PAYLOAD 248 -#define CM_DSD_ACK_PAYLOAD 249 -#define CM_DSDEACTVATE 250 -#define TOTAL_MASKED_ADDRESS_IN_BYTES 32 - -#define MAC_REQ 0 -#define LINK_RESP 1 -#define RSSI_INDICATION 2 - -#define SS_INFO 4 -#define STATISTICS_INFO 5 -#define CM_INDICATION 6 -#define PARAM_RESP 7 -#define BUFFER_1K 1024 -#define BUFFER_2K (BUFFER_1K*2) -#define BUFFER_4K (BUFFER_2K*2) -#define BUFFER_8K (BUFFER_4K*2) -#define BUFFER_16K (BUFFER_8K*2) -#define DOWNLINK_DIR 0 -#define UPLINK_DIR 1 - -#define BCM_SIGNATURE "BECEEM" - - -#define GPIO_OUTPUT_REGISTER 0x0F00003C +#define CM_RESPONSES 0xA0 +#define STATUS_RSP 0xA1 +#define LINK_CONTROL_RESP 0xA2 +#define IDLE_MODE_STATUS 0xA3 +#define STATS_POINTER_RESP 0xA6 +#define MGMT_MSG_INFO_SW_STATUS 0xA7 +#define AUTH_SS_HOST_MSG 0xA8 + +#define CM_DSA_ACK_PAYLOAD 247 +#define CM_DSC_ACK_PAYLOAD 248 +#define CM_DSD_ACK_PAYLOAD 249 +#define CM_DSDEACTVATE 250 +#define TOTAL_MASKED_ADDRESS_IN_BYTES 32 + +#define MAC_REQ 0 +#define LINK_RESP 1 +#define RSSI_INDICATION 2 + +#define SS_INFO 4 +#define STATISTICS_INFO 5 +#define CM_INDICATION 6 +#define PARAM_RESP 7 +#define BUFFER_1K 1024 +#define BUFFER_2K BUFFER_1K*2 +#define BUFFER_4K BUFFER_2K*2 +#define BUFFER_8K BUFFER_4K*2 +#define BUFFER_16K BUFFER_8K*2 +#define DOWNLINK_DIR 0 +#define UPLINK_DIR 1 + +#define BCM_SIGNATURE "BECEEM" + + +#define GPIO_OUTPUT_REGISTER 0x0F00003C #define BCM_GPIO_OUTPUT_SET_REG 0x0F000040 #define BCM_GPIO_OUTPUT_CLR_REG 0x0F000044 #define GPIO_MODE_REGISTER 0x0F000034 @@ -165,43 +165,44 @@ typedef struct _LINK_STATE { - UCHAR ucLinkStatus; - UCHAR bIdleMode; - UCHAR bShutdownMode; -} LINK_STATE, *PLINK_STATE; + UCHAR ucLinkStatus; + UCHAR bIdleMode; + UCHAR bShutdownMode; +}LINK_STATE, *PLINK_STATE; enum enLinkStatus { - WAIT_FOR_SYNC = 1, - PHY_SYNC_ACHIVED = 2, - LINKUP_IN_PROGRESS = 3, - LINKUP_DONE = 4, - DREG_RECEIVED = 5, - LINK_STATUS_RESET_RECEIVED = 6, - PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7, - LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8, - COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW = 9 + WAIT_FOR_SYNC = 1, + PHY_SYNC_ACHIVED = 2, + LINKUP_IN_PROGRESS = 3, + LINKUP_DONE = 4, + DREG_RECEIVED = 5, + LINK_STATUS_RESET_RECEIVED = 6, + PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7, + LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8, + COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW =9 }; -typedef enum _E_PHS_DSC_ACTION { - eAddPHSRule = 0, +typedef enum _E_PHS_DSC_ACTION +{ + eAddPHSRule=0, eSetPHSRule, eDeletePHSRule, eDeleteAllPHSRules -} E_PHS_DSC_ACTION; +}E_PHS_DSC_ACTION; -#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 /* Host to Mac */ -#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 /* Mac to Host */ -#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 /* 0b000010000 */ -#define MINIMUM_PENDING_DESCRIPTORS 5 +#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 // Host to Mac +#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 // Mac to Host +#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 //0b000010000 +#define MINIMUM_PENDING_DESCRIPTORS 5 #define SHUTDOWN_HOSTINITIATED_REQUESTPAYLOAD 0xCC #define SHUTDOWN_ACK_FROM_DRIVER 0x1 #define SHUTDOWN_NACK_FROM_DRIVER 0x2 -#define LINK_SYNC_UP_SUBTYPE 0x0001 -#define LINK_SYNC_DOWN_SUBTYPE 0x0001 +#define LINK_SYNC_UP_SUBTYPE 0x0001 +#define LINK_SYNC_DOWN_SUBTYPE 0x0001 @@ -225,9 +226,9 @@ typedef enum _E_PHS_DSC_ACTION { #define MAX_PENDING_CTRL_PACKET (MAX_CTRL_QUEUE_LEN-10) -#define WIMAX_MAX_MTU (MTU_SIZE + ETH_HLEN) +#define WIMAX_MAX_MTU (MTU_SIZE + ETH_HLEN) #define AUTO_LINKUP_ENABLE 0x2 -#define AUTO_SYNC_DISABLE 0x1 +#define AUTO_SYNC_DISABLE 0x1 #define AUTO_FIRM_DOWNLOAD 0x1 #define SETTLE_DOWN_TIME 50 @@ -241,9 +242,9 @@ typedef enum _E_PHS_DSC_ACTION { #define TARGET_CAN_NOT_GO_TO_IDLE_MODE 3 #define IDLE_MODE_PAYLOAD_LENGTH 8 -#define IP_HEADER(Buffer) ((IPHeaderFormat *)(Buffer)) -#define IPV4 4 -#define IP_VERSION(byte) (((byte&0xF0)>>4)) +#define IP_HEADER(Buffer) ((IPHeaderFormat*)(Buffer)) +#define IPV4 4 +#define IP_VERSION(byte) (((byte&0xF0)>>4)) #define SET_MAC_ADDRESS 193 #define SET_MAC_ADDRESS_RESPONSE 236 @@ -262,15 +263,15 @@ typedef enum _E_PHS_DSC_ACTION { #define INVALID_QUEUE_INDEX NO_OF_QUEUES -#define INVALID_PID ((pid_t)-1) -#define DDR_80_MHZ 0 -#define DDR_100_MHZ 1 -#define DDR_120_MHZ 2 /* Additional Frequency for T3LP */ -#define DDR_133_MHZ 3 -#define DDR_140_MHZ 4 /* Not Used (Reserved for future) */ -#define DDR_160_MHZ 5 /* Additional Frequency for T3LP */ -#define DDR_180_MHZ 6 /* Not Used (Reserved for future) */ -#define DDR_200_MHZ 7 /* Not Used (Reserved for future) */ +#define INVALID_PID (pid_t)-1 +#define DDR_80_MHZ 0 +#define DDR_100_MHZ 1 +#define DDR_120_MHZ 2 // Additional Frequency for T3LP +#define DDR_133_MHZ 3 +#define DDR_140_MHZ 4 // Not Used (Reserved for future) +#define DDR_160_MHZ 5 // Additional Frequency for T3LP +#define DDR_180_MHZ 6 // Not Used (Reserved for future) +#define DDR_200_MHZ 7 // Not Used (Reserved for future) #define MIPS_200_MHZ 0 #define MIPS_160_MHZ 1 @@ -290,27 +291,27 @@ typedef enum _E_PHS_DSC_ACTION { #define EEPROM_REJECT_REG_3 0x0f003008 #define EEPROM_REJECT_REG_4 0x0f003020 #define EEPROM_REJECT_MASK 0x0fffffff -#define VSG_MODE 0x3 +#define VSG_MODE 0x3 /* Idle Mode Related Registers */ #define DEBUG_INTERRUPT_GENERATOR_REGISTOR 0x0F00007C -#define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC +#define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC -#define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e -#define DEVICE_INT_OUT_EP_REG0 0x0F011870 -#define DEVICE_INT_OUT_EP_REG1 0x0F011874 +#define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e +#define DEVICE_INT_OUT_EP_REG0 0x0F011870 +#define DEVICE_INT_OUT_EP_REG1 0x0F011874 #define BIN_FILE "/lib/firmware/macxvi200.bin" #define CFG_FILE "/lib/firmware/macxvi.cfg" #define SF_MAX_ALLOWED_PACKETS_TO_BACKUP 128 -#define MIN_VAL(x, y) ((x) < (y) ? (x) : (y)) +#define MIN_VAL(x,y) ((x)<(y)?(x):(y)) #define MAC_ADDRESS_SIZE 6 #define EEPROM_COMMAND_Q_REG 0x0F003018 #define EEPROM_READ_DATA_Q_REG 0x0F003020 -#define CHIP_ID_REG 0x0F000000 -#define GPIO_MODE_REG 0x0F000034 -#define GPIO_OUTPUT_REG 0x0F00003C -#define WIMAX_MAX_ALLOWED_RATE (1024*1024*50) +#define CHIP_ID_REG 0x0F000000 +#define GPIO_MODE_REG 0x0F000034 +#define GPIO_OUTPUT_REG 0x0F00003C +#define WIMAX_MAX_ALLOWED_RATE 1024*1024*50 #define T3 0xbece0300 #define TARGET_SFID_TXDESC_MAP_LOC 0xBFFFF400 @@ -318,29 +319,31 @@ typedef enum _E_PHS_DSC_ACTION { #define RWM_READ 0 #define RWM_WRITE 1 -#define T3LPB 0xbece3300 -#define BCS220_2 0xbece3311 -#define BCS220_2BC 0xBECE3310 -#define BCS250_BC 0xbece3301 -#define BCS220_3 0xbece3321 +#define T3LPB 0xbece3300 +#define BCS220_2 0xbece3311 +#define BCS220_2BC 0xBECE3310 +#define BCS250_BC 0xbece3301 +#define BCS220_3 0xbece3321 -#define HPM_CONFIG_LDO145 0x0F000D54 -#define HPM_CONFIG_MSW 0x0F000D58 +#define HPM_CONFIG_LDO145 0x0F000D54 +#define HPM_CONFIG_MSW 0x0F000D58 #define T3B 0xbece0310 -typedef enum eNVM_TYPE { +typedef enum eNVM_TYPE +{ NVM_AUTODETECT = 0, NVM_EEPROM, NVM_FLASH, NVM_UNKNOWN -} NVM_TYPE; +}NVM_TYPE; -typedef enum ePMU_MODES { +typedef enum ePMU_MODES +{ HYBRID_MODE_7C = 0, INTERNAL_MODE_6 = 1, HYBRID_MODE_6 = 2 -} PMU_MODE; +}PMU_MODE; #define MAX_RDM_WRM_RETIRES 1 @@ -357,4 +360,4 @@ enum eAbortPattern { #define SKB_CB_LATENCY_OFFSET 1 #define SKB_CB_TCPACK_OFFSET 2 -#endif /* __MACROS_H__ */ +#endif //__MACROS_H__ diff --git a/trunk/drivers/staging/bcm/headers.h b/trunk/drivers/staging/bcm/headers.h index da47db8c8f29..947d06325681 100644 --- a/trunk/drivers/staging/bcm/headers.h +++ b/trunk/drivers/staging/bcm/headers.h @@ -74,6 +74,4 @@ #define DRV_VERSION VER_FILEVERSION_STR #define PFX DRV_NAME " " -extern struct class *bcm_class; - #endif diff --git a/trunk/drivers/staging/bcm/nvm.c b/trunk/drivers/staging/bcm/nvm.c index 3de0daf5edb2..4da5b7b54a1a 100644 --- a/trunk/drivers/staging/bcm/nvm.c +++ b/trunk/drivers/staging/bcm/nvm.c @@ -4013,8 +4013,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) if(uiTotalDataToCopy < ISOLength) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); - Status = STATUS_FAILURE; - goto out; + return STATUS_FAILURE; } uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - @@ -4027,8 +4026,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) if(uiTotalDataToCopy < ISOLength) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); - Status = STATUS_FAILURE; - goto out; + return STATUS_FAILURE; } uiTotalDataToCopy = ISOLength; @@ -4145,8 +4143,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) if(uiTotalDataToCopy < ISOLength) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); - Status = STATUS_FAILURE; - goto out; + return STATUS_FAILURE; } uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - @@ -4159,8 +4156,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) if(uiTotalDataToCopy < ISOLength) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); - Status = STATUS_FAILURE; - goto out; + return STATUS_FAILURE; } uiTotalDataToCopy = ISOLength; @@ -4261,7 +4257,6 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) } -out: kfree(Buff); return Status; diff --git a/trunk/drivers/staging/brcm80211/Kconfig b/trunk/drivers/staging/brcm80211/Kconfig index 59e9c8548d01..379cf16e89f7 100644 --- a/trunk/drivers/staging/brcm80211/Kconfig +++ b/trunk/drivers/staging/brcm80211/Kconfig @@ -7,12 +7,10 @@ config BRCMSMAC default n depends on PCI depends on WLAN && MAC80211 - depends on BCMA=n + depends on X86 || MIPS select BRCMUTIL select FW_LOADER select CRC_CCITT - select CRC8 - select CORDIC ---help--- This module adds support for PCIe wireless adapters based on Broadcom IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll @@ -23,8 +21,11 @@ config BRCMFMAC default n depends on MMC depends on WLAN && CFG80211 + depends on X86 || MIPS select BRCMUTIL select FW_LOADER + select WIRELESS_EXT + select WEXT_PRIV ---help--- This module adds support for embedded wireless adapters based on Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's diff --git a/trunk/drivers/staging/brcm80211/TODO b/trunk/drivers/staging/brcm80211/TODO index 7f68762b1c3f..e2e2ef9bd7ac 100644 --- a/trunk/drivers/staging/brcm80211/TODO +++ b/trunk/drivers/staging/brcm80211/TODO @@ -4,6 +4,10 @@ Bugs ==== - none known at this moment +brcmfmac +===================== +- ASSERTS deprecated in mainline, replace by warning + error handling + brcm80211 info page ===================== http://linuxwireless.org/en/users/Drivers/brcm80211 diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh.c b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh.c index 0c845c945f2f..f4e72ed126b0 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh.c @@ -21,9 +21,6 @@ #include #include #include -#include -#include -#include #include #include @@ -32,11 +29,35 @@ #include #include "dhd.h" #include "dhd_bus.h" -#include "dhd_dbg.h" #include "sdio_host.h" #define SDIOH_API_ACCESS_RETRY_LIMIT 2 +#define BRCMF_SD_ERROR_VAL 0x0001 /* Error */ +#define BRCMF_SD_INFO_VAL 0x0002 /* Info */ + + +#ifdef BCMDBG +#define BRCMF_SD_ERROR(x) \ + do { \ + if ((brcmf_sdio_msglevel & BRCMF_SD_ERROR_VAL) && \ + net_ratelimit()) \ + printk x; \ + } while (0) +#define BRCMF_SD_INFO(x) \ + do { \ + if ((brcmf_sdio_msglevel & BRCMF_SD_INFO_VAL) && \ + net_ratelimit()) \ + printk x; \ + } while (0) +#else /* BCMDBG */ +#define BRCMF_SD_ERROR(x) +#define BRCMF_SD_INFO(x) +#endif /* BCMDBG */ + +/* debugging macros */ +#define SDLX_MSG(x) + #define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */ #define SDIOH_CMD_TYPE_APPEND 1 /* Append command */ #define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */ @@ -44,206 +65,220 @@ #define SDIOH_DATA_PIO 0 /* PIO mode */ #define SDIOH_DATA_DMA 1 /* DMA mode */ +struct brcmf_sdio_card { + bool init_success; /* underlying driver successfully attached */ + void *sdioh; /* handler for sdioh */ + u32 vendevid; /* Target Vendor and Device ID on SD bus */ + bool regfail; /* Save status of last + reg_read/reg_write call */ + u32 sbwad; /* Save backplane window address */ +}; + +/** + * SDIO Host Controller info + */ +struct sdio_hc { + struct sdio_hc *next; + struct device *dev; /* platform device handle */ + void *regs; /* SDIO Host Controller address */ + struct brcmf_sdio_card *card; + void *ch; + unsigned int oob_irq; + unsigned long oob_flags; /* OOB Host specifiction + as edge and etc */ + bool oob_irq_registered; +}; + +/* local copy of bcm sd handler */ +static struct brcmf_sdio_card *l_card; + +const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL; + +static struct sdio_hc *sdhcinfo; + +/* driver info, initialized when brcmf_sdio_register is called */ +static struct brcmf_sdioh_driver drvinfo = { NULL, NULL }; + /* Module parameters specific to each host-controller driver */ +module_param(sd_msglevel, uint, 0); + +extern uint sd_f2_blocksize; module_param(sd_f2_blocksize, int, 0); -/* IOVar table */ -enum { - IOV_MSGLEVEL = 1, - IOV_DEVREG, - IOV_HCIREGS, - IOV_RXCHAIN -}; +/* forward declarations */ +int brcmf_sdio_probe(struct device *dev); +EXPORT_SYMBOL(brcmf_sdio_probe); -const struct brcmu_iovar sdioh_iovars[] = { - {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)} - , - {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0} - , - {NULL, 0, 0, 0, 0} -}; +int brcmf_sdio_remove(struct device *dev); +EXPORT_SYMBOL(brcmf_sdio_remove); -int -brcmf_sdcard_iovar_op(struct brcmf_sdio_dev *sdiodev, const char *name, - void *params, int plen, void *arg, int len, bool set) +struct brcmf_sdio_card* +brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq) { - const struct brcmu_iovar *vi = NULL; - int bcmerror = 0; - int val_size; - s32 int_val = 0; - bool bool_val; - u32 actionid; - - if (name == NULL || len < 0) - return -EINVAL; - - /* Set does not take qualifiers */ - if (set && (params || plen)) - return -EINVAL; - - /* Get must have return space;*/ - if (!set && !(arg && len)) - return -EINVAL; - - BRCMF_TRACE(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"), - name)); - - vi = brcmu_iovar_lookup(sdioh_iovars, name); - if (vi == NULL) { - bcmerror = -ENOTSUPP; - goto exit; + struct brcmf_sdio_card *card; + + card = kzalloc(sizeof(struct brcmf_sdio_card), GFP_ATOMIC); + if (card == NULL) { + BRCMF_SD_ERROR(("sdcard_attach: out of memory")); + return NULL; } - bcmerror = brcmu_iovar_lencheck(vi, arg, len, set); - if (bcmerror != 0) - goto exit; + /* save the handler locally */ + l_card = card; - /* Set up params so get and set can share the convenience variables */ - if (params == NULL) { - params = arg; - plen = len; + card->sdioh = brcmf_sdioh_attach(cfghdl, irq); + if (!card->sdioh) { + brcmf_sdcard_detach(card); + return NULL; } - if (vi->type == IOVT_VOID) - val_size = 0; - else if (vi->type == IOVT_BUFFER) - val_size = len; - else - val_size = sizeof(int); - - if (plen >= (int)sizeof(int_val)) - memcpy(&int_val, params, sizeof(int_val)); - - bool_val = (int_val != 0) ? true : false; - - actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); - switch (actionid) { - case IOV_GVAL(IOV_RXCHAIN): - int_val = false; - memcpy(arg, &int_val, val_size); - break; - - case IOV_GVAL(IOV_DEVREG): - { - struct brcmf_sdreg *sd_ptr = - (struct brcmf_sdreg *) params; - u8 data = 0; - - if (brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, - sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = -EIO; - break; - } - - int_val = (int)data; - memcpy(arg, &int_val, sizeof(int_val)); - break; - } + card->init_success = true; - case IOV_SVAL(IOV_DEVREG): - { - struct brcmf_sdreg *sd_ptr = - (struct brcmf_sdreg *) params; - u8 data = (u8) sd_ptr->value; - - if (brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, - sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = -EIO; - break; - } - break; - } + *regsva = SI_ENUM_BASE; - default: - bcmerror = -ENOTSUPP; - break; - } -exit: - - return bcmerror; + /* Report the BAR, to fix if needed */ + card->sbwad = SI_ENUM_BASE; + return card; } -static void brcmf_sdioh_irqhandler(struct sdio_func *func) +int brcmf_sdcard_detach(struct brcmf_sdio_card *card) { - struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); - - BRCMF_TRACE(("brcmf: ***IRQHandler\n")); - - sdio_release_host(func); - - brcmf_sdbrcm_isr(sdiodev->bus); + if (card != NULL) { + if (card->sdioh) { + brcmf_sdioh_detach(card->sdioh); + card->sdioh = NULL; + } + kfree(card); + } - sdio_claim_host(func); + l_card = NULL; + return 0; } -int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev) +int +brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name, + void *params, int plen, void *arg, int len, bool set) { - BRCMF_TRACE(("%s: Entering\n", __func__)); - - sdio_claim_host(sdiodev->func[1]); - sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler); - sdio_release_host(sdiodev->func[1]); + return brcmf_sdioh_iovar_op(card->sdioh, name, params, plen, arg, + len, set); +} - return 0; +int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card) +{ + return brcmf_sdioh_interrupt_set(card->sdioh, true); } -int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) +int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card) { - BRCMF_TRACE(("%s: Entering\n", __func__)); + return brcmf_sdioh_interrupt_set(card->sdioh, false); +} - sdio_claim_host(sdiodev->func[1]); - sdio_release_irq(sdiodev->func[1]); - sdio_release_host(sdiodev->func[1]); +int brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card, + void (*fn)(void *), void *argh) +{ + return brcmf_sdioh_interrupt_register(card->sdioh, fn, argh); +} - return 0; +int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card) +{ + return brcmf_sdioh_interrupt_deregister(card->sdioh); } -u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, +u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint fnc_num, u32 addr, int *err) { int status; s32 retry = 0; u8 data = 0; + if (!card) + card = l_card; + do { if (retry) /* wait for 1 ms till bus get settled down */ udelay(1000); - status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num, - addr, (u8 *) &data); + status = + brcmf_sdioh_cfg_read(card->sdioh, fnc_num, addr, + (u8 *) &data); } while (status != 0 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); if (err) *err = status; - BRCMF_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n", + BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n", __func__, fnc_num, addr, data)); return data; } void -brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, +brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint fnc_num, u32 addr, u8 data, int *err) { int status; s32 retry = 0; + if (!card) + card = l_card; + do { if (retry) /* wait for 1 ms till bus get settled down */ udelay(1000); - status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num, - addr, (u8 *) &data); + status = + brcmf_sdioh_cfg_write(card->sdioh, fnc_num, addr, + (u8 *) &data); } while (status != 0 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); if (err) *err = status; - BRCMF_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n", + BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n", + __func__, fnc_num, addr, data)); +} + +u32 brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num, + u32 addr, int *err) +{ + int status; + u32 data = 0; + + if (!card) + card = l_card; + + status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL, + SDIOH_READ, fnc_num, addr, &data, 4); + + if (err) + *err = status; + + BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n", + __func__, fnc_num, addr, data)); + + return data; +} + +void +brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, uint fnc_num, + u32 addr, u32 data, int *err) +{ + int status; + + if (!card) + card = l_card; + + status = + brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL, + SDIOH_WRITE, fnc_num, addr, &data, 4); + + if (err) + *err = status; + + BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n", __func__, fnc_num, addr, data)); } -int brcmf_sdcard_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, u8 * cis, +int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 * cis, uint length) { int status; @@ -253,14 +288,17 @@ int brcmf_sdcard_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, u8 * cis, bool ascii = func & ~0xf; func &= 0x7; - status = brcmf_sdioh_cis_read(sdiodev, func, cis, length); + if (!card) + card = l_card; + + status = brcmf_sdioh_cis_read(card->sdioh, func, cis, length); if (ascii) { /* Move binary bits to tmp and format them into the provided buffer. */ tmp_buf = kmalloc(length, GFP_ATOMIC); if (tmp_buf == NULL) { - BRCMF_ERROR(("%s: out of memory\n", __func__)); + BRCMF_SD_ERROR(("%s: out of memory\n", __func__)); return -ENOMEM; } memcpy(tmp_buf, cis, length); @@ -277,18 +315,18 @@ int brcmf_sdcard_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, u8 * cis, } static int -brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) +brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address) { int err = 0; - brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); if (!err) - brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, (address >> 16) & SBSDIO_SBADDRMID_MASK, &err); if (!err) - brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err); @@ -296,31 +334,34 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) return err; } -u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size) +u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size) { int status; u32 word = 0; uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; - BRCMF_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr)); + BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr)); + + if (!card) + card = l_card; - if (bar0 != sdiodev->sbwad) { - if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0)) + if (bar0 != card->sbwad) { + if (brcmf_sdcard_set_sbaddr_window(card, bar0)) return 0xFFFFFFFF; - sdiodev->sbwad = bar0; + card->sbwad = bar0; } addr &= SBSDIO_SB_OFT_ADDR_MASK; if (size == 4) addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - status = brcmf_sdioh_request_word(sdiodev, SDIOH_CMD_TYPE_NORMAL, + status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ, SDIO_FUNC_1, addr, &word, size); - sdiodev->regfail = (status != 0); + card->regfail = (status != 0); - BRCMF_INFO(("u32data = 0x%x\n", word)); + BRCMF_SD_INFO(("u32data = 0x%x\n", word)); /* if ok, return appropriately masked word */ if (status == 0) { @@ -332,60 +373,66 @@ u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size) case sizeof(u32): return word; default: - sdiodev->regfail = true; + card->regfail = true; } } /* otherwise, bad sdio access or invalid size */ - BRCMF_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__, + BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__, addr, size)); return 0xFFFFFFFF; } -u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, +u32 brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size, u32 data) { int status; uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; int err = 0; - BRCMF_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", + BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", __func__, addr, size * 8, data)); - if (bar0 != sdiodev->sbwad) { - err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); + if (!card) + card = l_card; + + if (bar0 != card->sbwad) { + err = brcmf_sdcard_set_sbaddr_window(card, bar0); if (err) return err; - sdiodev->sbwad = bar0; + card->sbwad = bar0; } addr &= SBSDIO_SB_OFT_ADDR_MASK; if (size == 4) addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; status = - brcmf_sdioh_request_word(sdiodev, SDIOH_CMD_TYPE_NORMAL, + brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size); - sdiodev->regfail = (status != 0); + card->regfail = (status != 0); if (status == 0) return 0; - BRCMF_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n", + BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n", __func__, data, addr, size)); return 0xFFFFFFFF; } -bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev) +bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card) { - return sdiodev->regfail; + return card->regfail; } int -brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, +brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn, uint flags, - u8 *buf, uint nbytes, struct sk_buff *pkt) + u8 *buf, uint nbytes, struct sk_buff *pkt, + void (*complete)(void *handle, int status, + bool sync_waiting), + void *handle) { int status; uint incr_fix; @@ -393,19 +440,19 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; int err = 0; - BRCMF_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", + BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", __func__, fn, addr, nbytes)); /* Async not implemented yet */ if (flags & SDIO_REQ_ASYNC) return -ENOTSUPP; - if (bar0 != sdiodev->sbwad) { - err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); + if (bar0 != card->sbwad) { + err = brcmf_sdcard_set_sbaddr_window(card, bar0); if (err) return err; - sdiodev->sbwad = bar0; + card->sbwad = bar0; } addr &= SBSDIO_SB_OFT_ADDR_MASK; @@ -415,34 +462,37 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, if (width == 4) addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - status = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_PIO, + status = brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO, incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt); return status; } int -brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt) +brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn, + uint flags, u8 *buf, uint nbytes, void *pkt, + void (*complete)(void *handle, int status, + bool sync_waiting), + void *handle) { uint incr_fix; uint width; uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; int err = 0; - BRCMF_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", + BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", __func__, fn, addr, nbytes)); /* Async not implemented yet */ if (flags & SDIO_REQ_ASYNC) return -ENOTSUPP; - if (bar0 != sdiodev->sbwad) { - err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); + if (bar0 != card->sbwad) { + err = brcmf_sdcard_set_sbaddr_window(card, bar0); if (err) return err; - sdiodev->sbwad = bar0; + card->sbwad = bar0; } addr &= SBSDIO_SB_OFT_ADDR_MASK; @@ -452,86 +502,129 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, if (width == 4) addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_PIO, + return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO, incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt); } -int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, +int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr, u8 *buf, uint nbytes) { addr &= SBSDIO_SB_OFT_ADDR_MASK; addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_PIO, + return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1, addr, 4, nbytes, buf, NULL); } -int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) +int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn) { - char t_func = (char)fn; - BRCMF_TRACE(("%s: Enter\n", __func__)); - - /* issue abort cmd52 command through F0 */ - brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, - SDIO_CCCR_ABORT, &t_func); + return brcmf_sdioh_abort(card->sdioh, fn); +} - BRCMF_TRACE(("%s: Exit\n", __func__)); - return 0; +int brcmf_sdcard_query_device(struct brcmf_sdio_card *card) +{ + card->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0; + return card->vendevid; } -u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_dev *sdiodev) +u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card) { - return sdiodev->sbwad; + if (!card) + card = l_card; + + return card->sbwad; } -int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) +int brcmf_sdio_probe(struct device *dev) { + struct sdio_hc *sdhc = NULL; u32 regs = 0; - int ret = 0; + struct brcmf_sdio_card *card = NULL; + int irq = 0; + u32 vendevid; + unsigned long irq_flags = 0; + + /* allocate SDIO Host Controller state info */ + sdhc = kzalloc(sizeof(struct sdio_hc), GFP_ATOMIC); + if (!sdhc) { + SDLX_MSG(("%s: out of memory\n", __func__)); + goto err; + } + sdhc->dev = (void *)dev; - ret = brcmf_sdioh_attach(sdiodev); - if (ret) - goto out; + card = brcmf_sdcard_attach((void *)0, ®s, irq); + if (!card) { + SDLX_MSG(("%s: attach failed\n", __func__)); + goto err; + } - regs = SI_ENUM_BASE; + sdhc->card = card; + sdhc->oob_irq = irq; + sdhc->oob_flags = irq_flags; + sdhc->oob_irq_registered = false; /* to make sure.. */ - /* Report the BAR, to fix if needed */ - sdiodev->sbwad = SI_ENUM_BASE; + /* chain SDIO Host Controller info together */ + sdhc->next = sdhcinfo; + sdhcinfo = sdhc; + /* Read the vendor/device ID from the CIS */ + vendevid = brcmf_sdcard_query_device(card); /* try to attach to the target device */ - sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev); - if (!sdiodev->bus) { - BRCMF_ERROR(("%s: device attach failed\n", __func__)); - ret = -ENODEV; - goto out; + sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF), + 0, 0, 0, 0, regs, card); + if (!sdhc->ch) { + SDLX_MSG(("%s: device attach failed\n", __func__)); + goto err; } -out: - if (ret) - brcmf_sdio_remove(sdiodev); + return 0; - return ret; + /* error handling */ +err: + if (sdhc) { + if (sdhc->card) + brcmf_sdcard_detach(sdhc->card); + kfree(sdhc); + } + + return -ENODEV; } -EXPORT_SYMBOL(brcmf_sdio_probe); -int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) +int brcmf_sdio_remove(struct device *dev) { - if (sdiodev->bus) { - brcmf_sdbrcm_disconnect(sdiodev->bus); - sdiodev->bus = NULL; + struct sdio_hc *sdhc, *prev; + + sdhc = sdhcinfo; + drvinfo.detach(sdhc->ch); + brcmf_sdcard_detach(sdhc->card); + /* find the SDIO Host Controller state for this pdev + and take it out from the list */ + for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { + if (sdhc->dev == (void *)dev) { + if (prev) + prev->next = sdhc->next; + else + sdhcinfo = NULL; + break; + } + prev = sdhc; + } + if (!sdhc) { + SDLX_MSG(("%s: failed\n", __func__)); + return 0; } - brcmf_sdioh_detach(sdiodev); - - sdiodev->sbwad = 0; - + /* release SDIO Host Controller info */ + kfree(sdhc); return 0; } -EXPORT_SYMBOL(brcmf_sdio_remove); -int brcmf_sdio_register(void) +int brcmf_sdio_register(struct brcmf_sdioh_driver *driver) { + drvinfo = *driver; + + SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n")); return brcmf_sdio_function_init(); } @@ -540,10 +633,10 @@ void brcmf_sdio_unregister(void) brcmf_sdio_function_cleanup(); } -void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable) +void brcmf_sdio_wdtmr_enable(bool enable) { if (enable) - brcmf_sdbrcm_wd_timer(sdiodev->bus, brcmf_watchdog_ms); + brcmf_sdbrcm_wd_timer(sdhcinfo->ch, brcmf_watchdog_ms); else - brcmf_sdbrcm_wd_timer(sdiodev->bus, 0); + brcmf_sdbrcm_wd_timer(sdhcinfo->ch, 0); } diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c index fca966cd30f9..38bd9ba3096f 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -34,17 +34,95 @@ #include "dhd_dbg.h" #include "wl_cfg80211.h" +#define BLOCK_SIZE_64 64 +#define BLOCK_SIZE_512 512 +#define BLOCK_SIZE_4318 64 +#define BLOCK_SIZE_4328 512 + +/* private bus modes */ +#define SDIOH_MODE_SD4 2 + +#define CLIENT_INTR 0x100 /* Get rid of this! */ + #if !defined(SDIO_VENDOR_ID_BROADCOM) #define SDIO_VENDOR_ID_BROADCOM 0x02d0 #endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */ +#define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000 + #define DMA_ALIGN_MASK 0x03 +#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) +#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB 0x0492 /* BCM94325SDGWB */ +#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */ +#if !defined(SDIO_DEVICE_ID_BROADCOM_4325) +#define SDIO_DEVICE_ID_BROADCOM_4325 0x0493 +#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */ #if !defined(SDIO_DEVICE_ID_BROADCOM_4329) #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */ +#if !defined(SDIO_DEVICE_ID_BROADCOM_4319) +#define SDIO_DEVICE_ID_BROADCOM_4319 0x4319 +#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */ + +/* Common msglevel constants */ +#define SDH_ERROR_VAL 0x0001 /* Error */ +#define SDH_TRACE_VAL 0x0002 /* Trace */ +#define SDH_INFO_VAL 0x0004 /* Info */ +#define SDH_DEBUG_VAL 0x0008 /* Debug */ +#define SDH_DATA_VAL 0x0010 /* Data */ +#define SDH_CTRL_VAL 0x0020 /* Control Regs */ +#define SDH_LOG_VAL 0x0040 /* Enable bcmlog */ +#define SDH_DMA_VAL 0x0080 /* DMA */ + +#ifdef BCMDBG +#define sd_err(x) \ + do { \ + if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \ + printk x; \ + } while (0) +#define sd_trace(x) \ + do { \ + if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \ + printk x; \ + } while (0) +#define sd_info(x) \ + do { \ + if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \ + printk x; \ + } while (0) +#define sd_debug(x) \ + do { \ + if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \ + printk x; \ + } while (0) +#define sd_data(x) \ + do { \ + if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \ + printk x; \ + } while (0) +#define sd_ctrl(x) \ + do { \ + if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \ + printk x; \ + } while (0) +#else +#define sd_err(x) +#define sd_trace(x) +#define sd_info(x) +#define sd_debug(x) +#define sd_data(x) +#define sd_ctrl(x) +#endif + +struct sdos_info { + struct sdioh_info *sd; + spinlock_t lock; +}; -static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr); +static void brcmf_sdioh_irqhandler(struct sdio_func *func); +static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func); +static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr); static int brcmf_ops_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id); static void brcmf_ops_sdio_remove(struct sdio_func *func); @@ -56,85 +134,94 @@ static int brcmf_sdio_resume(struct device *dev); uint sd_f2_blocksize = 512; /* Default blocksize */ +uint sd_msglevel = 0x01; + +/* module param defaults */ +static int clockoverride; + +module_param(clockoverride, int, 0644); +MODULE_PARM_DESC(clockoverride, "SDIO card clock override"); + +struct brcmf_sdmmc_instance *gInstance; + +struct device sdmmc_dev; + /* devices we support, null terminated */ static const struct sdio_device_id brcmf_sdmmc_ids[] = { + {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT)}, + {SDIO_DEVICE + (SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)}, + {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325)}, {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, + {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319)}, { /* end: all zeroes */ }, }; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static const struct dev_pm_ops brcmf_sdio_pm_ops = { .suspend = brcmf_sdio_suspend, .resume = brcmf_sdio_resume, }; -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_PM */ static struct sdio_driver brcmf_sdmmc_driver = { .probe = brcmf_ops_sdio_probe, .remove = brcmf_ops_sdio_remove, .name = "brcmfmac", .id_table = brcmf_sdmmc_ids, -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM .drv = { .pm = &brcmf_sdio_pm_ops, }, -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_PM */ }; MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); -#ifdef CONFIG_PM_SLEEP -DECLARE_WAIT_QUEUE_HEAD(sdioh_request_byte_wait); -DECLARE_WAIT_QUEUE_HEAD(sdioh_request_word_wait); -DECLARE_WAIT_QUEUE_HEAD(sdioh_request_packet_wait); -DECLARE_WAIT_QUEUE_HEAD(sdioh_request_buffer_wait); -#define BRCMF_PM_RESUME_WAIT(a, b) do { \ - int retry = 0; \ - while (atomic_read(&b->suspend) && retry++ != 30) { \ - wait_event_timeout(a, false, HZ/100); \ - } \ - } while (0) -#define BRCMF_PM_RESUME_RETURN_ERROR(a, b) \ - do { if (atomic_read(&b->suspend)) return a; } while (0) -#else -#define BRCMF_PM_RESUME_WAIT(a, b) -#define BRCMF_PM_RESUME_RETURN_ERROR(a, b) -#endif /* CONFIG_PM_SLEEP */ +BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait); +BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_word_wait); +BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait); +BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait); static int -brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr, +brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr, int regsize, u32 *data); -static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) +static int brcmf_sdioh_enablefuncs(struct sdioh_info *sd) { int err_ret; u32 fbraddr; u8 func; - BRCMF_TRACE(("%s\n", __func__)); + sd_trace(("%s\n", __func__)); /* Get the Card's common CIS address */ - sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, - SDIO_CCCR_CIS); - BRCMF_INFO(("%s: Card's Common CIS Ptr = 0x%x\n", __func__, - sdiodev->func_cis_ptr[0])); + sd->com_cis_ptr = brcmf_sdioh_get_cisaddr(sd, SDIO_CCCR_CIS); + sd->func_cis_ptr[0] = sd->com_cis_ptr; + sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__, + sd->com_cis_ptr)); /* Get the Card's function CIS (for each function) */ for (fbraddr = SDIO_FBR_BASE(1), func = 1; - func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { - sdiodev->func_cis_ptr[func] = - brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); - BRCMF_INFO(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func, - sdiodev->func_cis_ptr[func])); + func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { + sd->func_cis_ptr[func] = + brcmf_sdioh_get_cisaddr(sd, SDIO_FBR_CIS + fbraddr); + sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func, + sd->func_cis_ptr[func])); } + sd->func_cis_ptr[0] = sd->com_cis_ptr; + sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__, + sd->com_cis_ptr)); + /* Enable Function 1 */ - sdio_claim_host(sdiodev->func[1]); - err_ret = sdio_enable_func(sdiodev->func[1]); - sdio_release_host(sdiodev->func[1]); - if (err_ret) - BRCMF_ERROR(("brcmf_sdioh_enablefuncs: Failed to enable F1 " + sdio_claim_host(gInstance->func[1]); + err_ret = sdio_enable_func(gInstance->func[1]); + sdio_release_host(gInstance->func[1]); + if (err_ret) { + sd_err(("brcmf_sdioh_enablefuncs: Failed to enable F1 " "Err: 0x%08x\n", err_ret)); + } return false; } @@ -142,64 +229,375 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) /* * Public entry points & extern's */ -int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) +struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq) { - int err_ret = 0; + struct sdioh_info *sd; + int err_ret; - BRCMF_TRACE(("%s\n", __func__)); + sd_trace(("%s\n", __func__)); - sdiodev->num_funcs = 2; + if (gInstance == NULL) { + sd_err(("%s: SDIO Device not present\n", __func__)); + return NULL; + } - sdio_claim_host(sdiodev->func[1]); - err_ret = sdio_set_block_size(sdiodev->func[1], 64); - sdio_release_host(sdiodev->func[1]); - if (err_ret) { - BRCMF_ERROR(("%s: Failed to set F1 blocksize\n", __func__)); - goto out; + sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC); + if (sd == NULL) { + sd_err(("sdioh_attach: out of memory\n")); + return NULL; + } + if (brcmf_sdioh_osinit(sd) != 0) { + sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__)); + kfree(sd); + return NULL; } - sdio_claim_host(sdiodev->func[2]); - err_ret = sdio_set_block_size(sdiodev->func[2], sd_f2_blocksize); - sdio_release_host(sdiodev->func[2]); - if (err_ret) { - BRCMF_ERROR(("%s: Failed to set F2 blocksize" - " to %d\n", __func__, sd_f2_blocksize)); - goto out; + sd->num_funcs = 2; + sd->use_client_ints = true; + sd->client_block_size[0] = 64; + + gInstance->sd = sd; + + /* Claim host controller */ + sdio_claim_host(gInstance->func[1]); + + sd->client_block_size[1] = 64; + err_ret = sdio_set_block_size(gInstance->func[1], 64); + if (err_ret) + sd_err(("brcmf_sdioh_attach: Failed to set F1 blocksize\n")); + + /* Release host controller F1 */ + sdio_release_host(gInstance->func[1]); + + if (gInstance->func[2]) { + /* Claim host controller F2 */ + sdio_claim_host(gInstance->func[2]); + + sd->client_block_size[2] = sd_f2_blocksize; + err_ret = + sdio_set_block_size(gInstance->func[2], sd_f2_blocksize); + if (err_ret) + sd_err(("brcmf_sdioh_attach: Failed to set F2 blocksize" + " to %d\n", sd_f2_blocksize)); + + /* Release host controller F2 */ + sdio_release_host(gInstance->func[2]); } - brcmf_sdioh_enablefuncs(sdiodev); + brcmf_sdioh_enablefuncs(sd); -out: - BRCMF_TRACE(("%s: Done\n", __func__)); - return err_ret; + sd_trace(("%s: Done\n", __func__)); + return sd; +} + +extern int brcmf_sdioh_detach(struct sdioh_info *sd) +{ + sd_trace(("%s\n", __func__)); + + if (sd) { + + /* Disable Function 2 */ + sdio_claim_host(gInstance->func[2]); + sdio_disable_func(gInstance->func[2]); + sdio_release_host(gInstance->func[2]); + + /* Disable Function 1 */ + sdio_claim_host(gInstance->func[1]); + sdio_disable_func(gInstance->func[1]); + sdio_release_host(gInstance->func[1]); + + /* deregister irq */ + brcmf_sdioh_osfree(sd); + + kfree(sd); + } + return 0; } -void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) +/* Configure callback to client when we receive client interrupt */ +extern int +brcmf_sdioh_interrupt_register(struct sdioh_info *sd, void (*fn)(void *), + void *argh) { - BRCMF_TRACE(("%s\n", __func__)); + sd_trace(("%s: Entering\n", __func__)); + if (fn == NULL) { + sd_err(("%s: interrupt handler is NULL, not registering\n", + __func__)); + return -EINVAL; + } - /* Disable Function 2 */ - sdio_claim_host(sdiodev->func[2]); - sdio_disable_func(sdiodev->func[2]); - sdio_release_host(sdiodev->func[2]); + sd->intr_handler = fn; + sd->intr_handler_arg = argh; + sd->intr_handler_valid = true; - /* Disable Function 1 */ - sdio_claim_host(sdiodev->func[1]); - sdio_disable_func(sdiodev->func[1]); - sdio_release_host(sdiodev->func[1]); + /* register and unmask irq */ + if (gInstance->func[2]) { + sdio_claim_host(gInstance->func[2]); + sdio_claim_irq(gInstance->func[2], brcmf_sdioh_irqhandler_f2); + sdio_release_host(gInstance->func[2]); + } + + if (gInstance->func[1]) { + sdio_claim_host(gInstance->func[1]); + sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler); + sdio_release_host(gInstance->func[1]); + } + return 0; } -static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) +extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd) +{ + sd_trace(("%s: Entering\n", __func__)); + + if (gInstance->func[1]) { + /* register and unmask irq */ + sdio_claim_host(gInstance->func[1]); + sdio_release_irq(gInstance->func[1]); + sdio_release_host(gInstance->func[1]); + } + + if (gInstance->func[2]) { + /* Claim host controller F2 */ + sdio_claim_host(gInstance->func[2]); + sdio_release_irq(gInstance->func[2]); + /* Release host controller F2 */ + sdio_release_host(gInstance->func[2]); + } + + sd->intr_handler_valid = false; + sd->intr_handler = NULL; + sd->intr_handler_arg = NULL; + + return 0; +} + +/* IOVar table */ +enum { + IOV_MSGLEVEL = 1, + IOV_BLOCKSIZE, + IOV_USEINTS, + IOV_NUMINTS, + IOV_DEVREG, + IOV_HCIREGS, + IOV_RXCHAIN +}; + +const struct brcmu_iovar sdioh_iovars[] = { + {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0}, + {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) | + size) */ + {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0}, + {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0}, + {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)} + , + {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0} + , + {NULL, 0, 0, 0, 0} +}; + +int +brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name, + void *params, int plen, void *arg, int len, bool set) +{ + const struct brcmu_iovar *vi = NULL; + int bcmerror = 0; + int val_size; + s32 int_val = 0; + bool bool_val; + u32 actionid; + + if (name == NULL || len <= 0) + return -EINVAL; + + /* Set does not take qualifiers */ + if (set && (params || plen)) + return -EINVAL; + + /* Get must have return space;*/ + if (!set && !(arg && len)) + return -EINVAL; + + sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"), + name)); + + vi = brcmu_iovar_lookup(sdioh_iovars, name); + if (vi == NULL) { + bcmerror = -ENOTSUPP; + goto exit; + } + + bcmerror = brcmu_iovar_lencheck(vi, arg, len, set); + if (bcmerror != 0) + goto exit; + + /* Set up params so get and set can share the convenience variables */ + if (params == NULL) { + params = arg; + plen = len; + } + + if (vi->type == IOVT_VOID) + val_size = 0; + else if (vi->type == IOVT_BUFFER) + val_size = len; + else + val_size = sizeof(int); + + if (plen >= (int)sizeof(int_val)) + memcpy(&int_val, params, sizeof(int_val)); + + bool_val = (int_val != 0) ? true : false; + + actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); + switch (actionid) { + case IOV_GVAL(IOV_MSGLEVEL): + int_val = (s32) sd_msglevel; + memcpy(arg, &int_val, val_size); + break; + + case IOV_SVAL(IOV_MSGLEVEL): + sd_msglevel = int_val; + break; + + case IOV_GVAL(IOV_BLOCKSIZE): + if ((u32) int_val > si->num_funcs) { + bcmerror = -EINVAL; + break; + } + int_val = (s32) si->client_block_size[int_val]; + memcpy(arg, &int_val, val_size); + break; + + case IOV_SVAL(IOV_BLOCKSIZE): + { + uint func = ((u32) int_val >> 16); + uint blksize = (u16) int_val; + uint maxsize; + + if (func > si->num_funcs) { + bcmerror = -EINVAL; + break; + } + + switch (func) { + case 0: + maxsize = 32; + break; + case 1: + maxsize = BLOCK_SIZE_4318; + break; + case 2: + maxsize = BLOCK_SIZE_4328; + break; + default: + maxsize = 0; + } + if (blksize > maxsize) { + bcmerror = -EINVAL; + break; + } + if (!blksize) + blksize = maxsize; + + /* Now set it */ + si->client_block_size[func] = blksize; + + break; + } + + case IOV_GVAL(IOV_RXCHAIN): + int_val = false; + memcpy(arg, &int_val, val_size); + break; + + case IOV_GVAL(IOV_USEINTS): + int_val = (s32) si->use_client_ints; + memcpy(arg, &int_val, val_size); + break; + + case IOV_SVAL(IOV_USEINTS): + si->use_client_ints = (bool) int_val; + if (si->use_client_ints) + si->intmask |= CLIENT_INTR; + else + si->intmask &= ~CLIENT_INTR; + + break; + + case IOV_GVAL(IOV_NUMINTS): + int_val = (s32) si->intrcount; + memcpy(arg, &int_val, val_size); + break; + + case IOV_GVAL(IOV_DEVREG): + { + struct brcmf_sdreg *sd_ptr = + (struct brcmf_sdreg *) params; + u8 data = 0; + + if (brcmf_sdioh_cfg_read + (si, sd_ptr->func, sd_ptr->offset, &data)) { + bcmerror = -EIO; + break; + } + + int_val = (int)data; + memcpy(arg, &int_val, sizeof(int_val)); + break; + } + + case IOV_SVAL(IOV_DEVREG): + { + struct brcmf_sdreg *sd_ptr = + (struct brcmf_sdreg *) params; + u8 data = (u8) sd_ptr->value; + + if (brcmf_sdioh_cfg_write + (si, sd_ptr->func, sd_ptr->offset, &data)) { + bcmerror = -EIO; + break; + } + break; + } + + default: + bcmerror = -ENOTSUPP; + break; + } +exit: + + return bcmerror; +} + +extern int +brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data) +{ + int status; + /* No lock needed since brcmf_sdioh_request_byte does locking */ + status = brcmf_sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data); + return status; +} + +extern int +brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data) +{ + /* No lock needed since brcmf_sdioh_request_byte does locking */ + int status; + status = brcmf_sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data); + return status; +} + +static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr) { /* read 24 bits and return valid 17 bit addr */ int i; u32 scratch, regdata; u8 *ptr = (u8 *)&scratch; for (i = 0; i < 3; i++) { - if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1, - ®data)) != SUCCESS) - BRCMF_ERROR(("%s: Can't read!\n", __func__)); + if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, ®data)) != + SUCCESS) + sd_err(("%s: Can't read!\n", __func__)); *ptr++ = (u8) regdata; regaddr++; @@ -212,29 +610,28 @@ static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) } extern int -brcmf_sdioh_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, - u8 *cisd, u32 length) +brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length) { u32 count; int offset; u32 foo; u8 *cis = cisd; - BRCMF_TRACE(("%s: Func = %d\n", __func__, func)); + sd_trace(("%s: Func = %d\n", __func__, func)); - if (!sdiodev->func_cis_ptr[func]) { + if (!sd->func_cis_ptr[func]) { memset(cis, 0, length); - BRCMF_ERROR(("%s: no func_cis_ptr[%d]\n", __func__, func)); + sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func)); return -ENOTSUPP; } - BRCMF_ERROR(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func, - sdiodev->func_cis_ptr[func])); + sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func, + sd->func_cis_ptr[func])); for (count = 0; count < length; count++) { - offset = sdiodev->func_cis_ptr[func] + count; - if (brcmf_sdioh_card_regread(sdiodev, 0, offset, 1, &foo) < 0) { - BRCMF_ERROR(("%s: regread failed: Can't read CIS\n", + offset = sd->func_cis_ptr[func] + count; + if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) { + sd_err(("%s: regread failed: Can't read CIS\n", __func__)); return -EIO; } @@ -247,16 +644,16 @@ brcmf_sdioh_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, } extern int -brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, +brcmf_sdioh_request_byte(struct sdioh_info *sd, uint rw, uint func, uint regaddr, u8 *byte) { int err_ret; - BRCMF_INFO(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func, + sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func, regaddr)); - BRCMF_PM_RESUME_WAIT(sdioh_request_byte_wait, sdiodev); - BRCMF_PM_RESUME_RETURN_ERROR(-EIO, sdiodev); + BRCMF_PM_RESUME_WAIT(sdioh_request_byte_wait); + BRCMF_PM_RESUME_RETURN_ERROR(-EIO); if (rw) { /* CMD52 Write */ if (func == 0) { /* Can only directly write to some F0 registers. @@ -264,16 +661,15 @@ brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, * as a special case. */ if (regaddr == SDIO_CCCR_IOEx) { - if (sdiodev->func[2]) { - sdio_claim_host(sdiodev->func[2]); + if (gInstance->func[2]) { + sdio_claim_host(gInstance->func[2]); if (*byte & SDIO_FUNC_ENABLE_2) { /* Enable Function 2 */ err_ret = sdio_enable_func - (sdiodev->func[2]); + (gInstance->func[2]); if (err_ret) - BRCMF_ERROR(( - "request_byte: " + sd_err(("request_byte: " "enable F2 " "failed:%d\n", err_ret)); @@ -281,67 +677,66 @@ brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, /* Disable Function 2 */ err_ret = sdio_disable_func - (sdiodev->func[2]); + (gInstance->func[2]); if (err_ret) - BRCMF_ERROR(( - "request_byte: " + sd_err(("request_byte: " "Disab F2 " "failed:%d\n", err_ret)); } - sdio_release_host(sdiodev->func[2]); + sdio_release_host(gInstance->func[2]); } } /* to allow abort command through F1 */ else if (regaddr == SDIO_CCCR_ABORT) { - sdio_claim_host(sdiodev->func[func]); + sdio_claim_host(gInstance->func[func]); /* * this sdio_f0_writeb() can be replaced * with another api * depending upon MMC driver change. * As of this time, this is temporaray one */ - sdio_writeb(sdiodev->func[func], *byte, + sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - sdio_release_host(sdiodev->func[func]); + sdio_release_host(gInstance->func[func]); } else if (regaddr < 0xF0) { - BRCMF_ERROR(("brcmf: F0 Wr:0x%02x: write " + sd_err(("brcmf: F0 Wr:0x%02x: write " "disallowed\n", regaddr)); } else { /* Claim host controller, perform F0 write, and release */ - sdio_claim_host(sdiodev->func[func]); - sdio_f0_writeb(sdiodev->func[func], *byte, + sdio_claim_host(gInstance->func[func]); + sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - sdio_release_host(sdiodev->func[func]); + sdio_release_host(gInstance->func[func]); } } else { /* Claim host controller, perform Fn write, and release */ - sdio_claim_host(sdiodev->func[func]); - sdio_writeb(sdiodev->func[func], *byte, regaddr, + sdio_claim_host(gInstance->func[func]); + sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - sdio_release_host(sdiodev->func[func]); + sdio_release_host(gInstance->func[func]); } } else { /* CMD52 Read */ /* Claim host controller, perform Fn read, and release */ - sdio_claim_host(sdiodev->func[func]); + sdio_claim_host(gInstance->func[func]); if (func == 0) { *byte = - sdio_f0_readb(sdiodev->func[func], regaddr, + sdio_f0_readb(gInstance->func[func], regaddr, &err_ret); } else { *byte = - sdio_readb(sdiodev->func[func], regaddr, + sdio_readb(gInstance->func[func], regaddr, &err_ret); } - sdio_release_host(sdiodev->func[func]); + sdio_release_host(gInstance->func[func]); } if (err_ret) - BRCMF_ERROR(("brcmf: Failed to %s byte F%d:@0x%05x=%02x, " + sd_err(("brcmf: Failed to %s byte F%d:@0x%05x=%02x, " "Err: %d\n", rw ? "Write" : "Read", func, regaddr, *byte, err_ret)); @@ -349,61 +744,61 @@ brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, } extern int -brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, uint cmd_type, uint rw, +brcmf_sdioh_request_word(struct sdioh_info *sd, uint cmd_type, uint rw, uint func, uint addr, u32 *word, uint nbytes) { int err_ret = -EIO; if (func == 0) { - BRCMF_ERROR(("%s: Only CMD52 allowed to F0.\n", __func__)); + sd_err(("%s: Only CMD52 allowed to F0.\n", __func__)); return -EINVAL; } - BRCMF_INFO(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", + sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", __func__, cmd_type, rw, func, addr, nbytes)); - BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait, sdiodev); - BRCMF_PM_RESUME_RETURN_ERROR(-EIO, sdiodev); + BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait); + BRCMF_PM_RESUME_RETURN_ERROR(-EIO); /* Claim host controller */ - sdio_claim_host(sdiodev->func[func]); + sdio_claim_host(gInstance->func[func]); if (rw) { /* CMD52 Write */ - if (nbytes == 4) - sdio_writel(sdiodev->func[func], *word, addr, + if (nbytes == 4) { + sdio_writel(gInstance->func[func], *word, addr, &err_ret); - else if (nbytes == 2) - sdio_writew(sdiodev->func[func], (*word & 0xFFFF), + } else if (nbytes == 2) { + sdio_writew(gInstance->func[func], (*word & 0xFFFF), addr, &err_ret); - else - BRCMF_ERROR(("%s: Invalid nbytes: %d\n", - __func__, nbytes)); + } else { + sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes)); + } } else { /* CMD52 Read */ - if (nbytes == 4) + if (nbytes == 4) { *word = - sdio_readl(sdiodev->func[func], addr, &err_ret); - else if (nbytes == 2) + sdio_readl(gInstance->func[func], addr, &err_ret); + } else if (nbytes == 2) { *word = - sdio_readw(sdiodev->func[func], addr, + sdio_readw(gInstance->func[func], addr, &err_ret) & 0xFFFF; - else - BRCMF_ERROR(("%s: Invalid nbytes: %d\n", - __func__, nbytes)); + } else { + sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes)); + } } /* Release host controller */ - sdio_release_host(sdiodev->func[func]); + sdio_release_host(gInstance->func[func]); - if (err_ret) - BRCMF_ERROR(("brcmf: Failed to %s word, Err: 0x%08x\n", + if (err_ret) { + sd_err(("brcmf: Failed to %s word, Err: 0x%08x\n", rw ? "Write" : "Read", err_ret)); + } return err_ret; } static int -brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc, - uint write, uint func, uint addr, - struct sk_buff *pkt) +brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write, + uint func, uint addr, struct sk_buff *pkt) { bool fifo = (fix_inc == SDIOH_DATA_FIX); u32 SGCount = 0; @@ -411,46 +806,46 @@ brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc, struct sk_buff *pnext; - BRCMF_TRACE(("%s: Enter\n", __func__)); + sd_trace(("%s: Enter\n", __func__)); - BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait, sdiodev); - BRCMF_PM_RESUME_RETURN_ERROR(-EIO, sdiodev); + BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait); + BRCMF_PM_RESUME_RETURN_ERROR(-EIO); /* Claim host controller */ - sdio_claim_host(sdiodev->func[func]); + sdio_claim_host(gInstance->func[func]); for (pnext = pkt; pnext; pnext = pnext->next) { uint pkt_len = pnext->len; pkt_len += 3; pkt_len &= 0xFFFFFFFC; if ((write) && (!fifo)) { - err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, + err_ret = sdio_memcpy_toio(gInstance->func[func], addr, ((u8 *) (pnext->data)), pkt_len); } else if (write) { - err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, + err_ret = sdio_memcpy_toio(gInstance->func[func], addr, ((u8 *) (pnext->data)), pkt_len); } else if (fifo) { - err_ret = sdio_readsb(sdiodev->func[func], + err_ret = sdio_readsb(gInstance->func[func], ((u8 *) (pnext->data)), addr, pkt_len); } else { - err_ret = sdio_memcpy_fromio(sdiodev->func[func], + err_ret = sdio_memcpy_fromio(gInstance->func[func], ((u8 *) (pnext->data)), addr, pkt_len); } if (err_ret) { - BRCMF_ERROR(("%s: %s FAILED %p[%d], addr=0x%05x, " - "pkt_len=%d, ERR=0x%08x\n", __func__, + sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d," + "ERR=0x%08x\n", __func__, (write) ? "TX" : "RX", pnext, SGCount, addr, pkt_len, err_ret)); } else { - BRCMF_TRACE(("%s: %s xfr'd %p[%d], addr=0x%05x, " - "len=%d\n", __func__, - (write) ? "TX" : "RX", - pnext, SGCount, addr, pkt_len)); + sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n", + __func__, + (write) ? "TX" : "RX", + pnext, SGCount, addr, pkt_len)); } if (!fifo) @@ -460,9 +855,9 @@ brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc, } /* Release host controller */ - sdio_release_host(sdiodev->func[func]); + sdio_release_host(gInstance->func[func]); - BRCMF_TRACE(("%s: Exit\n", __func__)); + sd_trace(("%s: Exit\n", __func__)); return err_ret; } @@ -482,26 +877,25 @@ brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc, * */ extern int -brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, uint pio_dma, - uint fix_inc, uint write, uint func, uint addr, - uint reg_width, uint buflen_u, u8 *buffer, - struct sk_buff *pkt) +brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc, + uint write, uint func, uint addr, uint reg_width, + uint buflen_u, u8 *buffer, struct sk_buff *pkt) { int Status; struct sk_buff *mypkt = NULL; - BRCMF_TRACE(("%s: Enter\n", __func__)); + sd_trace(("%s: Enter\n", __func__)); - BRCMF_PM_RESUME_WAIT(sdioh_request_buffer_wait, sdiodev); - BRCMF_PM_RESUME_RETURN_ERROR(-EIO, sdiodev); + BRCMF_PM_RESUME_WAIT(sdioh_request_buffer_wait); + BRCMF_PM_RESUME_RETURN_ERROR(-EIO); /* Case 1: we don't have a packet. */ if (pkt == NULL) { - BRCMF_DATA(("%s: Creating new %s Packet, len=%d\n", + sd_data(("%s: Creating new %s Packet, len=%d\n", __func__, write ? "TX" : "RX", buflen_u)); mypkt = brcmu_pkt_buf_get_skb(buflen_u); if (!mypkt) { - BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed: " - "len %d\n", __func__, buflen_u)); + sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n", + __func__, buflen_u)); return -EIO; } @@ -509,8 +903,8 @@ brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, uint pio_dma, if (write) memcpy(mypkt->data, buffer, buflen_u); - Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, - func, addr, mypkt); + Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func, + addr, mypkt); /* For a read, copy the packet data back to the buffer. */ if (!write) @@ -522,12 +916,12 @@ brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, uint pio_dma, * Case 2: We have a packet, but it is unaligned. * In this case, we cannot have a chain (pkt->next == NULL) */ - BRCMF_DATA(("%s: Creating aligned %s Packet, len=%d\n", + sd_data(("%s: Creating aligned %s Packet, len=%d\n", __func__, write ? "TX" : "RX", pkt->len)); mypkt = brcmu_pkt_buf_get_skb(pkt->len); if (!mypkt) { - BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed: " - "len %d\n", __func__, pkt->len)); + sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n", + __func__, pkt->len)); return -EIO; } @@ -535,8 +929,8 @@ brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, uint pio_dma, if (write) memcpy(mypkt->data, pkt->data, pkt->len); - Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, - func, addr, mypkt); + Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func, + addr, mypkt); /* For a read, copy the packet data back to the buffer. */ if (!write) @@ -545,77 +939,128 @@ brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, uint pio_dma, brcmu_pkt_buf_free_skb(mypkt); } else { /* case 3: We have a packet and it is aligned. */ - BRCMF_DATA(("%s: Aligned %s Packet, direct DMA\n", + sd_data(("%s: Aligned %s Packet, direct DMA\n", __func__, write ? "Tx" : "Rx")); - Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, - func, addr, pkt); + Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func, + addr, pkt); } return Status; } +/* this function performs "abort" for both of host & device */ +extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func) +{ + char t_func = (char)func; + sd_trace(("%s: Enter\n", __func__)); + + /* issue abort cmd52 command through F0 */ + brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT, + &t_func); + + sd_trace(("%s: Exit\n", __func__)); + return 0; +} + +/* Disable device interrupt */ +void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd) +{ + sd_trace(("%s: %d\n", __func__, sd->use_client_ints)); + sd->intmask &= ~CLIENT_INTR; +} + +/* Enable device interrupt */ +void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd) +{ + sd_trace(("%s: %d\n", __func__, sd->use_client_ints)); + sd->intmask |= CLIENT_INTR; +} + /* Read client card reg */ int -brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr, +brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr, int regsize, u32 *data) { if ((func == 0) || (regsize == 1)) { u8 temp = 0; - brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr, - &temp); + brcmf_sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp); *data = temp; *data &= 0xff; - BRCMF_DATA(("%s: byte read data=0x%02x\n", __func__, *data)); + sd_data(("%s: byte read data=0x%02x\n", __func__, *data)); } else { - brcmf_sdioh_request_word(sdiodev, 0, SDIOH_READ, func, regaddr, - data, regsize); + brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, + regsize); if (regsize == 2) *data &= 0xffff; - BRCMF_DATA(("%s: word read data=0x%08x\n", __func__, *data)); + sd_data(("%s: word read data=0x%08x\n", __func__, *data)); } return SUCCESS; } +static void brcmf_sdioh_irqhandler(struct sdio_func *func) +{ + struct sdioh_info *sd; + + sd_trace(("brcmf: ***IRQHandler\n")); + sd = gInstance->sd; + + sdio_release_host(gInstance->func[0]); + + if (sd->use_client_ints) { + sd->intrcount++; + (sd->intr_handler) (sd->intr_handler_arg); + } else { + sd_err(("brcmf: ***IRQHandler\n")); + + sd_err(("%s: Not ready for intr: enabled %d, handler %p\n", + __func__, sd->client_intr_enabled, sd->intr_handler)); + } + + sdio_claim_host(gInstance->func[0]); +} + +/* interrupt handler for F2 (dummy handler) */ +static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func) +{ + struct sdioh_info *sd; + + sd_trace(("brcmf: ***IRQHandlerF2\n")); + + sd = gInstance->sd; +} + static int brcmf_ops_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { int ret = 0; - struct brcmf_sdio_dev *sdiodev; - BRCMF_TRACE(("sdio_probe: %s Enter\n", __func__)); - BRCMF_TRACE(("sdio_probe: func->class=%x\n", func->class)); - BRCMF_TRACE(("sdio_vendor: 0x%04x\n", func->vendor)); - BRCMF_TRACE(("sdio_device: 0x%04x\n", func->device)); - BRCMF_TRACE(("Function#: 0x%04x\n", func->num)); + static struct sdio_func sdio_func_0; + sd_trace(("sdio_probe: %s Enter\n", __func__)); + sd_trace(("sdio_probe: func->class=%x\n", func->class)); + sd_trace(("sdio_vendor: 0x%04x\n", func->vendor)); + sd_trace(("sdio_device: 0x%04x\n", func->device)); + sd_trace(("Function#: 0x%04x\n", func->num)); if (func->num == 1) { - if (dev_get_drvdata(&func->card->dev)) { - BRCMF_ERROR(("%s: card private drvdata occupied.\n", - __func__)); - return -ENXIO; + sdio_func_0.num = 0; + sdio_func_0.card = func->card; + gInstance->func[0] = &sdio_func_0; + if (func->device == 0x4) { /* 4318 */ + gInstance->func[2] = NULL; + sd_trace(("NIC found, calling brcmf_sdio_probe...\n")); + ret = brcmf_sdio_probe(&sdmmc_dev); } - sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL); - if (!sdiodev) - return -ENOMEM; - sdiodev->func[0] = func->card->sdio_func[0]; - sdiodev->func[1] = func; - dev_set_drvdata(&func->card->dev, sdiodev); - - atomic_set(&sdiodev->suspend, false); } - if (func->num == 2) { - sdiodev = dev_get_drvdata(&func->card->dev); - if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) - return -ENODEV; - sdiodev->func[2] = func; + gInstance->func[func->num] = func; + if (func->num == 2) { brcmf_cfg80211_sdio_func(func); - BRCMF_TRACE(("F2 found, calling brcmf_sdio_probe...\n")); - ret = brcmf_sdio_probe(sdiodev); + sd_trace(("F2 found, calling brcmf_sdio_probe...\n")); + ret = brcmf_sdio_probe(&sdmmc_dev); } return ret; @@ -623,65 +1068,102 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, static void brcmf_ops_sdio_remove(struct sdio_func *func) { - struct brcmf_sdio_dev *sdiodev; - BRCMF_TRACE(("%s Enter\n", __func__)); - BRCMF_INFO(("func->class=%x\n", func->class)); - BRCMF_INFO(("sdio_vendor: 0x%04x\n", func->vendor)); - BRCMF_INFO(("sdio_device: 0x%04x\n", func->device)); - BRCMF_INFO(("Function#: 0x%04x\n", func->num)); + sd_trace(("%s Enter\n", __func__)); + sd_info(("func->class=%x\n", func->class)); + sd_info(("sdio_vendor: 0x%04x\n", func->vendor)); + sd_info(("sdio_device: 0x%04x\n", func->device)); + sd_info(("Function#: 0x%04x\n", func->num)); if (func->num == 2) { - sdiodev = dev_get_drvdata(&func->card->dev); - BRCMF_TRACE(("F2 found, calling brcmf_sdio_remove...\n")); - brcmf_sdio_remove(sdiodev); - dev_set_drvdata(&func->card->dev, NULL); - kfree(sdiodev); + sd_trace(("F2 found, calling brcmf_sdio_remove...\n")); + brcmf_sdio_remove(&sdmmc_dev); } } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int brcmf_sdio_suspend(struct device *dev) { mmc_pm_flag_t sdio_flags; - struct brcmf_sdio_dev *sdiodev; - struct sdio_func *func = dev_to_sdio_func(dev); int ret = 0; - BRCMF_TRACE(("%s\n", __func__)); - - sdiodev = dev_get_drvdata(&func->card->dev); - - atomic_set(&sdiodev->suspend, true); + sd_trace(("%s\n", __func__)); - sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); + sdio_flags = sdio_get_host_pm_caps(gInstance->func[1]); if (!(sdio_flags & MMC_PM_KEEP_POWER)) { - BRCMF_ERROR(("Host can't keep power while suspended\n")); + sd_err(("Host can't keep power while suspended\n")); return -EINVAL; } - ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER); + ret = sdio_set_host_pm_flags(gInstance->func[1], MMC_PM_KEEP_POWER); if (ret) { - BRCMF_ERROR(("Failed to set pm_flags\n")); + sd_err(("Failed to set pm_flags\n")); return ret; } - brcmf_sdio_wdtmr_enable(sdiodev, false); + brcmf_sdio_wdtmr_enable(false); return ret; } static int brcmf_sdio_resume(struct device *dev) { - struct brcmf_sdio_dev *sdiodev; - struct sdio_func *func = dev_to_sdio_func(dev); + brcmf_sdio_wdtmr_enable(true); + return 0; +} +#endif /* CONFIG_PM */ + +int brcmf_sdioh_osinit(struct sdioh_info *sd) +{ + struct sdos_info *sdos; + + sdos = kmalloc(sizeof(struct sdos_info), GFP_ATOMIC); + sd->sdos_info = (void *)sdos; + if (sdos == NULL) + return -ENOMEM; + + sdos->sd = sd; + spin_lock_init(&sdos->lock); + return 0; +} + +void brcmf_sdioh_osfree(struct sdioh_info *sd) +{ + struct sdos_info *sdos; + + sdos = (struct sdos_info *)sd->sdos_info; + kfree(sdos); +} + +/* Interrupt enable/disable */ +int brcmf_sdioh_interrupt_set(struct sdioh_info *sd, bool enable) +{ + unsigned long flags; + struct sdos_info *sdos; + + sd_trace(("%s: %s\n", __func__, enable ? "Enabling" : "Disabling")); + + sdos = (struct sdos_info *)sd->sdos_info; + + if (enable && !(sd->intr_handler && sd->intr_handler_arg)) { + sd_err(("%s: no handler registered, will not enable\n", + __func__)); + return -EINVAL; + } + + /* Ensure atomicity for enable/disable calls */ + spin_lock_irqsave(&sdos->lock, flags); + + sd->client_intr_enabled = enable; + if (enable) + brcmf_sdioh_dev_intr_on(sd); + else + brcmf_sdioh_dev_intr_off(sd); + + spin_unlock_irqrestore(&sdos->lock, flags); - sdiodev = dev_get_drvdata(&func->card->dev); - brcmf_sdio_wdtmr_enable(sdiodev, true); - atomic_set(&sdiodev->suspend, false); return 0; } -#endif /* CONFIG_PM_SLEEP */ /* * module init @@ -689,8 +1171,13 @@ static int brcmf_sdio_resume(struct device *dev) int brcmf_sdio_function_init(void) { int error = 0; - BRCMF_TRACE(("brcmf_sdio_function_init: %s Enter\n", __func__)); + sd_trace(("brcmf_sdio_function_init: %s Enter\n", __func__)); + gInstance = kzalloc(sizeof(struct brcmf_sdmmc_instance), GFP_KERNEL); + if (!gInstance) + return -ENOMEM; + + memset(&sdmmc_dev, 0, sizeof(sdmmc_dev)); error = sdio_register_driver(&brcmf_sdmmc_driver); return error; @@ -701,7 +1188,9 @@ int brcmf_sdio_function_init(void) */ void brcmf_sdio_function_cleanup(void) { - BRCMF_TRACE(("%s Enter\n", __func__)); + sd_trace(("%s Enter\n", __func__)); sdio_unregister_driver(&brcmf_sdmmc_driver); + + kfree(gInstance); } diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd.h b/trunk/drivers/staging/brcm80211/brcmfmac/dhd.h index ee09c17db58d..82bf04df16d0 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd.h +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd.h @@ -117,16 +117,11 @@ #define BRCMF_SCAN_RESULTS_ABORTED 3 #define BRCMF_SCAN_RESULTS_NO_MEM 4 -/* Indicates this key is using soft encrypt */ -#define WL_SOFT_KEY (1 << 0) -/* primary (ie tx) key */ -#define BRCMF_PRIMARY_KEY (1 << 1) -/* Reserved for backward compat */ -#define WL_KF_RES_4 (1 << 4) -/* Reserved for backward compat */ -#define WL_KF_RES_5 (1 << 5) -/* Indicates a group key for a IBSS PEER */ -#define WL_IBSS_PEER_GROUP_KEY (1 << 6) +#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */ +#define BRCMF_PRIMARY_KEY (1 << 1) /* primary (ie tx) key */ +#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */ +#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */ +#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */ /* For supporting multiple interfaces */ #define BRCMF_MAX_IFS 16 @@ -338,18 +333,13 @@ enum brcmf_bus_state { * that indicates which bits within the pattern should be matched. */ struct brcmf_pkt_filter_pattern { - /* - * Offset within received packet to start pattern matching. - * Offset '0' is the first byte of the ethernet header. - */ - u32 offset; - /* Size of the pattern. Bitmask must be the same size.*/ - u32 size_bytes; - /* - * Variable length mask and pattern data. mask starts at offset 0. - * Pattern immediately follows mask. - */ - u8 mask_and_pattern[1]; + u32 offset; /* Offset within received packet to start pattern matching. + * Offset '0' is the first byte of the ethernet header. + */ + u32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */ + u8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts + * at offset 0. Pattern immediately follows mask. + */ }; /* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ @@ -383,10 +373,10 @@ struct brcmf_bss_info { u8 SSID_len; u8 SSID[32]; struct { - uint count; /* # rates in this set */ - u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ + uint count; /* # rates in this set */ + u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ } rateset; /* supported rates */ - u16 chanspec; /* chanspec for bss */ + chanspec_t chanspec; /* chanspec for bss */ u16 atim_window; /* units are Kusec */ u8 dtim_period; /* DTIM period */ s16 RSSI; /* receive signal strength (in dBm) */ @@ -419,7 +409,7 @@ struct brcmf_scan_params { * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT */ u8 scan_type; /* flags, 0 use default */ - s32 nprobes; /* -1 use default, number of probes per channel */ + s32 nprobes; /* -1 use default, number of probes per channel */ s32 active_time; /* -1 use default, dwell time per channel for * active scanning */ @@ -470,16 +460,14 @@ struct brcmf_scan_results { /* used for association with a specific BSSID and chanspec list */ struct brcmf_assoc_params { - /* 00:00:00:00:00:00: broadcast scan */ - u8 bssid[ETH_ALEN]; - /* 0: all available channels, otherwise count of chanspecs in - * chanspec_list */ - s32 chanspec_num; - /* list of chanspecs */ - u16 chanspec_list[1]; + u8 bssid[ETH_ALEN]; /* 00:00:00:00:00:00: broadcast scan */ + s32 chanspec_num; /* 0: all available channels, + * otherwise count of chanspecs in chanspec_list + */ + chanspec_t chanspec_list[1]; /* list of chanspecs */ }; #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ - (sizeof(struct brcmf_assoc_params) - sizeof(u16)) + (sizeof(struct brcmf_assoc_params) - sizeof(chanspec_t)) /* used for join with or without a specific bssid and channel list */ struct brcmf_join_params { @@ -507,8 +495,8 @@ struct brcmf_wsec_key { u32 len; /* key length */ u8 data[WLAN_MAX_KEY_LEN]; /* key data */ u32 pad_1[18]; - u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ - u32 flags; /* misc flags */ + u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ + u32 flags; /* misc flags */ u32 pad_2[2]; int pad_3; int iv_initialized; /* has IV been initialized already? */ @@ -570,45 +558,32 @@ struct brcmf_pub { /* Dongle media info */ bool iswl; /* Dongle-resident driver is wl */ unsigned long drv_version; /* Version of dongle-resident driver */ - u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ + u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ struct dngl_stats dstats; /* Stats for dongle-based data */ /* Additional stats for the bus level */ - - /* Data packets sent to dongle */ - unsigned long tx_packets; - /* Multicast data packets sent to dongle */ - unsigned long tx_multicast; - /* Errors in sending data to dongle */ - unsigned long tx_errors; - /* Control packets sent to dongle */ - unsigned long tx_ctlpkts; - /* Errors sending control frames to dongle */ - unsigned long tx_ctlerrs; - /* Packets sent up the network interface */ - unsigned long rx_packets; - /* Multicast packets sent up the network interface */ - unsigned long rx_multicast; - /* Errors processing rx data packets */ - unsigned long rx_errors; - /* Control frames processed from dongle */ - unsigned long rx_ctlpkts; - - /* Errors in processing rx control frames */ - unsigned long rx_ctlerrs; - /* Packets dropped locally (no memory) */ - unsigned long rx_dropped; - /* Packets flushed due to unscheduled sendup thread */ - unsigned long rx_flushed; - /* Number of times dpc scheduled by watchdog timer */ - unsigned long wd_dpc_sched; - - /* Number of packets where header read-ahead was used. */ - unsigned long rx_readahead_cnt; - /* Number of tx packets we had to realloc for headroom */ - unsigned long tx_realloc; - /* Number of flow control pkts recvd */ - unsigned long fc_packets; + unsigned long tx_packets; /* Data packets sent to dongle */ + unsigned long tx_multicast; /* Multicast data packets sent to dongle */ + unsigned long tx_errors; /* Errors in sending data to dongle */ + unsigned long tx_ctlpkts; /* Control packets sent to dongle */ + unsigned long tx_ctlerrs; /* Errors sending control frames to dongle */ + unsigned long rx_packets; /* Packets sent up the network interface */ + unsigned long rx_multicast; /* Multicast packets sent up the network + interface */ + unsigned long rx_errors; /* Errors processing rx data packets */ + unsigned long rx_ctlpkts; /* Control frames processed from dongle */ + unsigned long rx_ctlerrs; /* Errors in processing rx control frames */ + unsigned long rx_dropped; /* Packets dropped locally (no memory) */ + unsigned long rx_flushed; /* Packets flushed due to + unscheduled sendup thread */ + unsigned long wd_dpc_sched; /* Number of times dpc scheduled by + watchdog timer */ + + unsigned long rx_readahead_cnt; /* Number of packets where header read-ahead + was used. */ + unsigned long tx_realloc; /* Number of tx packets we had to realloc for + headroom */ + unsigned long fc_packets; /* Number of flow control pkts recvd */ /* Last error return */ int bcmerror; @@ -639,15 +614,67 @@ struct brcmf_if_event { u8 bssidx; }; +struct brcmf_timeout { + u32 limit; /* Expiration time (usec) */ + u32 increment; /* Current expiration increment (usec) */ + u32 elapsed; /* Current elapsed time (usec) */ + u32 tick; /* O/S tick time (usec) */ +}; + struct bcmevent_name { uint event; const char *name; }; +#if defined(CONFIG_PM_SLEEP) +extern atomic_t brcmf_mmc_suspend; +#define BRCMF_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); +#define _BRCMF_PM_RESUME_WAIT(a, b) do { \ + int retry = 0; \ + while (atomic_read(&brcmf_mmc_suspend) && retry++ != b) { \ + wait_event_timeout(a, false, HZ/100); \ + } \ + } while (0) +#define BRCMF_PM_RESUME_WAIT(a) _BRCMF_PM_RESUME_WAIT(a, 30) +#define BRCMF_PM_RESUME_RETURN_ERROR(a) \ + do { if (atomic_read(&brcmf_mmc_suspend)) return a; } while (0) + +#define BRCMF_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); +#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \ + uint countdown = (us) + 9999; \ + while ((exp) && (countdown >= 10000)) { \ + wait_event_timeout(a, false, HZ/100); \ + countdown -= 10000; \ + } \ + } while (0) + +#else + +#define BRCMF_PM_RESUME_WAIT_INIT(a) +#define BRCMF_PM_RESUME_WAIT(a) +#define BRCMF_PM_RESUME_RETURN_ERROR(a) + +#define BRCMF_SPINWAIT_SLEEP_INIT(a) +#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \ + uint countdown = (us) + 9; \ + while ((exp) && (countdown >= 10)) { \ + udelay(10); \ + countdown -= 10; \ + } \ + } while (0) + +#endif /* defined(CONFIG_PM_SLEEP) */ + /* * Insmod parameters for debug/test */ +/* Use interrupts */ +extern uint brcmf_intr; + +/* Use polling */ +extern uint brcmf_poll; + /* ARP offload agent mode */ extern uint brcmf_arp_mode; @@ -669,9 +696,25 @@ extern uint brcmf_roam; /* Roaming mode control */ extern uint brcmf_radio_up; +/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */ +extern int brcmf_idletime; +#define BRCMF_IDLETIME_TICKS 1 + +/* SDIO Drive Strength */ +extern uint brcmf_sdiod_drive_strength; + /* Override to force tx queueing all the time */ extern uint brcmf_force_tx_queueing; +#ifdef SDTEST +/* Echo packet generator (SDIO), pkts/s */ +extern uint brcmf_pktgen; + +/* Echo packet len (0 => sawtooth, max 1800) */ +extern uint brcmf_pktgen_len; +#define BRCMF_MAX_PKTGEN_LEN 1800 +#endif + extern const struct bcmevent_name bcmevent_names[]; extern const int bcmevent_names_size; @@ -749,10 +792,18 @@ extern int brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, /* OS independent layer functions */ extern int brcmf_os_proto_block(struct brcmf_pub *drvr); extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr); +extern int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition, + bool *pending); +extern int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr); +extern unsigned int brcmf_os_get_ioctl_resp_timeout(void); +extern void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec); #ifdef BCMDBG extern int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size); #endif /* BCMDBG */ +extern void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec); +extern int brcmf_timeout_expired(struct brcmf_timeout *tmo); + extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name); extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx, void *pktdata, struct brcmf_event_msg *, @@ -760,9 +811,8 @@ extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx, extern void brcmf_c_init(void); -extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, - struct net_device *net, char *name, u8 *mac_addr, - u32 flags, u8 bssidx); +extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle, + char *name, u8 *mac_addr, u32 flags, u8 bssidx); extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx); /* Send packet to dongle via data channel */ @@ -815,6 +865,34 @@ struct brcmf_c_ioctl { #define BRCMF_BTA_VAL 0x1000 #define BRCMF_ISCAN_VAL 0x2000 +#ifdef SDTEST +/* For pktgen iovar */ +struct brcmf_pktgen { + uint version; /* To allow structure change tracking */ + uint freq; /* Max ticks between tx/rx attempts */ + uint count; /* Test packets to send/rcv each attempt */ + uint print; /* Print counts every attempts */ + uint total; /* Total packets (or bursts) */ + uint minlen; /* Minimum length of packets to send */ + uint maxlen; /* Maximum length of packets to send */ + uint numsent; /* Count of test packets sent */ + uint numrcvd; /* Count of test packets received */ + uint numfail; /* Count of test send failures */ + uint mode; /* Test mode (type of test packets) */ + uint stop; /* Stop after this many tx failures */ +}; + +/* Version in case structure changes */ +#define BRCMF_PKTGEN_VERSION 2 + +/* Type of test packets to use */ +#define BRCMF_PKTGEN_ECHO 1 /* Send echo requests */ +#define BRCMF_PKTGEN_SEND 2 /* Send discard packets */ +#define BRCMF_PKTGEN_RXBURST 3 /* Request dongle send N packets */ +#define BRCMF_PKTGEN_RECV 4 /* Continuous rx from continuous + tx dongle */ +#endif /* SDTEST */ + /* Enter idle immediately (no timeout) */ #define BRCMF_IDLE_IMMEDIATE (-1) diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_common.c index bd655a31087a..fdec4683c422 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_common.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_common.c @@ -55,6 +55,7 @@ enum { IOV_LOGCAL, IOV_LOGSTAMP, IOV_GPIOOB, + IOV_IOCTLTIMEOUT, IOV_LAST }; @@ -75,6 +76,8 @@ const struct brcmu_iovar brcmf_iovars[] = { , {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0} , + {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0} + , {NULL, 0, 0, 0, 0} }; @@ -224,6 +227,21 @@ brcmf_c_doiovar(struct brcmf_pub *drvr, const struct brcmu_iovar *vi, brcmf_bus_clearcounts(drvr); break; + case IOV_GVAL(IOV_IOCTLTIMEOUT):{ + int_val = (s32) brcmf_os_get_ioctl_resp_timeout(); + memcpy(arg, &int_val, sizeof(int_val)); + break; + } + + case IOV_SVAL(IOV_IOCTLTIMEOUT):{ + if (int_val <= 0) + bcmerror = -EINVAL; + else + brcmf_os_set_ioctl_resp_timeout((unsigned int) + int_val); + break; + } + default: bcmerror = -ENOTSUPP; break; @@ -266,17 +284,18 @@ bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, /* Evict packet according to discard policy */ p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : brcmu_pktq_pdeq_tail(q, eprec); - if (p == NULL) + if (p == NULL) { BRCMF_ERROR(("%s: brcmu_pktq_penq() failed, oldest %d.", __func__, discard_oldest)); - + } brcmu_pkt_buf_free_skb(p); } /* Enqueue */ p = brcmu_pktq_penq(q, prec, pkt); - if (p == NULL) + if (p == NULL) { BRCMF_ERROR(("%s: brcmu_pktq_penq() failed.", __func__)); + } return p != NULL; } @@ -292,7 +311,7 @@ brcmf_c_iovar_op(struct brcmf_pub *drvr, const char *name, BRCMF_TRACE(("%s: Enter\n", __func__)); - if (name == NULL || len < 0) + if (name == NULL || len <= 0) return -EINVAL; /* Set does not take qualifiers */ @@ -523,19 +542,20 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) case BRCMF_E_ASSOC: case BRCMF_E_REASSOC: - if (status == BRCMF_E_STATUS_SUCCESS) + if (status == BRCMF_E_STATUS_SUCCESS) { BRCMF_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n", event_name, eabuf)); - else if (status == BRCMF_E_STATUS_TIMEOUT) + } else if (status == BRCMF_E_STATUS_TIMEOUT) { BRCMF_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n", event_name, eabuf)); - else if (status == BRCMF_E_STATUS_FAIL) + } else if (status == BRCMF_E_STATUS_FAIL) { BRCMF_EVENT(("MACEVENT: %s, MAC %s, FAILURE," " reason %d\n", event_name, eabuf, (int)reason)); - else + } else { BRCMF_EVENT(("MACEVENT: %s, MAC %s, unexpected status " "%d\n", event_name, eabuf, (int)status)); + } break; case BRCMF_E_DEAUTH_IND: @@ -554,16 +574,16 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) sprintf(err_msg, "AUTH unknown: %d", (int)auth_type); auth_str = err_msg; } - if (event_type == BRCMF_E_AUTH_IND) + if (event_type == BRCMF_E_AUTH_IND) { BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name, eabuf, auth_str)); - else if (status == BRCMF_E_STATUS_SUCCESS) + } else if (status == BRCMF_E_STATUS_SUCCESS) { BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n", event_name, eabuf, auth_str)); - else if (status == BRCMF_E_STATUS_TIMEOUT) + } else if (status == BRCMF_E_STATUS_TIMEOUT) { BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n", event_name, eabuf, auth_str)); - else if (status == BRCMF_E_STATUS_FAIL) { + } else if (status == BRCMF_E_STATUS_FAIL) { BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, " "reason %d\n", event_name, eabuf, auth_str, (int)reason)); @@ -574,27 +594,29 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) case BRCMF_E_JOIN: case BRCMF_E_ROAM: case BRCMF_E_SET_SSID: - if (status == BRCMF_E_STATUS_SUCCESS) + if (status == BRCMF_E_STATUS_SUCCESS) { BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); - else if (status == BRCMF_E_STATUS_FAIL) + } else if (status == BRCMF_E_STATUS_FAIL) { BRCMF_EVENT(("MACEVENT: %s, failed\n", event_name)); - else if (status == BRCMF_E_STATUS_NO_NETWORKS) + } else if (status == BRCMF_E_STATUS_NO_NETWORKS) { BRCMF_EVENT(("MACEVENT: %s, no networks found\n", event_name)); - else + } else { BRCMF_EVENT(("MACEVENT: %s, unexpected status %d\n", event_name, (int)status)); + } break; case BRCMF_E_BEACON_RX: - if (status == BRCMF_E_STATUS_SUCCESS) + if (status == BRCMF_E_STATUS_SUCCESS) { BRCMF_EVENT(("MACEVENT: %s, SUCCESS\n", event_name)); - else if (status == BRCMF_E_STATUS_FAIL) + } else if (status == BRCMF_E_STATUS_FAIL) { BRCMF_EVENT(("MACEVENT: %s, FAIL\n", event_name)); - else + } else { BRCMF_EVENT(("MACEVENT: %s, status %d\n", event_name, status)); + } break; case BRCMF_E_LINK: @@ -660,19 +682,20 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) + be16_to_cpu(hdr.len)) = '\0'; if (be32_to_cpu(hdr.discarded_bytes) - || be32_to_cpu(hdr.discarded_printf)) - BRCMF_ERROR(("\nWLC_E_TRACE: [Discarded traces " - "in dongle -->discarded_bytes %d " - "discarded_printf %d]\n", - be32_to_cpu(hdr.discarded_bytes), - be32_to_cpu(hdr.discarded_printf))) - ; + || be32_to_cpu(hdr.discarded_printf)) { + BRCMF_ERROR( + ("\nWLC_E_TRACE: [Discarded traces in dongle -->" + "discarded_bytes %d discarded_printf %d]\n", + be32_to_cpu(hdr.discarded_bytes), + be32_to_cpu(hdr.discarded_printf))); + } nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1; - if (nblost > 0) - BRCMF_ERROR(("\nWLC_E_TRACE: [Event lost --> " - "seqnum %d nblost %d\n", - be32_to_cpu(hdr.seqnum), nblost)); + if (nblost > 0) { + BRCMF_ERROR( + ("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n", + be32_to_cpu(hdr.seqnum), nblost)); + } seqnum_prev = be32_to_cpu(hdr.seqnum); /* Display the trace buffer. Advance from \n to \n to @@ -818,21 +841,18 @@ static int brcmf_c_pattern_atoh(char *src, char *dst) int i; if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { BRCMF_ERROR(("Mask invalid format. Needs to start with 0x\n")); - return -EINVAL; + return -1; } src = src + 2; /* Skip past 0x */ if (strlen(src) % 2 != 0) { BRCMF_ERROR(("Mask invalid format. Length must be even.\n")); - return -EINVAL; + return -1; } for (i = 0; *src != '\0'; i++) { - unsigned long res; char num[3]; strncpy(num, src, 2); num[2] = '\0'; - if (kstrtoul(num, 16, &res)) - return -EINVAL; - dst[i] = (u8)res; + dst[i] = (u8) simple_strtoul(num, NULL, 16); src += 2; } return i; @@ -842,7 +862,6 @@ void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable, int master_mode) { - unsigned long res; char *argv[8]; int i = 0; const char *str; @@ -879,9 +898,7 @@ brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable, pkt_filterp = (struct brcmf_pkt_filter_enable *) (buf + str_len + 1); /* Parse packet filter id. */ - enable_parm.id = 0; - if (!kstrtoul(argv[i], 0, &res)) - enable_parm.id = (u32)res; + enable_parm.id = simple_strtoul(argv[i], NULL, 0); /* Parse enable/disable value. */ enable_parm.enable = enable; @@ -918,7 +935,6 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) const char *str; struct brcmf_pkt_filter pkt_filter; struct brcmf_pkt_filter *pkt_filterp; - unsigned long res; int buf_len; int str_len; int rc; @@ -928,7 +944,7 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) int i = 0; char *arg_save = 0, *arg_org = 0; - arg_save = kstrdup(arg, GFP_ATOMIC); + arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC); if (!arg_save) { BRCMF_ERROR(("%s: kmalloc failed\n", __func__)); goto fail; @@ -942,6 +958,8 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) goto fail; } + strcpy(arg_save, arg); + argv[i] = strsep(&arg_save, " "); while (argv[i++]) argv[i] = strsep(&arg_save, " "); @@ -960,9 +978,7 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) pkt_filterp = (struct brcmf_pkt_filter *) (buf + str_len + 1); /* Parse packet filter id. */ - pkt_filter.id = 0; - if (!kstrtoul(argv[i], 0, &res)) - pkt_filter.id = (u32)res; + pkt_filter.id = simple_strtoul(argv[i], NULL, 0); if (NULL == argv[++i]) { BRCMF_ERROR(("Polarity not provided\n")); @@ -970,9 +986,7 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) } /* Parse filter polarity. */ - pkt_filter.negate_match = 0; - if (!kstrtoul(argv[i], 0, &res)) - pkt_filter.negate_match = (u32)res; + pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0); if (NULL == argv[++i]) { BRCMF_ERROR(("Filter type not provided\n")); @@ -980,9 +994,7 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) } /* Parse filter type. */ - pkt_filter.type = 0; - if (!kstrtoul(argv[i], 0, &res)) - pkt_filter.type = (u32)res; + pkt_filter.type = simple_strtoul(argv[i], NULL, 0); if (NULL == argv[++i]) { BRCMF_ERROR(("Offset not provided\n")); @@ -990,9 +1002,7 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) } /* Parse pattern filter offset. */ - pkt_filter.u.pattern.offset = 0; - if (!kstrtoul(argv[i], 0, &res)) - pkt_filter.u.pattern.offset = (u32)res; + pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0); if (NULL == argv[++i]) { BRCMF_ERROR(("Bitmask not provided\n")); @@ -1089,6 +1099,7 @@ int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr) "event_msgs" + '\0' + bitvec */ uint up = 0; char buf[128], *ptr; + uint power_mode = PM_FAST; u32 dongle_align = BRCMF_SDALIGN; u32 glom = 0; uint bcn_timeout = 3; @@ -1101,10 +1112,11 @@ int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr) /* Set Country code */ if (drvr->country_code[0] != 0) { if (brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_COUNTRY, - drvr->country_code, - sizeof(drvr->country_code)) < 0) + drvr->country_code, + sizeof(drvr->country_code)) < 0) { BRCMF_ERROR(("%s: country code setting failed\n", __func__)); + } } /* query for 'ver' to get version info from firmware */ @@ -1116,6 +1128,10 @@ int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr) /* Print fw version info */ BRCMF_ERROR(("Firmware version = %s\n", buf)); + /* Set PowerSave mode */ + brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_PM, (char *)&power_mode, + sizeof(power_mode)); + /* Match Host and Dongle rx alignment */ brcmu_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux.c index b8f9922c56e1..05dada98eb6b 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux.c @@ -28,9 +28,8 @@ #include #include #include +#include #include -#include -#include #include #include #include @@ -43,6 +42,11 @@ #include "wl_cfg80211.h" #include "bcmchip.h" +#if defined(CONFIG_PM_SLEEP) +#include +atomic_t brcmf_mmc_suspend; +#endif /* defined(CONFIG_PM_SLEEP) */ + MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver."); MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards"); @@ -71,11 +75,12 @@ struct brcmf_info { /* OS/stack specifics */ struct brcmf_if *iflist[BRCMF_MAX_IFS]; - struct mutex proto_block; + struct semaphore proto_sem; + wait_queue_head_t ioctl_resp_wait; /* Thread to issue ioctl for multicast */ struct task_struct *sysioc_tsk; - wait_queue_head_t sysioc_waitq; + struct semaphore sysioc_sem; bool set_multicast; bool set_macaddress; u8 macvalue[ETH_ALEN]; @@ -110,6 +115,8 @@ module_param(brcmf_pkt_filter_init, uint, 0); uint brcmf_master_mode = true; module_param(brcmf_master_mode, uint, 0); +module_param(brcmf_dongle_memsize, int, 0); + /* Contorl fw roaming */ uint brcmf_roam = 1; @@ -122,6 +129,29 @@ module_param_string(iface_name, iface_name, IFNAMSIZ, 0); /* The following are specific to the SDIO dongle */ +/* IOCTL response timeout */ +int brcmf_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT; + +/* Idle timeout for backplane clock */ +int brcmf_idletime = BRCMF_IDLETIME_TICKS; +module_param(brcmf_idletime, int, 0); + +/* Use polling */ +uint brcmf_poll; +module_param(brcmf_poll, uint, 0); + +/* Use interrupts */ +uint brcmf_intr = true; +module_param(brcmf_intr, uint, 0); + +/* SDIO Drive Strength (in milliamps) */ +uint brcmf_sdiod_drive_strength = 6; +module_param(brcmf_sdiod_drive_strength, uint, 0); + +/* Tx/Rx bounds */ +module_param(brcmf_txbound, uint, 0); +module_param(brcmf_rxbound, uint, 0); + #ifdef SDTEST /* Echo packet generator (pkts/s) */ uint brcmf_pktgen; @@ -134,10 +164,68 @@ module_param(brcmf_pktgen_len, uint, 0); static int brcmf_toe_get(struct brcmf_info *drvr_priv, int idx, u32 *toe_ol); static int brcmf_toe_set(struct brcmf_info *drvr_priv, int idx, u32 toe_ol); -static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, - void *pktdata, struct brcmf_event_msg *event_ptr, +static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata, + struct brcmf_event_msg *event_ptr, void **data_ptr); +/* + * Generalized timeout mechanism. Uses spin sleep with exponential + * back-off until + * the sleep time reaches one jiffy, then switches over to task delay. Usage: + * + * brcmf_timeout_start(&tmo, usec); + * while (!brcmf_timeout_expired(&tmo)) + * if (poll_something()) + * break; + * if (brcmf_timeout_expired(&tmo)) + * fatal(); + */ + +void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec) +{ + tmo->limit = usec; + tmo->increment = 0; + tmo->elapsed = 0; + tmo->tick = 1000000 / HZ; +} + +int brcmf_timeout_expired(struct brcmf_timeout *tmo) +{ + /* Does nothing the first call */ + if (tmo->increment == 0) { + tmo->increment = 1; + return 0; + } + + if (tmo->elapsed >= tmo->limit) + return 1; + + /* Add the delay that's about to take place */ + tmo->elapsed += tmo->increment; + + if (tmo->increment < tmo->tick) { + udelay(tmo->increment); + tmo->increment *= 2; + if (tmo->increment > tmo->tick) + tmo->increment = tmo->tick; + } else { + wait_queue_head_t delay_wait; + DECLARE_WAITQUEUE(wait, current); + int pending; + init_waitqueue_head(&delay_wait); + add_wait_queue(&delay_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + pending = signal_pending(current); + remove_wait_queue(&delay_wait, &wait); + set_current_state(TASK_RUNNING); + if (pending) + return 1; /* Interrupted */ + } + + return 0; +} + static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net) { int i = 0; @@ -304,8 +392,7 @@ static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx) } } -static int -_brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr) +static int _brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr) { char buf[32]; struct brcmf_ioctl ioc; @@ -325,17 +412,18 @@ _brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr) ioc.set = true; ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len); - if (ret < 0) + if (ret < 0) { BRCMF_ERROR(("%s: set cur_etheraddr failed\n", brcmf_ifname(&drvr_priv->pub, ifidx))); - else + } else { memcpy(drvr_priv->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN); + } return ret; } #ifdef SOFTAP -static struct net_device *ap_net_dev; +extern struct net_device *ap_net_dev; #endif /* Virtual interfaces only ((ifp && ifp->info && ifp->idx == true) */ @@ -370,8 +458,7 @@ static void brcmf_op_if(struct brcmf_if *ifp) } if (ret == 0) { strcpy(ifp->net->name, ifp->name); - memcpy(netdev_priv(ifp->net), &drvr_priv, - sizeof(drvr_priv)); + memcpy(netdev_priv(ifp->net), &drvr_priv, sizeof(drvr_priv)); err = brcmf_net_attach(&drvr_priv->pub, ifp->idx); if (err != 0) { BRCMF_ERROR(("%s: brcmf_net_attach failed, " @@ -382,7 +469,7 @@ static void brcmf_op_if(struct brcmf_if *ifp) #ifdef SOFTAP /* semaphore that the soft AP CODE waits on */ - struct semaphore ap_eth_sema; + extern struct semaphore ap_eth_sema; /* save ptr to wl0.1 netdev for use in wl_iw.c */ @@ -434,20 +521,12 @@ static int _brcmf_sysioc_thread(void *data) #ifdef SOFTAP bool in_ap = false; #endif - DECLARE_WAITQUEUE(wait, current); - allow_signal(SIGTERM); - add_wait_queue(&drvr_priv->sysioc_waitq, &wait); - while (1) { - prepare_to_wait(&drvr_priv->sysioc_waitq, &wait, - TASK_INTERRUPTIBLE); - - /* wait for event */ - schedule(); + allow_signal(SIGTERM); + while (down_interruptible(&drvr_priv->sysioc_sem) == 0) { if (kthread_should_stop()) break; - for (i = 0; i < BRCMF_MAX_IFS; i++) { struct brcmf_if *ifentry = drvr_priv->iflist[i]; if (ifentry) { @@ -494,7 +573,6 @@ static int _brcmf_sysioc_thread(void *data) } } } - finish_wait(&drvr_priv->sysioc_waitq, &wait); return 0; } @@ -512,7 +590,8 @@ static int brcmf_netdev_set_mac_address(struct net_device *dev, void *addr) memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN); drvr_priv->set_macaddress = true; - wake_up(&drvr_priv->sysioc_waitq); + up(&drvr_priv->sysioc_sem); + return ret; } @@ -526,7 +605,7 @@ static void brcmf_netdev_set_multicast_list(struct net_device *dev) return; drvr_priv->set_multicast = true; - wake_up(&drvr_priv->sysioc_waitq); + up(&drvr_priv->sysioc_sem); } int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) @@ -692,9 +771,9 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb, drvr->dstats.rx_bytes += skb->len; drvr->rx_packets++; /* Local count */ - if (in_interrupt()) + if (in_interrupt()) { netif_rx(skb); - else + } else { /* If the receive is not processed inside an ISR, * the softirqd must be woken explicitly to service * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled @@ -702,6 +781,7 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb, * to do it manually. */ netif_rx_ni(skb); + } } } @@ -736,9 +816,10 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *net) ifp = drvr_priv->iflist[ifidx]; - if (drvr_priv->pub.up) + if (drvr_priv->pub.up) { /* Use the protocol to get dongle stats */ brcmf_proto_dstats(&drvr_priv->pub); + } /* Copy dongle stats to net device stats */ ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets; @@ -978,7 +1059,7 @@ static int brcmf_netdev_ioctl_entry(struct net_device *net, struct ifreq *ifr, return -1; if (cmd == SIOCETHTOOL) - return brcmf_ethtool(drvr_priv, ifr->ifr_data); + return brcmf_ethtool(drvr_priv, (void *)ifr->ifr_data); if (cmd != SIOCDEVPRIVATE) return -EOPNOTSUPP; @@ -1027,8 +1108,7 @@ static int brcmf_netdev_ioctl_entry(struct net_device *net, struct ifreq *ifr, /* check for local brcmf ioctl and handle it */ if (driver == BRCMF_IOCTL_MAGIC) { - bcmerror = brcmf_c_ioctl((void *)&drvr_priv->pub, &ioc, - buf, buflen); + bcmerror = brcmf_c_ioctl((void *)&drvr_priv->pub, &ioc, buf, buflen); if (bcmerror) drvr_priv->pub.bcmerror = bcmerror; goto done; @@ -1058,8 +1138,9 @@ static int brcmf_netdev_ioctl_entry(struct net_device *net, struct ifreq *ifr, if (is_set_key_cmd) brcmf_netdev_wait_pend8021x(net); - bcmerror = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, - (struct brcmf_ioctl *)&ioc, buf, buflen); + bcmerror = + brcmf_proto_ioctl(&drvr_priv->pub, ifidx, (struct brcmf_ioctl *)&ioc, + buf, buflen); done: if (!bcmerror && buf && ioc.buf) { @@ -1140,12 +1221,12 @@ static int brcmf_netdev_open(struct net_device *net) } int -brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *net, - char *name, u8 *mac_addr, u32 flags, u8 bssidx) +brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle, char *name, + u8 *mac_addr, u32 flags, u8 bssidx) { struct brcmf_if *ifp; - BRCMF_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, net)); + BRCMF_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle)); ifp = drvr_priv->iflist[ifidx]; if (!ifp) { @@ -1163,12 +1244,12 @@ brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *net, if (mac_addr != NULL) memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); - if (net == NULL) { + if (handle == NULL) { ifp->state = BRCMF_E_IF_ADD; ifp->idx = ifidx; - wake_up(&drvr_priv->sysioc_waitq); + up(&drvr_priv->sysioc_sem); } else - ifp->net = net; + ifp->net = (struct net_device *)handle; return 0; } @@ -1187,7 +1268,7 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx) ifp->state = BRCMF_E_IF_DEL; ifp->idx = ifidx; - wake_up(&drvr_priv->sysioc_waitq); + up(&drvr_priv->sysioc_sem); } struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) @@ -1228,12 +1309,14 @@ struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) strcat(net->name, "%d"); } - if (brcmf_add_if(drvr_priv, 0, net, net->name, NULL, 0, 0) == + if (brcmf_add_if(drvr_priv, 0, (void *)net, net->name, NULL, 0, 0) == BRCMF_BAD_IF) goto fail; net->netdev_ops = NULL; - mutex_init(&drvr_priv->proto_block); + sema_init(&drvr_priv->proto_sem, 1); + /* Initialize other structure content */ + init_waitqueue_head(&drvr_priv->ioctl_resp_wait); /* Link to info module */ drvr_priv->pub.info = drvr_priv; @@ -1255,9 +1338,9 @@ struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) } if (brcmf_sysioc) { - init_waitqueue_head(&drvr_priv->sysioc_waitq); - drvr_priv->sysioc_tsk = kthread_run(_brcmf_sysioc_thread, - drvr_priv, "_brcmf_sysioc"); + sema_init(&drvr_priv->sysioc_sem, 0); + drvr_priv->sysioc_tsk = kthread_run(_brcmf_sysioc_thread, drvr_priv, + "_brcmf_sysioc"); if (IS_ERR(drvr_priv->sysioc_tsk)) { printk(KERN_WARNING "_brcmf_sysioc thread failed to start\n"); @@ -1271,6 +1354,9 @@ struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) */ memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv)); +#if defined(CONFIG_PM_SLEEP) + atomic_set(&brcmf_mmc_suspend, false); +#endif /* defined(CONFIG_PM_SLEEP) */ return &drvr_priv->pub; fail: @@ -1498,7 +1584,7 @@ int brcmf_os_proto_block(struct brcmf_pub *drvr) struct brcmf_info *drvr_priv = drvr->info; if (drvr_priv) { - mutex_lock(&drvr_priv->proto_block); + down(&drvr_priv->proto_sem); return 1; } return 0; @@ -1509,16 +1595,61 @@ int brcmf_os_proto_unblock(struct brcmf_pub *drvr) struct brcmf_info *drvr_priv = drvr->info; if (drvr_priv) { - mutex_unlock(&drvr_priv->proto_block); + up(&drvr_priv->proto_sem); return 1; } return 0; } -static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, - void *pktdata, struct brcmf_event_msg *event, - void **data) +unsigned int brcmf_os_get_ioctl_resp_timeout(void) +{ + return (unsigned int)brcmf_ioctl_timeout_msec; +} + +void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec) +{ + brcmf_ioctl_timeout_msec = (int)timeout_msec; +} + +int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition, + bool *pending) +{ + struct brcmf_info *drvr_priv = drvr->info; + DECLARE_WAITQUEUE(wait, current); + int timeout = brcmf_ioctl_timeout_msec; + + /* Convert timeout in millsecond to jiffies */ + timeout = timeout * HZ / 1000; + + /* Wait until control frame is available */ + add_wait_queue(&drvr_priv->ioctl_resp_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + while (!(*condition) && (!signal_pending(current) && timeout)) + timeout = schedule_timeout(timeout); + + if (signal_pending(current)) + *pending = true; + + set_current_state(TASK_RUNNING); + remove_wait_queue(&drvr_priv->ioctl_resp_wait, &wait); + + return timeout; +} + +int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr) +{ + struct brcmf_info *drvr_priv = drvr->info; + + if (waitqueue_active(&drvr_priv->ioctl_resp_wait)) + wake_up_interruptible(&drvr_priv->ioctl_resp_wait); + + return 0; +} + +static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata, + struct brcmf_event_msg *event, void **data) { int bcmerror = 0; diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c index 7632a0ebd970..7fa95b6213c5 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -35,9 +34,56 @@ #include #include "sdio_host.h" +/* register access macros */ +#ifndef __BIG_ENDIAN +#ifndef __mips__ +#define R_REG(r, typ) \ + brcmf_sdcard_reg_read(NULL, (r), sizeof(typ)) +#else /* __mips__ */ +#define R_REG(r, typ) \ + ({ \ + __typeof(*(r)) __osl_v; \ + __asm__ __volatile__("sync"); \ + __osl_v = brcmf_sdcard_reg_read(NULL, (r),\ + sizeof(typ)); \ + __asm__ __volatile__("sync"); \ + __osl_v; \ + }) +#endif /* __mips__ */ + +#else /* __BIG_ENDIAN */ +#define R_REG(r, typ) \ + brcmf_sdcard_reg_read(NULL, (r), sizeof(typ)) +#endif /* __BIG_ENDIAN */ + +#define OR_REG(r, v, typ) \ + brcmf_sdcard_reg_write(NULL, (r), sizeof(typ), R_REG(r, typ) | (v)) + #ifdef BCMDBG /* ARM trap handling */ + +/* Trap types defined by ARM (see arminc.h) */ + +#if defined(__ARM_ARCH_4T__) +#define MAX_TRAP_TYPE (TR_FIQ + 1) +#elif defined(__ARM_ARCH_7M__) +#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS) +#endif /* __ARM_ARCH_7M__ */ + +/* The trap structure is defined here as offsets for assembly */ +#define TR_TYPE 0x00 +#define TR_EPC 0x04 +#define TR_CPSR 0x08 +#define TR_SPSR 0x0c +#define TR_REGS 0x10 +#define TR_REG(n) (TR_REGS + (n) * 4) +#define TR_SP TR_REG(13) +#define TR_LR TR_REG(14) +#define TR_PC TR_REG(15) + +#define TRAP_T_SIZE 80 + struct brcmf_trap { u32 type; u32 epc; @@ -80,8 +126,8 @@ struct rte_console { * (at risk of conflicting with * the real UART). vcons_out is currently unused. */ - uint vcons_in; - uint vcons_out; + volatile uint vcons_in; + volatile uint vcons_out; /* Output (logging) buffer * Console output is written to a ring buffer log_buf at index log_idx. @@ -139,63 +185,48 @@ struct rte_console { #endif /* SBSDIO_DEVICE_CTL */ - -/* 1: device will assert busy signal when receiving CMD53 */ -#define SBSDIO_DEVCTL_SETBUSY 0x01 -/* 1: assertion of sdio interrupt is synchronous to the sdio clock */ -#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 -/* 1: mask all interrupts to host except the chipActive (rev 8) */ -#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 -/* 1: isolate internal sdio signals, put external pads in tri-state; requires - * sdio bus power cycle to clear (rev 9) */ -#define SBSDIO_DEVCTL_PADS_ISO 0x08 -/* Force SD->SB reset mapping (rev 11) */ -#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 -/* Determined by CoreControl bit */ -#define SBSDIO_DEVCTL_RST_CORECTL 0x00 -/* Force backplane reset */ -#define SBSDIO_DEVCTL_RST_BPRESET 0x10 -/* Force no backplane reset */ -#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 +#define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when + * receiving CMD53 + */ +#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 /* 1: assertion of sdio interrupt is + * synchronous to the sdio clock + */ +#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 /* 1: mask all interrupts to host + * except the chipActive (rev 8) + */ +#define SBSDIO_DEVCTL_PADS_ISO 0x08 /* 1: isolate internal sdio signals, put + * external pads in tri-state; requires + * sdio bus power cycle to clear (rev 9) + */ +#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 /* Force SD->SB reset mapping (rev 11) */ +#define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */ +#define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */ +#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */ /* SBSDIO_FUNC1_CHIPCLKCSR */ - -/* Force ALP request to backplane */ -#define SBSDIO_FORCE_ALP 0x01 -/* Force HT request to backplane */ -#define SBSDIO_FORCE_HT 0x02 -/* Force ILP request to backplane */ -#define SBSDIO_FORCE_ILP 0x04 -/* Make ALP ready (power up xtal) */ -#define SBSDIO_ALP_AVAIL_REQ 0x08 -/* Make HT ready (power up PLL) */ -#define SBSDIO_HT_AVAIL_REQ 0x10 -/* Squelch clock requests from HW */ -#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 -/* Status: ALP is ready */ -#define SBSDIO_ALP_AVAIL 0x40 -/* Status: HT is ready */ -#define SBSDIO_HT_AVAIL 0x80 - -#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) -#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) -#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) -#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval)) - -#define SBSDIO_CLKAV(regval, alponly) \ - (SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval))) - +#define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */ +#define SBSDIO_FORCE_HT 0x02 /* Force HT request to backplane */ +#define SBSDIO_FORCE_ILP 0x04 /* Force ILP request to backplane */ +#define SBSDIO_ALP_AVAIL_REQ 0x08 /* Make ALP ready (power up xtal) */ +#define SBSDIO_HT_AVAIL_REQ 0x10 /* Make HT ready (power up PLL) */ +#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 /* Squelch clock requests from HW */ +#define SBSDIO_ALP_AVAIL 0x40 /* Status: ALP is ready */ +#define SBSDIO_HT_AVAIL 0x80 /* Status: HT is ready */ + +#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) +#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) +#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) +#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval)) +#define SBSDIO_CLKAV(regval, alponly) (SBSDIO_ALPAV(regval) && \ + (alponly ? 1 : SBSDIO_HTAV(regval))) /* direct(mapped) cis space */ +#define SBSDIO_CIS_BASE_COMMON 0x1000 /* MAPPED common CIS address */ +#define SBSDIO_CIS_SIZE_LIMIT 0x200 /* maximum bytes in one CIS */ +#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF /* cis offset addr is < 17 bits */ -/* MAPPED common CIS address */ -#define SBSDIO_CIS_BASE_COMMON 0x1000 -/* maximum bytes in one CIS */ -#define SBSDIO_CIS_SIZE_LIMIT 0x200 -/* cis offset addr is < 17 bits */ -#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF - -/* manfid tuple length, include tuple, link bytes */ -#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 +#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 /* manfid tuple length, include tuple, + * link bytes + */ /* intstatus */ #define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */ @@ -251,7 +282,11 @@ struct rte_console { /* Total length of frame header for dongle protocol */ #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) +#ifdef SDTEST +#define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN) +#else #define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN) +#endif /* * Software allocation of To SB Mailbox resources @@ -398,18 +433,12 @@ struct rte_console { #define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ /* sbtmstatelow */ +#define SBTML_RESET 0x0001 /* reset */ +#define SBTML_REJ_MASK 0x0006 /* reject field */ +#define SBTML_REJ 0x0002 /* reject */ +#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */ -/* reset */ -#define SBTML_RESET 0x0001 -/* reject field */ -#define SBTML_REJ_MASK 0x0006 -/* reject */ -#define SBTML_REJ 0x0002 -/* temporary reject, for error recovery */ -#define SBTML_TMPREJ 0x0004 - -/* Shift to locate the SI control flags in sbtml */ -#define SBTML_SICF_SHIFT 16 +#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */ /* sbtmstatehigh */ #define SBTMH_SERR 0x0001 /* serror */ @@ -417,8 +446,7 @@ struct rte_console { #define SBTMH_BUSY 0x0004 /* busy */ #define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ -/* Shift to locate the SI status flags in sbtmh */ -#define SBTMH_SISF_SHIFT 16 +#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */ /* sbidlow */ #define SBIDL_INIT 0x80 /* initiator */ @@ -428,8 +456,7 @@ struct rte_console { #define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ #define SBIDH_RCE_SHIFT 8 #define SBCOREREV(sbidh) \ - ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \ - ((sbidh) & SBIDH_RC_MASK)) + ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) #define SBIDH_CC_MASK 0x8ff0 /* core code */ #define SBIDH_CC_SHIFT 4 #define SBIDH_VC_MASK 0xffff0000 /* vendor code */ @@ -442,12 +469,13 @@ struct rte_console { (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \ ((prio^2)) : (prio)) +BRCMF_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep); + /* * Core reg address translation. * Both macro's returns a 32 bits byte address on the backplane bus. */ -#define CORE_CC_REG(base, field) \ - (base + offsetof(struct chipcregs, field)) +#define CORE_CC_REG(base, field) (base + offsetof(chipcregs_t, field)) #define CORE_BUS_REG(base, field) \ (base + offsetof(struct sdpcmd_regs, field)) #define CORE_SB(base, field) \ @@ -586,7 +614,7 @@ struct chip_info { struct brcmf_bus { struct brcmf_pub *drvr; - struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ + struct brcmf_sdio_card *card; /* Handle for sdio card calls */ struct chip_info *ci; /* Chip info struct */ char *vars; /* Variables (from CIS and/or other) */ uint varsz; /* Size of variables buffer */ @@ -594,11 +622,14 @@ struct brcmf_bus { u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ u32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */ + u32 bus; /* gSPI or SDIO bus */ u32 hostintmask; /* Copy of Host Interrupt Mask */ u32 intstatus; /* Intstatus bits (events) pending */ bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ bool fcstate; /* State of dongle flow-control */ + u16 cl_devid; /* cached devid for brcmf_sdio_probe_attach() */ + uint blocksize; /* Block size of SDIO transfers */ uint roundup; /* Max roundup limit */ @@ -629,6 +660,7 @@ struct brcmf_bus { bool intr; /* Use interrupts */ bool poll; /* Use polling */ bool ipend; /* Device interrupt is pending */ + bool intdis; /* Interrupts disabled by isr */ uint intrcount; /* Count of device interrupt callbacks */ uint lastintrs; /* Count as of last watchdog timer */ uint spurious; /* Count of spurious interrupts */ @@ -657,6 +689,30 @@ struct brcmf_bus { /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ bool usebufpool; +#ifdef SDTEST + /* external loopback */ + bool ext_loop; + u8 loopid; + + /* pktgen configuration */ + uint pktgen_freq; /* Ticks between bursts */ + uint pktgen_count; /* Packets to send each burst */ + uint pktgen_print; /* Bursts between count displays */ + uint pktgen_total; /* Stop after this many */ + uint pktgen_minlen; /* Minimum packet data len */ + uint pktgen_maxlen; /* Maximum packet data len */ + uint pktgen_mode; /* Configured mode: tx, rx, or echo */ + uint pktgen_stop; /* Number of tx failures causing stop */ + + /* active pktgen fields */ + uint pktgen_tick; /* Tick counter for bursts */ + uint pktgen_ptick; /* Burst counter for printing */ + uint pktgen_sent; /* Number of test packets generated */ + uint pktgen_rcvd; /* Number of test packets received */ + uint pktgen_fail; /* Number of failed send attempts */ + u16 pktgen_len; /* Length of next packet to send */ +#endif /* SDTEST */ + /* Some additional counters */ uint tx_sderrs; /* Count of tx attempts with sd errors */ uint fcqueued; /* Tx packets that got queued */ @@ -683,7 +739,6 @@ struct brcmf_bus { spinlock_t txqlock; wait_queue_head_t ctrl_wait; - wait_queue_head_t ioctl_resp_wait; struct timer_list timer; struct completion watchdog_wait; @@ -750,6 +805,8 @@ struct sbconfig { #define CLK_PENDING 2 /* Not used yet */ #define CLK_AVAIL 3 +#define BRCMF_NOPMU(brcmf) (false) + #ifdef BCMDBG static int qcount[NUMPRIO]; static int tx_packets[NUMPRIO]; @@ -780,38 +837,20 @@ module_param(brcmf_console_ms, uint, 0); /* Tx/Rx bounds */ uint brcmf_txbound; uint brcmf_rxbound; -module_param(brcmf_txbound, uint, 0); -module_param(brcmf_rxbound, uint, 0); uint brcmf_txminmax; -int brcmf_idletime = 1; -module_param(brcmf_idletime, int, 0); - -/* SDIO Drive Strength (in milliamps) */ -uint brcmf_sdiod_drive_strength = 6; -module_param(brcmf_sdiod_drive_strength, uint, 0); - -/* Use polling */ -uint brcmf_poll; -module_param(brcmf_poll, uint, 0); - -/* Use interrupts */ -uint brcmf_intr = true; -module_param(brcmf_intr, uint, 0); - -/* IOCTL response timeout */ -static int brcmf_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT; - /* override the RAM size if possible */ #define DONGLE_MIN_MEMSIZE (128 * 1024) int brcmf_dongle_memsize; -module_param(brcmf_dongle_memsize, int, 0); static bool brcmf_alignctl; +static bool sd1idle; + static bool retrydata; #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata) +static const uint watermark = 8; static const uint firstread = BRCMF_FIRSTREAD; /* Retry count for register access failures */ @@ -852,9 +891,8 @@ r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) { *retryvar = 0; do { - *regvar = brcmf_sdcard_reg_read(bus->sdiodev, - bus->ci->buscorebase + reg_offset, sizeof(u32)); - } while (brcmf_sdcard_regfail(bus->sdiodev) && + *regvar = R_REG(bus->ci->buscorebase + reg_offset, u32); + } while (brcmf_sdcard_regfail(bus->card) && (++(*retryvar) <= retry_limit)); if (*retryvar) { bus->regfails += (*retryvar-1); @@ -870,10 +908,9 @@ w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar) { *retryvar = 0; do { - brcmf_sdcard_reg_write(bus->sdiodev, - bus->ci->buscorebase + reg_offset, + brcmf_sdcard_reg_write(NULL, bus->ci->buscorebase + reg_offset, sizeof(u32), regval); - } while (brcmf_sdcard_regfail(bus->sdiodev) && + } while (brcmf_sdcard_regfail(bus->card) && (++(*retryvar) <= retry_limit)); if (*retryvar) { bus->regfails += (*retryvar-1); @@ -883,10 +920,17 @@ w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar) } } +#define BRCMF_BUS SDIO_BUS + #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) +#ifdef SDTEST +static void brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, void *pkt, uint seq); +static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start); +#endif + #ifdef BCMDBG static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr, unsigned char *msg, uint msglen); @@ -897,10 +941,12 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter); static void brcmf_sdbrcm_release(struct brcmf_bus *bus); static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus); +static void brcmf_sdbrcm_disconnect(void *ptr); static bool brcmf_sdbrcm_chipmatch(u16 chipid); -static bool brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva); -static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus); -static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus); +static bool brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card, + u32 regsva, u16 devid); +static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card); +static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card); static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus); static uint brcmf_process_nvram_vars(char *varbuf, uint len); @@ -908,21 +954,24 @@ static uint brcmf_process_nvram_vars(char *varbuf, uint len); static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size); static int brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags, u8 *buf, uint nbytes, - struct sk_buff *pkt); + struct sk_buff *pkt, + void (*complete)(void *handle, int status, + bool sync_waiting), + void *handle); -static bool brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus); +static bool brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card); static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus); static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus); static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus); static void -brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_dev *sdiodev, u32 corebase); +brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase); static int brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs); static void -brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase); +brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase); static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, u32 drivestrength); @@ -937,16 +986,13 @@ static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus); static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus); static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus); static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus); -static int brcmf_sdbrcm_ioctl_resp_wait(struct brcmf_bus *bus, uint *condition, - bool *pending); -static int brcmf_sdbrcm_ioctl_resp_wake(struct brcmf_bus *bus); /* Packet free applicable unconditionally for sdio and sdspi. * Conditional if bufpool was present for gspi bus. */ static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt) { - if (bus->usebufpool) + if ((bus->bus != SPI_BUS) || bus->usebufpool) brcmu_pkt_buf_free_skb(pkt); } @@ -964,15 +1010,14 @@ static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size) static int brcmf_sdbrcm_set_siaddr_window(struct brcmf_bus *bus, u32 address) { int err = 0; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, - SBSDIO_FUNC1_SBADDRLOW, - (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, + (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); if (!err) - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, (address >> 16) & SBSDIO_SBADDRMID_MASK, &err); if (!err) - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err); @@ -984,11 +1029,12 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) { int err; u8 clkctl, clkreq, devctl; - unsigned long timeout; + struct brcmf_sdio_card *card; BRCMF_TRACE(("%s: Enter\n", __func__)); clkctl = 0; + card = bus->card; if (on) { /* Request HT Avail */ @@ -999,7 +1045,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) && (bus->ci->chiprev == 0)) clkreq |= SBSDIO_FORCE_ALP; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); if (err) { BRCMF_ERROR(("%s: HT Avail request error: %d\n", @@ -1016,7 +1062,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) } /* Check current status */ - clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); if (err) { BRCMF_ERROR(("%s: HT Avail read error: %d\n", @@ -1027,8 +1073,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) /* Go to pending and await interrupt if appropriate */ if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { /* Allow only clock-available interrupt */ - devctl = brcmf_sdcard_cfg_read(bus->sdiodev, - SDIO_FUNC_1, + devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); if (err) { BRCMF_ERROR(("%s: Devctl error setting CA:" @@ -1037,7 +1082,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) } devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); BRCMF_INFO(("CLKCTL: set PENDING\n")); bus->clkstate = CLK_PENDING; @@ -1046,25 +1091,22 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) } else if (bus->clkstate == CLK_PENDING) { /* Cancel CA-only interrupt filter */ devctl = - brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); } /* Otherwise, wait here (polling) for HT Avail */ - timeout = jiffies + - msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); - while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { - clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, - SDIO_FUNC_1, - SBSDIO_FUNC1_CHIPCLKCSR, - &err); - if (time_after(jiffies, timeout)) - break; - else - usleep_range(5000, 10000); + if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { + BRCMF_SPINWAIT_SLEEP(sdioh_spinwait_sleep, + ((clkctl = + brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, + SBSDIO_FUNC1_CHIPCLKCSR, + &err)), + !SBSDIO_CLKAV(clkctl, bus->alp_only)), + PMU_MAX_TRANSITION_DLY); } if (err) { BRCMF_ERROR(("%s: HT Avail request error: %d\n", @@ -1084,9 +1126,10 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) #if defined(BCMDBG) if (bus->alp_only != true) { - if (SBSDIO_ALPONLY(clkctl)) + if (SBSDIO_ALPONLY(clkctl)) { BRCMF_ERROR(("%s: HT Clock should be on.\n", __func__)); + } } #endif /* defined (BCMDBG) */ @@ -1096,16 +1139,15 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) if (bus->clkstate == CLK_PENDING) { /* Cancel CA-only interrupt filter */ - devctl = brcmf_sdcard_cfg_read(bus->sdiodev, - SDIO_FUNC_1, + devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); } bus->clkstate = CLK_SDONLY; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); BRCMF_INFO(("CLKCTL: turned OFF\n")); if (err) { @@ -1190,6 +1232,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok) int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) { + struct brcmf_sdio_card *card = bus->card; uint retries = 0; BRCMF_INFO(("brcmf_sdbrcm_bussleep: request %s (currently %s)\n", @@ -1206,6 +1249,9 @@ int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) return -EBUSY; + /* Disable SDIO interrupts (no longer interested) */ + brcmf_sdcard_intr_disable(bus->card); + /* Make sure the controller has the bus up */ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); @@ -1219,13 +1265,14 @@ int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) /* Turn off our contribution to the HT clock request */ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); /* Isolate the bus */ - if (bus->ci->chip != BCM4329_CHIP_ID) { - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + if (bus->ci->chip != BCM4329_CHIP_ID + && bus->ci->chip != BCM4319_CHIP_ID) { + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, SBSDIO_DEVCTL_PADS_ISO, NULL); } @@ -1236,14 +1283,14 @@ int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) } else { /* Waking up: bus power up is ok, set local state */ - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); /* Force pad isolation off if possible (in case power never toggled) */ if ((bus->ci->buscoretype == PCMCIA_CORE_ID) && (bus->ci->buscorerev >= 10)) - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL); /* Make sure the controller has the bus up */ @@ -1265,6 +1312,12 @@ int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) /* Change state */ bus->sleeping = false; + + /* Enable interrupts again */ + if (bus->intr && (bus->drvr->busstate == BRCMF_BUS_DATA)) { + bus->intdis = false; + brcmf_sdcard_intr_enable(bus->card); + } } return 0; @@ -1278,19 +1331,22 @@ int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) /* Writes a HW/SW header into the packet and sends it. */ /* Assumes: (a) header space already there, (b) caller holds lock */ -static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, - uint chan, bool free_pkt) +static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, uint chan, + bool free_pkt) { int ret; u8 *frame; u16 len, pad = 0; u32 swheader; uint retries = 0; + struct brcmf_sdio_card *card; struct sk_buff *new; int i; BRCMF_TRACE(("%s: Enter\n", __func__)); + card = bus->card; + if (bus->drvr->dongle_reset) { ret = -EPERM; goto done; @@ -1371,13 +1427,13 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, } /* Some controllers have trouble with odd bytes -- round to even */ - if (forcealign && (len & (ALIGNMENT - 1))) + if (forcealign && (len & (ALIGNMENT - 1))) { len = roundup(len, ALIGNMENT); + } do { - ret = brcmf_sdbrcm_send_buf(bus, - brcmf_sdcard_cur_sbwad(bus->sdiodev), - SDIO_FUNC_2, F2SYNC, frame, len, pkt); + ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card), + SDIO_FUNC_2, F2SYNC, frame, len, pkt, NULL, NULL); bus->f2txdata++; if (ret < 0) { @@ -1387,20 +1443,18 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, "terminate frame.\n", __func__, ret)); bus->tx_sderrs++; - brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_abort(card, SDIO_FUNC_2); + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL); bus->f1regdata++; for (i = 0; i < 3; i++) { u8 hi, lo; - hi = brcmf_sdcard_cfg_read(bus->sdiodev, - SDIO_FUNC_1, + hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCHI, NULL); - lo = brcmf_sdcard_cfg_read(bus->sdiodev, - SDIO_FUNC_1, + lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCLO, NULL); bus->f1regdata += 2; @@ -1436,6 +1490,20 @@ int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt) datalen = pkt->len; +#ifdef SDTEST + /* Push the test header if doing loopback */ + if (bus->ext_loop) { + u8 *data; + skb_push(pkt, SDPCM_TEST_HDRLEN); + data = pkt->data; + *data++ = SDPCM_TEST_ECHOREQ; + *data++ = (u8) bus->loopid++; + *data++ = (datalen >> 0); + *data++ = (datalen >> 8); + datalen += SDPCM_TEST_HDRLEN; + } +#endif /* SDTEST */ + /* Add space for the header */ skb_push(pkt, SDPCM_HDRLEN); /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */ @@ -1454,8 +1522,7 @@ int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt) /* Priority based enq */ spin_lock_bh(&bus->txqlock); - if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == - false) { + if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) { skb_pull(pkt, SDPCM_HDRLEN); brcmf_txcomplete(bus->drvr, pkt, false); brcmu_pkt_buf_free_skb(pkt); @@ -1487,8 +1554,14 @@ int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt) /* Make sure back plane ht clk is on, no pending allowed */ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); +#ifndef SDTEST BRCMF_TRACE(("%s: calling txpkt\n", __func__)); ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); +#else + ret = brcmf_sdbrcm_txpkt(bus, pkt, + (bus->ext_loop ? SDPCM_TEST_CHANNEL : + SDPCM_DATA_CHANNEL), true); +#endif if (ret) bus->drvr->tx_errors++; else @@ -1533,7 +1606,13 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes) spin_unlock_bh(&bus->txqlock); datalen = pkt->len - SDPCM_HDRLEN; +#ifndef SDTEST ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); +#else + ret = brcmf_sdbrcm_txpkt(bus, pkt, + (bus->ext_loop ? SDPCM_TEST_CHANNEL : + SDPCM_DATA_CHANNEL), true); +#endif if (ret) bus->drvr->tx_errors++; else @@ -1546,7 +1625,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes) offsetof(struct sdpcmd_regs, intstatus), &retries); bus->f2txdata++; - if (brcmf_sdcard_regfail(bus->sdiodev)) + if (brcmf_sdcard_regfail(bus->card)) break; if (intstatus & bus->hostintmask) bus->ipend = true; @@ -1568,6 +1647,7 @@ brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) u16 len; u32 swheader; uint retries = 0; + struct brcmf_sdio_card *card = bus->card; u8 doff = 0; int ret = -1; int i; @@ -1667,9 +1747,8 @@ brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) do { bus->ctrl_frame_stat = false; ret = brcmf_sdbrcm_send_buf(bus, - brcmf_sdcard_cur_sbwad(bus->sdiodev), - SDIO_FUNC_2, - F2SYNC, frame, len, NULL); + brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2, + F2SYNC, frame, len, NULL, NULL, NULL); if (ret < 0) { /* On failure, abort the command and @@ -1679,21 +1758,20 @@ brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) __func__, ret)); bus->tx_sderrs++; - brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); + brcmf_sdcard_abort(card, SDIO_FUNC_2); - brcmf_sdcard_cfg_write(bus->sdiodev, - SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL); bus->f1regdata++; for (i = 0; i < 3; i++) { u8 hi, lo; - hi = brcmf_sdcard_cfg_read(bus->sdiodev, + hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCHI, NULL); - lo = brcmf_sdcard_cfg_read(bus->sdiodev, + lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCLO, NULL); @@ -1703,10 +1781,10 @@ brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) } } - if (ret == 0) + if (ret == 0) { bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; - + } } while ((ret < 0) && retries++ < TXRETRIES); } @@ -1725,8 +1803,7 @@ brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) return ret ? -EIO : 0; } -int -brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) +int brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) { int timeleft; uint rxlen = 0; @@ -1738,7 +1815,7 @@ brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) return -EIO; /* Wait until control frame is available */ - timeleft = brcmf_sdbrcm_ioctl_resp_wait(bus, &bus->rxlen, &pending); + timeleft = brcmf_os_ioctl_resp_wait(bus->drvr, &bus->rxlen, &pending); brcmf_sdbrcm_sdlock(bus); rxlen = bus->rxlen; @@ -1798,14 +1875,20 @@ enum { IOV_ALIGNCTL, IOV_SDALIGN, IOV_DEVRESET, + IOV_CPU, +#ifdef SDTEST + IOV_PKTGEN, + IOV_EXTLOOP, +#endif /* SDTEST */ + IOV_SPROM, IOV_TXBOUND, IOV_RXBOUND, IOV_TXMINMAX, IOV_IDLETIME, IOV_IDLECLOCK, + IOV_SD1IDLE, IOV_SLEEP, IOV_WDTICK, - IOV_IOCTLTIMEOUT, IOV_VARS }; @@ -1815,6 +1898,7 @@ const struct brcmu_iovar brcmf_sdio_iovars[] = { {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0}, {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0}, {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0}, + {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0}, {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int)}, {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0}, {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0}, @@ -1826,7 +1910,6 @@ const struct brcmu_iovar brcmf_sdio_iovars[] = { {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0}, {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0}, {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0}, - {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0}, #ifdef BCMDBG {"cons", IOV_CONS, 0, IOVT_BUFFER, 0} , @@ -1846,9 +1929,17 @@ const struct brcmu_iovar brcmf_sdio_iovars[] = { , {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0} , + {"cpu", IOV_CPU, 0, IOVT_BOOL, 0} + , {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0} , #endif /* BCMDBG */ +#ifdef SDTEST + {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0} + , + {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(struct brcmf_pktgen)} + , +#endif /* SDTEST */ {NULL, 0, 0, 0, 0} }; @@ -1942,6 +2033,19 @@ void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf) brcmu_bprintf(strbuf, "\n\n"); } +#ifdef SDTEST + if (bus->pktgen_count) { + brcmu_bprintf(strbuf, "pktgen config and count:\n"); + brcmu_bprintf(strbuf, + "freq %d count %d print %d total %d min %d len %d\n", + bus->pktgen_freq, bus->pktgen_count, + bus->pktgen_print, bus->pktgen_total, + bus->pktgen_minlen, bus->pktgen_maxlen); + brcmu_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n", + bus->pktgen_sent, bus->pktgen_rcvd, + bus->pktgen_fail); + } +#endif /* SDTEST */ #ifdef BCMDBG brcmu_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n", bus->dpc_sched, " not "); @@ -1966,6 +2070,62 @@ void brcmf_bus_clearcounts(struct brcmf_pub *drvr) bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0; } +#ifdef SDTEST +static int brcmf_sdbrcm_pktgen_get(struct brcmf_bus *bus, u8 *arg) +{ + struct brcmf_pktgen pktgen; + + pktgen.version = BRCMF_PKTGEN_VERSION; + pktgen.freq = bus->pktgen_freq; + pktgen.count = bus->pktgen_count; + pktgen.print = bus->pktgen_print; + pktgen.total = bus->pktgen_total; + pktgen.minlen = bus->pktgen_minlen; + pktgen.maxlen = bus->pktgen_maxlen; + pktgen.numsent = bus->pktgen_sent; + pktgen.numrcvd = bus->pktgen_rcvd; + pktgen.numfail = bus->pktgen_fail; + pktgen.mode = bus->pktgen_mode; + pktgen.stop = bus->pktgen_stop; + + memcpy(arg, &pktgen, sizeof(pktgen)); + + return 0; +} + +static int brcmf_sdbrcm_pktgen_set(struct brcmf_bus *bus, u8 *arg) +{ + struct brcmf_pktgen pktgen; + uint oldcnt, oldmode; + + memcpy(&pktgen, arg, sizeof(pktgen)); + if (pktgen.version != BRCMF_PKTGEN_VERSION) + return -EINVAL; + + oldcnt = bus->pktgen_count; + oldmode = bus->pktgen_mode; + + bus->pktgen_freq = pktgen.freq; + bus->pktgen_count = pktgen.count; + bus->pktgen_print = pktgen.print; + bus->pktgen_total = pktgen.total; + bus->pktgen_minlen = pktgen.minlen; + bus->pktgen_maxlen = pktgen.maxlen; + bus->pktgen_mode = pktgen.mode; + bus->pktgen_stop = pktgen.stop; + + bus->pktgen_tick = bus->pktgen_ptick = 0; + bus->pktgen_len = max(bus->pktgen_len, bus->pktgen_minlen); + bus->pktgen_len = min(bus->pktgen_len, bus->pktgen_maxlen); + + /* Clear counts for a new pktgen (mode change, or was stopped) */ + if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) + bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0; + + return 0; +} +#endif /* SDTEST */ + static int brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data, uint size) @@ -1993,8 +2153,8 @@ brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data, BRCMF_INFO(("%s: %s %d bytes at offset 0x%08x in window" " 0x%08x\n", __func__, (write ? "write" : "read"), dsize, sdaddr, (address & SBSDIO_SBWINDOW_MASK))); - bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write, - sdaddr, data, dsize); + bcmerror = + brcmf_sdcard_rwdata(bus->card, write, sdaddr, data, dsize); if (bcmerror) { BRCMF_ERROR(("%s: membytes transfer failed\n", __func__)); @@ -2020,17 +2180,16 @@ brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data, xfer_done: /* Return the window to backplane enumeration space for core access */ if (brcmf_sdbrcm_set_siaddr_window(bus, - brcmf_sdcard_cur_sbwad( - bus->sdiodev))) + brcmf_sdcard_cur_sbwad(bus->card))) { BRCMF_ERROR(("%s: FAILED to set window back to 0x%x\n", - __func__, brcmf_sdcard_cur_sbwad(bus->sdiodev))); + __func__, brcmf_sdcard_cur_sbwad(bus->card))); + } return bcmerror; } #ifdef BCMDBG -static int -brcmf_sdbrcm_readshared(struct brcmf_bus *bus, struct sdpcm_shared *sh) +static int brcmf_sdbrcm_readshared(struct brcmf_bus *bus, struct sdpcm_shared *sh) { u32 addr; int rv; @@ -2127,12 +2286,13 @@ static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size) "msgtrace address : 0x%08X\nconsole address : 0x%08X\n", sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr); - if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) + if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { /* NOTE: Misspelled assert is intentional - DO NOT FIX. * (Avoids conflict with real asserts for programmatic * parsing of output.) */ brcmu_bprintf(&strbuf, "Assrt not built in dongle\n"); + } if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) == 0) { @@ -2197,10 +2357,10 @@ static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size) BRCMF_ERROR(("%s: %s\n", __func__, strbuf.origbuf)); #ifdef BCMDBG - if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) + if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) { /* Mem dump to a file on device */ brcmf_sdbrcm_mem_dump(bus); - + } #endif /* BCMDBG */ done: @@ -2369,10 +2529,10 @@ int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len) return bcmerror; } -static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, - const struct brcmu_iovar *vi, u32 actionid, - const char *name, void *params, int plen, - void *arg, int len, int val_size) +static int +brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, const struct brcmu_iovar *vi, u32 actionid, + const char *name, void *params, int plen, void *arg, int len, + int val_size) { int bcmerror = 0; s32 int_val = 0; @@ -2426,6 +2586,16 @@ static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, case IOV_SVAL(IOV_INTR): bus->intr = bool_val; + bus->intdis = false; + if (bus->drvr->up) { + BRCMF_INTR(("%s: %s SDIO interrupts\n", __func__, + bus->intr ? "enable" : "disable")); + if (bus->intr) { + brcmf_sdcard_intr_enable(bus->card); + } else { + brcmf_sdcard_intr_disable(bus->card); + } + } break; case IOV_GVAL(IOV_POLLRATE): @@ -2459,6 +2629,15 @@ static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, bus->idleclock = int_val; break; + case IOV_GVAL(IOV_SD1IDLE): + int_val = (s32) sd1idle; + memcpy(arg, &int_val, val_size); + break; + + case IOV_SVAL(IOV_SD1IDLE): + sd1idle = bool_val; + break; + case IOV_SVAL(IOV_MEMBYTES): case IOV_GVAL(IOV_MEMBYTES): { @@ -2605,9 +2784,9 @@ static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, addr = bus->ci->buscorebase + sd_ptr->offset; size = sd_ptr->func; - int_val = (s32) brcmf_sdcard_reg_read(bus->sdiodev, - addr, size); - if (brcmf_sdcard_regfail(bus->sdiodev)) + int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr, + size); + if (brcmf_sdcard_regfail(bus->card)) bcmerror = -EIO; memcpy(arg, &int_val, sizeof(s32)); break; @@ -2622,9 +2801,9 @@ static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, addr = bus->ci->buscorebase + sd_ptr->offset; size = sd_ptr->func; - brcmf_sdcard_reg_write(bus->sdiodev, addr, size, + brcmf_sdcard_reg_write(bus->card, addr, size, sd_ptr->value); - if (brcmf_sdcard_regfail(bus->sdiodev)) + if (brcmf_sdcard_regfail(bus->card)) bcmerror = -EIO; break; } @@ -2640,9 +2819,9 @@ static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, addr = SI_ENUM_BASE + sdreg.offset; size = sdreg.func; - int_val = (s32) brcmf_sdcard_reg_read(bus->sdiodev, - addr, size); - if (brcmf_sdcard_regfail(bus->sdiodev)) + int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr, + size); + if (brcmf_sdcard_regfail(bus->card)) bcmerror = -EIO; memcpy(arg, &int_val, sizeof(s32)); break; @@ -2657,9 +2836,9 @@ static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, addr = SI_ENUM_BASE + sdreg.offset; size = sdreg.func; - brcmf_sdcard_reg_write(bus->sdiodev, addr, size, + brcmf_sdcard_reg_write(bus->card, addr, size, sdreg.value); - if (brcmf_sdcard_regfail(bus->sdiodev)) + if (brcmf_sdcard_regfail(bus->card)) bcmerror = -EIO; break; } @@ -2669,15 +2848,15 @@ static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, *(char *)arg = 0; strcat(arg, "\nFunc 0\n"); - brcmf_sdcard_cis_read(bus->sdiodev, 0x10, + brcmf_sdcard_cis_read(bus->card, 0x10, (u8 *) arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); strcat(arg, "\nFunc 1\n"); - brcmf_sdcard_cis_read(bus->sdiodev, 0x11, + brcmf_sdcard_cis_read(bus->card, 0x11, (u8 *) arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); strcat(arg, "\nFunc 2\n"); - brcmf_sdcard_cis_read(bus->sdiodev, 0x12, + brcmf_sdcard_cis_read(bus->card, 0x12, (u8 *) arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); break; @@ -2720,6 +2899,25 @@ static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, break; #endif /* BCMDBG */ +#ifdef SDTEST + case IOV_GVAL(IOV_EXTLOOP): + int_val = (s32) bus->ext_loop; + memcpy(arg, &int_val, val_size); + break; + + case IOV_SVAL(IOV_EXTLOOP): + bus->ext_loop = bool_val; + break; + + case IOV_GVAL(IOV_PKTGEN): + bcmerror = brcmf_sdbrcm_pktgen_get(bus, arg); + break; + + case IOV_SVAL(IOV_PKTGEN): + bcmerror = brcmf_sdbrcm_pktgen_set(bus, arg); + break; +#endif /* SDTEST */ + case IOV_SVAL(IOV_DEVRESET): BRCMF_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d " "busstate=%d\n", @@ -2752,20 +2950,6 @@ static int brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, brcmf_sdbrcm_wd_timer(bus, (uint) int_val); break; - case IOV_GVAL(IOV_IOCTLTIMEOUT):{ - int_val = brcmf_ioctl_timeout_msec; - memcpy(arg, &int_val, sizeof(int_val)); - break; - } - - case IOV_SVAL(IOV_IOCTLTIMEOUT):{ - if (int_val <= 0) - bcmerror = -EINVAL; - else - brcmf_ioctl_timeout_msec = int_val; - break; - } - default: bcmerror = -ENOTSUPP; break; @@ -2831,10 +3015,10 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus) varsize, varaddr)); } /* Compare the org NVRAM with the one read from RAM */ - if (memcmp(vbuffer, nvram_ularray, varsize)) + if (memcmp(vbuffer, nvram_ularray, varsize)) { BRCMF_ERROR(("%s: Downloaded NVRAM image is " "corrupted.\n", __func__)); - else + } else BRCMF_ERROR(("%s: Download/Upload/Compare of" " NVRAM ok.\n", __func__)); @@ -2885,10 +3069,9 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter) if (enter) { bus->alp_only = true; - brcmf_sdbrcm_chip_disablecore(bus->sdiodev, - bus->ci->armcorebase); + brcmf_sdbrcm_chip_disablecore(bus->card, bus->ci->armcorebase); - brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->ramcorebase); + brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->ramcorebase); /* Clear the top bit of memory */ if (bus->ramsize) { @@ -2897,7 +3080,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter) (u8 *)&zeros, 4); } } else { - regdata = brcmf_sdcard_reg_read(bus->sdiodev, + regdata = brcmf_sdcard_reg_read(bus->card, CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4); regdata &= (SBTML_RESET | SBTML_REJ_MASK | (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); @@ -2917,7 +3100,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter) w_sdreg32(bus, 0xFFFFFFFF, offsetof(struct sdpcmd_regs, intstatus), &retries); - brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->armcorebase); + brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->armcorebase); /* Allow HT Clock now that the ARM is running. */ bus->alp_only = false; @@ -2940,7 +3123,7 @@ brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name, BRCMF_TRACE(("%s: Enter\n", __func__)); - if (name == NULL || len < 0) + if (name == NULL || len <= 0) return -EINVAL; /* Set does not take qualifiers */ @@ -2961,8 +3144,26 @@ brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name, /* Turn on clock in case SD command needs backplane */ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); - bcmerror = brcmf_sdcard_iovar_op(bus->sdiodev, name, params, - plen, arg, len, set); + bcmerror = brcmf_sdcard_iovar_op(bus->card, name, params, plen, + arg, len, set); + + /* Similar check for blocksize change */ + if (set && strcmp(name, "sd_blocksize") == 0) { + s32 fnum = 2; + if (brcmf_sdcard_iovar_op + (bus->card, "sd_blocksize", &fnum, sizeof(s32), + &bus->blocksize, sizeof(s32), + false) != 0) { + bus->blocksize = 0; + BRCMF_ERROR(("%s: fail on %s get\n", __func__, + "sd_blocksize")); + } else { + BRCMF_INFO(("%s: noted sd_blocksize update," + " value now %d\n", __func__, + bus->blocksize)); + } + } + bus->roundup = min(max_roundup, bus->blocksize); if (bus->idletime == BRCMF_IDLE_IMMEDIATE && !bus->dpc_sched) { @@ -3040,20 +3241,22 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex) bus->drvr->busstate = BRCMF_BUS_DOWN; /* Force clocks on backplane to be sure F2 interrupt propagates */ - saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + saveclk = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); if (!err) { - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, (saveclk | SBSDIO_FORCE_HT), &err); } - if (err) + if (err) { BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n", __func__, err)); + } /* Turn off the bus (F2), free any pending packets */ BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__)); - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, + brcmf_sdcard_intr_disable(bus->card); + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx, SDIO_FUNC_ENABLE_1, NULL); /* Clear any pending interrupts now that F2 is disabled */ @@ -3077,7 +3280,7 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex) /* Clear rx control and wake any waiters */ bus->rxlen = 0; - brcmf_sdbrcm_ioctl_resp_wake(bus); + brcmf_os_ioctl_resp_wake(bus->drvr); /* Reset some F2 state stuff */ bus->rxskip = false; @@ -3090,7 +3293,7 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex) int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex) { struct brcmf_bus *bus = drvr->bus; - unsigned long timeout; + struct brcmf_timeout tmo; uint retries = 0; u8 ready, enable; int err, ret = 0; @@ -3100,7 +3303,7 @@ int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex) /* try to download image and nvram to the dongle */ if (drvr->busstate == BRCMF_BUS_DOWN) { - if (!(brcmf_sdbrcm_download_firmware(bus))) + if (!(brcmf_sdbrcm_download_firmware(bus, bus->card))) return -1; } @@ -3121,10 +3324,10 @@ int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex) /* Force clocks on backplane to be sure F2 interrupt propagates */ saveclk = - brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); if (!err) { - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, (saveclk | SBSDIO_FORCE_HT), &err); } @@ -3139,23 +3342,19 @@ int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex) offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries); enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, - enable, NULL); + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx, enable, + NULL); + + /* Give the dongle some time to do its thing and set IOR2 */ + brcmf_timeout_start(&tmo, BRCMF_WAIT_F2RDY * 1000); - timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY); ready = 0; - while (enable != ready) { - ready = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_0, + while (ready != enable && !brcmf_timeout_expired(&tmo)) + ready = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_0, SDIO_CCCR_IORx, NULL); - if (time_after(jiffies, timeout)) - break; - else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50)) - /* prevent busy waiting if it takes too long */ - msleep_interruptible(20); - } - BRCMF_INFO(("%s: enable 0x%02x, ready 0x%02x\n", - __func__, enable, ready)); + BRCMF_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n", + __func__, enable, ready, tmo.elapsed)); /* If F2 successfully enabled, set core and enable interrupts */ if (ready == enable) { @@ -3164,23 +3363,34 @@ int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex) w_sdreg32(bus, bus->hostintmask, offsetof(struct sdpcmd_regs, hostintmask), &retries); - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, - SBSDIO_WATERMARK, 8, &err); + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_WATERMARK, + (u8) watermark, &err); /* Set bus state according to enable result */ drvr->busstate = BRCMF_BUS_DATA; + + bus->intdis = false; + if (bus->intr) { + BRCMF_INTR(("%s: enable SDIO device interrupts\n", + __func__)); + brcmf_sdcard_intr_enable(bus->card); + } else { + BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__)); + brcmf_sdcard_intr_disable(bus->card); + } + } else { /* Disable F2 again */ enable = SDIO_FUNC_ENABLE_1; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, - SDIO_CCCR_IOEx, enable, NULL); + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx, + enable, NULL); } /* Restore previous clock setting */ - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, - SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, + saveclk, &err); #if defined(OOB_INTR_ONLY) /* Host registration for OOB interrupt */ @@ -3209,6 +3419,7 @@ int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex) static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx) { + struct brcmf_sdio_card *card = bus->card; uint retries = 0; u16 lastrbc; u8 hi, lo; @@ -3219,18 +3430,17 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx) (rtx ? ", send NAK" : ""))); if (abort) - brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); + brcmf_sdcard_abort(card, SDIO_FUNC_2); - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, - SBSDIO_FUNC1_FRAMECTRL, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err); bus->f1regdata++; /* Wait until the packet has been flushed (device/FIFO stable) */ for (lastrbc = retries = 0xffff; retries > 0; retries--) { - hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL); - lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, NULL); bus->f1regdata += 2; @@ -3245,12 +3455,13 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx) lastrbc = (hi << 8) + lo; } - if (!retries) + if (!retries) { BRCMF_ERROR(("%s: count never zeroed: last 0x%04x\n", __func__, lastrbc)); - else + } else { BRCMF_INFO(("%s: flush took %d iterations\n", __func__, (0xffff - retries))); + } if (rtx) { bus->rxrtx++; @@ -3266,19 +3477,24 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx) bus->nextlen = 0; /* If we can't reach the device, signal failure */ - if (err || brcmf_sdcard_regfail(bus->sdiodev)) + if (err || brcmf_sdcard_regfail(card)) bus->drvr->busstate = BRCMF_BUS_DOWN; } static void brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff) { + struct brcmf_sdio_card *card = bus->card; uint rdlen, pad; int sdret; BRCMF_TRACE(("%s: Enter\n", __func__)); + /* Control data already received in aligned rxctl */ + if ((bus->bus == SPI_BUS) && (!bus->usebufpool)) + goto gotpkt; + /* Set rxctl for frame (w/optional alignment) */ bus->rxctl = bus->rxbuf; if (brcmf_alignctl) { @@ -3294,6 +3510,12 @@ brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff) if (len <= firstread) goto gotpkt; + /* Copy the full data pkt in gSPI case and process ioctl. */ + if (bus->bus == SPI_BUS) { + memcpy(bus->rxctl, hdr, len); + goto gotpkt; + } + /* Raise rdlen to next SDIO block to avoid tail command */ rdlen = len - firstread; if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { @@ -3329,11 +3551,10 @@ brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff) } /* Read remainder of frame body into the rxctl buffer */ - sdret = brcmf_sdcard_recv_buf(bus->sdiodev, - brcmf_sdcard_cur_sbwad(bus->sdiodev), + sdret = brcmf_sdcard_recv_buf(card, brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2, F2SYNC, (bus->rxctl + firstread), rdlen, - NULL); + NULL, NULL, NULL); bus->f2rxdata++; /* Control frame failures need retransmission */ @@ -3360,7 +3581,7 @@ brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff) done: /* Awake any waiters */ - brcmf_sdbrcm_ioctl_resp_wake(bus); + brcmf_os_ioctl_resp_wake(bus->drvr); } static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq) @@ -3493,17 +3714,17 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq) * packet and and copy into the chain. */ if (usechain) { - errcode = brcmf_sdcard_recv_buf(bus->sdiodev, - brcmf_sdcard_cur_sbwad(bus->sdiodev), + errcode = brcmf_sdcard_recv_buf(bus->card, + brcmf_sdcard_cur_sbwad(bus->card), SDIO_FUNC_2, F2SYNC, (u8 *) pfirst->data, dlen, - pfirst); + pfirst, NULL, NULL); } else if (bus->dataptr) { - errcode = brcmf_sdcard_recv_buf(bus->sdiodev, - brcmf_sdcard_cur_sbwad(bus->sdiodev), + errcode = brcmf_sdcard_recv_buf(bus->card, + brcmf_sdcard_cur_sbwad(bus->card), SDIO_FUNC_2, F2SYNC, bus->dataptr, dlen, - NULL); + NULL, NULL, NULL); sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen, bus->dataptr); if (sublen != dlen) { @@ -3714,23 +3935,23 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq) if (pfirst->len == 0) { brcmu_pkt_buf_free_skb(pfirst); - if (plast) + if (plast) { plast->next = pnext; - else + } else { save_pfirst = pnext; - + } continue; - } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, - pfirst) != 0) { + } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pfirst) + != 0) { BRCMF_ERROR(("%s: rx protocol error\n", __func__)); bus->drvr->rx_errors++; brcmu_pkt_buf_free_skb(pfirst); - if (plast) + if (plast) { plast->next = pnext; - else + } else { save_pfirst = pnext; - + } continue; } @@ -3769,6 +3990,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq) static uint brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) { + struct brcmf_sdio_card *card = bus->card; + u16 len, check; /* Extracted hardware header fields */ u8 chan, seq, doff; /* Extracted software header fields */ u8 fcbits; /* Extracted fcbits from software header */ @@ -3786,8 +4009,20 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) int ifidx = 0; uint rxcount = 0; /* Total frames read */ +#if defined(BCMDBG) || defined(SDTEST) + bool sdtest = false; /* To limit message spew from test mode */ +#endif + BRCMF_TRACE(("%s: Enter\n", __func__)); +#ifdef SDTEST + /* Allow pktgen to override maxframes */ + if (bus->pktgen_count && (bus->pktgen_mode == BRCMF_PKTGEN_RECV)) { + maxframes = bus->pktgen_count; + sdtest = true; + } +#endif + /* Not finished unless we encounter no more frames indication */ *finished = false; @@ -3812,22 +4047,26 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) u16 nextlen = bus->nextlen; bus->nextlen = 0; - rdlen = len = nextlen << 4; - - /* Pad read to blocksize for efficiency */ - if (bus->roundup && bus->blocksize - && (rdlen > bus->blocksize)) { - pad = - bus->blocksize - - (rdlen % bus->blocksize); - if ((pad <= bus->roundup) - && (pad < bus->blocksize) - && ((rdlen + pad + firstread) < - MAX_RX_DATASZ)) - rdlen += pad; - } else if (rdlen % BRCMF_SDALIGN) { - rdlen += BRCMF_SDALIGN - - (rdlen % BRCMF_SDALIGN); + if (bus->bus == SPI_BUS) { + rdlen = len = nextlen; + } else { + rdlen = len = nextlen << 4; + + /* Pad read to blocksize for efficiency */ + if (bus->roundup && bus->blocksize + && (rdlen > bus->blocksize)) { + pad = + bus->blocksize - + (rdlen % bus->blocksize); + if ((pad <= bus->roundup) + && (pad < bus->blocksize) + && ((rdlen + pad + firstread) < + MAX_RX_DATASZ)) + rdlen += pad; + } else if (rdlen % BRCMF_SDALIGN) { + rdlen += + BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); + } } /* We use bus->rxctl buffer in WinXP for initial @@ -3843,24 +4082,66 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) /* Allocate a packet buffer */ pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN); if (!pkt) { - /* Give up on data, request rtx of events */ - BRCMF_ERROR(("%s (nextlen): " - "brcmu_pkt_buf_get_skb " - "failed:" - " len %d rdlen %d expected" - " rxseq %d\n", __func__, - len, rdlen, rxseq)); - continue; + if (bus->bus == SPI_BUS) { + bus->usebufpool = false; + bus->rxctl = bus->rxbuf; + if (brcmf_alignctl) { + bus->rxctl += firstread; + pad = ((unsigned long)bus->rxctl % + BRCMF_SDALIGN); + if (pad) + bus->rxctl += + (BRCMF_SDALIGN - pad); + bus->rxctl -= firstread; + } + rxbuf = bus->rxctl; + /* Read the entire frame */ + sdret = brcmf_sdcard_recv_buf(card, + brcmf_sdcard_cur_sbwad(card), + SDIO_FUNC_2, F2SYNC, + rxbuf, rdlen, + NULL, NULL, NULL); + bus->f2rxdata++; + + /* Control frame failures need + retransmission */ + if (sdret < 0) { + BRCMF_ERROR(("%s: read %d " + "control bytes " + "failed: %d\n", + __func__, + rdlen, sdret)); + /* dhd.rx_ctlerrs is higher */ + bus->rxc_errors++; + brcmf_sdbrcm_rxfail(bus, true, + (bus->bus == + SPI_BUS) ? false + : true); + continue; + } + } else { + /* Give up on data, + request rtx of events */ + BRCMF_ERROR(("%s (nextlen): " + "brcmu_pkt_buf_get_skb " + "failed:" + " len %d rdlen %d expected" + " rxseq %d\n", __func__, + len, rdlen, rxseq)); + continue; + } } else { + if (bus->bus == SPI_BUS) + bus->usebufpool = true; + PKTALIGN(pkt, rdlen, BRCMF_SDALIGN); rxbuf = (u8 *) (pkt->data); /* Read the entire frame */ - sdret = brcmf_sdcard_recv_buf(bus->sdiodev, - brcmf_sdcard_cur_sbwad( - bus->sdiodev), + sdret = brcmf_sdcard_recv_buf(card, + brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2, F2SYNC, rxbuf, rdlen, - pkt); + pkt, NULL, NULL); bus->f2rxdata++; if (sdret < 0) { @@ -3873,7 +4154,10 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) * Don't attempt NAK for * gSPI */ - brcmf_sdbrcm_rxfail(bus, true, true); + brcmf_sdbrcm_rxfail(bus, true, + (bus->bus == + SPI_BUS) ? false : + true); continue; } } @@ -3923,7 +4207,8 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) "expected rxseq %d\n", __func__, nextlen, len, roundup(len, 16), rxseq)); - brcmf_sdbrcm_rxfail(bus, true, true); + brcmf_sdbrcm_rxfail(bus, true, + bus->bus != SPI_BUS); brcmf_sdbrcm_pktfree2(bus, pkt); continue; } @@ -3995,16 +4280,29 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) #endif if (chan == SDPCM_CONTROL_CHANNEL) { - BRCMF_ERROR(("%s (nextlen): readahead" - " on control packet %d?\n", - __func__, seq)); - /* Force retry w/normal header read */ - bus->nextlen = 0; - brcmf_sdbrcm_rxfail(bus, false, true); + if (bus->bus == SPI_BUS) { + brcmf_sdbrcm_read_control(bus, rxbuf, + len, doff); + } else { + BRCMF_ERROR(("%s (nextlen): readahead" + " on control packet %d?\n", + __func__, seq)); + /* Force retry w/normal header read */ + bus->nextlen = 0; + brcmf_sdbrcm_rxfail(bus, false, true); + } brcmf_sdbrcm_pktfree2(bus, pkt); continue; } + if ((bus->bus == SPI_BUS) && !bus->usebufpool) { + BRCMF_ERROR(("Received %d bytes on %d channel." + " Running out of " "rx pktbuf's or" + " not yet malloced.\n", + len, chan)); + continue; + } + /* Validate data offset */ if ((doff < SDPCM_HDRLEN) || (doff > len)) { BRCMF_ERROR(("%s (nextlen): bad data offset %d:" @@ -4018,12 +4316,15 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) /* All done with this one -- now deliver the packet */ goto deliver; } + /* gSPI frames should not be handled in fractions */ + if (bus->bus == SPI_BUS) + break; /* Read frame header (hardware and software) */ - sdret = brcmf_sdcard_recv_buf(bus->sdiodev, - brcmf_sdcard_cur_sbwad(bus->sdiodev), + sdret = brcmf_sdcard_recv_buf(card, + brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2, F2SYNC, bus->rxhdr, firstread, - NULL); + NULL, NULL, NULL); bus->f2rxhdrs++; if (sdret < 0) { @@ -4177,10 +4478,10 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) PKTALIGN(pkt, rdlen, BRCMF_SDALIGN); /* Read the remaining frame data */ - sdret = brcmf_sdcard_recv_buf(bus->sdiodev, - brcmf_sdcard_cur_sbwad(bus->sdiodev), + sdret = brcmf_sdcard_recv_buf(card, + brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)), - rdlen, pkt); + rdlen, pkt, NULL, NULL); bus->f2rxdata++; if (sdret < 0) { @@ -4236,6 +4537,14 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) __skb_trim(pkt, len); skb_pull(pkt, doff); +#ifdef SDTEST + /* Test channel packets are processed separately */ + if (chan == SDPCM_TEST_CHANNEL) { + brcmf_sdbrcm_checkdied(bus, pkt, seq); + continue; + } +#endif /* SDTEST */ + if (pkt->len == 0) { brcmu_pkt_buf_free_skb(pkt); continue; @@ -4254,7 +4563,7 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) rxcount = maxframes - rxleft; #ifdef BCMDBG /* Message if we hit the limit */ - if (!rxleft) + if (!rxleft && !sdtest) BRCMF_DATA(("%s: hit rx limit of %d frames\n", __func__, maxframes)); else @@ -4337,15 +4646,17 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus) HMB_DATA_NAKHANDLED | HMB_DATA_FC | HMB_DATA_FWREADY | - HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) + HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) { BRCMF_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data)); + } return intstatus; } static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) { + struct brcmf_sdio_card *card = bus->card; u32 intstatus, newstatus = 0; uint retries = 0; uint rxlimit = brcmf_rxbound; /* Rx frames to read before resched */ @@ -4368,7 +4679,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) #ifdef BCMDBG /* Check for inconsistent device control */ - devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); if (err) { BRCMF_ERROR(("%s: error reading DEVCTL: %d\n", @@ -4378,7 +4689,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) #endif /* BCMDBG */ /* Read CSR, if clock on switch to AVAIL, else ignore */ - clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); if (err) { BRCMF_ERROR(("%s: error reading CSR: %d\n", __func__, @@ -4390,8 +4701,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) devctl, clkctl)); if (SBSDIO_HTAV(clkctl)) { - devctl = brcmf_sdcard_cfg_read(bus->sdiodev, - SDIO_FUNC_1, + devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); if (err) { BRCMF_ERROR(("%s: error reading DEVCTL: %d\n", @@ -4399,7 +4709,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) bus->drvr->busstate = BRCMF_BUS_DOWN; } devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); if (err) { BRCMF_ERROR(("%s: error writing DEVCTL: %d\n", @@ -4425,7 +4735,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) r_sdreg32(bus, &newstatus, offsetof(struct sdpcmd_regs, intstatus), &retries); bus->f1regdata++; - if (brcmf_sdcard_regfail(bus->sdiodev)) + if (brcmf_sdcard_regfail(bus->card)) newstatus = 0; newstatus &= bus->hostintmask; bus->fcstate = !!(newstatus & I_HMB_FC_STATE); @@ -4502,14 +4812,24 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) bus->intstatus = intstatus; clkwait: + /* Re-enable interrupts to detect new device events (mailbox, rx frame) + * or clock availability. (Allows tx loop to check ipend if desired.) + * (Unless register access seems hosed, as we may not be able to ACK...) + */ + if (bus->intr && bus->intdis && !brcmf_sdcard_regfail(card)) { + BRCMF_INTR(("%s: enable SDIO interrupts, rxdone %d" + " framecnt %d\n", __func__, rxdone, framecnt)); + bus->intdis = false; + brcmf_sdcard_intr_enable(card); + } + if (DATAOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { int ret, i; - ret = brcmf_sdbrcm_send_buf(bus, - brcmf_sdcard_cur_sbwad(bus->sdiodev), + ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf, - (u32) bus->ctrl_frame_len, NULL); + (u32) bus->ctrl_frame_len, NULL, NULL, NULL); if (ret < 0) { /* On failure, abort the command and @@ -4518,21 +4838,19 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) "terminate frame.\n", __func__, ret)); bus->tx_sderrs++; - brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); + brcmf_sdcard_abort(card, SDIO_FUNC_2); - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL); bus->f1regdata++; for (i = 0; i < 3; i++) { u8 hi, lo; - hi = brcmf_sdcard_cfg_read(bus->sdiodev, - SDIO_FUNC_1, + hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCHI, NULL); - lo = brcmf_sdcard_cfg_read(bus->sdiodev, - SDIO_FUNC_1, + lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCLO, NULL); bus->f1regdata += 2; @@ -4562,10 +4880,10 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) /* On failed register access, all bets are off: no resched or interrupts */ if ((bus->drvr->busstate == BRCMF_BUS_DOWN) || - brcmf_sdcard_regfail(bus->sdiodev)) { + brcmf_sdcard_regfail(card)) { BRCMF_ERROR(("%s: failed backplane access over SDIO, halting " "operation %d\n", __func__, - brcmf_sdcard_regfail(bus->sdiodev))); + brcmf_sdcard_regfail(card))); bus->drvr->busstate = BRCMF_BUS_DOWN; bus->intstatus = 0; } else if (bus->clkstate == CLK_PENDING) { @@ -4595,6 +4913,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) void brcmf_sdbrcm_isr(void *arg) { struct brcmf_bus *bus = (struct brcmf_bus *) arg; + struct brcmf_sdio_card *card; BRCMF_TRACE(("%s: Enter\n", __func__)); @@ -4602,6 +4921,7 @@ void brcmf_sdbrcm_isr(void *arg) BRCMF_ERROR(("%s : bus is null pointer , exit\n", __func__)); return; } + card = bus->card; if (bus->drvr->busstate == BRCMF_BUS_DOWN) { BRCMF_ERROR(("%s : bus is down. we have nothing to do\n", @@ -4619,9 +4939,14 @@ void brcmf_sdbrcm_isr(void *arg) } /* Disable additional interrupts (is this needed now)? */ - if (!bus->intr) + if (bus->intr) + BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__)); + else BRCMF_ERROR(("brcmf_sdbrcm_isr() w/o interrupt configured!\n")); + brcmf_sdcard_intr_disable(card); + bus->intdis = true; + #if defined(SDIO_ISR_THREAD) BRCMF_TRACE(("Calling brcmf_sdbrcm_dpc() from %s\n", __func__)); while (brcmf_sdbrcm_dpc(bus)) @@ -4633,6 +4958,268 @@ void brcmf_sdbrcm_isr(void *arg) } +#ifdef SDTEST +static void brcmf_sdbrcm_pktgen_init(struct brcmf_bus *bus) +{ + /* Default to specified length, or full range */ + if (brcmf_pktgen_len) { + bus->pktgen_maxlen = min(brcmf_pktgen_len, + BRCMF_MAX_PKTGEN_LEN); + bus->pktgen_minlen = bus->pktgen_maxlen; + } else { + bus->pktgen_maxlen = BRCMF_MAX_PKTGEN_LEN; + bus->pktgen_minlen = 0; + } + bus->pktgen_len = (u16) bus->pktgen_minlen; + + /* Default to per-watchdog burst with 10s print time */ + bus->pktgen_freq = 1; + bus->pktgen_print = 10000 / brcmf_watchdog_ms; + bus->pktgen_count = (brcmf_pktgen * brcmf_watchdog_ms + 999) / 1000; + + /* Default to echo mode */ + bus->pktgen_mode = BRCMF_PKTGEN_ECHO; + bus->pktgen_stop = 1; +} + +static void brcmf_sdbrcm_pktgen(struct brcmf_bus *bus) +{ + struct sk_buff *pkt; + u8 *data; + uint pktcount; + uint fillbyte; + u16 len; + + /* Display current count if appropriate */ + if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) { + bus->pktgen_ptick = 0; + printk(KERN_DEBUG "%s: send attempts %d rcvd %d\n", + __func__, bus->pktgen_sent, bus->pktgen_rcvd); + } + + /* For recv mode, just make sure dongle has started sending */ + if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) { + if (!bus->pktgen_rcvd) + brcmf_sdbrcm_sdtest_set(bus, true); + return; + } + + /* Otherwise, generate or request the specified number of packets */ + for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) { + /* Stop if total has been reached */ + if (bus->pktgen_total + && (bus->pktgen_sent >= bus->pktgen_total)) { + bus->pktgen_count = 0; + break; + } + + /* Allocate an appropriate-sized packet */ + len = bus->pktgen_len; + pkt = brcmu_pkt_buf_get_skb( + len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN, + true); + if (!pkt) { + BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n", + __func__)); + break; + } + PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), + BRCMF_SDALIGN); + data = (u8 *) (pkt->data) + SDPCM_HDRLEN; + + /* Write test header cmd and extra based on mode */ + switch (bus->pktgen_mode) { + case BRCMF_PKTGEN_ECHO: + *data++ = SDPCM_TEST_ECHOREQ; + *data++ = (u8) bus->pktgen_sent; + break; + + case BRCMF_PKTGEN_SEND: + *data++ = SDPCM_TEST_DISCARD; + *data++ = (u8) bus->pktgen_sent; + break; + + case BRCMF_PKTGEN_RXBURST: + *data++ = SDPCM_TEST_BURST; + *data++ = (u8) bus->pktgen_count; + break; + + default: + BRCMF_ERROR(("Unrecognized pktgen mode %d\n", + bus->pktgen_mode)); + brcmu_pkt_buf_free_skb(pkt, true); + bus->pktgen_count = 0; + return; + } + + /* Write test header length field */ + *data++ = (len >> 0); + *data++ = (len >> 8); + + /* Then fill in the remainder -- N/A for burst, + but who cares... */ + for (fillbyte = 0; fillbyte < len; fillbyte++) + *data++ = + SDPCM_TEST_FILL(fillbyte, (u8) bus->pktgen_sent); + +#ifdef BCMDBG + if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { + data = (u8 *) (pkt->data) + SDPCM_HDRLEN; + printk(KERN_DEBUG "brcmf_sdbrcm_pktgen: Tx Data:\n"); + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data, + pkt->len - SDPCM_HDRLEN); + } +#endif + + /* Send it */ + if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) { + bus->pktgen_fail++; + if (bus->pktgen_stop + && bus->pktgen_stop == bus->pktgen_fail) + bus->pktgen_count = 0; + } + bus->pktgen_sent++; + + /* Bump length if not fixed, wrap at max */ + if (++bus->pktgen_len > bus->pktgen_maxlen) + bus->pktgen_len = (u16) bus->pktgen_minlen; + + /* Special case for burst mode: just send one request! */ + if (bus->pktgen_mode == BRCMF_PKTGEN_RXBURST) + break; + } +} + +static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start) +{ + struct sk_buff *pkt; + u8 *data; + + /* Allocate the packet */ + pkt = brcmu_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + + BRCMF_SDALIGN, true); + if (!pkt) { + BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n", __func__)); + return; + } + PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), BRCMF_SDALIGN); + data = (u8 *) (pkt->data) + SDPCM_HDRLEN; + + /* Fill in the test header */ + *data++ = SDPCM_TEST_SEND; + *data++ = start; + *data++ = (bus->pktgen_maxlen >> 0); + *data++ = (bus->pktgen_maxlen >> 8); + + /* Send it */ + if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) + bus->pktgen_fail++; +} + +static void +brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, struct sk_buff *pkt, uint seq) +{ + u8 *data; + uint pktlen; + + u8 cmd; + u8 extra; + u16 len; + u16 offset; + + /* Check for min length */ + pktlen = pkt->len; + if (pktlen < SDPCM_TEST_HDRLEN) { + BRCMF_ERROR(("brcmf_sdbrcm_checkdied: toss runt frame, pktlen " + "%d\n", pktlen)); + brcmu_pkt_buf_free_skb(pkt, false); + return; + } + + /* Extract header fields */ + data = pkt->data; + cmd = *data++; + extra = *data++; + len = *data++; + len += *data++ << 8; + + /* Check length for relevant commands */ + if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ + || cmd == SDPCM_TEST_ECHORSP) { + if (pktlen != len + SDPCM_TEST_HDRLEN) { + BRCMF_ERROR(("brcmf_sdbrcm_checkdied: frame length " + "mismatch, pktlen %d seq %d" + " cmd %d extra %d len %d\n", + pktlen, seq, cmd, extra, len)); + brcmu_pkt_buf_free_skb(pkt, false); + return; + } + } + + /* Process as per command */ + switch (cmd) { + case SDPCM_TEST_ECHOREQ: + /* Rx->Tx turnaround ok (even on NDIS w/current + implementation) */ + *(u8 *) (pkt->data) = SDPCM_TEST_ECHORSP; + if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0) + bus->pktgen_sent++; + else { + bus->pktgen_fail++; + brcmu_pkt_buf_free_skb(pkt, false); + } + bus->pktgen_rcvd++; + break; + + case SDPCM_TEST_ECHORSP: + if (bus->ext_loop) { + brcmu_pkt_buf_free_skb(pkt, false); + bus->pktgen_rcvd++; + break; + } + + for (offset = 0; offset < len; offset++, data++) { + if (*data != SDPCM_TEST_FILL(offset, extra)) { + BRCMF_ERROR(("brcmf_sdbrcm_checkdied: echo" + " data mismatch: " + "offset %d (len %d) " + "expect 0x%02x rcvd 0x%02x\n", + offset, len, + SDPCM_TEST_FILL(offset, extra), + *data)); + break; + } + } + brcmu_pkt_buf_free_skb(pkt, false); + bus->pktgen_rcvd++; + break; + + case SDPCM_TEST_DISCARD: + brcmu_pkt_buf_free_skb(pkt, false); + bus->pktgen_rcvd++; + break; + + case SDPCM_TEST_BURST: + case SDPCM_TEST_SEND: + default: + BRCMF_INFO(("brcmf_sdbrcm_checkdied: unsupported or unknown " + "command, pktlen %d seq %d" " cmd %d extra %d" + " len %d\n", pktlen, seq, cmd, extra, len)); + brcmu_pkt_buf_free_skb(pkt, false); + break; + } + + /* For recv mode, stop at limie (and tell dongle to stop sending) */ + if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) { + if (bus->pktgen_total + && (bus->pktgen_rcvd >= bus->pktgen_total)) { + bus->pktgen_count = 0; + brcmf_sdbrcm_sdtest_set(bus, false); + } + } +} +#endif /* SDTEST */ + extern bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr) { struct brcmf_bus *bus; @@ -4662,7 +5249,7 @@ extern bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr) if (!bus->dpc_sched) { u8 devpend; - devpend = brcmf_sdcard_cfg_read(bus->sdiodev, + devpend = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_0, SDIO_CCCR_INTx, NULL); intstatus = @@ -4675,6 +5262,8 @@ extern bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr) if (intstatus) { bus->pollcnt++; bus->ipend = true; + if (bus->intr) + brcmf_sdcard_intr_disable(bus->card); bus->dpc_sched = true; brcmf_sdbrcm_sched_dpc(bus); @@ -4700,6 +5289,16 @@ extern bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr) } #endif /* BCMDBG */ +#ifdef SDTEST + /* Generate packets if configured */ + if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) { + /* Make sure backplane clock is on */ + brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); + bus->pktgen_tick = 0; + brcmf_sdbrcm_pktgen(bus); + } +#endif + /* On idle timeout clear activity flag and/or turn off clock */ if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { if (++bus->idlecount >= bus->idletime) { @@ -4786,13 +5385,18 @@ static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr, static bool brcmf_sdbrcm_chipmatch(u16 chipid) { + if (chipid == BCM4325_CHIP_ID) + return true; if (chipid == BCM4329_CHIP_ID) return true; + if (chipid == BCM4319_CHIP_ID) + return true; return false; } -void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, - u32 regsva, struct brcmf_sdio_dev *sdiodev) +static void *brcmf_sdbrcm_probe(u16 venid, u16 devid, u16 bus_no, + u16 slot, u16 func, uint bustype, u32 regsva, + void *card) { int ret; struct brcmf_bus *bus; @@ -4808,6 +5412,7 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, brcmf_txbound = BRCMF_TXBOUND; brcmf_rxbound = BRCMF_RXBOUND; brcmf_alignctl = true; + sd1idle = true; brcmf_readahead = true; retrydata = false; brcmf_dongle_memsize = 0; @@ -4818,10 +5423,55 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, brcmf_c_init(); BRCMF_TRACE(("%s: Enter\n", __func__)); + BRCMF_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid)); /* We make an assumption about address window mappings: * regsva == SI_ENUM_BASE*/ + /* SDIO car passes venid and devid based on CIS parsing -- but + * low-power start + * means early parse could fail, so here we should get either an ID + * we recognize OR (-1) indicating we must request power first. + */ + /* Check the Vendor ID */ + switch (venid) { + case 0x0000: + case PCI_VENDOR_ID_BROADCOM: + break; + default: + BRCMF_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid)); + return NULL; + } + + /* Check the Device ID and make sure it's one that we support */ + switch (devid) { + case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */ + case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */ + case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */ + BRCMF_INFO(("%s: found 4325 Dongle\n", __func__)); + break; + case BCM4329_D11NDUAL_ID: /* 4329 802.11n dualband device */ + case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */ + case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */ + case 0x4329: + BRCMF_INFO(("%s: found 4329 Dongle\n", __func__)); + break; + case BCM4319_D11N_ID: /* 4319 802.11n id */ + case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */ + case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */ + BRCMF_INFO(("%s: found 4319 Dongle\n", __func__)); + break; + case 0: + BRCMF_INFO(("%s: allow device id 0, will check chip" + " internals\n", __func__)); + break; + + default: + BRCMF_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n", + __func__, venid, devid)); + return NULL; + } + /* Allocate private bus interface state */ bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); if (!bus) { @@ -4829,14 +5479,15 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, __func__)); goto fail; } - bus->sdiodev = sdiodev; - sdiodev->bus = bus; + bus->card = card; + bus->cl_devid = (u16) devid; + bus->bus = BRCMF_BUS; bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; bus->usebufpool = false; /* Use bufpool if allocated, else use locally malloced rxbuf */ /* attempt to attach to the dongle */ - if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { + if (!(brcmf_sdbrcm_probe_attach(bus, card, regsva, devid))) { BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_attach failed\n", __func__)); goto fail; @@ -4844,7 +5495,6 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, spin_lock_init(&bus->txqlock); init_waitqueue_head(&bus->ctrl_wait); - init_waitqueue_head(&bus->ioctl_resp_wait); /* Set up the watchdog timer */ init_timer(&bus->timer); @@ -4898,13 +5548,13 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, } /* Allocate buffers */ - if (!(brcmf_sdbrcm_probe_malloc(bus))) { + if (!(brcmf_sdbrcm_probe_malloc(bus, card))) { BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_malloc failed\n", __func__)); goto fail; } - if (!(brcmf_sdbrcm_probe_init(bus))) { + if (!(brcmf_sdbrcm_probe_init(bus, card))) { BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_init failed\n", __func__)); goto fail; } @@ -4912,7 +5562,8 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, /* Register interrupt callback, but mask it (not operational yet). */ BRCMF_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __func__)); - ret = brcmf_sdcard_intr_reg(bus->sdiodev); + brcmf_sdcard_intr_disable(card); + ret = brcmf_sdcard_intr_reg(card, brcmf_sdbrcm_isr, bus); if (ret != 0) { BRCMF_ERROR(("%s: FAILED: sdcard_intr_reg returned %d\n", __func__, ret)); @@ -4945,12 +5596,11 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, } static bool -brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) +brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card, u32 regsva, + u16 devid) { u8 clkctl = 0; int err = 0; - int reg_addr; - u32 reg_val; bus->alp_only = true; @@ -4961,7 +5611,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) #ifdef BCMDBG printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n", - brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4)); + brcmf_sdcard_reg_read(bus->card, SI_ENUM_BASE, 4)); #endif /* BCMDBG */ @@ -4970,12 +5620,11 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) * programs PLL control regs */ - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, - SBSDIO_FUNC1_CHIPCLKCSR, - BRCMF_INIT_CLKCTL1, &err); + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, + BRCMF_INIT_CLKCTL1, &err); if (!err) clkctl = - brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { @@ -5000,27 +5649,27 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) brcmf_sdbrcm_sdiod_drive_strength_init(bus, brcmf_sdiod_drive_strength); /* Get info on the ARM and SOCRAM cores... */ - brcmf_sdcard_reg_read(bus->sdiodev, - CORE_SB(bus->ci->armcorebase, sbidhigh), 4); - bus->orig_ramsize = bus->ci->ramsize; - if (!(bus->orig_ramsize)) { - BRCMF_ERROR(("%s: failed to find SOCRAM memory!\n", - __func__)); - goto fail; - } - bus->ramsize = bus->orig_ramsize; - if (brcmf_dongle_memsize) - brcmf_sdbrcm_setmemsize(bus, brcmf_dongle_memsize); + if (!BRCMF_NOPMU(bus)) { + brcmf_sdcard_reg_read(bus->card, + CORE_SB(bus->ci->armcorebase, sbidhigh), 4); + bus->orig_ramsize = bus->ci->ramsize; + if (!(bus->orig_ramsize)) { + BRCMF_ERROR(("%s: failed to find SOCRAM memory!\n", + __func__)); + goto fail; + } + bus->ramsize = bus->orig_ramsize; + if (brcmf_dongle_memsize) + brcmf_sdbrcm_setmemsize(bus, brcmf_dongle_memsize); - BRCMF_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n", - bus->ramsize, bus->orig_ramsize)); + BRCMF_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n", + bus->ramsize, bus->orig_ramsize)); + } /* Set core control so an SDIO reset does a backplane reset */ - reg_addr = bus->ci->buscorebase + - offsetof(struct sdpcmd_regs, corecontrol); - reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32)); - brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32), - reg_val | CC_BPRESEN); + OR_REG(bus->ci->buscorebase + offsetof(struct sdpcmd_regs, + corecontrol), + CC_BPRESEN, u32); brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); @@ -5040,7 +5689,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) return false; } -static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus) +static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card) { BRCMF_TRACE(("%s: Enter\n", __func__)); @@ -5080,12 +5729,18 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus) return false; } -static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus) +static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card) { + s32 fnum; + BRCMF_TRACE(("%s: Enter\n", __func__)); +#ifdef SDTEST + brcmf_sdbrcm_pktgen_init(bus); +#endif /* SDTEST */ + /* Disable F2 to clear any intermediate frame state on the dongle */ - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, + brcmf_sdcard_cfg_write(card, SDIO_FUNC_0, SDIO_CCCR_IOEx, SDIO_FUNC_ENABLE_1, NULL); bus->drvr->busstate = BRCMF_BUS_DOWN; @@ -5093,8 +5748,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus) bus->rxflow = false; /* Done with backplane-dependent accesses, can drop clock... */ - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, - SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); + brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, + NULL); /* ...and initialize clock/power states */ bus->clkstate = CLK_SDONLY; @@ -5102,27 +5757,35 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus) bus->idleclock = BRCMF_IDLE_ACTIVE; /* Query the F2 block size, set roundup accordingly */ - bus->blocksize = bus->sdiodev->func[2]->cur_blksize; + fnum = 2; + if (brcmf_sdcard_iovar_op(card, "sd_blocksize", &fnum, sizeof(s32), + &bus->blocksize, sizeof(s32), false) != 0) { + bus->blocksize = 0; + BRCMF_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize")); + } else { + BRCMF_INFO(("%s: Initial value for %s is %d\n", + __func__, "sd_blocksize", bus->blocksize)); + } bus->roundup = min(max_roundup, bus->blocksize); /* Query if bus module supports packet chaining, default to use if supported */ - if (brcmf_sdcard_iovar_op(bus->sdiodev, "sd_rxchain", NULL, 0, + if (brcmf_sdcard_iovar_op(card, "sd_rxchain", NULL, 0, &bus->sd_rxchain, sizeof(s32), - false) != 0) + false) != 0) { bus->sd_rxchain = false; - else + } else { BRCMF_INFO(("%s: bus module (through sdiocard API) %s" " chaining\n", __func__, bus->sd_rxchain ? "supports" : "does not support")); - + } bus->use_rxchain = (bool) bus->sd_rxchain; return true; } static bool -brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) +brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card) { bool ret; @@ -5143,7 +5806,8 @@ static void brcmf_sdbrcm_release(struct brcmf_bus *bus) if (bus) { /* De-register interrupt handler */ - brcmf_sdcard_intr_dereg(bus->sdiodev); + brcmf_sdcard_intr_disable(bus->card); + brcmf_sdcard_intr_dereg(bus->card); if (bus->drvr) { brcmf_detach(bus->drvr); @@ -5193,18 +5857,29 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus) BRCMF_TRACE(("%s: Disconnected\n", __func__)); } -void brcmf_sdbrcm_disconnect(void *ptr) +static void brcmf_sdbrcm_disconnect(void *ptr) { struct brcmf_bus *bus = (struct brcmf_bus *)ptr; BRCMF_TRACE(("%s: Enter\n", __func__)); - if (bus) + if (bus) { brcmf_sdbrcm_release(bus); + } BRCMF_TRACE(("%s: Disconnected\n", __func__)); } +/* Register/Unregister functions are called by the main DHD entry + * point (e.g. module insertion) to link with the bus driver, in + * order to look for or await the device. + */ + +static struct brcmf_sdioh_driver brcmf_sdio = { + brcmf_sdbrcm_probe, + brcmf_sdbrcm_disconnect +}; + int brcmf_bus_register(void) { BRCMF_TRACE(("%s: Enter\n", __func__)); @@ -5224,7 +5899,7 @@ int brcmf_bus_register(void) return -EINVAL; } while (0); - return brcmf_sdio_register(); + return brcmf_sdio_register(&brcmf_sdio); } void brcmf_bus_unregister(void) @@ -5245,7 +5920,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus) bus->fw_name = BCM4329_FW_NAME; ret = request_firmware(&bus->firmware, bus->fw_name, - &bus->sdiodev->func[2]->dev); + &gInstance->func[2]->dev); if (ret) { BRCMF_ERROR(("%s: Fail to request firmware %d\n", __func__, ret)); @@ -5347,7 +6022,7 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus) bus->nv_name = BCM4329_NV_NAME; ret = request_firmware(&bus->firmware, bus->nv_name, - &bus->sdiodev->func[2]->dev); + &gInstance->func[2]->dev); if (ret) { BRCMF_ERROR(("%s: Fail to request nvram %d\n", __func__, ret)); return ret; @@ -5409,9 +6084,10 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) } /* External nvram takes precedence if specified */ - if (brcmf_sdbrcm_download_nvram(bus)) + if (brcmf_sdbrcm_download_nvram(bus)) { BRCMF_ERROR(("%s: dongle nvram file download failed\n", __func__)); + } /* Take arm out of reset */ if (brcmf_sdbrcm_download_state(bus, false)) { @@ -5429,10 +6105,14 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) static int brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags, - u8 *buf, uint nbytes, struct sk_buff *pkt) + u8 *buf, uint nbytes, struct sk_buff *pkt, + void (*complete)(void *handle, int status, + bool sync_waiting), + void *handle) { return brcmf_sdcard_send_buf - (bus->sdiodev, addr, fn, flags, buf, nbytes, pkt); + (bus->card, addr, fn, flags, buf, nbytes, pkt, complete, + handle); } int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag) @@ -5470,9 +6150,11 @@ int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag) /* Turn on WLAN */ /* Attempt to re-attach & download */ - if (brcmf_sdbrcm_probe_attach(bus, SI_ENUM_BASE)) { + if (brcmf_sdbrcm_probe_attach(bus, bus->card, + SI_ENUM_BASE, + bus->cl_devid)) { /* Attempt to download binary to the dongle */ - if (brcmf_sdbrcm_probe_init(bus)) { + if (brcmf_sdbrcm_probe_init(bus, bus->card)) { /* Re-init bus, enable F2 transfer */ brcmf_sdbrcm_bus_init(bus->drvr, false); @@ -5497,7 +6179,7 @@ int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag) } static int -brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev, +brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_card *card, struct chip_info *ci, u32 regs) { u32 regdata; @@ -5509,7 +6191,7 @@ brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev, * other ways of recognition should be added here. */ ci->cccorebase = regs; - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_CC_REG(ci->cccorebase, chipid), 4); ci->chip = regdata & CID_ID_MASK; ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; @@ -5531,15 +6213,15 @@ brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev, return -ENODEV; } - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(ci->cccorebase, sbidhigh), 4); ci->ccrev = SBCOREREV(regdata); - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_CC_REG(ci->cccorebase, pmucapabilities), 4); ci->pmurev = regdata & PCAP_REV_MASK; - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(ci->buscorebase, sbidhigh), 4); ci->buscorerev = SBCOREREV(regdata); ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT; @@ -5549,87 +6231,87 @@ brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev, ci->buscorerev, ci->buscoretype)); /* get chipcommon capabilites */ - ci->cccaps = brcmf_sdcard_reg_read(sdiodev, + ci->cccaps = brcmf_sdcard_reg_read(card, CORE_CC_REG(ci->cccorebase, capabilities), 4); return 0; } static void -brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_dev *sdiodev, u32 corebase) +brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase) { u32 regdata; - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatelow), 4); if (regdata & SBTML_RESET) return; - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatelow), 4); if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) { /* * set target reject and spin until busy is clear * (preserve core-specific bits) */ - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatelow), 4); - brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), - 4, regdata | SBTML_REJ); + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4, + regdata | SBTML_REJ); - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatelow), 4); udelay(1); - SPINWAIT((brcmf_sdcard_reg_read(sdiodev, + SPINWAIT((brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatehigh), 4) & SBTMH_BUSY), 100000); - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatehigh), 4); if (regdata & SBTMH_BUSY) BRCMF_ERROR(("%s: ARM core still busy\n", __func__)); - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbidlow), 4); if (regdata & SBIDL_INIT) { - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4) | SBIM_RJ; - brcmf_sdcard_reg_write(sdiodev, + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbimstate), 4, regdata); - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4); udelay(1); - SPINWAIT((brcmf_sdcard_reg_read(sdiodev, + SPINWAIT((brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4) & SBIM_BY), 100000); } /* set reset and reject while enabling the clocks */ - brcmf_sdcard_reg_write(sdiodev, + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4, (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | SBTML_REJ | SBTML_RESET)); - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatelow), 4); udelay(10); /* clear the initiator reject bit */ - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbidlow), 4); if (regdata & SBIDL_INIT) { - regdata = brcmf_sdcard_reg_read(sdiodev, + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4) & ~SBIM_RJ; - brcmf_sdcard_reg_write(sdiodev, + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbimstate), 4, regdata); } } /* leave reset and reject asserted */ - brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4, (SBTML_REJ | SBTML_RESET)); udelay(1); } @@ -5644,17 +6326,19 @@ brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs) BRCMF_TRACE(("%s: Enter\n", __func__)); /* alloc chip_info_t */ - ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC); + ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC); if (NULL == ci) { BRCMF_ERROR(("%s: malloc failed!\n", __func__)); return -ENOMEM; } + memset((unsigned char *)ci, 0, sizeof(struct chip_info)); + /* bus/core/clk setup for register access */ /* Try forcing SDIO core to do ALPAvail request only */ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, - SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, + clkset, &err); if (err) { BRCMF_ERROR(("%s: error writing for HT off\n", __func__)); goto fail; @@ -5662,11 +6346,11 @@ brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs) /* If register supported, wait for ALPAvail and then force ALP */ /* This may take up to 15 milliseconds */ - clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL); if ((clkval & ~SBSDIO_AVBITS) == clkset) { SPINWAIT(((clkval = - brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)), @@ -5679,7 +6363,7 @@ brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs) } clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); udelay(65); @@ -5691,10 +6375,10 @@ brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs) } /* Also, disable the extra SDIO pull-ups */ - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, - SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, + 0, NULL); - err = brcmf_sdbrcm_chip_recognition(bus->sdiodev, ci, regs); + err = brcmf_sdbrcm_chip_recognition(bus->card, ci, regs); if (err) goto fail; @@ -5702,24 +6386,24 @@ brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs) * Make sure any on-chip ARM is off (in case strapping is wrong), * or downloaded code was already running. */ - brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ci->armcorebase); + brcmf_sdbrcm_chip_disablecore(bus->card, ci->armcorebase); - brcmf_sdcard_reg_write(bus->sdiodev, + brcmf_sdcard_reg_write(bus->card, CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0); - brcmf_sdcard_reg_write(bus->sdiodev, + brcmf_sdcard_reg_write(bus->card, CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0); /* Disable F2 to clear any intermediate frame state on the dongle */ - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx, SDIO_FUNC_ENABLE_1, NULL); /* WAR: cmd52 backplane read so core HW will drop ALPReq */ - clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, + clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1, 0, NULL); /* Done with backplane-dependent accesses, can drop clock... */ - brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, - SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); + brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, + 0, NULL); bus->ci = ci; return 0; @@ -5730,7 +6414,7 @@ brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs) } static void -brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase) +brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase) { u32 regdata; @@ -5738,38 +6422,37 @@ brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase) * Must do the disable sequence first to work for * arbitrary current core state. */ - brcmf_sdbrcm_chip_disablecore(sdiodev, corebase); + brcmf_sdbrcm_chip_disablecore(card, corebase); /* * Now do the initialization sequence. * set reset while enabling the clock and * forcing them on throughout the core */ - brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4, ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | SBTML_RESET); udelay(1); - regdata = brcmf_sdcard_reg_read(sdiodev, - CORE_SB(corebase, sbtmstatehigh), 4); + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatehigh), + 4); if (regdata & SBTMH_SERR) - brcmf_sdcard_reg_write(sdiodev, - CORE_SB(corebase, sbtmstatehigh), 4, 0); + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatehigh), + 4, 0); - regdata = brcmf_sdcard_reg_read(sdiodev, - CORE_SB(corebase, sbimstate), 4); + regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4); if (regdata & (SBIM_IBE | SBIM_TO)) - brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4, + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbimstate), 4, regdata & ~(SBIM_IBE | SBIM_TO)); /* clear reset and allow it to propagate throughout the core */ - brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4, (SICF_FGC << SBTML_SICF_SHIFT) | (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); udelay(1); /* leave clock enabled */ - brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, + brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4, (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); udelay(1); } @@ -5816,8 +6499,8 @@ static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = { #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) -static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, - u32 drivestrength) { +static void +brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, u32 drivestrength) { struct sdiod_drive_str *str_tab = NULL; u32 str_mask = 0; u32 str_shift = 0; @@ -5863,15 +6546,15 @@ static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, } } - brcmf_sdcard_reg_write(bus->sdiodev, + brcmf_sdcard_reg_write(bus->card, CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4, 1); - cc_data_temp = brcmf_sdcard_reg_read(bus->sdiodev, + cc_data_temp = brcmf_sdcard_reg_read(bus->card, CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4); cc_data_temp &= ~str_mask; drivestrength_sel <<= str_shift; cc_data_temp |= drivestrength_sel; - brcmf_sdcard_reg_write(bus->sdiodev, + brcmf_sdcard_reg_write(bus->card, CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4, cc_data_temp); @@ -6087,33 +6770,3 @@ static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus) MODULE_FIRMWARE(BCM4329_FW_NAME); MODULE_FIRMWARE(BCM4329_NV_NAME); - -static int brcmf_sdbrcm_ioctl_resp_wait(struct brcmf_bus *bus, uint *condition, - bool *pending) -{ - DECLARE_WAITQUEUE(wait, current); - int timeout = msecs_to_jiffies(brcmf_ioctl_timeout_msec); - - /* Wait until control frame is available */ - add_wait_queue(&bus->ioctl_resp_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - while (!(*condition) && (!signal_pending(current) && timeout)) - timeout = schedule_timeout(timeout); - - if (signal_pending(current)) - *pending = true; - - set_current_state(TASK_RUNNING); - remove_wait_queue(&bus->ioctl_resp_wait, &wait); - - return timeout; -} - -static int brcmf_sdbrcm_ioctl_resp_wake(struct brcmf_bus *bus) -{ - if (waitqueue_active(&bus->ioctl_resp_wait)) - wake_up_interruptible(&bus->ioctl_resp_wait); - - return 0; -} diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/sdio_host.h b/trunk/drivers/staging/brcm80211/brcmfmac/sdio_host.h index 03ae16aac321..d34547215060 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/sdio_host.h +++ b/trunk/drivers/staging/brcm80211/brcmfmac/sdio_host.h @@ -18,6 +18,7 @@ #define _BRCM_SDH_H_ #include +extern const uint brcmf_sdio_msglevel; #define SDIO_FUNC_0 0 #define SDIO_FUNC_1 1 @@ -40,71 +41,46 @@ /* Maximum number of I/O funcs */ #define SDIOD_MAX_IOFUNCS 7 -/* as of sdiod rev 0, supports 3 functions */ -#define SBSDIO_NUM_FUNCTION 3 +#define SBSDIO_NUM_FUNCTION 3 /* as of sdiod rev 0, supports 3 functions */ /* function 1 miscellaneous registers */ - -/* sprom command and status */ -#define SBSDIO_SPROM_CS 0x10000 -/* sprom info register */ -#define SBSDIO_SPROM_INFO 0x10001 -/* sprom indirect access data byte 0 */ -#define SBSDIO_SPROM_DATA_LOW 0x10002 -/* sprom indirect access data byte 1 */ -#define SBSDIO_SPROM_DATA_HIGH 0x10003 -/* sprom indirect access addr byte 0 */ -#define SBSDIO_SPROM_ADDR_LOW 0x10004 -/* sprom indirect access addr byte 0 */ -#define SBSDIO_SPROM_ADDR_HIGH 0x10005 -/* xtal_pu (gpio) output */ -#define SBSDIO_CHIP_CTRL_DATA 0x10006 -/* xtal_pu (gpio) enable */ -#define SBSDIO_CHIP_CTRL_EN 0x10007 -/* rev < 7, watermark for sdio device */ -#define SBSDIO_WATERMARK 0x10008 -/* control busy signal generation */ -#define SBSDIO_DEVICE_CTL 0x10009 - -/* SB Address Window Low (b15) */ -#define SBSDIO_FUNC1_SBADDRLOW 0x1000A -/* SB Address Window Mid (b23:b16) */ -#define SBSDIO_FUNC1_SBADDRMID 0x1000B -/* SB Address Window High (b31:b24) */ -#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C -/* Frame Control (frame term/abort) */ -#define SBSDIO_FUNC1_FRAMECTRL 0x1000D -/* ChipClockCSR (ALP/HT ctl/status) */ -#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E -/* SdioPullUp (on cmd, d0-d2) */ -#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F -/* Write Frame Byte Count Low */ -#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 -/* Write Frame Byte Count High */ -#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A -/* Read Frame Byte Count Low */ -#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B -/* Read Frame Byte Count High */ -#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C +#define SBSDIO_SPROM_CS 0x10000 /* sprom command and status */ +#define SBSDIO_SPROM_INFO 0x10001 /* sprom info register */ +#define SBSDIO_SPROM_DATA_LOW 0x10002 /* sprom indirect access data byte 0 */ +#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* sprom indirect access data byte 1 */ +#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* sprom indirect access addr byte 0 */ +#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* sprom indirect access addr byte 0 */ +#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu (gpio) output */ +#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu (gpio) enable */ +#define SBSDIO_WATERMARK 0x10008 /* rev < 7, watermark for sdio device */ +#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */ + +/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */ +#define SBSDIO_FUNC1_SBADDRLOW 0x1000A /* SB Address Window Low (b15) */ +#define SBSDIO_FUNC1_SBADDRMID 0x1000B /* SB Address Window Mid (b23:b16) */ +#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C /* SB Address Window High (b31:b24) */ +#define SBSDIO_FUNC1_FRAMECTRL 0x1000D /* Frame Control (frame term/abort) */ +#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E /* ChipClockCSR (ALP/HT ctl/status) */ +#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F /* SdioPullUp (on cmd, d0-d2) */ +#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 /* Write Frame Byte Count Low */ +#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A /* Write Frame Byte Count High */ +#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B /* Read Frame Byte Count Low */ +#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C /* Read Frame Byte Count High */ #define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ #define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */ /* function 1 OCP space */ - -/* sb offset addr is <= 15 bits, 32k */ -#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF +#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */ #define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 -/* with b15, maps to 32-bit SB access */ -#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 +#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */ +/* some duplication with sbsdpcmdev.h here */ /* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */ - #define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */ #define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */ #define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */ -/* Address bits from SBADDR regs */ -#define SBSDIO_SBWINDOW_MASK 0xffff8000 +#define SBSDIO_SBWINDOW_MASK 0xffff8000 /* Address bits from SBADDR regs */ #define SDIOH_READ 0 /* Read request */ #define SDIOH_WRITE 1 /* Write request */ @@ -116,27 +92,68 @@ #define SUCCESS 0 #define ERROR 1 +/* forward declarations */ +struct brcmf_sdio_card; + struct brcmf_sdreg { int func; int offset; int value; }; -struct brcmf_sdio_dev { - struct sdio_func *func[SDIO_MAX_FUNCS]; - u8 num_funcs; /* Supported funcs on client */ +struct sdioh_info { + struct osl_info *osh; /* osh handler */ + bool client_intr_enabled; /* interrupt connnected flag */ + bool intr_handler_valid; /* client driver interrupt handler valid */ + void (*intr_handler)(void *); /* registered interrupt handler */ + void *intr_handler_arg; /* argument to call interrupt handler */ + u16 intmask; /* Current active interrupts */ + void *sdos_info; /* Pointer to per-OS private data */ + + uint irq; /* Client irq */ + int intrcount; /* Client interrupts */ + bool sd_blockmode; /* sd_blockmode == false => 64 Byte Cmd 53s. */ + /* Must be on for sd_multiblock to be effective */ + bool use_client_ints; /* If this is false, make sure to restore */ + int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ + u8 num_funcs; /* Supported funcs on client */ + u32 com_cis_ptr; u32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; - u32 sbwad; /* Save backplane window address */ - bool regfail; /* status of last reg_r/w call */ - void *bus; - atomic_t suspend; /* suspend flag */ + uint max_dma_len; + uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */ + /* SDDMA_DESCRIPTOR SGList[32]; *//* Scatter/Gather DMA List */ }; +struct brcmf_sdmmc_instance { + struct sdioh_info *sd; + struct sdio_func *func[SDIOD_MAX_IOFUNCS]; + u32 host_claimed; +}; + +/* Attach and build an interface to the underlying SD host driver. + * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by + * brcmf_sdcard. + * - Returns the sdio card handle and virtual address base for register access. + * The returned handle should be used in all subsequent calls, but the bcmsh + * implementation may maintain a single "default" handle (e.g. the first or + * most recent one) to enable single-instance implementations to pass NULL. + */ +extern struct brcmf_sdio_card* +brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq); + +/* Detach - freeup resources allocated in attach */ +extern int brcmf_sdcard_detach(struct brcmf_sdio_card *card); + +/* Enable/disable SD interrupt */ +extern int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card); +extern int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card); + /* Register/deregister device interrupt handler. */ extern int -brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev); +brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card, + void (*fn)(void *), void *argh); -extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev); +extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card); /* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). * fn: function number @@ -144,11 +161,20 @@ extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev); * data: data byte to write * err: pointer to error code (or NULL) */ -extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint func, +extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint func, u32 addr, int *err); -extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func, +extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint func, u32 addr, u8 data, int *err); +/* Read/Write 4bytes from/to cfg space */ +extern u32 +brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num, + u32 addr, int *err); + +extern void brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, + uint fnc_num, u32 addr, + u32 data, int *err); + /* Read CIS content for specified function. * fn: function whose CIS is being requested (0 is common CIS) * cis: pointer to memory location to place results @@ -156,7 +182,7 @@ extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func, * Internally, this routine uses the values from the cis base regs (0x9-0xB) * to form an SDIO-space address to read the data from. */ -extern int brcmf_sdcard_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, +extern int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 *cis, uint length); /* Synchronous access to device (client) core registers via CMD53 to F1. @@ -165,14 +191,14 @@ extern int brcmf_sdcard_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, * data: data for register write */ extern u32 -brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size); +brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size); extern u32 -brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, +brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size, u32 data); /* Indicate if last reg read/write failed */ -extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev); +extern bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card); /* Buffer transfer to/from device (client) core via cmd53. * fn: function number @@ -187,20 +213,22 @@ extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev); * NOTE: Async operation is not currently supported. */ extern int -brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt); +brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn, + uint flags, u8 *buf, uint nbytes, void *pkt, + void (*complete)(void *handle, int status, + bool sync_waiting), + void *handle); extern int -brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt); +brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn, + uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt, + void (*complete)(void *handle, int status, + bool sync_waiting), + void *handle); /* Flags bits */ - -/* Four-byte target (backplane) width (vs. two-byte) */ -#define SDIO_REQ_4BYTE 0x1 -/* Fixed address (FIFO) (vs. incrementing address) */ -#define SDIO_REQ_FIXED 0x2 -/* Async request (vs. sync request) */ -#define SDIO_REQ_ASYNC 0x4 +#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */ +#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */ +#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */ /* Pending (non-error) return code */ #define BCME_PENDING 1 @@ -212,64 +240,108 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, * nbytes: number of bytes to transfer to/from buf * Returns 0 or error code. */ -extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, - u32 addr, u8 *buf, uint nbytes); +extern int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr, + u8 *buf, uint nbytes); /* Issue an abort to the specified function */ -extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); +extern int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn); + +/* Returns the "Device ID" of target device on the SDIO bus. */ +extern int brcmf_sdcard_query_device(struct brcmf_sdio_card *card); /* Miscellaneous knob tweaker. */ -extern int brcmf_sdcard_iovar_op(struct brcmf_sdio_dev *sdiodev, - const char *name, void *params, int plen, - void *arg, int len, bool set); +extern int brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name, + void *params, int plen, void *arg, int len, + bool set); + +/* helper functions */ + +/* callback functions */ +struct brcmf_sdioh_driver { + /* attach to device */ + void *(*attach) (u16 vend_id, u16 dev_id, u16 bus, u16 slot, + u16 func, uint bustype, u32 regsva, void *param); + /* detach from device */ + void (*detach) (void *ch); +}; + +struct sdioh_info; /* platform specific/high level functions */ extern int brcmf_sdio_function_init(void); -extern int brcmf_sdio_register(void); +extern int brcmf_sdio_register(struct brcmf_sdioh_driver *driver); extern void brcmf_sdio_unregister(void); extern void brcmf_sdio_function_cleanup(void); -extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); -extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev); +extern int brcmf_sdio_probe(struct device *dev); +extern int brcmf_sdio_remove(struct device *dev); /* Function to return current window addr */ -extern u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_dev *sdiodev); +extern u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card); + +/* Allocate/init/free per-OS private data */ +extern int brcmf_sdioh_osinit(struct sdioh_info *sd); +extern void brcmf_sdioh_osfree(struct sdioh_info *sd); + +/* Core interrupt enable/disable of device interrupts */ +extern void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd); +extern void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd); /* attach, return handler on success, NULL if failed. * The handler shall be provided by all subsequent calls. No local cache * cfghdl points to the starting address of pci device mapped memory */ -extern int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev); -extern void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev); +extern struct sdioh_info *brcmf_sdioh_attach(void *cfghdl, uint irq); +extern int brcmf_sdioh_detach(struct sdioh_info *si); + +extern int +brcmf_sdioh_interrupt_register(struct sdioh_info *si, + void (*sdioh_cb_fn)(void *), void *argh); + +extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *si); + +/* enable or disable SD interrupt */ +extern int +brcmf_sdioh_interrupt_set(struct sdioh_info *si, bool enable_disable); /* read or write one byte using cmd52 */ -extern int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, - uint fnc, uint addr, u8 *byte); +extern int +brcmf_sdioh_request_byte(struct sdioh_info *si, uint rw, uint fnc, uint addr, + u8 *byte); /* read or write 2/4 bytes using cmd53 */ extern int -brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, uint cmd_type, +brcmf_sdioh_request_word(struct sdioh_info *si, uint cmd_type, uint rw, uint fnc, uint addr, u32 *word, uint nbyte); /* read or write any buffer using cmd53 */ extern int -brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, uint pio_dma, +brcmf_sdioh_request_buffer(struct sdioh_info *si, uint pio_dma, uint fix_inc, uint rw, uint fnc_num, u32 addr, uint regwidth, u32 buflen, u8 *buffer, struct sk_buff *pkt); /* get cis data */ -extern int brcmf_sdioh_cis_read(struct brcmf_sdio_dev *sdiodev, uint fuc, - u8 *cis, u32 length); +extern int +brcmf_sdioh_cis_read(struct sdioh_info *si, uint fuc, u8 *cis, u32 length); + +extern int +brcmf_sdioh_cfg_read(struct sdioh_info *si, uint fuc, u32 addr, u8 *data); +extern int +brcmf_sdioh_cfg_write(struct sdioh_info *si, uint fuc, u32 addr, u8 *data); + +/* handle iovars */ +extern int brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name, + void *params, int plen, void *arg, int len, bool set); + +/* Issue abort to the specified function and clear controller as needed */ +extern int brcmf_sdioh_abort(struct sdioh_info *si, uint fnc); /* Watchdog timer interface for pm ops */ -extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, - bool enable); +extern void brcmf_sdio_wdtmr_enable(bool enable); + +extern uint sd_msglevel; /* Debug message level */ -extern uint sd_f2_blocksize; +extern struct brcmf_sdmmc_instance *gInstance; -extern void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, - u32 regsva, struct brcmf_sdio_dev *sdiodev); -extern void brcmf_sdbrcm_disconnect(void *ptr); -extern void brcmf_sdbrcm_isr(void *arg); #endif /* _BRCM_SDH_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c index 80bb30a8a762..821206d3e536 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -117,7 +118,7 @@ static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el); static struct brcmf_cfg80211_event_q * brcmf_deq_event(struct brcmf_cfg80211_priv *cfg_priv); static s32 brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 type, - const struct brcmf_event_msg *msg); + const struct brcmf_event_msg *msg, void *data); static void brcmf_put_event(struct brcmf_cfg80211_event_q *e); static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv); static s32 brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, @@ -134,11 +135,11 @@ static s32 brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv, void *data); static s32 brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, - const struct brcmf_event_msg *e, + const struct brcmf_event_msg *e, void *data, bool completed); static s32 brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, - const struct brcmf_event_msg *e); + const struct brcmf_event_msg *e, void *data); static s32 brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e, void *data); @@ -676,12 +677,12 @@ brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, err = brcmf_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size, iscan->ioctl_buf, BRCMF_C_IOCTL_SMLEN); if (unlikely(err)) { - if (err == -EBUSY) + if (err == -EBUSY) { WL_INFO("system busy : iscan canceled\n"); - else + } else { WL_ERR("error (%d)\n", err); + } } - kfree(params); return err; } @@ -708,14 +709,10 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv) } brcmf_set_mpc(ndev, 0); cfg_priv->iscan_kickstart = true; - err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START); - if (err) { - brcmf_set_mpc(ndev, 1); - cfg_priv->iscan_kickstart = false; - return err; - } + brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START); mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); iscan->timer_on = 1; + return err; } @@ -793,12 +790,12 @@ __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN, &sr->ssid, sizeof(sr->ssid)); if (err) { - if (err == -EBUSY) - WL_INFO("system busy : scan for \"%s\" " - "canceled\n", sr->ssid.SSID); - else + if (err == -EBUSY) { + WL_INFO("system busy : scan for \"%s\" canceled\n", + sr->ssid.SSID); + } else { WL_ERR("WLC_SCAN error (%d)\n", err); - + } brcmf_set_mpc(ndev, 1); goto scan_out; } @@ -1052,7 +1049,6 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, } else { memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN); } - brcmf_update_prof(cfg_priv, NULL, &join_params.params.bssid, WL_PROF_BSSID); @@ -1097,8 +1093,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, return err; } -static s32 -brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); s32 err = 0; @@ -1113,8 +1108,8 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) return err; } -static s32 brcmf_set_wpa_version(struct net_device *dev, - struct cfg80211_connect_params *sme) +static s32 +brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev); struct brcmf_cfg80211_security *sec; @@ -1178,8 +1173,7 @@ brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) } static s32 -brcmf_set_set_cipher(struct net_device *dev, - struct cfg80211_connect_params *sme) +brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev); struct brcmf_cfg80211_security *sec; @@ -1426,20 +1420,28 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, goto done; } + brcmf_update_prof(cfg_priv, NULL, sme->bssid, WL_PROF_BSSID); + /* + ** Join with specific BSSID and cached SSID + ** If SSID is zero join based on BSSID only + */ memset(&join_params, 0, sizeof(join_params)); join_params_size = sizeof(join_params.ssid); - join_params.ssid.SSID_len = - min(sizeof(join_params.ssid.SSID), sme->ssid_len); + join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len); memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len); join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len); brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID); - memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN); + if (sme->bssid) + memcpy(join_params.params.bssid, sme->bssid, ETH_ALEN); + else + memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN); - if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) + if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { WL_CONN("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, join_params.ssid.SSID_len); + } brcmf_ch_to_chanspec(cfg_priv->channel, &join_params, &join_params_size); @@ -1517,8 +1519,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, /* Make sure radio is off or on as far as software is concerned */ disable = WL_RADIO_SW_DISABLE << 16; disable = cpu_to_le32(disable); - err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_RADIO, &disable, - sizeof(disable)); + err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_RADIO, &disable, sizeof(disable)); if (unlikely(err)) WL_ERR("WLC_SET_RADIO error (%d)\n", err); @@ -1953,9 +1954,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, scb_val.val = 0; err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RSSI, &scb_val, sizeof(struct brcmf_scb_val)); - if (unlikely(err)) + if (unlikely(err)) { WL_ERR("Could not get rssi (%d)\n", err); - + } rssi = le32_to_cpu(scb_val.val); sinfo->filled |= STATION_INFO_SIGNAL; sinfo->signal = rssi; @@ -1973,24 +1974,9 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, { s32 pm; s32 err = 0; - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); WL_TRACE("Enter\n"); - - /* - * Powersave enable/disable request is coming from the - * cfg80211 even before the interface is up. In that - * scenario, driver will be storing the power save - * preference in cfg_priv struct to apply this to - * FW later while initializing the dongle - */ - cfg_priv->pwr_save = enabled; - if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { - - WL_INFO("Device is not ready," - "storing the value in cfg_priv struct\n"); - goto done; - } + CHECK_SYS_UP(); pm = enabled ? PM_FAST : PM_OFF; pm = cpu_to_le32(pm); @@ -2003,7 +1989,6 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, else WL_ERR("error (%d)\n", err); } -done: WL_TRACE("Exit\n"); return err; } @@ -2040,7 +2025,7 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, const u8 *addr, const struct cfg80211_bitrate_mask *mask) { - struct brcm_rateset rateset; + struct wl_rateset rateset; s32 rate; s32 val; s32 err_bg; @@ -2064,8 +2049,7 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy); if (!legacy) - legacy = brcmf_find_msb( - mask->control[IEEE80211_BAND_5GHZ].legacy); + legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy); val = wl_g_rates[legacy - 1].bitrate * 100000; @@ -2106,6 +2090,10 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) */ WL_TRACE("Enter\n"); +#if defined(CONFIG_PM_SLEEP) + atomic_set(&brcmf_mmc_suspend, false); +#endif /* defined(CONFIG_PM_SLEEP) */ + if (test_bit(WL_STATUS_READY, &cfg_priv->status)) brcmf_invoke_iscan(wiphy_to_cfg(wiphy)); @@ -2167,6 +2155,10 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, brcmf_set_mpc(ndev, 1); } +#if defined(CONFIG_PM_SLEEP) + atomic_set(&brcmf_mmc_suspend, true); +#endif /* defined(CONFIG_PM_SLEEP) */ + WL_TRACE("Exit\n"); return 0; @@ -2198,7 +2190,7 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_pmksa *pmksa) { struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids; + struct _pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids; s32 err = 0; int i; @@ -2232,7 +2224,7 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_pmksa *pmksa) { struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - struct pmkid_list pmkid; + struct _pmkid_list pmkid; s32 err = 0; int i; @@ -2255,7 +2247,7 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, if ((cfg_priv->pmk_list->pmkids.npmkid > 0) && (i < cfg_priv->pmk_list->pmkids.npmkid)) { memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0, - sizeof(struct pmkid)); + sizeof(pmkid_t)); for (; i < (cfg_priv->pmk_list->pmkids.npmkid - 1); i++) { memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID, @@ -2631,7 +2623,7 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); } else - brcmf_bss_connect_done(cfg_priv, ndev, e, true); + brcmf_bss_connect_done(cfg_priv, ndev, e, data, true); } else if (brcmf_is_linkdown(cfg_priv, e)) { WL_CONN("Linkdown\n"); if (brcmf_is_ibssmode(cfg_priv)) { @@ -2640,7 +2632,7 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, &cfg_priv->status)) brcmf_link_down(cfg_priv); } else { - brcmf_bss_connect_done(cfg_priv, ndev, e, false); + brcmf_bss_connect_done(cfg_priv, ndev, e, data, false); if (test_and_clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { cfg80211_disconnected(ndev, 0, NULL, 0, @@ -2653,7 +2645,7 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, if (brcmf_is_ibssmode(cfg_priv)) clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); else - brcmf_bss_connect_done(cfg_priv, ndev, e, false); + brcmf_bss_connect_done(cfg_priv, ndev, e, data, false); } return err; @@ -2670,9 +2662,9 @@ brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv, if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) - brcmf_bss_roaming_done(cfg_priv, ndev, e); + brcmf_bss_roaming_done(cfg_priv, ndev, e, data); else - brcmf_bss_connect_done(cfg_priv, ndev, e, true); + brcmf_bss_connect_done(cfg_priv, ndev, e, data, true); } return err; @@ -2788,7 +2780,7 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, size_t *join_params_size) { - u16 chanspec = 0; + chanspec_t chanspec = 0; if (ch != 0) { join_params->params.chanspec_num = 1; @@ -2803,7 +2795,7 @@ static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, chanspec |= WL_CHANSPEC_CTL_SB_NONE; *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE + - join_params->params.chanspec_num * sizeof(u16); + join_params->params.chanspec_num * sizeof(chanspec_t); join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK; join_params->params.chanspec_list[0] |= chanspec; @@ -2883,14 +2875,9 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) static s32 brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, - const struct brcmf_event_msg *e) + const struct brcmf_event_msg *e, void *data) { struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); - struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); - struct brcmf_channel_info channel; - struct ieee80211_channel *notify_channel; - struct ieee80211_supported_band *band; - u32 freq; s32 err = 0; WL_TRACE("Enter\n"); @@ -2899,21 +2886,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID); brcmf_update_bss_info(cfg_priv); - brcmf_dev_ioctl(ndev, BRCMF_C_GET_CHANNEL, &channel, sizeof(channel)); - - channel.target_channel = le32_to_cpu(channel.target_channel); - WL_CONN("Roamed to channel %d\n", channel.target_channel); - - if (channel.target_channel <= CH_MAX_2G_CHANNEL) - band = wiphy->bands[IEEE80211_BAND_2GHZ]; - else - band = wiphy->bands[IEEE80211_BAND_5GHZ]; - - freq = ieee80211_channel_to_frequency(channel.target_channel, - band->band); - notify_channel = ieee80211_get_channel(wiphy, freq); - - cfg80211_roamed(ndev, notify_channel, + cfg80211_roamed(ndev, NULL, (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID), conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); @@ -2927,7 +2900,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, static s32 brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, const struct brcmf_event_msg *e, - bool completed) + void *data, bool completed) { struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); s32 err = 0; @@ -3161,7 +3134,7 @@ static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) static s32 brcmf_create_event_handler(struct brcmf_cfg80211_priv *cfg_priv) { - init_waitqueue_head(&cfg_priv->event_waitq); + sema_init(&cfg_priv->event_sync, 0); cfg_priv->event_tsk = kthread_run(brcmf_event_handler, cfg_priv, "wl_event_handler"); if (IS_ERR(cfg_priv->event_tsk)) { @@ -3184,24 +3157,12 @@ static void brcmf_destroy_event_handler(struct brcmf_cfg80211_priv *cfg_priv) static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv) { struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); - struct brcmf_ssid ssid; if (cfg_priv->iscan_on && iscan->tsk) { iscan->state = WL_ISCAN_STATE_IDLE; send_sig(SIGTERM, iscan->tsk, 1); - - /* - * The iscan task may want to acquire the rtnl_lock - * so release it here upon stopping the task. - */ - rtnl_unlock(); kthread_stop(iscan->tsk); - rtnl_lock(); iscan->tsk = NULL; - - /* Abort iscan running in FW */ - memset(&ssid, 0, sizeof(ssid)); - brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT); } } @@ -3230,7 +3191,7 @@ static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan) { if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) { WL_SCAN("wake up iscan\n"); - wake_up(&iscan->waitq); + up(&iscan->sync); return 0; } @@ -3268,7 +3229,6 @@ brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, WL_SCAN("results->count = %d\n", results->count); WL_SCAN("results->buflen = %d\n", results->buflen); *status = le32_to_cpu(list_buf->status); - WL_SCAN("status = %d\n", *status); *bss_list = results; return err; @@ -3336,19 +3296,13 @@ static s32 brcmf_iscan_thread(void *data) (struct brcmf_cfg80211_iscan_ctrl *)data; struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); struct brcmf_cfg80211_iscan_eloop *el = &iscan->el; - DECLARE_WAITQUEUE(wait, current); u32 status; int err = 0; sched_setscheduler(current, SCHED_FIFO, ¶m); allow_signal(SIGTERM); status = BRCMF_SCAN_RESULTS_PARTIAL; - add_wait_queue(&iscan->waitq, &wait); - while (1) { - prepare_to_wait(&iscan->waitq, &wait, TASK_INTERRUPTIBLE); - - schedule(); - + while (likely(!down_interruptible(&iscan->sync))) { if (kthread_should_stop()) break; if (iscan->timer_on) { @@ -3365,7 +3319,6 @@ static s32 brcmf_iscan_thread(void *data) rtnl_unlock(); el->handler[status](cfg_priv); } - finish_wait(&iscan->waitq, &wait); if (iscan->timer_on) { del_timer_sync(&iscan->timer); iscan->timer_on = 0; @@ -3390,10 +3343,11 @@ static void brcmf_iscan_timer(unsigned long data) static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv) { struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); + int err = 0; if (cfg_priv->iscan_on && !iscan->tsk) { iscan->state = WL_ISCAN_STATE_IDLE; - init_waitqueue_head(&iscan->waitq); + sema_init(&iscan->sync, 0); iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan"); if (IS_ERR(iscan->tsk)) { WL_ERR("Could not create iscan thread\n"); @@ -3402,7 +3356,7 @@ static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv) } } - return 0; + return err; } static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el) @@ -3422,14 +3376,20 @@ static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv) if (cfg_priv->iscan_on) { iscan->dev = cfg_to_ndev(cfg_priv); + iscan->state = WL_ISCAN_STATE_IDLE; brcmf_init_iscan_eloop(&iscan->el); iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS; init_timer(&iscan->timer); iscan->timer.data = (unsigned long) iscan; iscan->timer.function = brcmf_iscan_timer; - err = brcmf_invoke_iscan(cfg_priv); - if (!err) - iscan->data = cfg_priv; + sema_init(&iscan->sync, 0); + iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan"); + if (IS_ERR(iscan->tsk)) { + WL_ERR("Could not create iscan thread\n"); + iscan->tsk = NULL; + return -ENOMEM; + } + iscan->data = cfg_priv; } return err; @@ -3437,15 +3397,14 @@ static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv) static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv) { + struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); s32 err = 0; cfg_priv->scan_request = NULL; -#ifndef WL_POWERSAVE_DISABLED - cfg_priv->pwr_save = true; -#endif /* WL_POWERSAVE_DISABLED */ + cfg_priv->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT); cfg_priv->iscan_on = true; /* iscan on & off switch. we enable iscan per default */ - cfg_priv->roam_on = true; /* roam on & off switch. + cfg_priv->roam_on = false; /* roam on & off switch. we enable roam per default */ cfg_priv->iscan_kickstart = false; @@ -3541,7 +3500,7 @@ void brcmf_cfg80211_detach(void) static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv) { - wake_up(&cfg_priv->event_waitq); + up(&cfg_priv->event_sync); } static s32 brcmf_event_handler(void *data) @@ -3550,39 +3509,27 @@ static s32 brcmf_event_handler(void *data) (struct brcmf_cfg80211_priv *)data; struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 }; struct brcmf_cfg80211_event_q *e; - DECLARE_WAITQUEUE(wait, current); sched_setscheduler(current, SCHED_FIFO, ¶m); allow_signal(SIGTERM); - add_wait_queue(&cfg_priv->event_waitq, &wait); - while (1) { - prepare_to_wait(&cfg_priv->event_waitq, &wait, - TASK_INTERRUPTIBLE); - - schedule(); - + while (likely(!down_interruptible(&cfg_priv->event_sync))) { if (kthread_should_stop()) break; - e = brcmf_deq_event(cfg_priv); if (unlikely(!e)) { WL_ERR("event queue empty...\n"); - continue; + BUG(); } - - do { - WL_INFO("event type (%d)\n", e->etype); - if (cfg_priv->el.handler[e->etype]) - cfg_priv->el.handler[e->etype](cfg_priv, - cfg_to_ndev(cfg_priv), - &e->emsg, e->edata); - else - WL_INFO("Unknown Event (%d): ignoring\n", - e->etype); - brcmf_put_event(e); - } while ((e = brcmf_deq_event(cfg_priv))); - } - finish_wait(&cfg_priv->event_waitq, &wait); + WL_INFO("event type (%d)\n", e->etype); + if (cfg_priv->el.handler[e->etype]) { + cfg_priv->el.handler[e->etype](cfg_priv, + cfg_to_ndev(cfg_priv), + &e->emsg, e->edata); + } else { + WL_INFO("Unknown Event (%d): ignoring\n", e->etype); + } + brcmf_put_event(e); + } WL_INFO("was terminated\n"); return 0; } @@ -3594,7 +3541,7 @@ brcmf_cfg80211_event(struct net_device *ndev, u32 event_type = be32_to_cpu(e->event_type); struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); - if (likely(!brcmf_enq_event(cfg_priv, event_type, e))) + if (likely(!brcmf_enq_event(cfg_priv, event_type, e, data))) brcmf_wakeup_event(cfg_priv); } @@ -3644,7 +3591,7 @@ static struct brcmf_cfg80211_event_q *brcmf_deq_event( static s32 brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, - const struct brcmf_event_msg *msg) + const struct brcmf_event_msg *msg, void *data) { struct brcmf_cfg80211_event_q *e; s32 err = 0; @@ -3871,7 +3818,6 @@ s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv, bool need_lock) { struct net_device *ndev; struct wireless_dev *wdev; - s32 power_mode; s32 err = 0; if (cfg_priv->dongle_up) @@ -3888,16 +3834,6 @@ s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv, bool need_lock) err = brcmf_dongle_eventmsg(ndev); if (unlikely(err)) goto default_conf_out; - - power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF; - power_mode = cpu_to_le32(power_mode); - err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_PM, - &power_mode, sizeof(power_mode)); - if (err) - goto default_conf_out; - WL_INFO("power save set to %s\n", - (power_mode ? "enabled" : "disabled")); - err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1), WL_BEACON_TIMEOUT); if (unlikely(err)) diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h b/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h index 0542bac2d79e..f26d08793ca8 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h +++ b/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h @@ -249,7 +249,7 @@ struct brcmf_cfg80211_iscan_ctrl { u32 timer_on; s32 state; struct task_struct *tsk; - wait_queue_head_t waitq; + struct semaphore sync; struct brcmf_cfg80211_iscan_eloop el; void *data; s8 ioctl_buf[BRCMF_C_IOCTL_SMLEN]; @@ -272,8 +272,8 @@ struct brcmf_cfg80211_assoc_ielen { /* wpa2 pmk list */ struct brcmf_cfg80211_pmk_list { - struct pmkid_list pmkids; - struct pmkid foo[MAXPMKID - 1]; + pmkid_list_t pmkids; + pmkid_t foo[MAXPMKID - 1]; }; /* dongle private data of cfg80211 interface */ @@ -295,12 +295,13 @@ struct brcmf_cfg80211_priv { cfg80211 layer */ struct brcmf_cfg80211_ie ie; /* information element object for internal purpose */ + struct semaphore event_sync; /* for synchronization of main event + thread */ struct brcmf_cfg80211_profile *profile; /* holding dongle profile */ struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */ struct brcmf_cfg80211_connect_info conn_info; /* association info */ struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */ struct task_struct *event_tsk; /* task of main event handler thread */ - wait_queue_head_t event_waitq; /* wait queue for main event handling */ unsigned long status; /* current dongle status */ void *pub; u32 channel; /* current channel */ @@ -317,7 +318,7 @@ struct brcmf_cfg80211_priv { u8 *ioctl_buf; /* ioctl buffer */ u8 *extra_buf; /* maily to grab assoc information */ struct dentry *debugfsdir; - u8 ci[0] __aligned(NETDEV_ALIGN); + u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN))); }; #define cfg_to_wiphy(w) (w->wdev->wiphy) @@ -340,8 +341,7 @@ static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list, } #define for_each_bss(list, bss, __i) \ - for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, \ - bss = next_bss(list, bss)) + for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss)) extern s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data); extern void brcmf_cfg80211_detach(void); diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/Makefile b/trunk/drivers/staging/brcm80211/brcmsmac/Makefile index 3147c487188f..1ea3e0c48f3e 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/Makefile +++ b/trunk/drivers/staging/brcm80211/brcmsmac/Makefile @@ -33,6 +33,7 @@ BRCMSMAC_OFILES := \ alloc.o \ ampdu.o \ antsel.o \ + bmac.o \ channel.o \ main.o \ phy_shim.o \ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/aiutils.c b/trunk/drivers/staging/brcm80211/brcmsmac/aiutils.c index c9c41a5327b4..a25901e9981b 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/aiutils.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/aiutils.c @@ -12,10 +12,7 @@ * 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. - * - * File contents: support functions for PCI/PCIe */ - #include #include @@ -31,68 +28,48 @@ #include "aiutils.h" /* slow_clk_ctl */ - /* slow clock source mask */ -#define SCC_SS_MASK 0x00000007 - /* source of slow clock is LPO */ -#define SCC_SS_LPO 0x00000000 - /* source of slow clock is crystal */ -#define SCC_SS_XTAL 0x00000001 - /* source of slow clock is PCI */ -#define SCC_SS_PCI 0x00000002 - /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ -#define SCC_LF 0x00000200 - /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */ -#define SCC_LP 0x00000400 - /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */ -#define SCC_FS 0x00000800 - /* IgnorePllOffReq, 1/0: - * power logic ignores/honors PLL clock disable requests from core - */ -#define SCC_IP 0x00001000 - /* XtalControlEn, 1/0: - * power logic does/doesn't disable crystal when appropriate - */ -#define SCC_XC 0x00002000 - /* XtalPU (RO), 1/0: crystal running/disabled */ -#define SCC_XP 0x00004000 - /* ClockDivider (SlowClk = 1/(4+divisor)) */ -#define SCC_CD_MASK 0xffff0000 +#define SCC_SS_MASK 0x00000007 /* slow clock source mask */ +#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */ +#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */ +#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */ +#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ +#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled, + * 0: LPO is enabled + */ +#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, + * 0: power logic control + */ +#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors + * PLL clock disable requests from core + */ +#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't + * disable crystal when appropriate + */ +#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ +#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ #define SCC_CD_SHIFT 16 /* system_clk_ctl */ - /* ILPen: Enable Idle Low Power */ -#define SYCC_IE 0x00000001 - /* ALPen: Enable Active Low Power */ -#define SYCC_AE 0x00000002 - /* ForcePLLOn */ -#define SYCC_FP 0x00000004 - /* Force ALP (or HT if ALPen is not set */ -#define SYCC_AR 0x00000008 - /* Force HT */ -#define SYCC_HR 0x00000010 - /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ -#define SYCC_CD_MASK 0xffff0000 +#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */ +#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */ +#define SYCC_FP 0x00000004 /* ForcePLLOn */ +#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */ +#define SYCC_HR 0x00000010 /* Force HT */ +#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ #define SYCC_CD_SHIFT 16 #define CST4329_SPROM_OTP_SEL_MASK 0x00000003 - /* OTP is powered up, use def. CIS, no SPROM */ -#define CST4329_DEFCIS_SEL 0 - /* OTP is powered up, SPROM is present */ -#define CST4329_SPROM_SEL 1 - /* OTP is powered up, no SPROM */ -#define CST4329_OTP_SEL 2 - /* OTP is powered down, SPROM is present */ -#define CST4329_OTP_PWRDN 3 - +#define CST4329_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ +#define CST4329_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ +#define CST4329_OTP_SEL 2 /* OTP is powered up, no SPROM */ +#define CST4329_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ #define CST4329_SPI_SDIO_MODE_MASK 0x00000004 #define CST4329_SPI_SDIO_MODE_SHIFT 2 /* 43224 chip-specific ChipControl register bits */ #define CCTRL43224_GPIO_TOGGLE 0x8000 - /* 12 mA drive strength */ -#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 - /* 12 mA drive strength for later 43224s */ -#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 +#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */ +#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */ /* 43236 Chip specific ChipStatus register bits */ #define CST43236_SFLASH_MASK 0x00000040 @@ -101,44 +78,29 @@ #define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ #define CST43236_BOOT_MASK 0x00001800 #define CST43236_BOOT_SHIFT 11 -#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ -#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ -#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ +#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ +#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ +#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ #define CST43236_BOOT_FROM_INVALID 3 /* 4331 chip-specific ChipControl register bits */ - /* 0 disable */ -#define CCTRL4331_BT_COEXIST (1<<0) - /* 0 SECI is disabled (JTAG functional) */ -#define CCTRL4331_SECI (1<<1) - /* 0 disable */ -#define CCTRL4331_EXT_LNA (1<<2) - /* sprom/gpio13-15 mux */ -#define CCTRL4331_SPROM_GPIO13_15 (1<<3) - /* 0 ext pa disable, 1 ext pa enabled */ -#define CCTRL4331_EXTPA_EN (1<<4) - /* set drive out GPIO_CLK on sprom_cs pin */ -#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) - /* use sprom_cs pin as PCIE mdio interface */ -#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) - /* aband extpa will be at gpio2/5 and sprom_dout */ -#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) - /* override core control on pipe_AuxClkEnable */ -#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) - /* override core control on pipe_AuxPowerDown */ -#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) - /* pcie_auxclkenable */ -#define CCTRL4331_PCIE_AUXCLKEN (1<<10) - /* pcie_pipe_pllpowerdown */ -#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) - /* enable bt_shd0 at gpio4 */ -#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) - /* enable bt_shd1 at gpio5 */ -#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) +#define CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */ +#define CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ +#define CCTRL4331_EXT_LNA (1<<2) /* 0 disable */ +#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /* sprom/gpio13-15 mux */ +#define CCTRL4331_EXTPA_EN (1<<4) /* 0 ext pa disable, 1 ext pa enabled */ +#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /* set drive out GPIO_CLK on sprom_cs pin */ +#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /* use sprom_cs pin as PCIE mdio interface */ +#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */ +#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /* override core control on pipe_AuxClkEnable */ +#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */ +#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */ +#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */ +#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */ +#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */ /* 4331 Chip specific ChipStatus register bits */ - /* crystal frequency 20/40Mhz */ -#define CST4331_XTAL_FREQ 0x00000001 +#define CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */ #define CST4331_SPROM_PRESENT 0x00000002 #define CST4331_OTP_PRESENT 0x00000004 #define CST4331_LDO_RF 0x00000008 @@ -148,26 +110,19 @@ #define CST4319_SPI_CPULESSUSB 0x00000001 #define CST4319_SPI_CLK_POL 0x00000002 #define CST4319_SPI_CLK_PH 0x00000008 - /* gpio [7:6], SDIO CIS selection */ -#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 +#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /* gpio [7:6], SDIO CIS selection */ #define CST4319_SPROM_OTP_SEL_SHIFT 6 - /* use default CIS, OTP is powered up */ -#define CST4319_DEFCIS_SEL 0x00000000 - /* use SPROM, OTP is powered up */ -#define CST4319_SPROM_SEL 0x00000040 - /* use OTP, OTP is powered up */ -#define CST4319_OTP_SEL 0x00000080 - /* use SPROM, OTP is powered down */ -#define CST4319_OTP_PWRDN 0x000000c0 - /* gpio [8], sdio/usb mode */ -#define CST4319_SDIO_USB_MODE 0x00000100 +#define CST4319_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ +#define CST4319_SPROM_SEL 0x00000040 /* use SPROM, OTP is powered up */ +#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */ +#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */ +#define CST4319_SDIO_USB_MODE 0x00000100 /* gpio [8], sdio/usb mode */ #define CST4319_REMAP_SEL_MASK 0x00000600 #define CST4319_ILPDIV_EN 0x00000800 #define CST4319_XTAL_PD_POL 0x00001000 #define CST4319_LPO_SEL 0x00002000 #define CST4319_RES_INIT_MODE 0x0000c000 - /* PALDO is configured with external PNP */ -#define CST4319_PALDO_EXTPNP 0x00010000 +#define CST4319_PALDO_EXTPNP 0x00010000 /* PALDO is configured with external PNP */ #define CST4319_CBUCK_MODE_MASK 0x00060000 #define CST4319_CBUCK_MODE_BURST 0x00020000 #define CST4319_CBUCK_MODE_LPBURST 0x00060000 @@ -198,8 +153,7 @@ #define CST4313_SPROM_OTP_SEL_SHIFT 0 /* 4313 Chip specific ChipControl register bits */ - /* 12 mA drive strengh for later 4313 */ -#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 +#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ #define BCM47162_DMP() ((sih->chip == BCM47162_CHIP_ID) && \ (sih->chiprev == 0) && \ @@ -273,12 +227,9 @@ #define SD_SG32 0x00000008 #define SD_SZ_ALIGN 0x00000fff -/* PCI config space bit 4 for 4306c0 slow clock source */ -#define PCI_CFG_GPIO_SCS 0x10 -/* PCI config space GPIO 14 for Xtal power-up */ -#define PCI_CFG_GPIO_XTAL 0x40 -/* PCI config space GPIO 15 for PLL power-down */ -#define PCI_CFG_GPIO_PLL 0x80 +#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ +#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal power-up */ +#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL power-down */ /* power control defines */ #define PLL_DELAY 150 /* us pll on delay */ @@ -436,10 +387,10 @@ get_erom_ent(struct si_pub *sih, u32 **eromptr, u32 mask, u32 match) } SI_VMSG(("%s: Returning ent 0x%08x\n", __func__, ent)); - if (inv + nom) + if (inv + nom) { SI_VMSG((" after %d invalid and %d non-matching entries\n", inv, nom)); - + } return ent; } @@ -483,24 +434,41 @@ static void ai_hwfixup(struct si_info *sii) } /* parse the enumeration rom to identify all cores */ -void ai_scan(struct si_pub *sih, struct chipcregs *cc) +void ai_scan(struct si_pub *sih, void *regs) { struct si_info *sii = SI_INFO(sih); + chipcregs_t *cc = (chipcregs_t *) regs; u32 erombase, *eromptr, *eromlim; - void *regs = cc; erombase = R_REG(&cc->eromptr); - /* Set wrappers address */ - sii->curwrap = (void *)((unsigned long)cc + SI_CORE_SIZE); + switch (sih->bustype) { + case SI_BUS: + eromptr = (u32 *) REG_MAP(erombase, SI_CORE_SIZE); + break; + + case PCI_BUS: + /* Set wrappers address */ + sii->curwrap = (void *)((unsigned long)regs + SI_CORE_SIZE); + + /* Now point the window at the erom */ + pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase); + eromptr = regs; + break; + + case SPI_BUS: + case SDIO_BUS: + eromptr = (u32 *)(unsigned long)erombase; + break; - /* Now point the window at the erom */ - pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase); - eromptr = regs; + default: + SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", + sih->bustype)); + return; + } eromlim = eromptr + (ER_REMAPCONTROL / sizeof(u32)); - SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, " - "eromlim = 0x%p\n", regs, erombase, eromptr, eromlim)); + SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n", regs, erombase, eromptr, eromlim)); while (eromptr < eromlim) { u32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; u32 mpd, asd, addrl, addrh, sizel, sizeh; @@ -534,9 +502,7 @@ void ai_scan(struct si_pub *sih, struct chipcregs *cc) nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; - SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr " - "0x%p, with nmw = %d, nsw = %d, nmp = %d & nsp = %d\n", - mfg, cid, crev, base, nmw, nsw, nmp, nsp)); + SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, " "nsw = %d, nmp = %d & nsp = %d\n", mfg, cid, crev, base, nmw, nsw, nmp, nsp)); if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) continue; @@ -545,8 +511,9 @@ void ai_scan(struct si_pub *sih, struct chipcregs *cc) if (cid == OOB_ROUTER_CORE_ID) { asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); - if (asd != 0) + if (asd != 0) { sii->oob_router = addrl; + } } continue; } @@ -560,8 +527,7 @@ void ai_scan(struct si_pub *sih, struct chipcregs *cc) for (i = 0; i < nmp; i++) { mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); if ((mpd & ER_TAG) != ER_MP) { - SI_ERROR(("Not enough MP entries for " - "component 0x%x\n", cid)); + SI_ERROR(("Not enough MP entries for component 0x%x\n", cid)); goto error; } SI_VMSG((" Master port %d, mp: %d id: %d\n", i, @@ -584,8 +550,7 @@ void ai_scan(struct si_pub *sih, struct chipcregs *cc) br = true; else if ((addrh != 0) || (sizeh != 0) || (sizel != SI_CORE_SIZE)) { - SI_ERROR(("First Slave ASD for core 0x%04x " - "malformed (0x%08x)\n", cid, asd)); + SI_ERROR(("First Slave ASD for core 0x%04x malformed " "(0x%08x)\n", cid, asd)); goto error; } } @@ -669,29 +634,55 @@ void ai_scan(struct si_pub *sih, struct chipcregs *cc) return; } -/* - * This function changes the logical "focus" to the indicated core. - * Return the current core's virtual address. Since each core starts with the - * same set of registers (BIST, clock control, etc), the returned address - * contains the first register of this 'common' register block (not to be - * confused with 'common core'). +/* This function changes the logical "focus" to the indicated core. + * Return the current core's virtual address. */ void *ai_setcoreidx(struct si_pub *sih, uint coreidx) { struct si_info *sii = SI_INFO(sih); u32 addr = sii->coresba[coreidx]; u32 wrap = sii->wrapba[coreidx]; + void *regs; if (coreidx >= sii->numcores) return NULL; - /* point bar0 window */ - pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr); - /* point bar0 2nd 4KB window */ - pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap); + switch (sih->bustype) { + case SI_BUS: + /* map new one */ + if (!sii->regs[coreidx]) { + sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE); + } + sii->curmap = regs = sii->regs[coreidx]; + if (!sii->wrappers[coreidx]) { + sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE); + } + sii->curwrap = sii->wrappers[coreidx]; + break; + + case PCI_BUS: + /* point bar0 window */ + pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr); + regs = sii->curmap; + /* point bar0 2nd 4KB window */ + pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap); + break; + + case SPI_BUS: + case SDIO_BUS: + sii->curmap = regs = (void *)(unsigned long)addr; + sii->curwrap = (void *)(unsigned long)wrap; + break; + + default: + regs = NULL; + break; + } + + sii->curmap = regs; sii->curidx = coreidx; - return sii->curmap; + return regs; } /* Return the number of address spaces in current core */ @@ -714,8 +705,7 @@ u32 ai_addrspace(struct si_pub *sih, uint asidx) else if (asidx == 1) return sii->coresba2[cidx]; else { - SI_ERROR(("%s: Need to parse the erom again to find addr " - "space %d\n", __func__, asidx)); + SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", __func__, asidx)); return 0; } } @@ -734,8 +724,7 @@ u32 ai_addrspacesize(struct si_pub *sih, uint asidx) else if (asidx == 1) return sii->coresba2_size[cidx]; else { - SI_ERROR(("%s: Need to parse the erom again to find addr " - "space %d\n", __func__, asidx)); + SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", __func__, asidx)); return 0; } } @@ -747,8 +736,7 @@ uint ai_flag(struct si_pub *sih) sii = SI_INFO(sih); if (BCM47162_DMP()) { - SI_ERROR(("%s: Attempting to read MIPS DMP registers " - "on 47162a0", __func__)); + SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __func__)); return sii->curidx; } ai = sii->curwrap; @@ -846,8 +834,7 @@ u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val) sii = SI_INFO(sih); if (BCM47162_DMP()) { - SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) " - "on 47162a0", __func__)); + SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0", __func__)); return 0; } @@ -864,10 +851,11 @@ u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val) /* *************** from siutils.c ************** */ /* local prototypes */ static struct si_info *ai_doattach(struct si_info *sii, void *regs, - struct pci_dev *sdh, - char **vars, uint *varsz); -static bool ai_buscore_prep(struct si_info *sii); -static bool ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx); + uint bustype, void *sdh, char **vars, + uint *varsz); +static bool ai_buscore_prep(struct si_info *sii, uint bustype); +static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype, + u32 savewin, uint *origidx, void *regs); static void ai_nvram_process(struct si_info *sii, char *pvars); /* dev path concatenation util */ @@ -876,16 +864,20 @@ static char *ai_devpathvar(struct si_pub *sih, char *var, int len, static bool _ai_clkctl_cc(struct si_info *sii, uint mode); static bool ai_ispcie(struct si_info *sii); +/* global variable to indicate reservation/release of gpio's */ +static u32 ai_gpioreservation; + /* * Allocate a si handle. * devid - pci device id (used to determine chip#) * osh - opaque OS handle * regs - virtual address of initial core registers + * bustype - pci/sb/sdio/etc * vars - pointer to a pointer area for "environment" variables * varsz - pointer to int to return the size of the vars */ -struct si_pub * -ai_attach(void *regs, struct pci_dev *sdh, char **vars, uint *varsz) +struct si_pub *ai_attach(void *regs, uint bustype, + void *sdh, char **vars, uint *varsz) { struct si_info *sii; @@ -896,7 +888,8 @@ ai_attach(void *regs, struct pci_dev *sdh, char **vars, uint *varsz) return NULL; } - if (ai_doattach(sii, regs, sdh, vars, varsz) == NULL) { + if (ai_doattach(sii, regs, bustype, sdh, vars, varsz) == + NULL) { kfree(sii); return NULL; } @@ -909,21 +902,20 @@ ai_attach(void *regs, struct pci_dev *sdh, char **vars, uint *varsz) /* global kernel resource */ static struct si_info ksii; -static bool ai_buscore_prep(struct si_info *sii) +static bool ai_buscore_prep(struct si_info *sii, uint bustype) { /* kludge to enable the clock on the 4306 which lacks a slowclock */ - if (!ai_ispcie(sii)) + if (bustype == PCI_BUS && !ai_ispcie(sii)) ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON); return true; } -static bool -ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx) +static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype, + u32 savewin, uint *origidx, void *regs) { bool pci, pcie; uint i; uint pciidx, pcieidx, pcirev, pcierev; - struct chipcregs *cc; cc = ai_setcoreidx(&sii->pub, SI_CC_IDX); @@ -967,19 +959,21 @@ ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx) SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", i, cid, crev, sii->coresba[i], sii->regs[i])); - if (cid == PCI_CORE_ID) { - pciidx = i; - pcirev = crev; - pci = true; - } else if (cid == PCIE_CORE_ID) { - pcieidx = i; - pcierev = crev; - pcie = true; + if (bustype == PCI_BUS) { + if (cid == PCI_CORE_ID) { + pciidx = i; + pcirev = crev; + pci = true; + } else if (cid == PCIE_CORE_ID) { + pcieidx = i; + pcierev = crev; + pcie = true; + } } /* find the core idx before entering this func. */ if ((savewin && (savewin == sii->coresba[i])) || - (cc == sii->regs[i])) + (regs == sii->regs[i])) *origidx = i; } @@ -1003,17 +997,20 @@ ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx) sii->pub.buscoretype, sii->pub.buscorerev)); /* fixup necessary chip/core configurations */ - if (SI_FAST(sii)) { - if (!sii->pch) { - sii->pch = pcicore_init(&sii->pub, sii->pbus, - (void *)PCIEREGS(sii)); - if (sii->pch == NULL) - return false; + if (sii->pub.bustype == PCI_BUS) { + if (SI_FAST(sii)) { + if (!sii->pch) { + sii->pch = (void *)pcicore_init( + &sii->pub, sii->pbus, + (void *)PCIEREGS(sii)); + if (sii->pch == NULL) + return false; + } + } + if (ai_pci_fixcfg(&sii->pub)) { + SI_ERROR(("si_doattach: si_pci_fixcfg failed\n")); + return false; } - } - if (ai_pci_fixcfg(&sii->pub)) { - SI_ERROR(("si_doattach: si_pci_fixcfg failed\n")); - return false; } /* return to the original core */ @@ -1022,45 +1019,62 @@ ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx) return true; } -/* - * get boardtype and boardrev - */ static __used void ai_nvram_process(struct si_info *sii, char *pvars) { uint w = 0; - /* do a pci config read to get subsystem id and subvendor id */ - pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w); - /* Let nvram variables override subsystem Vend/ID */ - sii->pub.boardvendor = (u16)ai_getdevpathintvar(&sii->pub, - "boardvendor"); - if (sii->pub.boardvendor == 0) - sii->pub.boardvendor = w & 0xffff; - else - SI_ERROR(("Overriding boardvendor: 0x%x instead of " - "0x%x\n", sii->pub.boardvendor, w & 0xffff)); + /* get boardtype and boardrev */ + switch (sii->pub.bustype) { + case PCI_BUS: + /* do a pci config read to get subsystem id and subvendor id */ + pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w); + /* Let nvram variables override subsystem Vend/ID */ + sii->pub.boardvendor = (u16)ai_getdevpathintvar(&sii->pub, + "boardvendor"); + if (sii->pub.boardvendor == 0) + sii->pub.boardvendor = w & 0xffff; + else + SI_ERROR(("Overriding boardvendor: 0x%x instead of " + "0x%x\n", sii->pub.boardvendor, w & 0xffff)); + sii->pub.boardtype = (u16)ai_getdevpathintvar(&sii->pub, + "boardtype"); + if (sii->pub.boardtype == 0) + sii->pub.boardtype = (w >> 16) & 0xffff; + else + SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n" + , sii->pub.boardtype, (w >> 16) & 0xffff)); + break; - sii->pub.boardtype = (u16)ai_getdevpathintvar(&sii->pub, - "boardtype"); - if (sii->pub.boardtype == 0) - sii->pub.boardtype = (w >> 16) & 0xffff; - else - SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n" - , sii->pub.boardtype, (w >> 16) & 0xffff)); + sii->pub.boardvendor = getintvar(pvars, "manfid"); + sii->pub.boardtype = getintvar(pvars, "prodid"); + break; - if (sii->pub.boardtype == 0) + case SI_BUS: + case JTAG_BUS: + sii->pub.boardvendor = PCI_VENDOR_ID_BROADCOM; + sii->pub.boardtype = getintvar(pvars, "prodid"); + if (pvars == NULL || (sii->pub.boardtype == 0)) { + sii->pub.boardtype = getintvar(NULL, "boardtype"); + if (sii->pub.boardtype == 0) + sii->pub.boardtype = 0xffff; + } + break; + } + + if (sii->pub.boardtype == 0) { SI_ERROR(("si_doattach: unknown board type\n")); + } sii->pub.boardflags = getintvar(pvars, "boardflags"); } static struct si_info *ai_doattach(struct si_info *sii, - void *regs, struct pci_dev *pbus, - char **vars, uint *varsz) + void *regs, uint bustype, void *pbus, + char **vars, uint *varsz) { struct si_pub *sih = &sii->pub; u32 w, savewin; - struct chipcregs *cc; + chipcregs_t *cc; char *pvars = NULL; uint socitype; uint origidx; @@ -1074,18 +1088,35 @@ static struct si_info *ai_doattach(struct si_info *sii, sii->curmap = regs; sii->pbus = pbus; + /* check to see if we are a si core mimic'ing a pci core */ + if (bustype == PCI_BUS) { + pci_read_config_dword(sii->pbus, PCI_SPROM_CONTROL, &w); + if (w == 0xffffffff) { + SI_ERROR(("%s: incoming bus is PCI but it's a lie, " + " switching to SI devid:0x%x\n", + __func__, devid)); + bustype = SI_BUS; + } + } + /* find Chipcommon address */ - pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin); - if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) - savewin = SI_ENUM_BASE; + if (bustype == PCI_BUS) { + pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin); + if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) + savewin = SI_ENUM_BASE; + pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, + SI_ENUM_BASE); + cc = (chipcregs_t *) regs; + } else { + cc = (chipcregs_t *) REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); + } - pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, - SI_ENUM_BASE); - cc = (struct chipcregs *) regs; + sih->bustype = bustype; /* bus/core/clk setup for register access */ - if (!ai_buscore_prep(sii)) { - SI_ERROR(("si_doattach: si_core_clk_prep failed\n")); + if (!ai_buscore_prep(sii, bustype)) { + SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", + bustype)); return NULL; } @@ -1109,7 +1140,7 @@ static struct si_info *ai_doattach(struct si_info *sii, if (socitype == SOCI_AI) { SI_MSG(("Found chip type AI (0x%08x)\n", w)); /* pass chipc address instead of original core base */ - ai_scan(&sii->pub, cc); + ai_scan(&sii->pub, (void *)cc); } else { SI_ERROR(("Found chip of unknown type (0x%08x)\n", w)); return NULL; @@ -1121,13 +1152,14 @@ static struct si_info *ai_doattach(struct si_info *sii, } /* bus/core/clk setup */ origidx = SI_CC_IDX; - if (!ai_buscore_setup(sii, savewin, &origidx)) { + if (!ai_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { SI_ERROR(("si_doattach: si_buscore_setup failed\n")); goto exit; } /* Init nvram from sprom/otp if they exist */ - if (srom_var_init(&sii->pub, cc, vars, varsz)) { + if (srom_var_init + (&sii->pub, bustype, regs, vars, varsz)) { SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n")); goto exit; } @@ -1135,7 +1167,7 @@ static struct si_info *ai_doattach(struct si_info *sii, ai_nvram_process(sii, pvars); /* === NVRAM, clock is ready === */ - cc = (struct chipcregs *) ai_setcore(sih, CC_CORE_ID, 0); + cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0); W_REG(&cc->gpiopullup, 0); W_REG(&cc->gpiopulldown, 0); ai_setcoreidx(sih, origidx); @@ -1158,11 +1190,11 @@ static struct si_info *ai_doattach(struct si_info *sii, w = getintvar(pvars, "leddc"); if (w == 0) w = DEFAULT_GPIOTIMERVAL; - ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, gpiotimerval), - ~0, w); + ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, gpiotimerval), ~0, w); - if (PCIE(sii)) + if (PCIE(sii)) { pcicore_attach(sii->pch, pvars, SI_DOATTACH); + } if (sih->chip == BCM43224_CHIP_ID) { /* @@ -1172,7 +1204,7 @@ static struct si_info *ai_doattach(struct si_info *sii, if (sih->chiprev == 0) { SI_MSG(("Applying 43224A0 WARs\n")); ai_corereg(sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol), + offsetof(chipcregs_t, chipcontrol), CCTRL43224_GPIO_TOGGLE, CCTRL43224_GPIO_TOGGLE); si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE, @@ -1196,11 +1228,12 @@ static struct si_info *ai_doattach(struct si_info *sii, } return sii; - exit: - if (sii->pch) - pcicore_deinit(sii->pch); - sii->pch = NULL; + if (sih->bustype == PCI_BUS) { + if (sii->pch) + pcicore_deinit(sii->pch); + sii->pch = NULL; + } return NULL; } @@ -1209,6 +1242,7 @@ static struct si_info *ai_doattach(struct si_info *sii, void ai_detach(struct si_pub *sih) { struct si_info *sii; + uint idx; struct si_pub *si_local = NULL; memcpy(&si_local, &sih, sizeof(struct si_pub **)); @@ -1218,9 +1252,18 @@ void ai_detach(struct si_pub *sih) if (sii == NULL) return; - if (sii->pch) - pcicore_deinit(sii->pch); - sii->pch = NULL; + if (sih->bustype == SI_BUS) + for (idx = 0; idx < SI_MAXCORES; idx++) + if (sii->regs[idx]) { + iounmap(sii->regs[idx]); + sii->regs[idx] = NULL; + } + + if (sih->bustype == PCI_BUS) { + if (sii->pch) + pcicore_deinit(sii->pch); + sii->pch = NULL; + } if (sii != &ksii) kfree(sii); @@ -1236,9 +1279,9 @@ ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn, sii = SI_INFO(sih); sii->intr_arg = intr_arg; - sii->intrsoff_fn = (u32 (*)(void *)) intrsoff_fn; - sii->intrsrestore_fn = (void (*) (void *, u32)) intrsrestore_fn; - sii->intrsenabled_fn = (bool (*)(void *)) intrsenabled_fn; + sii->intrsoff_fn = (si_intrsoff_t) intrsoff_fn; + sii->intrsrestore_fn = (si_intrsrestore_t) intrsrestore_fn; + sii->intrsenabled_fn = (si_intrsenabled_t) intrsenabled_fn; /* save current core id. when this function called, the current core * must be the core which provides driver functions(il, et, wl, etc.) */ @@ -1328,9 +1371,9 @@ void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx, */ *origidx = coreid; if (coreid == CC_CORE_ID) - return CCREGS_FAST(sii); + return (void *)CCREGS_FAST(sii); else if (coreid == sih->buscoretype) - return PCIEREGS(sii); + return (void *)PCIEREGS(sii); } INTR_OFF(sii, *intr_val); *origidx = sii->curidx; @@ -1385,29 +1428,43 @@ uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, if (coreidx >= SI_MAXCORES) return 0; - /* - * If pci/pcie, we can get at pci/pcie regs - * and on newer cores to chipc - */ - if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { - /* Chipc registers are mapped at 12KB */ + if (sih->bustype == SI_BUS) { + /* If internal bus, we can always get at everything */ fast = true; - r = (u32 *)((char *)sii->curmap + - PCI_16KB0_CCREGS_OFFSET + regoff); - } else if (sii->pub.buscoreidx == coreidx) { + /* map if does not exist */ + if (!sii->regs[coreidx]) { + sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx], + SI_CORE_SIZE); + } + r = (u32 *) ((unsigned char *) sii->regs[coreidx] + regoff); + } else if (sih->bustype == PCI_BUS) { /* - * pci registers are at either in the last 2KB of - * an 8KB window or, in pcie and pci rev 13 at 8KB + * If pci/pcie, we can get at pci/pcie regs + * and on newer cores to chipc */ - fast = true; - if (SI_FAST(sii)) - r = (u32 *)((char *)sii->curmap + - PCI_16KB0_PCIREGS_OFFSET + regoff); - else - r = (u32 *)((char *)sii->curmap + - ((regoff >= SBCONFIGOFF) ? - PCI_BAR0_PCISBR_OFFSET : - PCI_BAR0_PCIREGS_OFFSET) + regoff); + if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { + /* Chipc registers are mapped at 12KB */ + + fast = true; + r = (u32 *) ((char *)sii->curmap + + PCI_16KB0_CCREGS_OFFSET + regoff); + } else if (sii->pub.buscoreidx == coreidx) { + /* + * pci registers are at either in the last 2KB of + * an 8KB window or, in pcie and pci rev 13 at 8KB + */ + fast = true; + if (SI_FAST(sii)) + r = (u32 *) ((char *)sii->curmap + + PCI_16KB0_PCIREGS_OFFSET + + regoff); + else + r = (u32 *) ((char *)sii->curmap + + ((regoff >= SBCONFIGOFF) ? + PCI_BAR0_PCISBR_OFFSET : + PCI_BAR0_PCIREGS_OFFSET) + + regoff); + } } if (!fast) { @@ -1499,17 +1556,19 @@ void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits) /* return the slow clock source - LPO, XTAL, or PCI */ static uint ai_slowclk_src(struct si_info *sii) { - struct chipcregs *cc; + chipcregs_t *cc; u32 val; if (sii->pub.ccrev < 6) { - pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, - &val); - if (val & PCI_CFG_GPIO_SCS) - return SCC_SS_PCI; + if (sii->pub.bustype == PCI_BUS) { + pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, + &val); + if (val & PCI_CFG_GPIO_SCS) + return SCC_SS_PCI; + } return SCC_SS_XTAL; } else if (sii->pub.ccrev < 10) { - cc = (struct chipcregs *) ai_setcoreidx(&sii->pub, sii->curidx); + cc = (chipcregs_t *) ai_setcoreidx(&sii->pub, sii->curidx); return R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK; } else /* Insta-clock */ return SCC_SS_XTAL; @@ -1519,8 +1578,7 @@ static uint ai_slowclk_src(struct si_info *sii) * return the ILP (slowclock) min or max frequency * precondition: we've established the chip has dynamic clk control */ -static uint -ai_slowclk_freq(struct si_info *sii, bool max_freq, struct chipcregs *cc) +static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, chipcregs_t *cc) { u32 slowclk; uint div; @@ -1554,8 +1612,9 @@ ai_slowclk_freq(struct si_info *sii, bool max_freq, struct chipcregs *cc) return 0; } -static void ai_clkctl_setdelay(struct si_info *sii, struct chipcregs *cc) +static void ai_clkctl_setdelay(struct si_info *sii, void *chipcregs) { + chipcregs_t *cc = (chipcregs_t *) chipcregs; uint slowmaxfreq, pll_delay, slowclk; uint pll_on_delay, fref_sel_delay; @@ -1587,7 +1646,7 @@ void ai_clkctl_init(struct si_pub *sih) { struct si_info *sii; uint origidx = 0; - struct chipcregs *cc; + chipcregs_t *cc; bool fast; if (!CCCTL_ENAB(sih)) @@ -1597,11 +1656,11 @@ void ai_clkctl_init(struct si_pub *sih) fast = SI_FAST(sii); if (!fast) { origidx = sii->curidx; - cc = (struct chipcregs *) ai_setcore(sih, CC_CORE_ID, 0); + cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0); if (cc == NULL) return; } else { - cc = (struct chipcregs *) CCREGS_FAST(sii); + cc = (chipcregs_t *) CCREGS_FAST(sii); if (cc == NULL) return; } @@ -1611,7 +1670,7 @@ void ai_clkctl_init(struct si_pub *sih) SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK, (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); - ai_clkctl_setdelay(sii, cc); + ai_clkctl_setdelay(sii, (void *)cc); if (!fast) ai_setcoreidx(sih, origidx); @@ -1625,7 +1684,7 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) { struct si_info *sii; uint origidx = 0; - struct chipcregs *cc; + chipcregs_t *cc; uint slowminfreq; u16 fpdelay; uint intr_val = 0; @@ -1647,11 +1706,11 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) if (!fast) { origidx = sii->curidx; INTR_OFF(sii, intr_val); - cc = (struct chipcregs *) ai_setcore(sih, CC_CORE_ID, 0); + cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0); if (cc == NULL) goto done; } else { - cc = (struct chipcregs *) CCREGS_FAST(sii); + cc = (chipcregs_t *) CCREGS_FAST(sii); if (cc == NULL) goto done; } @@ -1676,56 +1735,63 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) sii = SI_INFO(sih); - /* pcie core doesn't have any mapping to control the xtal pu */ - if (PCIE(sii)) - return -1; + switch (sih->bustype) { - pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in); - pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out); - pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen); + case PCI_BUS: + /* pcie core doesn't have any mapping to control the xtal pu */ + if (PCIE(sii)) + return -1; - /* - * Avoid glitching the clock if GPRS is already using it. - * We can't actually read the state of the PLLPD so we infer it - * by the value of XTAL_PU which *is* readable via gpioin. - */ - if (on && (in & PCI_CFG_GPIO_XTAL)) - return 0; + pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in); + pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out); + pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen); - if (what & XTAL) - outen |= PCI_CFG_GPIO_XTAL; - if (what & PLL) - outen |= PCI_CFG_GPIO_PLL; + /* + * Avoid glitching the clock if GPRS is already using it. + * We can't actually read the state of the PLLPD so we infer it + * by the value of XTAL_PU which *is* readable via gpioin. + */ + if (on && (in & PCI_CFG_GPIO_XTAL)) + return 0; - if (on) { - /* turn primary xtal on */ - if (what & XTAL) { - out |= PCI_CFG_GPIO_XTAL; + if (what & XTAL) + outen |= PCI_CFG_GPIO_XTAL; + if (what & PLL) + outen |= PCI_CFG_GPIO_PLL; + + if (on) { + /* turn primary xtal on */ + if (what & XTAL) { + out |= PCI_CFG_GPIO_XTAL; + if (what & PLL) + out |= PCI_CFG_GPIO_PLL; + pci_write_config_dword(sii->pbus, + PCI_GPIO_OUT, out); + pci_write_config_dword(sii->pbus, + PCI_GPIO_OUTEN, outen); + udelay(XTAL_ON_DELAY); + } + + /* turn pll on */ + if (what & PLL) { + out &= ~PCI_CFG_GPIO_PLL; + pci_write_config_dword(sii->pbus, + PCI_GPIO_OUT, out); + mdelay(2); + } + } else { + if (what & XTAL) + out &= ~PCI_CFG_GPIO_XTAL; if (what & PLL) out |= PCI_CFG_GPIO_PLL; pci_write_config_dword(sii->pbus, PCI_GPIO_OUT, out); pci_write_config_dword(sii->pbus, PCI_GPIO_OUTEN, outen); - udelay(XTAL_ON_DELAY); } - /* turn pll on */ - if (what & PLL) { - out &= ~PCI_CFG_GPIO_PLL; - pci_write_config_dword(sii->pbus, - PCI_GPIO_OUT, out); - mdelay(2); - } - } else { - if (what & XTAL) - out &= ~PCI_CFG_GPIO_XTAL; - if (what & PLL) - out |= PCI_CFG_GPIO_PLL; - pci_write_config_dword(sii->pbus, - PCI_GPIO_OUT, out); - pci_write_config_dword(sii->pbus, - PCI_GPIO_OUTEN, outen); + default: + return -1; } return 0; @@ -1759,7 +1825,7 @@ bool ai_clkctl_cc(struct si_pub *sih, uint mode) static bool _ai_clkctl_cc(struct si_info *sii, uint mode) { uint origidx = 0; - struct chipcregs *cc; + chipcregs_t *cc; u32 scc; uint intr_val = 0; bool fast = SI_FAST(sii); @@ -1771,9 +1837,15 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode) if (!fast) { INTR_OFF(sii, intr_val); origidx = sii->curidx; - cc = (struct chipcregs *) ai_setcore(&sii->pub, CC_CORE_ID, 0); + + if ((sii->pub.bustype == SI_BUS) && + ai_setcore(&sii->pub, MIPS33_CORE_ID, 0) && + (ai_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10)) + goto done; + + cc = (chipcregs_t *) ai_setcore(&sii->pub, CC_CORE_ID, 0); } else { - cc = (struct chipcregs *) CCREGS_FAST(sii); + cc = (chipcregs_t *) CCREGS_FAST(sii); if (cc == NULL) goto done; } @@ -1841,7 +1913,7 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode) return mode == CLK_FAST; } -/* Build device path */ +/* Build device path. Support SI, PCI, and JTAG for now. */ int ai_devpath(struct si_pub *sih, char *path, int size) { int slen; @@ -1849,9 +1921,22 @@ int ai_devpath(struct si_pub *sih, char *path, int size) if (!path || size <= 0) return -1; - slen = snprintf(path, (size_t) size, "pci/%u/%u/", - (((SI_INFO(sih))->pbus))->bus->number, - PCI_SLOT(((struct pci_dev *)((SI_INFO(sih))->pbus))->devfn)); + switch (sih->bustype) { + case SI_BUS: + case JTAG_BUS: + slen = snprintf(path, (size_t) size, "sb/%u/", ai_coreidx(sih)); + break; + case PCI_BUS: + slen = snprintf(path, (size_t) size, "pci/%u/%u/", + ((struct pci_dev *)((SI_INFO(sih))->pbus))->bus->number, + PCI_SLOT( + ((struct pci_dev *)((SI_INFO(sih))->pbus))->devfn)); + break; + + default: + slen = -1; + break; + } if (slen < 0 || slen >= size) { path[0] = '\0'; @@ -1874,11 +1959,15 @@ char *ai_getdevpathvar(struct si_pub *sih, const char *name) /* Get a variable, but only if it has a devpath prefix */ int ai_getdevpathintvar(struct si_pub *sih, const char *name) { +#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS) + return getintvar(NULL, name); +#else char varname[SI_DEVPATH_BUFSZ + 32]; ai_devpathvar(sih, varname, sizeof(varname), name); return getintvar(NULL, varname); +#endif } char *ai_getnvramflvar(struct si_pub *sih, const char *name) @@ -1916,6 +2005,9 @@ static bool ai_ispcie(struct si_info *sii) { u8 cap_ptr; + if (sii->pub.bustype != PCI_BUS) + return false; + cap_ptr = pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL, NULL); @@ -1940,6 +2032,10 @@ void ai_pci_up(struct si_pub *sih) sii = SI_INFO(sih); + /* if not pci bus, we're done */ + if (sih->bustype != PCI_BUS) + return; + if (PCI_FORCEHT(sii)) _ai_clkctl_cc(sii, CLK_FAST); @@ -1965,6 +2061,10 @@ void ai_pci_down(struct si_pub *sih) sii = SI_INFO(sih); + /* if not pci bus, we're done */ + if (sih->bustype != PCI_BUS) + return; + /* release FORCEHT since chip is going to "down" state */ if (PCI_FORCEHT(sii)) _ai_clkctl_cc(sii, CLK_DYNAMIC); @@ -1979,12 +2079,15 @@ void ai_pci_down(struct si_pub *sih) void ai_pci_setup(struct si_pub *sih, uint coremask) { struct si_info *sii; - struct sbpciregs *regs = NULL; + void *regs = NULL; u32 siflag = 0, w; uint idx = 0; sii = SI_INFO(sih); + if (sii->pub.bustype != PCI_BUS) + return; + if (PCI(sii)) { /* get current core index */ idx = sii->curidx; @@ -2026,6 +2129,7 @@ int ai_pci_fixcfg(struct si_pub *sih) { uint origidx; void *regs = NULL; + struct si_info *sii = SI_INFO(sih); /* Fixup PI in SROM shadow area to enable the correct PCI core access */ @@ -2034,10 +2138,7 @@ int ai_pci_fixcfg(struct si_pub *sih) /* check 'pi' is correct and fix it if not */ regs = ai_setcore(&sii->pub, sii->pub.buscoretype, 0); - if (sii->pub.buscoretype == PCIE_CORE_ID) - pcicore_fixcfg_pcie(sii->pch, (struct sbpcieregs *)regs); - else if (sii->pub.buscoretype == PCI_CORE_ID) - pcicore_fixcfg_pci(sii->pch, (struct sbpciregs *)regs); + pcicore_fixcfg(sii->pch, regs); /* restore the original index */ ai_setcoreidx(&sii->pub, origidx); @@ -2051,34 +2152,47 @@ u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority) { uint regoff; - regoff = offsetof(struct chipcregs, gpiocontrol); + regoff = 0; + + /* gpios could be shared on router platforms + * ignore reservation if it's high priority (e.g., test apps) + */ + if ((priority != GPIO_HI_PRIORITY) && + (sih->bustype == SI_BUS) && (val || mask)) { + mask = priority ? (ai_gpioreservation & mask) : + ((ai_gpioreservation | mask) & ~(ai_gpioreservation)); + val &= mask; + } + + regoff = offsetof(chipcregs_t, gpiocontrol); return ai_corereg(sih, SI_CC_IDX, regoff, mask, val); } void ai_chipcontrl_epa4331(struct si_pub *sih, bool on) { struct si_info *sii; - struct chipcregs *cc; + chipcregs_t *cc; uint origidx; u32 val; sii = SI_INFO(sih); origidx = ai_coreidx(sih); - cc = (struct chipcregs *) ai_setcore(sih, CC_CORE_ID, 0); + cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0); val = R_REG(&cc->chipcontrol); if (on) { - if (sih->chippkg == 9 || sih->chippkg == 0xb) + if (sih->chippkg == 9 || sih->chippkg == 0xb) { /* Ext PA Controls for 4331 12x9 Package */ W_REG(&cc->chipcontrol, val | (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5)); - else + } else { /* Ext PA Controls for 4331 12x12 Package */ W_REG(&cc->chipcontrol, val | (CCTRL4331_EXTPA_EN)); + } } else { val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); W_REG(&cc->chipcontrol, val); @@ -2091,13 +2205,13 @@ void ai_chipcontrl_epa4331(struct si_pub *sih, bool on) void ai_epa_4313war(struct si_pub *sih) { struct si_info *sii; - struct chipcregs *cc; + chipcregs_t *cc; uint origidx; sii = SI_INFO(sih); origidx = ai_coreidx(sih); - cc = ai_setcore(sih, CC_CORE_ID, 0); + cc = (chipcregs_t *) ai_setcore(sih, CC_CORE_ID, 0); /* EPA Fix */ W_REG(&cc->gpiocontrol, @@ -2114,10 +2228,13 @@ bool ai_deviceremoved(struct si_pub *sih) sii = SI_INFO(sih); - pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w); - if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) - return true; - + switch (sih->bustype) { + case PCI_BUS: + pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w); + if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) + return true; + break; + } return false; } @@ -2126,7 +2243,7 @@ bool ai_is_sprom_available(struct si_pub *sih) if (sih->ccrev >= 31) { struct si_info *sii; uint origidx; - struct chipcregs *cc; + chipcregs_t *cc; u32 sromctrl; if ((sih->cccaps & CC_CAP_SROM) == 0) diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/aiutils.h b/trunk/drivers/staging/brcm80211/brcmsmac/aiutils.h index 375c06f7c025..e245c278bebc 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/aiutils.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/aiutils.h @@ -30,6 +30,8 @@ #define SI_PCI_MEM_SZ (64 * 1024 * 1024) /* Host Mode sb2pcitranslation1 (64 MB) */ #define SI_PCI_CFG 0x0c000000 +/* Byteswapped Physical SDRAM */ +#define SI_SDRAM_SWAPPED 0x10000000 /* Region 2 for sdram (512 MB) */ #define SI_SDRAM_R2 0x80000000 @@ -240,23 +242,16 @@ #define SRC_PRESENT 0x00000001 /* 4330 chip-specific ChipStatus register bits */ - /* SDIO || gSPI */ -#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) - /* USB || USBDA */ -#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) - /* SDIO */ -#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) - /* gSPI */ -#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) - /* USB packet-oriented */ -#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) - /* USB Direct Access */ -#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) +#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */ +#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */ +#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */ +#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */ +#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */ +#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */ #define CST4330_OTP_PRESENT 0x00000010 #define CST4330_LPO_AUTODET_EN 0x00000020 #define CST4330_ARMREMAP_0 0x00000040 - /* takes priority over OTP if both set */ -#define CST4330_SPROM_PRESENT 0x00000080 +#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */ #define CST4330_ILPDIV_EN 0x00000100 #define CST4330_LPO_SEL 0x00000200 #define CST4330_RES_INIT_MODE_SHIFT 10 @@ -328,8 +323,10 @@ #define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ #define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ -#define PCI(si) ((si)->pub.buscoretype == PCI_CORE_ID) -#define PCIE(si) ((si)->pub.buscoretype == PCIE_CORE_ID) +#define PCI(si) (((si)->pub.bustype == PCI_BUS) && \ + ((si)->pub.buscoretype == PCI_CORE_ID)) +#define PCIE(si) (((si)->pub.bustype == PCI_BUS) && \ + ((si)->pub.buscoretype == PCIE_CORE_ID)) #define PCI_FORCEHT(si) \ (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID)) @@ -347,6 +344,7 @@ * public (read-only) portion of aiutils handle returned by si_attach() */ struct si_pub { + uint bustype; /* SI_BUS, PCI_BUS */ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ uint buscorerev; /* buscore rev */ uint buscoreidx; /* buscore index */ @@ -427,6 +425,8 @@ struct si_pub { #define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK) #endif +typedef void (*gpio_handler_t) (u32 stat, void *arg); + /* External PA enable mask */ #define GPIO_CTRL_EPA_EN_MASK 0x40 @@ -444,12 +444,14 @@ struct si_pub { #define IS_SIM(chippkg) \ ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) -struct pci_dev; +typedef u32(*si_intrsoff_t) (void *intr_arg); +typedef void (*si_intrsrestore_t) (void *intr_arg, u32 arg); +typedef bool(*si_intrsenabled_t) (void *intr_arg); struct gpioh_item { void *arg; bool level; - void (*handler) (u32 stat, void *arg); + gpio_handler_t handler; u32 event; struct gpioh_item *next; }; @@ -457,16 +459,14 @@ struct gpioh_item { /* misc si info needed by some of the routines */ struct si_info { struct si_pub pub; /* back plane public state (must be first) */ - struct pci_dev *pbus; /* handle to pci bus */ + void *pbus; /* handle to bus (pci/sdio/..) */ uint dev_coreid; /* the core provides driver functions */ void *intr_arg; /* interrupt callback function arg */ - u32 (*intrsoff_fn) (void *intr_arg); /* turns chip interrupts off */ - /* restore chip interrupts */ - void (*intrsrestore_fn) (void *intr_arg, u32 arg); - /* check if interrupts are enabled */ - bool (*intrsenabled_fn) (void *intr_arg); + si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ + si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ + si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ - struct pcicore_info *pch; /* PCI/E core handle */ + void *pch; /* PCI/E core handle */ char *vars; uint varsz; @@ -493,12 +493,15 @@ struct si_info { }; /* AMBA Interconnect exported externs */ +extern void ai_scan(struct si_pub *sih, void *regs); + extern uint ai_flag(struct si_pub *sih); extern void ai_setint(struct si_pub *sih, int siflag); extern uint ai_coreidx(struct si_pub *sih); extern uint ai_corevendor(struct si_pub *sih); extern uint ai_corerev(struct si_pub *sih); extern bool ai_iscoreup(struct si_pub *sih); +extern void *ai_setcoreidx(struct si_pub *sih, uint coreidx); extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val); extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val); extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val); @@ -512,8 +515,9 @@ extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx); extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val); /* === exported functions === */ -extern struct si_pub *ai_attach(void *regs, struct pci_dev *sdh, char **vars, - uint *varsz); +extern struct si_pub *ai_attach(void *regs, uint bustype, + void *sdh, char **vars, uint *varsz); + extern void ai_detach(struct si_pub *sih); extern bool ai_pci_war16165(struct si_pub *sih); diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/alloc.c b/trunk/drivers/staging/brcm80211/brcmsmac/alloc.c index 7dc287576cb1..7f8dd7b396bf 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/alloc.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/alloc.c @@ -161,10 +161,11 @@ struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err, uint devid) } else { int i; - for (i = 1; i < MAXBANDS; i++) + for (i = 1; i < MAXBANDS; i++) { wlc->hw->bandstate[i] = (struct brcms_hw_band *) ((unsigned long)wlc->hw->bandstate[0] + (sizeof(struct brcms_hw_band) * i)); + } } wlc->modulecb = @@ -195,10 +196,11 @@ struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err, uint devid) goto fail; } else { int i; - for (i = 1; i < BRCMS_DEFAULT_KEYS; i++) + for (i = 1; i < BRCMS_DEFAULT_KEYS; i++) { wlc->wsec_def_keys[i] = (struct wsec_key *) ((unsigned long)wlc->wsec_def_keys[0] + (sizeof(struct wsec_key) * i)); + } } wlc->protection = kzalloc(sizeof(struct brcms_protection), @@ -222,10 +224,11 @@ struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err, uint devid) } else { int i; - for (i = 1; i < MAXBANDS; i++) + for (i = 1; i < MAXBANDS; i++) { wlc->bandstate[i] = (struct brcms_band *) ((unsigned long)wlc->bandstate[0] + (sizeof(struct brcms_band)*i)); + } } wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC); diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/ampdu.c b/trunk/drivers/staging/brcm80211/brcmsmac/ampdu.c index 6fc15918b5bd..fcaf61e3b134 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/ampdu.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/ampdu.c @@ -22,32 +22,19 @@ #include "main.h" #include "ampdu.h" -/* max number of mpdus in an ampdu */ -#define AMPDU_MAX_MPDU 32 -/* max number of mpdus in an ampdu to a legacy */ -#define AMPDU_NUM_MPDU_LEGACY 16 -/* max Tx ba window size (in pdu) */ -#define AMPDU_TX_BA_MAX_WSIZE 64 -/* default Tx ba window size (in pdu) */ -#define AMPDU_TX_BA_DEF_WSIZE 64 -/* default Rx ba window size (in pdu) */ -#define AMPDU_RX_BA_DEF_WSIZE 64 -/* max Rx ba window size (in pdu) */ -#define AMPDU_RX_BA_MAX_WSIZE 64 -/* max dur of tx ampdu (in msec) */ -#define AMPDU_MAX_DUR 5 -/* default tx retry limit */ -#define AMPDU_DEF_RETRY_LIMIT 5 -/* default tx retry limit at reg rate */ -#define AMPDU_DEF_RR_RETRY_LIMIT 2 -/* default weight of ampdu in txfifo */ -#define AMPDU_DEF_TXPKT_WEIGHT 2 -/* default ffpld reserved bytes */ -#define AMPDU_DEF_FFPLD_RSVD 2048 -/* # of inis to be freed on detach */ -#define AMPDU_INI_FREE 10 -/* max # of mpdus released at a time */ -#define AMPDU_SCB_MAX_RELEASE 20 +#define AMPDU_MAX_MPDU 32 /* max number of mpdus in an ampdu */ +#define AMPDU_NUM_MPDU_LEGACY 16 /* max number of mpdus in an ampdu to a legacy */ +#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */ +#define AMPDU_TX_BA_DEF_WSIZE 64 /* default Tx ba window size (in pdu) */ +#define AMPDU_RX_BA_DEF_WSIZE 64 /* max Rx ba window size (in pdu) */ +#define AMPDU_RX_BA_MAX_WSIZE 64 /* default Rx ba window size (in pdu) */ +#define AMPDU_MAX_DUR 5 /* max dur of tx ampdu (in msec) */ +#define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit */ +#define AMPDU_DEF_RR_RETRY_LIMIT 2 /* default tx retry limit at reg rate */ +#define AMPDU_DEF_TXPKT_WEIGHT 2 /* default weight of ampdu in txfifo */ +#define AMPDU_DEF_FFPLD_RSVD 2048 /* default ffpld reserved bytes */ +#define AMPDU_INI_FREE 10 /* # of inis to be freed on detach */ +#define AMPDU_SCB_MAX_RELEASE 20 /* max # of mpdus released at a time */ #define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */ #define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu @@ -72,68 +59,44 @@ * some counters might be redundant with the ones in wlc or ampdu structures. * This allows to maintain a specific state independently of * how often and/or when the wlc counters are updated. - * - * ampdu_pld_size: number of bytes to be pre-loaded - * mcs2ampdu_table: per-mcs max # of mpdus in an ampdu - * prev_txfunfl: num of underflows last read from the HW macstats counter - * accum_txfunfl: num of underflows since we modified pld params - * accum_txampdu: num of tx ampdu since we modified pld params - * prev_txampdu: previous reading of tx ampdu - * dmaxferrate: estimated dma avg xfer rate in kbits/sec */ struct brcms_fifo_info { - u16 ampdu_pld_size; - u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; - u16 prev_txfunfl; - u32 accum_txfunfl; - u32 accum_txampdu; - u32 prev_txampdu; - u32 dmaxferrate; + u16 ampdu_pld_size; /* number of bytes to be pre-loaded */ + u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; /* per-mcs max # of mpdus in an ampdu */ + u16 prev_txfunfl; /* num of underflows last read from the HW macstats counter */ + u32 accum_txfunfl; /* num of underflows since we modified pld params */ + u32 accum_txampdu; /* num of tx ampdu since we modified pld params */ + u32 prev_txampdu; /* previous reading of tx ampdu */ + u32 dmaxferrate; /* estimated dma avg xfer rate in kbits/sec */ }; -/* AMPDU module specific state - * - * wlc: pointer to main wlc structure - * scb_handle: scb cubby handle to retrieve data from scb - * ini_enable: per-tid initiator enable/disable of ampdu - * ba_tx_wsize: Tx ba window size (in pdu) - * ba_rx_wsize: Rx ba window size (in pdu) - * retry_limit: mpdu transmit retry limit - * rr_retry_limit: mpdu transmit retry limit at regular rate - * retry_limit_tid: per-tid mpdu transmit retry limit - * rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate - * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec - * max_pdu: max pdus allowed in ampdu - * dur: max duration of an ampdu (in msec) - * txpkt_weight: weight of ampdu in txfifo; reduces rate lag - * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes - * ffpld_rsvd: number of bytes to reserve for preload - * max_txlen: max size of ampdu per mcs, bw and sgi - * mfbr: enable multiple fallback rate - * tx_max_funl: underflows should be kept such that - * (tx_max_funfl*underflows) < tx frames - * fifo_tb: table of fifo infos - */ +/* AMPDU module specific state */ struct ampdu_info { - struct brcms_c_info *wlc; - int scb_handle; - u8 ini_enable[AMPDU_MAX_SCB_TID]; - u8 ba_tx_wsize; - u8 ba_rx_wsize; - u8 retry_limit; - u8 rr_retry_limit; - u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; + struct brcms_c_info *wlc; /* pointer to main wlc structure */ + int scb_handle; /* scb cubby handle to retrieve data from scb */ + u8 ini_enable[AMPDU_MAX_SCB_TID]; /* per-tid initiator enable/disable of ampdu */ + u8 ba_tx_wsize; /* Tx ba window size (in pdu) */ + u8 ba_rx_wsize; /* Rx ba window size (in pdu) */ + u8 retry_limit; /* mpdu transmit retry limit */ + u8 rr_retry_limit; /* mpdu transmit retry limit at regular rate */ + u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; /* per-tid mpdu transmit retry limit */ + /* per-tid mpdu transmit retry limit at regular rate */ u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID]; - u8 mpdu_density; - s8 max_pdu; - u8 dur; - u8 txpkt_weight; - u8 rx_factor; - u32 ffpld_rsvd; - u32 max_txlen[MCS_TABLE_SIZE][2][2]; - bool mfbr; - u32 tx_max_funl; + u8 mpdu_density; /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */ + s8 max_pdu; /* max pdus allowed in ampdu */ + u8 dur; /* max duration of an ampdu (in msec) */ + u8 txpkt_weight; /* weight of ampdu in txfifo; reduces rate lag */ + u8 rx_factor; /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */ + u32 ffpld_rsvd; /* number of bytes to reserve for preload */ + u32 max_txlen[MCS_TABLE_SIZE][2][2]; /* max size of ampdu per mcs, bw and sgi */ + void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */ + bool mfbr; /* enable multiple fallback rate */ + u32 tx_max_funl; /* underflows should be kept such that + * (tx_max_funfl*underflows) < tx frames + */ + /* table of fifo infos */ struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO]; + }; /* used for flushing ampdu packets */ @@ -200,10 +163,7 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc) ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT; ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD; - /* - * bump max ampdu rcv size to 64k for all 11n - * devices except 4321A0 and 4321A1 - */ + /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */ if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2)) ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K; else @@ -229,6 +189,17 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc) void brcms_c_ampdu_detach(struct ampdu_info *ampdu) { + int i; + + if (!ampdu) + return; + + /* free all ini's which were to be freed on callbacks which were never called */ + for (i = 0; i < AMPDU_INI_FREE; i++) { + kfree(ampdu->ini_free[i]); + } + + brcms_c_module_unregister(ampdu->wlc->pub, "ampdu", ampdu); kfree(ampdu); } @@ -250,8 +221,7 @@ static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu, if (ampdu->max_pdu != AUTO) scb_ampdu->max_pdu = (u8) ampdu->max_pdu; - scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, - AMPDU_SCB_MAX_RELEASE); + scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE); if (scb_ampdu->max_rx_ampdu_bytes) scb_ampdu->release = min_t(u8, scb_ampdu->release, @@ -347,13 +317,13 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl; if (txunfl_ratio > ampdu->tx_max_funl) { - if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) + if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) { fifo->accum_txfunfl = 0; - + } return 0; } - max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], - AMPDU_NUM_MPDU_LEGACY); + max_mpdu = + min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY); /* In case max value max_pdu is already lower than the fifo depth, there is nothing more we can do. @@ -375,12 +345,11 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) brcms_c_scb_ampdu_update_config_all(ampdu); /* - * compute a new dma xfer rate for max_mpdu @ max mcs. - * This is the minimum dma rate that can achieve no - * underflow condition for the current mpdu size. - * - * note : we divide/multiply by 100 to avoid integer overflows + compute a new dma xfer rate for max_mpdu @ max mcs. + This is the minimum dma rate that + can achieve no underflow condition for the current mpdu size. */ + /* note : we divide/multiply by 100 to avoid integer overflows */ fifo->dmaxferrate = (((phy_rate / 100) * (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size)) @@ -419,8 +388,8 @@ static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f) /* recompute the dma rate */ /* note : we divide/multiply by 100 to avoid integer overflows */ - max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], - AMPDU_NUM_MPDU_LEGACY); + max_mpdu = + min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY); phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false); dma_rate = (((phy_rate / 100) * @@ -491,8 +460,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, struct scb_ampdu_tid_ini *ini; u8 mcs = 0; bool use_rts = false, use_cts = false; - u32 rspec = 0, rspec_fallback = 0; - u32 rts_rspec = 0, rts_rspec_fallback = 0; + ratespec_t rspec = 0, rspec_fallback = 0; + ratespec_t rts_rspec = 0, rts_rspec_fallback = 0; u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ; struct ieee80211_rts *rts; u8 rr_retry_limit; @@ -517,9 +486,10 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, /* Let pressure continue to build ... */ qlen = pktq_plen(&qi->q, prec); if (ini->tx_in_transit > 0 && - qlen < min(scb_ampdu->max_pdu, ini->ba_wsize)) + qlen < min(scb_ampdu->max_pdu, ini->ba_wsize)) { /* Collect multiple MPDU's to be sent in the next AMPDU */ return -EBUSY; + } /* at this point we intend to transmit an AMPDU */ rr_retry_limit = ampdu->rr_retry_limit_tid[tid]; @@ -695,16 +665,13 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, break; } - if (count == scb_ampdu->max_pdu) + if (count == scb_ampdu->max_pdu) { break; + } - /* - * check to see if the next pkt is - * a candidate for aggregation - */ + /* check to see if the next pkt is a candidate for aggregation */ p = pktq_ppeek(&qi->q, prec); - /* tx_info must be checked with current p */ - tx_info = IEEE80211_SKB_CB(p); + tx_info = IEEE80211_SKB_CB(p); /* tx_info must be checked with current p */ if (p) { if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && @@ -719,10 +686,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, continue; } - /* - * check if there are enough - * descriptors available - */ + /* check if there are enough descriptors available */ if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) { wiphy_err(wiphy, "%s: No fifo space " "!!\n", __func__); @@ -833,10 +797,10 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, /* inform rate_sel if it this is a rate probe pkt */ frameid = le16_to_cpu(txh->TxFrameID); - if (frameid & TXFID_RATE_PROBE_MASK) + if (frameid & TXFID_RATE_PROBE_MASK) { wiphy_err(wiphy, "%s: XXX what to do with " "TXFID_RATE_PROBE_MASK!?\n", __func__); - + } for (i = 0; i < count; i++) brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1), ampdu->txpkt_weight); @@ -869,8 +833,9 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) { udelay(1); status_delay++; - if (status_delay > 10) + if (status_delay > 10) { return; /* error condition */ + } } s2 = R_REG(&wlc->regs->frmtxstatus2); @@ -958,8 +923,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, supr_status = txs->status & TX_STATUS_SUPR_MASK; if (txs->status & TX_STATUS_ACK_RCV) { - if (TX_STATUS_SUPR_UF == supr_status) + if (TX_STATUS_SUPR_UF == supr_status) { update_rate = false; + } WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE)); start_seq = txs->sequence >> SEQNUM_SHIFT; @@ -1001,17 +967,15 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, supr_status == TX_STATUS_SUPR_EXPTIME) { retry = false; } else if (supr_status == TX_STATUS_SUPR_EXPTIME) { - /* TX underflow: - * try tuning pre-loading or ampdu size - */ + /* TX underflow : try tuning pre-loading or ampdu size */ } else if (supr_status == TX_STATUS_SUPR_FRAG) { - /* - * if there were underflows, but pre-loading - * is not active, notify rate adaptation. + /* if there were underflows, but pre-loading is not active, + notify rate adaptation. */ if (brcms_c_ffpld_check_txfunfl(wlc, - prio2fifo[tid]) > 0) + prio2fifo[tid]) > 0) { tx_error = true; + } } } else if (txs->phyerr) { update_rate = false; @@ -1055,10 +1019,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, ini->tx_in_transit--; ini->txretry[index] = 0; - /* - * ampdu_ack_len: - * number of acked aggregated frames - */ + /* ampdu_ack_len: number of acked aggregated frames */ /* ampdu_len: number of aggregated frames */ brcms_c_ampdu_rate_status(wlc, tx_info, txs, mcs); @@ -1083,14 +1044,11 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, if (retry && (txrate[0].count < (int)retry_limit)) { ini->txretry[index]++; ini->tx_in_transit--; - /* - * Use high prededence for retransmit to - * give some punch - */ + /* Use high prededence for retransmit to give some punch */ /* brcms_c_txq_enq(wlc, scb, p, * BRCMS_PRIO_TO_PREC(tid)); */ brcms_c_txq_enq(wlc, scb, p, - BRCMS_PRIO_TO_HI_PREC(tid)); + BRCMS_PRIO_TO_HI_PREC(tid)); } else { /* Retry timeout */ ini->tx_in_transit--; @@ -1198,10 +1156,7 @@ void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu) { struct brcms_c_info *wlc = ampdu->wlc; - /* - * Extend ucode internal watchdog timer to - * match larger received frames - */ + /* Extend ucode internal watchdog timer to match larger received frames */ if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) == IEEE80211_HT_MAX_AMPDU_64K) { brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX); @@ -1256,8 +1211,9 @@ void brcms_c_ampdu_flush(struct brcms_c_info *wlc, ampdu_pars.sta = sta; ampdu_pars.tid = tid; - for (prec = 0; prec < pq->num_prec; prec++) + for (prec = 0; prec < pq->num_prec; prec++) { brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt, (void *)&du_pars); + } brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu); } diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/antsel.c b/trunk/drivers/staging/brcm80211/brcmsmac/antsel.c index 23e045379951..c4e76c093ae9 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/antsel.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/antsel.c @@ -18,6 +18,7 @@ #include #include "types.h" +#include "bmac.h" #include "main.h" #include "phy_shim.h" #include "antsel.h" @@ -110,16 +111,17 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) if (((u16) getintvar(asi->pub->vars, "aa2g") == 7) || ((u16) getintvar(asi->pub->vars, "aa5g") == 7)) { asi->antsel_avail = true; - } else if ( - (u16) getintvar(asi->pub->vars, "aa2g") == 3 || - (u16) getintvar(asi->pub->vars, "aa5g") == 3) { + } else + if (((u16) getintvar(asi->pub->vars, "aa2g") == + 3) + || ((u16) getintvar(asi->pub->vars, "aa5g") + == 3)) { asi->antsel_avail = false; } else { asi->antsel_avail = false; wiphy_err(wlc->wiphy, "antsel_attach: 2o3 " "board cfg invalid\n"); } - break; default: break; @@ -259,10 +261,7 @@ static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id) return antcfg; } -/* - * boardlevel antenna selection: - * convert ant_cfg to mimo_antsel (ucode interface) - */ +/* boardlevel antenna selection: convert ant_cfg to mimo_antsel (ucode interface) */ static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg) { u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg)); @@ -296,10 +295,7 @@ static int brcms_c_antsel_cfgupd(struct antsel_info *asi, ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF]; mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); brcms_c_write_shm(wlc, M_MIMO_ANTSEL_TXDFLT, mimo_antsel); - /* - * Update driver stats for currently selected - * default tx/rx antenna config - */ + /* Update driver stats for currently selected default tx/rx antenna config */ asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg; /* 2) Update RX antconfig for all frames that are not unicast data @@ -308,10 +304,7 @@ static int brcms_c_antsel_cfgupd(struct antsel_info *asi, ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF]; mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); brcms_c_write_shm(wlc, M_MIMO_ANTSEL_RXDFLT, mimo_antsel); - /* - * Update driver stats for currently selected - * default tx/rx antenna config - */ + /* Update driver stats for currently selected default tx/rx antenna config */ asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg; return 0; diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/bmac.c b/trunk/drivers/staging/brcm80211/brcmsmac/bmac.c new file mode 100644 index 000000000000..b25c51705566 --- /dev/null +++ b/trunk/drivers/staging/brcm80211/brcmsmac/bmac.c @@ -0,0 +1,3593 @@ +/* + * Copyright (c) 2010 Broadcom Corporation + * + * Permission to use, copy, modify, and/or 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 "types.h" +#include "rate.h" +#include "phy/phy_hal.h" +#include "channel.h" +#include "main.h" +#include "ucode_loader.h" +#include "mac80211_if.h" +#include "bmac.h" + +#define TIMER_INTERVAL_WATCHDOG_BMAC 1000 /* watchdog timer, in unit of ms */ + +#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */ +#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us, default */ +#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us, default */ +#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */ + +#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */ + +#ifndef BMAC_DUP_TO_REMOVE + +#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */ + +#endif /* BMAC_DUP_TO_REMOVE */ + +#define DMAREG(wlc_hw, direction, fifonum) \ + ((direction == DMA_TX) ? \ + (void *)&(wlc_hw->regs->fifo64regs[fifonum].dmaxmt) : \ + (void *)&(wlc_hw->regs->fifo64regs[fifonum].dmarcv)) + +#define APHY_SLOT_TIME 9 +#define BPHY_SLOT_TIME 20 + +/* + * The following table lists the buffer memory allocated to xmt fifos in HW. + * the size is in units of 256bytes(one block), total size is HW dependent + * ucode has default fifo partition, sw can overwrite if necessary + * + * This is documented in twiki under the topic UcodeTxFifo. Please ensure + * the twiki is updated before making changes. + */ + +#define XMTFIFOTBL_STARTREV 20 /* Starting corerev for the fifo size table */ + +static u16 xmtfifo_sz[][NFIFO] = { + {20, 192, 192, 21, 17, 5}, /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */ + {9, 58, 22, 14, 14, 5}, /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */ + {20, 192, 192, 21, 17, 5}, /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */ + {20, 192, 192, 21, 17, 5}, /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */ + {9, 58, 22, 14, 14, 5}, /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */ +}; + +static void brcms_b_clkctl_clk(struct brcms_hardware *wlc, uint mode); +static void brcms_b_coreinit(struct brcms_c_info *wlc); + +/* used by wlc_wakeucode_init() */ +static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, + const struct d11init *inits); +static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[], + const uint nbytes); +static void brcms_ucode_download(struct brcms_hardware *wlc); +static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw); + +/* used by brcms_c_dpc() */ +static bool brcms_b_dotxstatus(struct brcms_hardware *wlc, + struct tx_status *txs, u32 s2); +static bool brcms_b_txstatus(struct brcms_hardware *wlc, bool bound, + bool *fatal); +static bool brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound); + +/* used by brcms_c_down() */ +static void brcms_c_flushqueues(struct brcms_c_info *wlc); + +static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs); +static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw); +static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw); +static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw, + uint tx_fifo); +static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw, + uint tx_fifo); +static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw, + uint tx_fifo); + +/* Low Level Prototypes */ +static int brcms_b_bandtype(struct brcms_hardware *wlc_hw); +static void brcms_b_info_init(struct brcms_hardware *wlc_hw); +static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want); +static u16 brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, + u32 sel); +static void brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, + u16 v, u32 sel); +static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk); +static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme); +static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw); +static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw); +static bool brcms_c_validboardtype(struct brcms_hardware *wlc); +static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw); +static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw); +static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw); +static void brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init); +static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw); +static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool want, + mbool flags); +static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw); +static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw); +static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc); +static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask); +static void brcms_c_gpio_init(struct brcms_c_info *wlc); +static void brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw, + void *bcn, int len); +static void brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw, + void *bcn, int len); +static void brcms_b_bsinit(struct brcms_c_info *wlc, chanspec_t chanspec); +static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit); +static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit, + chanspec_t chanspec); +static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, + bool shortslot); +static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw); +static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw, + u8 rate); + +/* === Low Level functions === */ + +void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) +{ + wlc_hw->shortslot = shortslot; + + if (BAND_2G(brcms_b_bandtype(wlc_hw)) && wlc_hw->up) { + brcms_c_suspend_mac_and_wait(wlc_hw->wlc); + brcms_b_update_slot_timing(wlc_hw, shortslot); + brcms_c_enable_mac(wlc_hw->wlc); + } +} + +/* + * Update the slot timing for standard 11b/g (20us slots) + * or shortslot 11g (9us slots) + * The PSM needs to be suspended for this call. + */ +static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, + bool shortslot) +{ + d11regs_t *regs; + + regs = wlc_hw->regs; + + if (shortslot) { + /* 11g short slot: 11a timing */ + W_REG(®s->ifs_slot, 0x0207); /* APHY_SLOT_TIME */ + brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME); + } else { + /* 11g long slot: 11b timing */ + W_REG(®s->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */ + brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME); + } +} + +static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw) +{ + struct wiphy *wiphy = wlc_hw->wlc->wiphy; + + /* init microcode host flags */ + brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs); + + /* do band-specific ucode IHR, SHM, and SCR inits */ + if (D11REV_IS(wlc_hw->corerev, 23)) { + if (BRCMS_ISNPHY(wlc_hw->band)) { + brcms_c_write_inits(wlc_hw, d11n0bsinitvals16); + } else { + wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" + " %d\n", __func__, wlc_hw->unit, + wlc_hw->corerev); + } + } else { + if (D11REV_IS(wlc_hw->corerev, 24)) { + if (BRCMS_ISLCNPHY(wlc_hw->band)) { + brcms_c_write_inits(wlc_hw, + d11lcn0bsinitvals24); + } else + wiphy_err(wiphy, "%s: wl%d: unsupported phy in" + " core rev %d\n", __func__, + wlc_hw->unit, wlc_hw->corerev); + } else { + wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", + __func__, wlc_hw->unit, wlc_hw->corerev); + } + } +} + +/* switch to new band but leave it inactive */ +static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, + uint bandunit) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + u32 macintmask; + + BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); + + WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); + + /* disable interrupts */ + macintmask = brcms_intrsoff(wlc->wl); + + /* radio off */ + wlc_phy_switch_radio(wlc_hw->band->pi, OFF); + + brcms_b_core_phy_clk(wlc_hw, OFF); + + brcms_c_setxband(wlc_hw, bandunit); + + return macintmask; +} + +/* Process received frames */ +/* + * Return true if more frames need to be processed. false otherwise. + * Param 'bound' indicates max. # frames to process before break out. + */ +static bool +brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) +{ + struct sk_buff *p; + struct sk_buff *head = NULL; + struct sk_buff *tail = NULL; + uint n = 0; + uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1; + struct brcms_d11rxhdr *wlc_rxhdr = NULL; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + /* gather received frames */ + while ((p = dma_rx(wlc_hw->di[fifo]))) { + + if (!tail) + head = tail = p; + else { + tail->prev = p; + tail = p; + } + + /* !give others some time to run! */ + if (++n >= bound_limit) + break; + } + + /* post more rbufs */ + dma_rxfill(wlc_hw->di[fifo]); + + /* process each frame */ + while ((p = head) != NULL) { + head = head->prev; + p->prev = NULL; + + wlc_rxhdr = (struct brcms_d11rxhdr *) p->data; + + /* compute the RSSI from d11rxhdr and record it in wlc_rxd11hr */ + wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr); + + brcms_c_recv(wlc_hw->wlc, p); + } + + return n >= bound_limit; +} + +/* second-level interrupt processing + * Return true if another dpc needs to be re-scheduled. false otherwise. + * Param 'bounded' indicates if applicable loops should be bounded. + */ +bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) +{ + u32 macintstatus; + struct brcms_hardware *wlc_hw = wlc->hw; + d11regs_t *regs = wlc_hw->regs; + bool fatal = false; + struct wiphy *wiphy = wlc->wiphy; + + if (DEVICEREMOVED(wlc)) { + wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, + __func__); + brcms_down(wlc->wl); + return false; + } + + /* grab and clear the saved software intstatus bits */ + macintstatus = wlc->macintstatus; + wlc->macintstatus = 0; + + BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n", + wlc_hw->unit, macintstatus); + + WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */ + + /* BCN template is available */ + /* ZZZ: Use AP_ACTIVE ? */ + if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub)) + && (macintstatus & MI_BCNTPL)) { + brcms_c_update_beacon(wlc); + } + + /* tx status */ + if (macintstatus & MI_TFS) { + if (brcms_b_txstatus(wlc->hw, bounded, &fatal)) + wlc->macintstatus |= MI_TFS; + if (fatal) { + wiphy_err(wiphy, "MI_TFS: fatal\n"); + goto fatal; + } + } + + if (macintstatus & (MI_TBTT | MI_DTIM_TBTT)) + brcms_c_tbtt(wlc); + + /* ATIM window end */ + if (macintstatus & MI_ATIMWINEND) { + BCMMSG(wlc->wiphy, "end of ATIM window\n"); + OR_REG(®s->maccommand, wlc->qvalid); + wlc->qvalid = 0; + } + + /* received data or control frame, MI_DMAINT is indication of RX_FIFO interrupt */ + if (macintstatus & MI_DMAINT) + if (brcms_b_recv(wlc_hw, RX_FIFO, bounded)) + wlc->macintstatus |= MI_DMAINT; + + /* TX FIFO suspend/flush completion */ + if (macintstatus & MI_TXSTOP) + brcms_b_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO); + + /* noise sample collected */ + if (macintstatus & MI_BG_NOISE) { + wlc_phy_noise_sample_intr(wlc_hw->band->pi); + } + + if (macintstatus & MI_GP0) { + wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d " + "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now); + + printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n", + __func__, wlc_hw->sih->chip, + wlc_hw->sih->chiprev); + /* big hammer */ + brcms_init(wlc->wl); + } + + /* gptimer timeout */ + if (macintstatus & MI_TO) { + W_REG(®s->gptimer, 0); + } + + if (macintstatus & MI_RFDISABLE) { + BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the" + " RF Disable Input\n", wlc_hw->unit); + brcms_rfkill_set_hw_state(wlc->wl); + } + + /* send any enq'd tx packets. Just makes sure to jump start tx */ + if (!pktq_empty(&wlc->pkt_queue->q)) + brcms_c_send_q(wlc); + + /* it isn't done and needs to be resched if macintstatus is non-zero */ + return wlc->macintstatus != 0; + + fatal: + brcms_init(wlc->wl); + return wlc->macintstatus != 0; +} + +/* common low-level watchdog code */ +void brcms_b_watchdog(void *arg) +{ + struct brcms_c_info *wlc = (struct brcms_c_info *) arg; + struct brcms_hardware *wlc_hw = wlc->hw; + + BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); + + if (!wlc_hw->up) + return; + + /* increment second count */ + wlc_hw->now++; + + /* Check for FIFO error interrupts */ + brcms_b_fifoerrors(wlc_hw); + + /* make sure RX dma has buffers */ + dma_rxfill(wlc->hw->di[RX_FIFO]); + + wlc_phy_watchdog(wlc_hw->band->pi); +} + +void +brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, chanspec_t chanspec, + bool mute, struct txpwr_limits *txpwr) +{ + uint bandunit; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec); + + wlc_hw->chanspec = chanspec; + + /* Switch bands if necessary */ + if (NBANDS_HW(wlc_hw) > 1) { + bandunit = CHSPEC_BANDUNIT(chanspec); + if (wlc_hw->band->bandunit != bandunit) { + /* brcms_b_setband disables other bandunit, + * use light band switch if not up yet + */ + if (wlc_hw->up) { + wlc_phy_chanspec_radio_set(wlc_hw-> + bandstate[bandunit]-> + pi, chanspec); + brcms_b_setband(wlc_hw, bandunit, chanspec); + } else { + brcms_c_setxband(wlc_hw, bandunit); + } + } + } + + wlc_phy_initcal_enable(wlc_hw->band->pi, !mute); + + if (!wlc_hw->up) { + if (wlc_hw->clk) + wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, + chanspec); + wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); + } else { + wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec); + wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec); + + /* Update muting of the channel */ + brcms_b_mute(wlc_hw, mute, 0); + } +} + +int brcms_b_state_get(struct brcms_hardware *wlc_hw, + struct brcms_b_state *state) +{ + state->machwcap = wlc_hw->machwcap; + + return 0; +} + +static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) +{ + uint i; + char name[8]; + /* ucode host flag 2 needed for pio mode, independent of band and fifo */ + u16 pio_mhf2 = 0; + struct brcms_hardware *wlc_hw = wlc->hw; + uint unit = wlc_hw->unit; + struct brcms_tunables *tune = wlc->pub->tunables; + struct wiphy *wiphy = wlc->wiphy; + + /* name and offsets for dma_attach */ + snprintf(name, sizeof(name), "wl%d", unit); + + if (wlc_hw->di[0] == 0) { /* Init FIFOs */ + uint addrwidth; + int dma_attach_err = 0; + /* Find out the DMA addressing capability and let OS know + * All the channels within one DMA core have 'common-minimum' same + * capability + */ + addrwidth = + dma_addrwidth(wlc_hw->sih, DMAREG(wlc_hw, DMA_TX, 0)); + + if (!wl_alloc_dma_resources(wlc_hw->wlc->wl, addrwidth)) { + wiphy_err(wiphy, "wl%d: wlc_attach: alloc_dma_" + "resources failed\n", unit); + return false; + } + + /* + * FIFO 0 + * TX: TX_AC_BK_FIFO (TX AC Background data packets) + * RX: RX_FIFO (RX data packets) + */ + wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, + (wme ? DMAREG(wlc_hw, DMA_TX, 0) : + NULL), DMAREG(wlc_hw, DMA_RX, 0), + (wme ? tune->ntxd : 0), tune->nrxd, + tune->rxbufsz, -1, tune->nrxbufpost, + BRCMS_HWRXOFF, &brcm_msg_level); + dma_attach_err |= (NULL == wlc_hw->di[0]); + + /* + * FIFO 1 + * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets) + * (legacy) TX_DATA_FIFO (TX data packets) + * RX: UNUSED + */ + wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, + DMAREG(wlc_hw, DMA_TX, 1), NULL, + tune->ntxd, 0, 0, -1, 0, 0, + &brcm_msg_level); + dma_attach_err |= (NULL == wlc_hw->di[1]); + + /* + * FIFO 2 + * TX: TX_AC_VI_FIFO (TX AC Video data packets) + * RX: UNUSED + */ + wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, + DMAREG(wlc_hw, DMA_TX, 2), NULL, + tune->ntxd, 0, 0, -1, 0, 0, + &brcm_msg_level); + dma_attach_err |= (NULL == wlc_hw->di[2]); + /* + * FIFO 3 + * TX: TX_AC_VO_FIFO (TX AC Voice data packets) + * (legacy) TX_CTL_FIFO (TX control & mgmt packets) + */ + wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, + DMAREG(wlc_hw, DMA_TX, 3), + NULL, tune->ntxd, 0, 0, -1, + 0, 0, &brcm_msg_level); + dma_attach_err |= (NULL == wlc_hw->di[3]); +/* Cleaner to leave this as if with AP defined */ + + if (dma_attach_err) { + wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed" + "\n", unit); + return false; + } + + /* get pointer to dma engine tx flow control variable */ + for (i = 0; i < NFIFO; i++) + if (wlc_hw->di[i]) + wlc_hw->txavail[i] = + (uint *) dma_getvar(wlc_hw->di[i], + "&txavail"); + } + + /* initial ucode host flags */ + brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2); + + return true; +} + +static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw) +{ + uint j; + + for (j = 0; j < NFIFO; j++) { + if (wlc_hw->di[j]) { + dma_detach(wlc_hw->di[j]); + wlc_hw->di[j] = NULL; + } + } +} + +/* low level attach + * run backplane attach, init nvram + * run phy attach + * initialize software state for each core and band + * put the whole chip in reset(driver down state), no clock + */ +int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, uint unit, + bool piomode, void *regsva, uint bustype, void *btparam) +{ + struct brcms_hardware *wlc_hw; + d11regs_t *regs; + char *macaddr = NULL; + char *vars; + uint err = 0; + uint j; + bool wme = false; + struct shared_phy_params sha_params; + struct wiphy *wiphy = wlc->wiphy; + + BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor, + device); + + wme = true; + + wlc_hw = wlc->hw; + wlc_hw->wlc = wlc; + wlc_hw->unit = unit; + wlc_hw->band = wlc_hw->bandstate[0]; + wlc_hw->_piomode = piomode; + + /* populate struct brcms_hardware with default values */ + brcms_b_info_init(wlc_hw); + + /* + * Do the hardware portion of the attach. + * Also initialize software state that depends on the particular hardware + * we are running. + */ + wlc_hw->sih = ai_attach(regsva, bustype, btparam, + &wlc_hw->vars, &wlc_hw->vars_size); + if (wlc_hw->sih == NULL) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n", + unit); + err = 11; + goto fail; + } + vars = wlc_hw->vars; + + /* + * Get vendid/devid nvram overwrites, which could be different + * than those the BIOS recognizes for devices on PCMCIA_BUS, + * SDIO_BUS, and SROMless devices on PCI_BUS. + */ +#ifdef BCMBUSTYPE + bustype = BCMBUSTYPE; +#endif + if (bustype != SI_BUS) { + char *var; + + var = getvar(vars, "vendid"); + if (var) { + vendor = (u16) simple_strtoul(var, NULL, 0); + wiphy_err(wiphy, "Overriding vendor id = 0x%x\n", + vendor); + } + var = getvar(vars, "devid"); + if (var) { + u16 devid = (u16) simple_strtoul(var, NULL, 0); + if (devid != 0xffff) { + device = devid; + wiphy_err(wiphy, "Overriding device id = 0x%x" + "\n", device); + } + } + + /* verify again the device is supported */ + if (!brcms_c_chipmatch(vendor, device)) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " + "vendor/device (0x%x/0x%x)\n", + unit, vendor, device); + err = 12; + goto fail; + } + } + + wlc_hw->vendorid = vendor; + wlc_hw->deviceid = device; + + /* set bar0 window to point at D11 core */ + wlc_hw->regs = (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); + wlc_hw->corerev = ai_corerev(wlc_hw->sih); + + regs = wlc_hw->regs; + + wlc->regs = wlc_hw->regs; + + /* validate chip, chiprev and corerev */ + if (!brcms_c_isgoodchip(wlc_hw)) { + err = 13; + goto fail; + } + + /* initialize power control registers */ + ai_clkctl_init(wlc_hw->sih); + + /* request fastclock and force fastclock for the rest of attach + * bring the d11 core out of reset. + * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk is still false; + * But it will be called again inside wlc_corereset, after d11 is out of reset. + */ + brcms_b_clkctl_clk(wlc_hw, CLK_FAST); + brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); + + if (!brcms_b_validate_chip_access(wlc_hw)) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access " + "failed\n", unit); + err = 14; + goto fail; + } + + /* get the board rev, used just below */ + j = getintvar(vars, "boardrev"); + /* promote srom boardrev of 0xFF to 1 */ + if (j == BOARDREV_PROMOTABLE) + j = BOARDREV_PROMOTED; + wlc_hw->boardrev = (u16) j; + if (!brcms_c_validboardtype(wlc_hw)) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom " + "board type (0x%x)" " or revision level (0x%x)\n", + unit, wlc_hw->sih->boardtype, wlc_hw->boardrev); + err = 15; + goto fail; + } + wlc_hw->sromrev = (u8) getintvar(vars, "sromrev"); + wlc_hw->boardflags = (u32) getintvar(vars, "boardflags"); + wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2"); + + if (wlc_hw->boardflags & BFL_NOPLLDOWN) + brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED); + + if ((wlc_hw->sih->bustype == PCI_BUS) + && (ai_pci_war16165(wlc_hw->sih))) + wlc->war16165 = true; + + /* check device id(srom, nvram etc.) to set bands */ + if (wlc_hw->deviceid == BCM43224_D11N_ID || + wlc_hw->deviceid == BCM43224_D11N_ID_VEN1) { + /* Dualband boards */ + wlc_hw->_nbands = 2; + } else + wlc_hw->_nbands = 1; + + if ((wlc_hw->sih->chip == BCM43225_CHIP_ID)) + wlc_hw->_nbands = 1; + + /* BMAC_NOTE: remove init of pub values when brcms_c_attach() + * unconditionally does the init of these values + */ + wlc->vendorid = wlc_hw->vendorid; + wlc->deviceid = wlc_hw->deviceid; + wlc->pub->sih = wlc_hw->sih; + wlc->pub->corerev = wlc_hw->corerev; + wlc->pub->sromrev = wlc_hw->sromrev; + wlc->pub->boardrev = wlc_hw->boardrev; + wlc->pub->boardflags = wlc_hw->boardflags; + wlc->pub->boardflags2 = wlc_hw->boardflags2; + wlc->pub->_nbands = wlc_hw->_nbands; + + wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc); + + if (wlc_hw->physhim == NULL) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach " + "failed\n", unit); + err = 25; + goto fail; + } + + /* pass all the parameters to wlc_phy_shared_attach in one struct */ + sha_params.sih = wlc_hw->sih; + sha_params.physhim = wlc_hw->physhim; + sha_params.unit = unit; + sha_params.corerev = wlc_hw->corerev; + sha_params.vars = vars; + sha_params.vid = wlc_hw->vendorid; + sha_params.did = wlc_hw->deviceid; + sha_params.chip = wlc_hw->sih->chip; + sha_params.chiprev = wlc_hw->sih->chiprev; + sha_params.chippkg = wlc_hw->sih->chippkg; + sha_params.sromrev = wlc_hw->sromrev; + sha_params.boardtype = wlc_hw->sih->boardtype; + sha_params.boardrev = wlc_hw->boardrev; + sha_params.boardvendor = wlc_hw->sih->boardvendor; + sha_params.boardflags = wlc_hw->boardflags; + sha_params.boardflags2 = wlc_hw->boardflags2; + sha_params.bustype = wlc_hw->sih->bustype; + sha_params.buscorerev = wlc_hw->sih->buscorerev; + + /* alloc and save pointer to shared phy state area */ + wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params); + if (!wlc_hw->phy_sh) { + err = 16; + goto fail; + } + + /* initialize software state for each core and band */ + for (j = 0; j < NBANDS_HW(wlc_hw); j++) { + /* + * band0 is always 2.4Ghz + * band1, if present, is 5Ghz + */ + + /* So if this is a single band 11a card, use band 1 */ + if (IS_SINGLEBAND_5G(wlc_hw->deviceid)) + j = BAND_5G_INDEX; + + brcms_c_setxband(wlc_hw, j); + + wlc_hw->band->bandunit = j; + wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; + wlc->band->bandunit = j; + wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; + wlc->core->coreidx = ai_coreidx(wlc_hw->sih); + + wlc_hw->machwcap = R_REG(®s->machwcap); + wlc_hw->machwcap_backup = wlc_hw->machwcap; + + /* init tx fifo size */ + wlc_hw->xmtfifo_sz = + xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)]; + + /* Get a phy for this band */ + wlc_hw->band->pi = wlc_phy_attach(wlc_hw->phy_sh, + (void *)regs, brcms_b_bandtype(wlc_hw), vars, + wlc->wiphy); + if (wlc_hw->band->pi == NULL) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_" + "attach failed\n", unit); + err = 17; + goto fail; + } + + wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap); + + wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype, + &wlc_hw->band->phyrev, + &wlc_hw->band->radioid, + &wlc_hw->band->radiorev); + wlc_hw->band->abgphy_encore = + wlc_phy_get_encore(wlc_hw->band->pi); + wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi); + wlc_hw->band->core_flags = + wlc_phy_get_coreflags(wlc_hw->band->pi); + + /* verify good phy_type & supported phy revision */ + if (BRCMS_ISNPHY(wlc_hw->band)) { + if (NCONF_HAS(wlc_hw->band->phyrev)) + goto good_phy; + else + goto bad_phy; + } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { + if (LCNCONF_HAS(wlc_hw->band->phyrev)) + goto good_phy; + else + goto bad_phy; + } else { + bad_phy: + wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported " + "phy type/rev (%d/%d)\n", unit, + wlc_hw->band->phytype, wlc_hw->band->phyrev); + err = 18; + goto fail; + } + + good_phy: + /* BMAC_NOTE: wlc->band->pi should not be set below and should be done in the + * high level attach. However we can not make that change until all low level access + * is changed to wlc_hw->band->pi. Instead do the wlc->band->pi init below, keeping + * wlc_hw->band->pi as well for incremental update of low level fns, and cut over + * low only init when all fns updated. + */ + wlc->band->pi = wlc_hw->band->pi; + wlc->band->phytype = wlc_hw->band->phytype; + wlc->band->phyrev = wlc_hw->band->phyrev; + wlc->band->radioid = wlc_hw->band->radioid; + wlc->band->radiorev = wlc_hw->band->radiorev; + + /* default contention windows size limits */ + wlc_hw->band->CWmin = APHY_CWMIN; + wlc_hw->band->CWmax = PHY_CWMAX; + + if (!brcms_b_attach_dmapio(wlc, j, wme)) { + err = 19; + goto fail; + } + } + + /* disable core to match driver "down" state */ + brcms_c_coredisable(wlc_hw); + + /* Match driver "down" state */ + if (wlc_hw->sih->bustype == PCI_BUS) + ai_pci_down(wlc_hw->sih); + + /* register sb interrupt callback functions */ + ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff, + (void *)brcms_c_wlintrsrestore, NULL, wlc); + + /* turn off pll and xtal to match driver "down" state */ + brcms_b_xtal(wlc_hw, OFF); + + /* ********************************************************************* + * The hardware is in the DOWN state at this point. D11 core + * or cores are in reset with clocks off, and the board PLLs + * are off if possible. + * + * Beyond this point, wlc->sbclk == false and chip registers + * should not be touched. + ********************************************************************* + */ + + /* init etheraddr state variables */ + macaddr = brcms_c_get_macaddr(wlc_hw); + if (macaddr == NULL) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n", + unit); + err = 21; + goto fail; + } + brcmu_ether_atoe(macaddr, wlc_hw->etheraddr); + if (is_broadcast_ether_addr(wlc_hw->etheraddr) || + is_zero_ether_addr(wlc_hw->etheraddr)) { + wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n", + unit, macaddr); + err = 22; + goto fail; + } + + BCMMSG(wlc->wiphy, + "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n", + wlc_hw->deviceid, wlc_hw->_nbands, + wlc_hw->sih->boardtype, macaddr); + + return err; + + fail: + wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit, + err); + return err; +} + +/* + * Initialize brcms_c_info default values ... + * may get overrides later in this function + * BMAC_NOTES, move low out and resolve the dangling ones + */ +static void brcms_b_info_init(struct brcms_hardware *wlc_hw) +{ + struct brcms_c_info *wlc = wlc_hw->wlc; + + /* set default sw macintmask value */ + wlc->defmacintmask = DEF_MACINTMASK; + + /* various 802.11g modes */ + wlc_hw->shortslot = false; + + wlc_hw->SFBL = RETRY_SHORT_FB; + wlc_hw->LFBL = RETRY_LONG_FB; + + /* default mac retry limits */ + wlc_hw->SRL = RETRY_SHORT_DEF; + wlc_hw->LRL = RETRY_LONG_DEF; + wlc_hw->chanspec = CH20MHZ_CHSPEC(1); +} + +/* + * low level detach + */ +int brcms_b_detach(struct brcms_c_info *wlc) +{ + uint i; + struct brcms_hw_band *band; + struct brcms_hardware *wlc_hw = wlc->hw; + int callbacks; + + callbacks = 0; + + if (wlc_hw->sih) { + /* detach interrupt sync mechanism since interrupt is disabled and per-port + * interrupt object may has been freed. this must be done before sb core switch + */ + ai_deregister_intr_callback(wlc_hw->sih); + + if (wlc_hw->sih->bustype == PCI_BUS) + ai_pci_sleep(wlc_hw->sih); + } + + brcms_b_detach_dmapio(wlc_hw); + + band = wlc_hw->band; + for (i = 0; i < NBANDS_HW(wlc_hw); i++) { + if (band->pi) { + /* Detach this band's phy */ + wlc_phy_detach(band->pi); + band->pi = NULL; + } + band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)]; + } + + /* Free shared phy state */ + kfree(wlc_hw->phy_sh); + + wlc_phy_shim_detach(wlc_hw->physhim); + + /* free vars */ + kfree(wlc_hw->vars); + wlc_hw->vars = NULL; + + if (wlc_hw->sih) { + ai_detach(wlc_hw->sih); + wlc_hw->sih = NULL; + } + + return callbacks; + +} + +void brcms_b_reset(struct brcms_hardware *wlc_hw) +{ + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + /* reset the core */ + if (!DEVICEREMOVED(wlc_hw->wlc)) + brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); + + /* purge the dma rings */ + brcms_c_flushqueues(wlc_hw->wlc); + + brcms_c_reset_bmac_done(wlc_hw->wlc); +} + +void +brcms_b_init(struct brcms_hardware *wlc_hw, chanspec_t chanspec, + bool mute) { + u32 macintmask; + bool fastclk; + struct brcms_c_info *wlc = wlc_hw->wlc; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + /* request FAST clock if not on */ + fastclk = wlc_hw->forcefastclk; + if (!fastclk) + brcms_b_clkctl_clk(wlc_hw, CLK_FAST); + + /* disable interrupts */ + macintmask = brcms_intrsoff(wlc->wl); + + /* set up the specified band and chanspec */ + brcms_c_setxband(wlc_hw, CHSPEC_BANDUNIT(chanspec)); + wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); + + /* do one-time phy inits and calibration */ + wlc_phy_cal_init(wlc_hw->band->pi); + + /* core-specific initialization */ + brcms_b_coreinit(wlc); + + /* suspend the tx fifos and mute the phy for preism cac time */ + if (mute) + brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM); + + /* band-specific inits */ + brcms_b_bsinit(wlc, chanspec); + + /* restore macintmask */ + brcms_intrsrestore(wlc->wl, macintmask); + + /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac + * is suspended and brcms_c_enable_mac() will clear this override bit. + */ + mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND); + + /* + * initialize mac_suspend_depth to 1 to match ucode initial suspended state + */ + wlc_hw->mac_suspend_depth = 1; + + /* restore the clk */ + if (!fastclk) + brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); +} + +int brcms_b_up_prep(struct brcms_hardware *wlc_hw) +{ + uint coremask; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + /* + * Enable pll and xtal, initialize the power control registers, + * and force fastclock for the remainder of brcms_c_up(). + */ + brcms_b_xtal(wlc_hw, ON); + ai_clkctl_init(wlc_hw->sih); + brcms_b_clkctl_clk(wlc_hw, CLK_FAST); + + /* + * Configure pci/pcmcia here instead of in brcms_c_attach() + * to allow mfg hotswap: down, hotswap (chip power cycle), up. + */ + coremask = (1 << wlc_hw->wlc->core->coreidx); + + if (wlc_hw->sih->bustype == PCI_BUS) + ai_pci_setup(wlc_hw->sih, coremask); + + /* + * Need to read the hwradio status here to cover the case where the system + * is loaded with the hw radio disabled. We do not want to bring the driver up in this case. + */ + if (brcms_b_radio_read_hwdisabled(wlc_hw)) { + /* put SB PCI in down state again */ + if (wlc_hw->sih->bustype == PCI_BUS) + ai_pci_down(wlc_hw->sih); + brcms_b_xtal(wlc_hw, OFF); + return -ENOMEDIUM; + } + + if (wlc_hw->sih->bustype == PCI_BUS) + ai_pci_up(wlc_hw->sih); + + /* reset the d11 core */ + brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); + + return 0; +} + +int brcms_b_up_finish(struct brcms_hardware *wlc_hw) +{ + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + wlc_hw->up = true; + wlc_phy_hw_state_upd(wlc_hw->band->pi, true); + + /* FULLY enable dynamic power control and d11 core interrupt */ + brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); + brcms_intrson(wlc_hw->wlc->wl); + return 0; +} + +int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw) +{ + bool dev_gone; + uint callbacks = 0; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + if (!wlc_hw->up) + return callbacks; + + dev_gone = DEVICEREMOVED(wlc_hw->wlc); + + /* disable interrupts */ + if (dev_gone) + wlc_hw->wlc->macintmask = 0; + else { + /* now disable interrupts */ + brcms_intrsoff(wlc_hw->wlc->wl); + + /* ensure we're running on the pll clock again */ + brcms_b_clkctl_clk(wlc_hw, CLK_FAST); + } + /* down phy at the last of this stage */ + callbacks += wlc_phy_down(wlc_hw->band->pi); + + return callbacks; +} + +int brcms_b_down_finish(struct brcms_hardware *wlc_hw) +{ + uint callbacks = 0; + bool dev_gone; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + if (!wlc_hw->up) + return callbacks; + + wlc_hw->up = false; + wlc_phy_hw_state_upd(wlc_hw->band->pi, false); + + dev_gone = DEVICEREMOVED(wlc_hw->wlc); + + if (dev_gone) { + wlc_hw->sbclk = false; + wlc_hw->clk = false; + wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); + + /* reclaim any posted packets */ + brcms_c_flushqueues(wlc_hw->wlc); + } else { + + /* Reset and disable the core */ + if (ai_iscoreup(wlc_hw->sih)) { + if (R_REG(&wlc_hw->regs->maccontrol) & + MCTL_EN_MAC) + brcms_c_suspend_mac_and_wait(wlc_hw->wlc); + callbacks += brcms_reset(wlc_hw->wlc->wl); + brcms_c_coredisable(wlc_hw); + } + + /* turn off primary xtal and pll */ + if (!wlc_hw->noreset) { + if (wlc_hw->sih->bustype == PCI_BUS) + ai_pci_down(wlc_hw->sih); + brcms_b_xtal(wlc_hw, OFF); + } + } + + return callbacks; +} + +void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw) +{ + /* delay before first read of ucode state */ + udelay(40); + + /* wait until ucode is no longer asleep */ + SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) == + DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly); +} + +void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw, u8 *ea) +{ + memcpy(ea, wlc_hw->etheraddr, ETH_ALEN); +} + +static int brcms_b_bandtype(struct brcms_hardware *wlc_hw) +{ + return wlc_hw->band->bandtype; +} + +/* control chip clock to save power, enable dynamic clock or force fast clock */ +static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) +{ + if (PMUCTL_ENAB(wlc_hw->sih)) { + /* new chips with PMU, CCS_FORCEHT will distribute the HT clock on backplane, + * but mac core will still run on ALP(not HT) when it enters powersave mode, + * which means the FCA bit may not be set. + * should wakeup mac if driver wants it to run on HT. + */ + + if (wlc_hw->clk) { + if (mode == CLK_FAST) { + OR_REG(&wlc_hw->regs->clk_ctl_st, + CCS_FORCEHT); + + udelay(64); + + SPINWAIT(((R_REG + (&wlc_hw->regs-> + clk_ctl_st) & CCS_HTAVAIL) == 0), + PMU_MAX_TRANSITION_DLY); + WARN_ON(!(R_REG + (&wlc_hw->regs-> + clk_ctl_st) & CCS_HTAVAIL)); + } else { + if ((wlc_hw->sih->pmurev == 0) && + (R_REG + (&wlc_hw->regs-> + clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ))) + SPINWAIT(((R_REG + (&wlc_hw->regs-> + clk_ctl_st) & CCS_HTAVAIL) + == 0), + PMU_MAX_TRANSITION_DLY); + AND_REG(&wlc_hw->regs->clk_ctl_st, + ~CCS_FORCEHT); + } + } + wlc_hw->forcefastclk = (mode == CLK_FAST); + } else { + + /* old chips w/o PMU, force HT through cc, + * then use FCA to verify mac is running fast clock + */ + + wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode); + + /* check fast clock is available (if core is not in reset) */ + if (wlc_hw->forcefastclk && wlc_hw->clk) + WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) & + SISF_FCLKA)); + + /* keep the ucode wake bit on if forcefastclk is on + * since we do not want ucode to put us back to slow clock + * when it dozes for PM mode. + * Code below matches the wake override bit with current forcefastclk state + * Only setting bit in wake_override instead of waking ucode immediately + * since old code (wlc.c 1.4499) had this behavior. Older code set + * wlc->forcefastclk but only had the wake happen if the wakup_ucode work + * (protected by an up check) was executed just below. + */ + if (wlc_hw->forcefastclk) + mboolset(wlc_hw->wake_override, + BRCMS_WAKE_OVERRIDE_FORCEFAST); + else + mboolclr(wlc_hw->wake_override, + BRCMS_WAKE_OVERRIDE_FORCEFAST); + } +} + +/* set initial host flags value */ +static void +brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + + memset(mhfs, 0, MHFMAX * sizeof(u16)); + + mhfs[MHF2] |= mhf2_init; + + /* prohibit use of slowclock on multifunction boards */ + if (wlc_hw->boardflags & BFL_NOPLLDOWN) + mhfs[MHF1] |= MHF1_FORCEFASTCLK; + + if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) { + mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR; + mhfs[MHF1] |= MHF1_IQSWAP_WAR; + } +} + +/* set or clear ucode host flag bits + * it has an optimization for no-change write + * it only writes through shared memory when the core has clock; + * pre-CLK changes should use wlc_write_mhf to get around the optimization + * + * + * bands values are: BRCM_BAND_AUTO <--- Current band only + * BRCM_BAND_5G <--- 5G band only + * BRCM_BAND_2G <--- 2G band only + * BRCM_BAND_ALL <--- All bands + */ +void +brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val, + int bands) +{ + u16 save; + u16 addr[MHFMAX] = { + M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, + M_HOST_FLAGS5 + }; + struct brcms_hw_band *band; + + if ((val & ~mask) || idx >= MHFMAX) + return; /* error condition */ + + switch (bands) { + /* Current band only or all bands, + * then set the band to current band + */ + case BRCM_BAND_AUTO: + case BRCM_BAND_ALL: + band = wlc_hw->band; + break; + case BRCM_BAND_5G: + band = wlc_hw->bandstate[BAND_5G_INDEX]; + break; + case BRCM_BAND_2G: + band = wlc_hw->bandstate[BAND_2G_INDEX]; + break; + default: + band = NULL; /* error condition */ + } + + if (band) { + save = band->mhfs[idx]; + band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val; + + /* optimization: only write through if changed, and + * changed band is the current band + */ + if (wlc_hw->clk && (band->mhfs[idx] != save) + && (band == wlc_hw->band)) + brcms_b_write_shm(wlc_hw, addr[idx], + (u16) band->mhfs[idx]); + } + + if (bands == BRCM_BAND_ALL) { + wlc_hw->bandstate[0]->mhfs[idx] = + (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val; + wlc_hw->bandstate[1]->mhfs[idx] = + (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val; + } +} + +u16 brcms_b_mhf_get(struct brcms_hardware *wlc_hw, u8 idx, int bands) +{ + struct brcms_hw_band *band; + + if (idx >= MHFMAX) + return 0; /* error condition */ + switch (bands) { + case BRCM_BAND_AUTO: + band = wlc_hw->band; + break; + case BRCM_BAND_5G: + band = wlc_hw->bandstate[BAND_5G_INDEX]; + break; + case BRCM_BAND_2G: + band = wlc_hw->bandstate[BAND_2G_INDEX]; + break; + default: + band = NULL; /* error condition */ + } + + if (!band) + return 0; + + return band->mhfs[idx]; +} + +static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs) +{ + u8 idx; + u16 addr[] = { + M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, + M_HOST_FLAGS5 + }; + + for (idx = 0; idx < MHFMAX; idx++) { + brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]); + } +} + +/* set the maccontrol register to desired reset state and + * initialize the sw cache of the register + */ +static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw) +{ + /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */ + wlc_hw->maccontrol = 0; + wlc_hw->suspended_fifos = 0; + wlc_hw->wake_override = 0; + wlc_hw->mute_override = 0; + brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE); +} + +/* set or clear maccontrol bits */ +void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val) +{ + u32 maccontrol; + u32 new_maccontrol; + + if (val & ~mask) + return; /* error condition */ + maccontrol = wlc_hw->maccontrol; + new_maccontrol = (maccontrol & ~mask) | val; + + /* if the new maccontrol value is the same as the old, nothing to do */ + if (new_maccontrol == maccontrol) + return; + + /* something changed, cache the new value */ + wlc_hw->maccontrol = new_maccontrol; + + /* write the new values with overrides applied */ + brcms_c_mctrl_write(wlc_hw); +} + +/* write the software state of maccontrol and overrides to the maccontrol register */ +static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw) +{ + u32 maccontrol = wlc_hw->maccontrol; + + /* OR in the wake bit if overridden */ + if (wlc_hw->wake_override) + maccontrol |= MCTL_WAKE; + + /* set AP and INFRA bits for mute if needed */ + if (wlc_hw->mute_override) { + maccontrol &= ~(MCTL_AP); + maccontrol |= MCTL_INFRA; + } + + W_REG(&wlc_hw->regs->maccontrol, maccontrol); +} + +void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, + u32 override_bit) +{ + if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) { + mboolset(wlc_hw->wake_override, override_bit); + return; + } + + mboolset(wlc_hw->wake_override, override_bit); + + brcms_c_mctrl_write(wlc_hw); + brcms_b_wait_for_wake(wlc_hw); + + return; +} + +void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, + u32 override_bit) +{ + mboolclr(wlc_hw->wake_override, override_bit); + + if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) + return; + + brcms_c_mctrl_write(wlc_hw); + + return; +} + +/* When driver needs ucode to stop beaconing, it has to make sure that + * MCTL_AP is clear and MCTL_INFRA is set + * Mode MCTL_AP MCTL_INFRA + * AP 1 1 + * STA 0 1 <--- This will ensure no beacons + * IBSS 0 0 + */ +static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw) +{ + wlc_hw->mute_override = 1; + + /* if maccontrol already has AP == 0 and INFRA == 1 without this + * override, then there is no change to write + */ + if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) + return; + + brcms_c_mctrl_write(wlc_hw); + + return; +} + +/* Clear the override on AP and INFRA bits */ +static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw) +{ + if (wlc_hw->mute_override == 0) + return; + + wlc_hw->mute_override = 0; + + /* if maccontrol already has AP == 0 and INFRA == 1 without this + * override, then there is no change to write + */ + if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) + return; + + brcms_c_mctrl_write(wlc_hw); +} + +/* + * Write a MAC address to the given match reg offset in the RXE match engine. + */ +void +brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, + const u8 *addr) +{ + d11regs_t *regs; + u16 mac_l; + u16 mac_m; + u16 mac_h; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n", + wlc_hw->unit); + + regs = wlc_hw->regs; + mac_l = addr[0] | (addr[1] << 8); + mac_m = addr[2] | (addr[3] << 8); + mac_h = addr[4] | (addr[5] << 8); + + /* enter the MAC addr into the RXE match registers */ + W_REG(®s->rcm_ctl, RCM_INC_DATA | match_reg_offset); + W_REG(®s->rcm_mat_data, mac_l); + W_REG(®s->rcm_mat_data, mac_m); + W_REG(®s->rcm_mat_data, mac_h); + +} + +void +brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len, + void *buf) +{ + d11regs_t *regs; + u32 word; + bool be_bit; + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + regs = wlc_hw->regs; + W_REG(®s->tplatewrptr, offset); + + /* if MCTL_BIGEND bit set in mac control register, + * the chip swaps data in fifo, as well as data in + * template ram + */ + be_bit = (R_REG(®s->maccontrol) & MCTL_BIGEND) != 0; + + while (len > 0) { + memcpy(&word, buf, sizeof(u32)); + + if (be_bit) + word = cpu_to_be32(word); + else + word = cpu_to_le32(word); + + W_REG(®s->tplatewrdata, word); + + buf = (u8 *) buf + sizeof(u32); + len -= sizeof(u32); + } +} + +void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin) +{ + wlc_hw->band->CWmin = newmin; + + W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN); + (void)R_REG(&wlc_hw->regs->objaddr); + W_REG(&wlc_hw->regs->objdata, newmin); +} + +void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax) +{ + wlc_hw->band->CWmax = newmax; + + W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX); + (void)R_REG(&wlc_hw->regs->objaddr); + W_REG(&wlc_hw->regs->objdata, newmax); +} + +void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) +{ + bool fastclk; + + /* request FAST clock if not on */ + fastclk = wlc_hw->forcefastclk; + if (!fastclk) + brcms_b_clkctl_clk(wlc_hw, CLK_FAST); + + wlc_phy_bw_state_set(wlc_hw->band->pi, bw); + + brcms_b_phy_reset(wlc_hw); + wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi)); + + /* restore the clk */ + if (!fastclk) + brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); +} + +static void +brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw, void *bcn, + int len) +{ + d11regs_t *regs = wlc_hw->regs; + + brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3, + bcn); + /* write beacon length to SCR */ + brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len); + /* mark beacon0 valid */ + OR_REG(®s->maccommand, MCMD_BCN0VLD); +} + +static void +brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw, void *bcn, + int len) +{ + d11regs_t *regs = wlc_hw->regs; + + brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3, + bcn); + /* write beacon length to SCR */ + brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len); + /* mark beacon1 valid */ + OR_REG(®s->maccommand, MCMD_BCN1VLD); +} + +/* mac is assumed to be suspended at this point */ +void +brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw, void *bcn, + int len, bool both) +{ + d11regs_t *regs = wlc_hw->regs; + + if (both) { + brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len); + brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len); + } else { + /* bcn 0 */ + if (!(R_REG(®s->maccommand) & MCMD_BCN0VLD)) + brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len); + /* bcn 1 */ + else if (! + (R_REG(®s->maccommand) & MCMD_BCN1VLD)) + brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len); + } +} + +static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw) +{ + u16 v; + struct brcms_c_info *wlc = wlc_hw->wlc; + /* update SYNTHPU_DLY */ + + if (BRCMS_ISLCNPHY(wlc->band)) { + v = SYNTHPU_DLY_LPPHY_US; + } else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) { + v = SYNTHPU_DLY_NPHY_US; + } else { + v = SYNTHPU_DLY_BPHY_US; + } + + brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v); +} + +/* band-specific init */ +static void +brcms_b_bsinit(struct brcms_c_info *wlc, chanspec_t chanspec) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + + BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, + wlc_hw->band->bandunit); + + brcms_c_ucode_bsinit(wlc_hw); + + wlc_phy_init(wlc_hw->band->pi, chanspec); + + brcms_c_ucode_txant_set(wlc_hw); + + /* cwmin is band-specific, update hardware with value for current band */ + brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin); + brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax); + + brcms_b_update_slot_timing(wlc_hw, + BAND_5G(wlc_hw->band-> + bandtype) ? true : wlc_hw-> + shortslot); + + /* write phytype and phyvers */ + brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype); + brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev); + + /* initialize the txphyctl1 rate table since shmem is shared between bands */ + brcms_upd_ofdm_pctl1_table(wlc_hw); + + brcms_b_upd_synthpu(wlc_hw); +} + +static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) +{ + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk); + + wlc_hw->phyclk = clk; + + if (OFF == clk) { /* clear gmode bit, put phy into reset */ + + ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE), + (SICF_PRST | SICF_FGC)); + udelay(1); + ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST); + udelay(1); + + } else { /* take phy out of reset */ + + ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC); + udelay(1); + ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0); + udelay(1); + + } +} + +/* Perform a soft reset of the PHY PLL */ +void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw) +{ + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + ai_corereg(wlc_hw->sih, SI_CC_IDX, + offsetof(chipcregs_t, chipcontrol_addr), ~0, 0); + udelay(1); + ai_corereg(wlc_hw->sih, SI_CC_IDX, + offsetof(chipcregs_t, chipcontrol_data), 0x4, 0); + udelay(1); + ai_corereg(wlc_hw->sih, SI_CC_IDX, + offsetof(chipcregs_t, chipcontrol_data), 0x4, 4); + udelay(1); + ai_corereg(wlc_hw->sih, SI_CC_IDX, + offsetof(chipcregs_t, chipcontrol_data), 0x4, 0); + udelay(1); +} + +/* light way to turn on phy clock without reset for NPHY only + * refer to brcms_b_core_phy_clk for full version + */ +void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk) +{ + /* support(necessary for NPHY and HYPHY) only */ + if (!BRCMS_ISNPHY(wlc_hw->band)) + return; + + if (ON == clk) + ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC); + else + ai_core_cflags(wlc_hw->sih, SICF_FGC, 0); + +} + +void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk) +{ + if (ON == clk) + ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE); + else + ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0); +} + +void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) +{ + struct brcms_phy_pub *pih = wlc_hw->band->pi; + u32 phy_bw_clkbits; + bool phy_in_reset = false; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + if (pih == NULL) + return; + + phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi); + + /* Specific reset sequence required for NPHY rev 3 and 4 */ + if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) && + NREV_LE(wlc_hw->band->phyrev, 4)) { + /* Set the PHY bandwidth */ + ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits); + + udelay(1); + + /* Perform a soft reset of the PHY PLL */ + brcms_b_core_phypll_reset(wlc_hw); + + /* reset the PHY */ + ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE), + (SICF_PRST | SICF_PCLKE)); + phy_in_reset = true; + } else { + + ai_core_cflags(wlc_hw->sih, + (SICF_PRST | SICF_PCLKE | SICF_BWMASK), + (SICF_PRST | SICF_PCLKE | phy_bw_clkbits)); + } + + udelay(2); + brcms_b_core_phy_clk(wlc_hw, ON); + + if (pih) + wlc_phy_anacore(pih, ON); +} + +/* switch to and initialize new band */ +static void +brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit, + chanspec_t chanspec) { + struct brcms_c_info *wlc = wlc_hw->wlc; + u32 macintmask; + + /* Enable the d11 core before accessing it */ + if (!ai_iscoreup(wlc_hw->sih)) { + ai_core_reset(wlc_hw->sih, 0, 0); + brcms_c_mctrl_reset(wlc_hw); + } + + macintmask = brcms_c_setband_inact(wlc, bandunit); + + if (!wlc_hw->up) + return; + + brcms_b_core_phy_clk(wlc_hw, ON); + + /* band-specific initializations */ + brcms_b_bsinit(wlc, chanspec); + + /* + * If there are any pending software interrupt bits, + * then replace these with a harmless nonzero value + * so brcms_c_dpc() will re-enable interrupts when done. + */ + if (wlc->macintstatus) + wlc->macintstatus = MI_DMAINT; + + /* restore macintmask */ + brcms_intrsrestore(wlc->wl, macintmask); + + /* ucode should still be suspended.. */ + WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); +} + +/* low-level band switch utility routine */ +void brcms_c_setxband(struct brcms_hardware *wlc_hw, + uint bandunit) +{ + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, + bandunit); + + wlc_hw->band = wlc_hw->bandstate[bandunit]; + + /* BMAC_NOTE: until we eliminate need for wlc->band refs in low level code */ + wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit]; + + /* set gmode core flag */ + if (wlc_hw->sbclk && !wlc_hw->noreset) { + ai_core_cflags(wlc_hw->sih, SICF_GMODE, + ((bandunit == 0) ? SICF_GMODE : 0)); + } +} + +static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw) +{ + + /* reject unsupported corerev */ + if (!VALID_COREREV(wlc_hw->corerev)) { + wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n", + wlc_hw->corerev); + return false; + } + + return true; +} + +/* Validate some board info parameters */ +static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw) +{ + uint boardrev = wlc_hw->boardrev; + + /* 4 bits each for board type, major, minor, and tiny version */ + uint brt = (boardrev & 0xf000) >> 12; + uint b0 = (boardrev & 0xf00) >> 8; + uint b1 = (boardrev & 0xf0) >> 4; + uint b2 = boardrev & 0xf; + + /* voards from other vendors are always considered valid */ + if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM) + return true; + + /* do some boardrev sanity checks when boardvendor is Broadcom */ + if (boardrev == 0) + return false; + + if (boardrev <= 0xff) + return true; + + if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9) + || (b2 > 9)) + return false; + + return true; +} + +static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw) +{ + const char *varname = "macaddr"; + char *macaddr; + + /* If macaddr exists, use it (Sromrev4, CIS, ...). */ + macaddr = getvar(wlc_hw->vars, varname); + if (macaddr != NULL) + return macaddr; + + if (NBANDS_HW(wlc_hw) > 1) + varname = "et1macaddr"; + else + varname = "il0macaddr"; + + macaddr = getvar(wlc_hw->vars, varname); + if (macaddr == NULL) { + wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr " + "getvar(%s) not found\n", wlc_hw->unit, varname); + } + + return macaddr; +} + +/* + * Return true if radio is disabled, otherwise false. + * hw radio disable signal is an external pin, users activate it asynchronously + * this function could be called when driver is down and w/o clock + * it operates on different registers depending on corerev and boardflag. + */ +bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) +{ + bool v, clk, xtal; + u32 resetbits = 0, flags = 0; + + xtal = wlc_hw->sbclk; + if (!xtal) + brcms_b_xtal(wlc_hw, ON); + + /* may need to take core out of reset first */ + clk = wlc_hw->clk; + if (!clk) { + /* + * mac no longer enables phyclk automatically when driver + * accesses phyreg throughput mac. This can be skipped since + * only mac reg is accessed below + */ + flags |= SICF_PCLKE; + + /* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */ + if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || + (wlc_hw->sih->chip == BCM43225_CHIP_ID)) + wlc_hw->regs = + (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID, + 0); + ai_core_reset(wlc_hw->sih, flags, resetbits); + brcms_c_mctrl_reset(wlc_hw); + } + + v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0); + + /* put core back into reset */ + if (!clk) + ai_core_disable(wlc_hw->sih, 0); + + if (!xtal) + brcms_b_xtal(wlc_hw, OFF); + + return v; +} + +/* Initialize just the hardware when coming out of POR or S3/S5 system states */ +void brcms_b_hw_up(struct brcms_hardware *wlc_hw) +{ + if (wlc_hw->wlc->pub->hw_up) + return; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + /* + * Enable pll and xtal, initialize the power control registers, + * and force fastclock for the remainder of brcms_c_up(). + */ + brcms_b_xtal(wlc_hw, ON); + ai_clkctl_init(wlc_hw->sih); + brcms_b_clkctl_clk(wlc_hw, CLK_FAST); + + if (wlc_hw->sih->bustype == PCI_BUS) { + ai_pci_fixcfg(wlc_hw->sih); + + /* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */ + if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || + (wlc_hw->sih->chip == BCM43225_CHIP_ID)) + wlc_hw->regs = + (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID, + 0); + } + + /* Inform phy that a POR reset has occurred so it does a complete phy init */ + wlc_phy_por_inform(wlc_hw->band->pi); + + wlc_hw->ucode_loaded = false; + wlc_hw->wlc->pub->hw_up = true; + + if ((wlc_hw->boardflags & BFL_FEM) + && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) { + if (! + (wlc_hw->boardrev >= 0x1250 + && (wlc_hw->boardflags & BFL_FEM_BT))) + ai_epa_4313war(wlc_hw->sih); + } +} + +static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo) +{ + struct dma_pub *di = wlc_hw->di[fifo]; + return dma_rxreset(di); +} + +/* d11 core reset + * ensure fask clock during reset + * reset dma + * reset d11(out of reset) + * reset phy(out of reset) + * clear software macintstatus for fresh new start + * one testing hack wlc_hw->noreset will bypass the d11/phy reset + */ +void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) +{ + d11regs_t *regs; + uint i; + bool fastclk; + u32 resetbits = 0; + + if (flags == BRCMS_USE_COREFLAGS) + flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0); + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + regs = wlc_hw->regs; + + /* request FAST clock if not on */ + fastclk = wlc_hw->forcefastclk; + if (!fastclk) + brcms_b_clkctl_clk(wlc_hw, CLK_FAST); + + /* reset the dma engines except first time thru */ + if (ai_iscoreup(wlc_hw->sih)) { + for (i = 0; i < NFIFO; i++) + if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) { + wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: " + "dma_txreset[%d]: cannot stop dma\n", + wlc_hw->unit, __func__, i); + } + + if ((wlc_hw->di[RX_FIFO]) + && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) { + wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset" + "[%d]: cannot stop dma\n", + wlc_hw->unit, __func__, RX_FIFO); + } + } + /* if noreset, just stop the psm and return */ + if (wlc_hw->noreset) { + wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */ + brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0); + return; + } + + /* + * mac no longer enables phyclk automatically when driver accesses + * phyreg throughput mac, AND phy_reset is skipped at early stage when + * band->pi is invalid. need to enable PHY CLK + */ + flags |= SICF_PCLKE; + + /* reset the core + * In chips with PMU, the fastclk request goes through d11 core reg 0x1e0, which + * is cleared by the core_reset. have to re-request it. + * This adds some delay and we can optimize it by also requesting fastclk through + * chipcommon during this period if necessary. But that has to work coordinate + * with other driver like mips/arm since they may touch chipcommon as well. + */ + wlc_hw->clk = false; + ai_core_reset(wlc_hw->sih, flags, resetbits); + wlc_hw->clk = true; + if (wlc_hw->band && wlc_hw->band->pi) + wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true); + + brcms_c_mctrl_reset(wlc_hw); + + if (PMUCTL_ENAB(wlc_hw->sih)) + brcms_b_clkctl_clk(wlc_hw, CLK_FAST); + + brcms_b_phy_reset(wlc_hw); + + /* turn on PHY_PLL */ + brcms_b_core_phypll_ctl(wlc_hw, true); + + /* clear sw intstatus */ + wlc_hw->wlc->macintstatus = 0; + + /* restore the clk setting */ + if (!fastclk) + brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); +} + +/* txfifo sizes needs to be modified(increased) since the newer cores + * have more memory. + */ +static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw) +{ + d11regs_t *regs = wlc_hw->regs; + u16 fifo_nu; + u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk; + u16 txfifo_def, txfifo_def1; + u16 txfifo_cmd; + + /* tx fifos start at TXFIFO_START_BLK from the Base address */ + txfifo_startblk = TXFIFO_START_BLK; + + /* sequence of operations: reset fifo, set fifo size, reset fifo */ + for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) { + + txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu]; + txfifo_def = (txfifo_startblk & 0xff) | + (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT); + txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) | + ((((txfifo_endblk - + 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT); + txfifo_cmd = + TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT); + + W_REG(®s->xmtfifocmd, txfifo_cmd); + W_REG(®s->xmtfifodef, txfifo_def); + W_REG(®s->xmtfifodef1, txfifo_def1); + + W_REG(®s->xmtfifocmd, txfifo_cmd); + + txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu]; + } + /* + * need to propagate to shm location to be in sync since ucode/hw won't + * do this + */ + brcms_b_write_shm(wlc_hw, M_FIFOSIZE0, + wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]); + brcms_b_write_shm(wlc_hw, M_FIFOSIZE1, + wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]); + brcms_b_write_shm(wlc_hw, M_FIFOSIZE2, + ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw-> + xmtfifo_sz[TX_AC_BK_FIFO])); + brcms_b_write_shm(wlc_hw, M_FIFOSIZE3, + ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw-> + xmtfifo_sz[TX_BCMC_FIFO])); +} + +/* d11 core init + * reset PSM + * download ucode/PCM + * let ucode run to suspended + * download ucode inits + * config other core registers + * init dma + */ +static void brcms_b_coreinit(struct brcms_c_info *wlc) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + d11regs_t *regs; + u32 sflags; + uint bcnint_us; + uint i = 0; + bool fifosz_fixup = false; + int err = 0; + u16 buf[NFIFO]; + struct wiphy *wiphy = wlc->wiphy; + + regs = wlc_hw->regs; + + BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); + + /* reset PSM */ + brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE)); + + brcms_ucode_download(wlc_hw); + /* + * FIFOSZ fixup. driver wants to controls the fifo allocation. + */ + fifosz_fixup = true; + + /* let the PSM run to the suspended state, set mode to BSS STA */ + W_REG(®s->macintstatus, -1); + brcms_b_mctrl(wlc_hw, ~0, + (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE)); + + /* wait for ucode to self-suspend after auto-init */ + SPINWAIT(((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0), + 1000 * 1000); + if ((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0) + wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-" + "suspend!\n", wlc_hw->unit); + + brcms_c_gpio_init(wlc); + + sflags = ai_core_sflags(wlc_hw->sih, 0, 0); + + if (D11REV_IS(wlc_hw->corerev, 23)) { + if (BRCMS_ISNPHY(wlc_hw->band)) + brcms_c_write_inits(wlc_hw, d11n0initvals16); + else + wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" + " %d\n", __func__, wlc_hw->unit, + wlc_hw->corerev); + } else if (D11REV_IS(wlc_hw->corerev, 24)) { + if (BRCMS_ISLCNPHY(wlc_hw->band)) { + brcms_c_write_inits(wlc_hw, d11lcn0initvals24); + } else { + wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" + " %d\n", __func__, wlc_hw->unit, + wlc_hw->corerev); + } + } else { + wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", + __func__, wlc_hw->unit, wlc_hw->corerev); + } + + /* For old ucode, txfifo sizes needs to be modified(increased) */ + if (fifosz_fixup == true) { + brcms_b_corerev_fifofixup(wlc_hw); + } + + /* check txfifo allocations match between ucode and driver */ + buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0); + if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) { + i = TX_AC_BE_FIFO; + err = -1; + } + buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1); + if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) { + i = TX_AC_VI_FIFO; + err = -1; + } + buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2); + buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff; + buf[TX_AC_BK_FIFO] &= 0xff; + if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) { + i = TX_AC_BK_FIFO; + err = -1; + } + if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) { + i = TX_AC_VO_FIFO; + err = -1; + } + buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3); + buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff; + buf[TX_BCMC_FIFO] &= 0xff; + if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) { + i = TX_BCMC_FIFO; + err = -1; + } + if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) { + i = TX_ATIM_FIFO; + err = -1; + } + if (err != 0) { + wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d" + " driver size %d index %d\n", buf[i], + wlc_hw->xmtfifo_sz[i], i); + } + + /* make sure we can still talk to the mac */ + WARN_ON(R_REG(®s->maccontrol) == 0xffffffff); + + /* band-specific inits done by wlc_bsinit() */ + + /* Set up frame burst size and antenna swap threshold init values */ + brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST); + brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT); + + /* enable one rx interrupt per received frame */ + W_REG(®s->intrcvlazy[0], (1 << IRL_FC_SHIFT)); + + /* set the station mode (BSS STA) */ + brcms_b_mctrl(wlc_hw, + (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP), + (MCTL_INFRA | MCTL_DISCARD_PMQ)); + + /* set up Beacon interval */ + bcnint_us = 0x8000 << 10; + W_REG(®s->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT)); + W_REG(®s->tsf_cfpstart, bcnint_us); + W_REG(®s->macintstatus, MI_GP1); + + /* write interrupt mask */ + W_REG(®s->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK); + + /* allow the MAC to control the PHY clock (dynamic on/off) */ + brcms_b_macphyclk_set(wlc_hw, ON); + + /* program dynamic clock control fast powerup delay register */ + wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih); + W_REG(®s->scc_fastpwrup_dly, wlc->fastpwrup_dly); + + /* tell the ucode the corerev */ + brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev); + + /* tell the ucode MAC capabilities */ + brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L, + (u16) (wlc_hw->machwcap & 0xffff)); + brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H, + (u16) ((wlc_hw-> + machwcap >> 16) & 0xffff)); + + /* write retry limits to SCR, this done after PSM init */ + W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); + (void)R_REG(®s->objaddr); + W_REG(®s->objdata, wlc_hw->SRL); + W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); + (void)R_REG(®s->objaddr); + W_REG(®s->objdata, wlc_hw->LRL); + + /* write rate fallback retry limits */ + brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL); + brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL); + + AND_REG(®s->ifs_ctl, 0x0FFF); + W_REG(®s->ifs_aifsn, EDCF_AIFSN_MIN); + + /* dma initializations */ + wlc->txpend16165war = 0; + + /* init the tx dma engines */ + for (i = 0; i < NFIFO; i++) { + if (wlc_hw->di[i]) + dma_txinit(wlc_hw->di[i]); + } + + /* init the rx dma engine(s) and post receive buffers */ + dma_rxinit(wlc_hw->di[RX_FIFO]); + dma_rxfill(wlc_hw->di[RX_FIFO]); +} + +/* This function is used for changing the tsf frac register + * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz + * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz + * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz + * HTPHY Formula is 2^26/freq(MHz) e.g. + * For spuron2 - 126MHz -> 2^26/126 = 532610.0 + * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082 + * For spuron: 123MHz -> 2^26/123 = 545600.5 + * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341 + * For spur off: 120MHz -> 2^26/120 = 559240.5 + * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889 + */ + +void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) +{ + d11regs_t *regs; + regs = wlc_hw->regs; + + if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || + (wlc_hw->sih->chip == BCM43225_CHIP_ID)) { + if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ + W_REG(®s->tsf_clk_frac_l, 0x2082); + W_REG(®s->tsf_clk_frac_h, 0x8); + } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */ + W_REG(®s->tsf_clk_frac_l, 0x5341); + W_REG(®s->tsf_clk_frac_h, 0x8); + } else { /* 120Mhz */ + W_REG(®s->tsf_clk_frac_l, 0x8889); + W_REG(®s->tsf_clk_frac_h, 0x8); + } + } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { + if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */ + W_REG(®s->tsf_clk_frac_l, 0x7CE0); + W_REG(®s->tsf_clk_frac_h, 0xC); + } else { /* 80Mhz */ + W_REG(®s->tsf_clk_frac_l, 0xCCCD); + W_REG(®s->tsf_clk_frac_h, 0xC); + } + } +} + +/* Initialize GPIOs that are controlled by D11 core */ +static void brcms_c_gpio_init(struct brcms_c_info *wlc) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + d11regs_t *regs; + u32 gc, gm; + + regs = wlc_hw->regs; + + /* use GPIO select 0 to get all gpio signals from the gpio out reg */ + brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0); + + /* + * Common GPIO setup: + * G0 = LED 0 = WLAN Activity + * G1 = LED 1 = WLAN 2.4 GHz Radio State + * G2 = LED 2 = WLAN 5 GHz Radio State + * G4 = radio disable input (HI enabled, LO disabled) + */ + + gc = gm = 0; + + /* Allocate GPIOs for mimo antenna diversity feature */ + if (wlc_hw->antsel_type == ANTSEL_2x3) { + /* Enable antenna diversity, use 2x3 mode */ + brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, + MHF3_ANTSEL_EN, BRCM_BAND_ALL); + brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, + MHF3_ANTSEL_MODE, BRCM_BAND_ALL); + + /* init superswitch control */ + wlc_phy_antsel_init(wlc_hw->band->pi, false); + + } else if (wlc_hw->antsel_type == ANTSEL_2x4) { + gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13); + /* + * The board itself is powered by these GPIOs + * (when not sending pattern) so set them high + */ + OR_REG(®s->psm_gpio_oe, + (BOARD_GPIO_12 | BOARD_GPIO_13)); + OR_REG(®s->psm_gpio_out, + (BOARD_GPIO_12 | BOARD_GPIO_13)); + + /* Enable antenna diversity, use 2x4 mode */ + brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, + MHF3_ANTSEL_EN, BRCM_BAND_ALL); + brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0, + BRCM_BAND_ALL); + + /* Configure the desired clock to be 4Mhz */ + brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV, + ANTSEL_CLKDIV_4MHZ); + } + + /* gpio 9 controls the PA. ucode is responsible for wiggling out and oe */ + if (wlc_hw->boardflags & BFL_PACTRL) + gm |= gc |= BOARD_GPIO_PACTRL; + + /* apply to gpiocontrol register */ + ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY); +} + +static void brcms_ucode_download(struct brcms_hardware *wlc_hw) +{ + struct brcms_c_info *wlc; + wlc = wlc_hw->wlc; + + if (wlc_hw->ucode_loaded) + return; + + if (D11REV_IS(wlc_hw->corerev, 23)) { + if (BRCMS_ISNPHY(wlc_hw->band)) { + brcms_ucode_write(wlc_hw, bcm43xx_16_mimo, + bcm43xx_16_mimosz); + wlc_hw->ucode_loaded = true; + } else + wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " + "corerev %d\n", + __func__, wlc_hw->unit, wlc_hw->corerev); + } else if (D11REV_IS(wlc_hw->corerev, 24)) { + if (BRCMS_ISLCNPHY(wlc_hw->band)) { + brcms_ucode_write(wlc_hw, bcm43xx_24_lcn, + bcm43xx_24_lcnsz); + wlc_hw->ucode_loaded = true; + } else { + wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " + "corerev %d\n", + __func__, wlc_hw->unit, wlc_hw->corerev); + } + } +} + +static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[], + const uint nbytes) { + d11regs_t *regs = wlc_hw->regs; + uint i; + uint count; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + count = (nbytes / sizeof(u32)); + + W_REG(®s->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL)); + (void)R_REG(®s->objaddr); + for (i = 0; i < count; i++) + W_REG(®s->objdata, ucode[i]); +} + +static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, + const struct d11init *inits) +{ + int i; + volatile u8 *base; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + base = (volatile u8 *)wlc_hw->regs; + + for (i = 0; inits[i].addr != 0xffff; i++) { + if (inits[i].size == 2) + W_REG((u16 *)(base + inits[i].addr), + inits[i].value); + else if (inits[i].size == 4) + W_REG((u32 *)(base + inits[i].addr), + inits[i].value); + } +} + +static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw) +{ + u16 phyctl; + u16 phytxant = wlc_hw->bmac_phytxant; + u16 mask = PHY_TXC_ANT_MASK; + + /* set the Probe Response frame phy control word */ + phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS); + phyctl = (phyctl & ~mask) | phytxant; + brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl); + + /* set the Response (ACK/CTS) frame phy control word */ + phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD); + phyctl = (phyctl & ~mask) | phytxant; + brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl); +} + +void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant) +{ + /* update sw state */ + wlc_hw->bmac_phytxant = phytxant; + + /* push to ucode if up */ + if (!wlc_hw->up) + return; + brcms_c_ucode_txant_set(wlc_hw); + +} + +u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw) +{ + return (u16) wlc_hw->wlc->stf->txant; +} + +void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type) +{ + wlc_hw->antsel_type = antsel_type; + + /* Update the antsel type for phy module to use */ + wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type); +} + +void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) +{ + bool fatal = false; + uint unit; + uint intstatus, idx; + d11regs_t *regs = wlc_hw->regs; + struct wiphy *wiphy = wlc_hw->wlc->wiphy; + + unit = wlc_hw->unit; + + for (idx = 0; idx < NFIFO; idx++) { + /* read intstatus register and ignore any non-error bits */ + intstatus = + R_REG(®s->intctrlregs[idx].intstatus) & I_ERRORS; + if (!intstatus) + continue; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n", + unit, idx, intstatus); + + if (intstatus & I_RO) { + wiphy_err(wiphy, "wl%d: fifo %d: receive fifo " + "overflow\n", unit, idx); + fatal = true; + } + + if (intstatus & I_PC) { + wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n", + unit, idx); + fatal = true; + } + + if (intstatus & I_PD) { + wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit, + idx); + fatal = true; + } + + if (intstatus & I_DE) { + wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol " + "error\n", unit, idx); + fatal = true; + } + + if (intstatus & I_RU) { + wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor " + "underflow\n", idx, unit); + } + + if (intstatus & I_XU) { + wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo " + "underflow\n", idx, unit); + fatal = true; + } + + if (fatal) { + brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */ + break; + } else + W_REG(®s->intctrlregs[idx].intstatus, + intstatus); + } +} + +void brcms_c_intrson(struct brcms_c_info *wlc) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + wlc->macintmask = wlc->defmacintmask; + W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); +} + +/* callback for siutils.c, which has only wlc handler, no wl + * they both check up, not only because there is no need to off/restore d11 interrupt + * but also because per-port code may require sync with valid interrupt. + */ + +static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc) +{ + if (!wlc->hw->up) + return 0; + + return brcms_intrsoff(wlc->wl); +} + +static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask) +{ + if (!wlc->hw->up) + return; + + brcms_intrsrestore(wlc->wl, macintmask); +} + +u32 brcms_c_intrsoff(struct brcms_c_info *wlc) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + u32 macintmask; + + if (!wlc_hw->clk) + return 0; + + macintmask = wlc->macintmask; /* isr can still happen */ + + W_REG(&wlc_hw->regs->macintmask, 0); + (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */ + udelay(1); /* ensure int line is no longer driven */ + wlc->macintmask = 0; + + /* return previous macintmask; resolve race between us and our isr */ + return wlc->macintstatus ? 0 : macintmask; +} + +void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + if (!wlc_hw->clk) + return; + + wlc->macintmask = macintmask; + W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); +} + +static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, mbool flags) +{ + u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; + + if (on) { + /* suspend tx fifos */ + brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO); + brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO); + brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO); + brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO); + + /* zero the address match register so we do not send ACKs */ + brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, + null_ether_addr); + } else { + /* resume tx fifos */ + if (!wlc_hw->wlc->tx_suspended) { + brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO); + } + brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO); + brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO); + brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO); + + /* Restore address */ + brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, + wlc_hw->etheraddr); + } + + wlc_phy_mute_upd(wlc_hw->band->pi, on, flags); + + if (on) + brcms_c_ucode_mute_override_set(wlc_hw); + else + brcms_c_ucode_mute_override_clear(wlc_hw); +} + +int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, + uint *blocks) +{ + if (fifo >= NFIFO) + return -EINVAL; + + *blocks = wlc_hw->xmtfifo_sz[fifo]; + + return 0; +} + +/* brcms_b_tx_fifo_suspended: + * Check the MAC's tx suspend status for a tx fifo. + * + * When the MAC acknowledges a tx suspend, it indicates that no more + * packets will be transmitted out the radio. This is independent of + * DMA channel suspension---the DMA may have finished suspending, or may still + * be pulling data into a tx fifo, by the time the MAC acks the suspend + * request. + */ +static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw, + uint tx_fifo) +{ + /* check that a suspend has been requested and is no longer pending */ + + /* + * for DMA mode, the suspend request is set in xmtcontrol of the DMA engine, + * and the tx fifo suspend at the lower end of the MAC is acknowledged in the + * chnstatus register. + * The tx fifo suspend completion is independent of the DMA suspend completion and + * may be acked before or after the DMA is suspended. + */ + if (dma_txsuspended(wlc_hw->di[tx_fifo]) && + (R_REG(&wlc_hw->regs->chnstatus) & + (1 << tx_fifo)) == 0) + return true; + + return false; +} + +static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw, + uint tx_fifo) +{ + u8 fifo = 1 << tx_fifo; + + /* Two clients of this code, 11h Quiet period and scanning. */ + + /* only suspend if not already suspended */ + if ((wlc_hw->suspended_fifos & fifo) == fifo) + return; + + /* force the core awake only if not already */ + if (wlc_hw->suspended_fifos == 0) + brcms_c_ucode_wake_override_set(wlc_hw, + BRCMS_WAKE_OVERRIDE_TXFIFO); + + wlc_hw->suspended_fifos |= fifo; + + if (wlc_hw->di[tx_fifo]) { + /* Suspending AMPDU transmissions in the middle can cause underflow + * which may result in mismatch between ucode and driver + * so suspend the mac before suspending the FIFO + */ + if (BRCMS_PHY_11N_CAP(wlc_hw->band)) + brcms_c_suspend_mac_and_wait(wlc_hw->wlc); + + dma_txsuspend(wlc_hw->di[tx_fifo]); + + if (BRCMS_PHY_11N_CAP(wlc_hw->band)) + brcms_c_enable_mac(wlc_hw->wlc); + } +} + +static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw, + uint tx_fifo) +{ + /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case + * but need to be done here for PIO otherwise the watchdog will catch + * the inconsistency and fire + */ + /* Two clients of this code, 11h Quiet period and scanning. */ + if (wlc_hw->di[tx_fifo]) + dma_txresume(wlc_hw->di[tx_fifo]); + + /* allow core to sleep again */ + if (wlc_hw->suspended_fifos == 0) + return; + else { + wlc_hw->suspended_fifos &= ~(1 << tx_fifo); + if (wlc_hw->suspended_fifos == 0) + brcms_c_ucode_wake_override_clear(wlc_hw, + BRCMS_WAKE_OVERRIDE_TXFIFO); + } +} + +/* + * Read and clear macintmask and macintstatus and intstatus registers. + * This routine should be called with interrupts off + * Return: + * -1 if DEVICEREMOVED(wlc) evaluates to true; + * 0 if the interrupt is not for us, or we are in some special cases; + * device interrupt status bits otherwise. + */ +static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + d11regs_t *regs = wlc_hw->regs; + u32 macintstatus; + + /* macintstatus includes a DMA interrupt summary bit */ + macintstatus = R_REG(®s->macintstatus); + + BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit, + macintstatus); + + /* detect cardbus removed, in power down(suspend) and in reset */ + if (DEVICEREMOVED(wlc)) + return -1; + + /* DEVICEREMOVED succeeds even when the core is still resetting, + * handle that case here. + */ + if (macintstatus == 0xffffffff) + return 0; + + /* defer unsolicited interrupts */ + macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask); + + /* if not for us */ + if (macintstatus == 0) + return 0; + + /* interrupts are already turned off for CFE build + * Caution: For CFE Turning off the interrupts again has some undesired + * consequences + */ + /* turn off the interrupts */ + W_REG(®s->macintmask, 0); + (void)R_REG(®s->macintmask); /* sync readback */ + wlc->macintmask = 0; + + /* clear device interrupts */ + W_REG(®s->macintstatus, macintstatus); + + /* MI_DMAINT is indication of non-zero intstatus */ + if (macintstatus & MI_DMAINT) { + /* + * only fifo interrupt enabled is I_RI in + * RX_FIFO. If MI_DMAINT is set, assume it + * is set and clear the interrupt. + */ + W_REG(®s->intctrlregs[RX_FIFO].intstatus, + DEF_RXINTMASK); + } + + return macintstatus; +} + +/* Update wlc->macintstatus and wlc->intstatus[]. */ +/* Return true if they are updated successfully. false otherwise */ +bool brcms_c_intrsupd(struct brcms_c_info *wlc) +{ + u32 macintstatus; + + /* read and clear macintstatus and intstatus registers */ + macintstatus = wlc_intstatus(wlc, false); + + /* device is removed */ + if (macintstatus == 0xffffffff) + return false; + + /* update interrupt status in software */ + wlc->macintstatus |= macintstatus; + + return true; +} + +/* + * First-level interrupt processing. + * Return true if this was our interrupt, false otherwise. + * *wantdpc will be set to true if further brcms_c_dpc() processing is required, + * false otherwise. + */ +bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + u32 macintstatus; + + *wantdpc = false; + + if (!wlc_hw->up || !wlc->macintmask) + return false; + + /* read and clear macintstatus and intstatus registers */ + macintstatus = wlc_intstatus(wlc, true); + + if (macintstatus == 0xffffffff) + wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code" + " path\n"); + + /* it is not for us */ + if (macintstatus == 0) + return false; + + *wantdpc = true; + + /* save interrupt status bits */ + wlc->macintstatus = macintstatus; + + return true; + +} + +static bool +brcms_b_dotxstatus(struct brcms_hardware *wlc_hw, struct tx_status *txs, + u32 s2) +{ + /* discard intermediate indications for ucode with one legitimate case: + * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent + * tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts + * transmission count) + */ + if (!(txs->status & TX_STATUS_AMPDU) + && (txs->status & TX_STATUS_INTERMEDIATE)) { + return false; + } + + return brcms_c_dotxstatus(wlc_hw->wlc, txs, s2); +} + +/* process tx completion events in BMAC + * Return true if more tx status need to be processed. false otherwise. + */ +static bool +brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) +{ + bool morepending = false; + struct brcms_c_info *wlc = wlc_hw->wlc; + d11regs_t *regs; + struct tx_status txstatus, *txs; + u32 s1, s2; + uint n = 0; + /* + * Param 'max_tx_num' indicates max. # tx status to process before + * break out. + */ + uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1; + + BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); + + txs = &txstatus; + regs = wlc_hw->regs; + while (!(*fatal) + && (s1 = R_REG(®s->frmtxstatus)) & TXS_V) { + + if (s1 == 0xffffffff) { + wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", + wlc_hw->unit, __func__); + return morepending; + } + + s2 = R_REG(®s->frmtxstatus2); + + txs->status = s1 & TXS_STATUS_MASK; + txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT; + txs->sequence = s2 & TXS_SEQ_MASK; + txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT; + txs->lasttxtime = 0; + + *fatal = brcms_b_dotxstatus(wlc_hw, txs, s2); + + /* !give others some time to run! */ + if (++n >= max_tx_num) + break; + } + + if (*fatal) + return 0; + + if (n >= max_tx_num) + morepending = true; + + if (!pktq_empty(&wlc->pkt_queue->q)) + brcms_c_send_q(wlc); + + return morepending; +} + +void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + d11regs_t *regs = wlc_hw->regs; + u32 mc, mi; + struct wiphy *wiphy = wlc->wiphy; + + BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, + wlc_hw->band->bandunit); + + /* + * Track overlapping suspend requests + */ + wlc_hw->mac_suspend_depth++; + if (wlc_hw->mac_suspend_depth > 1) + return; + + /* force the core awake */ + brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND); + + mc = R_REG(®s->maccontrol); + + if (mc == 0xffffffff) { + wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, + __func__); + brcms_down(wlc->wl); + return; + } + WARN_ON(mc & MCTL_PSM_JMP_0); + WARN_ON(!(mc & MCTL_PSM_RUN)); + WARN_ON(!(mc & MCTL_EN_MAC)); + + mi = R_REG(®s->macintstatus); + if (mi == 0xffffffff) { + wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, + __func__); + brcms_down(wlc->wl); + return; + } + WARN_ON(mi & MI_MACSSPNDD); + + brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0); + + SPINWAIT(!(R_REG(®s->macintstatus) & MI_MACSSPNDD), + BRCMS_MAX_MAC_SUSPEND); + + if (!(R_REG(®s->macintstatus) & MI_MACSSPNDD)) { + wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS" + " and MI_MACSSPNDD is still not on.\n", + wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND); + wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, " + "psm_brc 0x%04x\n", wlc_hw->unit, + R_REG(®s->psmdebug), + R_REG(®s->phydebug), + R_REG(®s->psm_brc)); + } + + mc = R_REG(®s->maccontrol); + if (mc == 0xffffffff) { + wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, + __func__); + brcms_down(wlc->wl); + return; + } + WARN_ON(mc & MCTL_PSM_JMP_0); + WARN_ON(!(mc & MCTL_PSM_RUN)); + WARN_ON(mc & MCTL_EN_MAC); +} + +void brcms_c_enable_mac(struct brcms_c_info *wlc) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + d11regs_t *regs = wlc_hw->regs; + u32 mc, mi; + + BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, + wlc->band->bandunit); + + /* + * Track overlapping suspend requests + */ + wlc_hw->mac_suspend_depth--; + if (wlc_hw->mac_suspend_depth > 0) + return; + + mc = R_REG(®s->maccontrol); + WARN_ON(mc & MCTL_PSM_JMP_0); + WARN_ON(mc & MCTL_EN_MAC); + WARN_ON(!(mc & MCTL_PSM_RUN)); + + brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC); + W_REG(®s->macintstatus, MI_MACSSPNDD); + + mc = R_REG(®s->maccontrol); + WARN_ON(mc & MCTL_PSM_JMP_0); + WARN_ON(!(mc & MCTL_EN_MAC)); + WARN_ON(!(mc & MCTL_PSM_RUN)); + + mi = R_REG(®s->macintstatus); + WARN_ON(mi & MI_MACSSPNDD); + + brcms_c_ucode_wake_override_clear(wlc_hw, + BRCMS_WAKE_OVERRIDE_MACSUSPEND); +} + +static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw) +{ + u8 rate; + u8 rates[8] = { + BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M, + BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M + }; + u16 entry_ptr; + u16 pctl1; + uint i; + + if (!BRCMS_PHY_11N_CAP(wlc_hw->band)) + return; + + /* walk the phy rate table and update the entries */ + for (i = 0; i < ARRAY_SIZE(rates); i++) { + rate = rates[i]; + + entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate); + + /* read the SHM Rate Table entry OFDM PCTL1 values */ + pctl1 = + brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS); + + /* modify the value */ + pctl1 &= ~PHY_TXC1_MODE_MASK; + pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT); + + /* Update the SHM Rate Table entry OFDM PCTL1 values */ + brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS, + pctl1); + } +} + +static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw, + u8 rate) +{ + uint i; + u8 plcp_rate = 0; + struct plcp_signal_rate_lookup { + u8 rate; + u8 signal_rate; + }; + /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */ + const struct plcp_signal_rate_lookup rate_lookup[] = { + {BRCM_RATE_6M, 0xB}, + {BRCM_RATE_9M, 0xF}, + {BRCM_RATE_12M, 0xA}, + {BRCM_RATE_18M, 0xE}, + {BRCM_RATE_24M, 0x9}, + {BRCM_RATE_36M, 0xD}, + {BRCM_RATE_48M, 0x8}, + {BRCM_RATE_54M, 0xC} + }; + + for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) { + if (rate == rate_lookup[i].rate) { + plcp_rate = rate_lookup[i].signal_rate; + break; + } + } + + /* Find the SHM pointer to the rate table entry by looking in the + * Direct-map Table + */ + return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2)); +} + +void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode) +{ + wlc_hw->hw_stf_ss_opmode = stf_mode; + + if (wlc_hw->clk) + brcms_upd_ofdm_pctl1_table(wlc_hw); +} + +void +brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr, + u32 *tsf_h_ptr) +{ + d11regs_t *regs = wlc_hw->regs; + + /* read the tsf timer low, then high to get an atomic read */ + *tsf_l_ptr = R_REG(®s->tsf_timerlow); + *tsf_h_ptr = R_REG(®s->tsf_timerhigh); + + return; +} + +static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw) +{ + d11regs_t *regs; + u32 w, val; + struct wiphy *wiphy = wlc_hw->wlc->wiphy; + + BCMMSG(wiphy, "wl%d\n", wlc_hw->unit); + + regs = wlc_hw->regs; + + /* Validate dchip register access */ + + W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); + (void)R_REG(®s->objaddr); + w = R_REG(®s->objdata); + + /* Can we write and read back a 32bit register? */ + W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); + (void)R_REG(®s->objaddr); + W_REG(®s->objdata, (u32) 0xaa5555aa); + + W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); + (void)R_REG(®s->objaddr); + val = R_REG(®s->objdata); + if (val != (u32) 0xaa5555aa) { + wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " + "expected 0xaa5555aa\n", wlc_hw->unit, val); + return false; + } + + W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); + (void)R_REG(®s->objaddr); + W_REG(®s->objdata, (u32) 0x55aaaa55); + + W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); + (void)R_REG(®s->objaddr); + val = R_REG(®s->objdata); + if (val != (u32) 0x55aaaa55) { + wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " + "expected 0x55aaaa55\n", wlc_hw->unit, val); + return false; + } + + W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); + (void)R_REG(®s->objaddr); + W_REG(®s->objdata, w); + + /* clear CFPStart */ + W_REG(®s->tsf_cfpstart, 0); + + w = R_REG(®s->maccontrol); + if ((w != (MCTL_IHR_EN | MCTL_WAKE)) && + (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) { + wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = " + "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w, + (MCTL_IHR_EN | MCTL_WAKE), + (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE)); + return false; + } + + return true; +} + +#define PHYPLL_WAIT_US 100000 + +void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) +{ + d11regs_t *regs; + u32 tmp; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + tmp = 0; + regs = wlc_hw->regs; + + if (on) { + if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) { + OR_REG(®s->clk_ctl_st, + (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL | + CCS_ERSRC_REQ_PHYPLL)); + SPINWAIT((R_REG(®s->clk_ctl_st) & + (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT), + PHYPLL_WAIT_US); + + tmp = R_REG(®s->clk_ctl_st); + if ((tmp & (CCS_ERSRC_AVAIL_HT)) != + (CCS_ERSRC_AVAIL_HT)) { + wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY" + " PLL failed\n", __func__); + } + } else { + OR_REG(®s->clk_ctl_st, + (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL)); + SPINWAIT((R_REG(®s->clk_ctl_st) & + (CCS_ERSRC_AVAIL_D11PLL | + CCS_ERSRC_AVAIL_PHYPLL)) != + (CCS_ERSRC_AVAIL_D11PLL | + CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US); + + tmp = R_REG(®s->clk_ctl_st); + if ((tmp & + (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) + != + (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) { + wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on " + "PHY PLL failed\n", __func__); + } + } + } else { + /* Since the PLL may be shared, other cores can still be requesting it; + * so we'll deassert the request but not wait for status to comply. + */ + AND_REG(®s->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL); + tmp = R_REG(®s->clk_ctl_st); + } +} + +void brcms_c_coredisable(struct brcms_hardware *wlc_hw) +{ + bool dev_gone; + + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + + dev_gone = DEVICEREMOVED(wlc_hw->wlc); + + if (dev_gone) + return; + + if (wlc_hw->noreset) + return; + + /* radio off */ + wlc_phy_switch_radio(wlc_hw->band->pi, OFF); + + /* turn off analog core */ + wlc_phy_anacore(wlc_hw->band->pi, OFF); + + /* turn off PHYPLL to save power */ + brcms_b_core_phypll_ctl(wlc_hw, false); + + /* No need to set wlc->pub->radio_active = OFF + * because this function needs down capability and + * radio_active is designed for BCMNODOWN. + */ + + /* remove gpio controls */ + if (wlc_hw->ucode_dbgsel) + ai_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY); + + wlc_hw->clk = false; + ai_core_disable(wlc_hw->sih, 0); + wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); +} + +/* power both the pll and external oscillator on/off */ +static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want) +{ + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want); + + /* dont power down if plldown is false or we must poll hw radio disable */ + if (!want && wlc_hw->pllreq) + return; + + if (wlc_hw->sih) + ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want); + + wlc_hw->sbclk = want; + if (!wlc_hw->sbclk) { + wlc_hw->clk = false; + if (wlc_hw->band && wlc_hw->band->pi) + wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); + } +} + +static void brcms_c_flushqueues(struct brcms_c_info *wlc) +{ + struct brcms_hardware *wlc_hw = wlc->hw; + uint i; + + wlc->txpend16165war = 0; + + /* free any posted tx packets */ + for (i = 0; i < NFIFO; i++) + if (wlc_hw->di[i]) { + dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL); + TXPKTPENDCLR(wlc, i); + BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i); + } + + /* free any posted rx packets */ + dma_rxreclaim(wlc_hw->di[RX_FIFO]); +} + +u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset) +{ + return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL); +} + +void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v) +{ + brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL); +} + +static u16 +brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel) +{ + d11regs_t *regs = wlc_hw->regs; + volatile u16 *objdata_lo = (volatile u16 *)®s->objdata; + volatile u16 *objdata_hi = objdata_lo + 1; + u16 v; + + W_REG(®s->objaddr, sel | (offset >> 2)); + (void)R_REG(®s->objaddr); + if (offset & 2) { + v = R_REG(objdata_hi); + } else { + v = R_REG(objdata_lo); + } + + return v; +} + +static void +brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v, + u32 sel) +{ + d11regs_t *regs = wlc_hw->regs; + volatile u16 *objdata_lo = (volatile u16 *)®s->objdata; + volatile u16 *objdata_hi = objdata_lo + 1; + + W_REG(®s->objaddr, sel | (offset >> 2)); + (void)R_REG(®s->objaddr); + if (offset & 2) { + W_REG(objdata_hi, v); + } else { + W_REG(objdata_lo, v); + } +} + +/* Copy a buffer to shared memory of specified type . + * SHM 'offset' needs to be an even address and + * Buffer length 'len' must be an even number of bytes + * 'sel' selects the type of memory + */ +void +brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset, + const void *buf, int len, u32 sel) +{ + u16 v; + const u8 *p = (const u8 *)buf; + int i; + + if (len <= 0 || (offset & 1) || (len & 1)) + return; + + for (i = 0; i < len; i += 2) { + v = p[i] | (p[i + 1] << 8); + brcms_b_write_objmem(wlc_hw, offset + i, v, sel); + } +} + +/* Copy a piece of shared memory of specified type to a buffer . + * SHM 'offset' needs to be an even address and + * Buffer length 'len' must be an even number of bytes + * 'sel' selects the type of memory + */ +void +brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf, + int len, u32 sel) +{ + u16 v; + u8 *p = (u8 *) buf; + int i; + + if (len <= 0 || (offset & 1) || (len & 1)) + return; + + for (i = 0; i < len; i += 2) { + v = brcms_b_read_objmem(wlc_hw, offset + i, sel); + p[i] = v & 0xFF; + p[i + 1] = (v >> 8) & 0xFF; + } +} + +void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf, + uint *len) +{ + BCMMSG(wlc_hw->wlc->wiphy, "nvram vars totlen=%d\n", + wlc_hw->vars_size); + + *buf = wlc_hw->vars; + *len = wlc_hw->vars_size; +} + +void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL, u16 LRL) +{ + wlc_hw->SRL = SRL; + wlc_hw->LRL = LRL; + + /* write retry limit to SCR, shouldn't need to suspend */ + if (wlc_hw->up) { + W_REG(&wlc_hw->regs->objaddr, + OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); + (void)R_REG(&wlc_hw->regs->objaddr); + W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL); + W_REG(&wlc_hw->regs->objaddr, + OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); + (void)R_REG(&wlc_hw->regs->objaddr); + W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL); + } +} + +void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, mbool req_bit) +{ + if (set) { + if (mboolisset(wlc_hw->pllreq, req_bit)) + return; + + mboolset(wlc_hw->pllreq, req_bit); + + if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { + if (!wlc_hw->sbclk) { + brcms_b_xtal(wlc_hw, ON); + } + } + } else { + if (!mboolisset(wlc_hw->pllreq, req_bit)) + return; + + mboolclr(wlc_hw->pllreq, req_bit); + + if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { + if (wlc_hw->sbclk) { + brcms_b_xtal(wlc_hw, OFF); + } + } + } + + return; +} + +u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate) +{ + u16 table_ptr; + u8 phy_rate, index; + + /* get the phy specific rate encoding for the PLCP SIGNAL field */ + if (IS_OFDM(rate)) + table_ptr = M_RT_DIRMAP_A; + else + table_ptr = M_RT_DIRMAP_B; + + /* for a given rate, the LS-nibble of the PLCP SIGNAL field is + * the index into the rate table. + */ + phy_rate = rate_info[rate] & BRCMS_RATE_MASK; + index = phy_rate & 0xf; + + /* Find the SHM pointer to the rate table entry by looking in the + * Direct-map Table + */ + return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2)); +} + +void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail) +{ + wlc_hw->antsel_avail = antsel_avail; +} diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/bmac.h b/trunk/drivers/staging/brcm80211/brcmsmac/bmac.h new file mode 100644 index 000000000000..3c9ad4f3bd22 --- /dev/null +++ b/trunk/drivers/staging/brcm80211/brcmsmac/bmac.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2010 Broadcom Corporation + * + * Permission to use, copy, modify, and/or 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. + */ +#ifndef _BRCM_BOTTOM_MAC_H_ +#define _BRCM_BOTTOM_MAC_H_ + +#include +#include "types.h" + +/* dup state between BMAC(struct brcms_hardware) and HIGH(struct brcms_c_info) + driver */ +struct brcms_b_state { + u32 machwcap; /* mac hw capibility */ + u32 preamble_ovr; /* preamble override */ +}; + +enum { + IOV_BMAC_DIAG, + IOV_BMAC_SBGPIOTIMERVAL, + IOV_BMAC_SBGPIOOUT, + IOV_BMAC_CCGPIOCTRL, /* CC GPIOCTRL REG */ + IOV_BMAC_CCGPIOOUT, /* CC GPIOOUT REG */ + IOV_BMAC_CCGPIOOUTEN, /* CC GPIOOUTEN REG */ + IOV_BMAC_CCGPIOIN, /* CC GPIOIN REG */ + IOV_BMAC_WPSGPIO, /* WPS push button GPIO pin */ + IOV_BMAC_OTPDUMP, + IOV_BMAC_OTPSTAT, + IOV_BMAC_PCIEASPM, /* obfuscation clkreq/aspm control */ + IOV_BMAC_PCIEADVCORRMASK, /* advanced correctable error mask */ + IOV_BMAC_PCIECLKREQ, /* PCIE 1.1 clockreq enab support */ + IOV_BMAC_PCIELCREG, /* PCIE LCREG */ + IOV_BMAC_SBGPIOTIMERMASK, + IOV_BMAC_RFDISABLEDLY, + IOV_BMAC_PCIEREG, /* PCIE REG */ + IOV_BMAC_PCICFGREG, /* PCI Config register */ + IOV_BMAC_PCIESERDESREG, /* PCIE SERDES REG (dev, 0}offset) */ + IOV_BMAC_PCIEGPIOOUT, /* PCIEOUT REG */ + IOV_BMAC_PCIEGPIOOUTEN, /* PCIEOUTEN REG */ + IOV_BMAC_PCIECLKREQENCTRL, /* clkreqenctrl REG (PCIE REV > 6.0 */ + IOV_BMAC_DMALPBK, + IOV_BMAC_CCREG, + IOV_BMAC_COREREG, + IOV_BMAC_SDCIS, + IOV_BMAC_SDIO_DRIVE, + IOV_BMAC_OTPW, + IOV_BMAC_NVOTPW, + IOV_BMAC_SROM, + IOV_BMAC_SRCRC, + IOV_BMAC_CIS_SOURCE, + IOV_BMAC_CISVAR, + IOV_BMAC_OTPLOCK, + IOV_BMAC_OTP_CHIPID, + IOV_BMAC_CUSTOMVAR1, + IOV_BMAC_BOARDFLAGS, + IOV_BMAC_BOARDFLAGS2, + IOV_BMAC_WPSLED, + IOV_BMAC_NVRAM_SOURCE, + IOV_BMAC_OTP_RAW_READ, + IOV_BMAC_LAST +}; + +extern int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, + uint unit, bool piomode, void *regsva, uint bustype, + void *btparam); +extern int brcms_b_detach(struct brcms_c_info *wlc); +extern void brcms_b_watchdog(void *arg); + +/* up/down, reset, clk */ +extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, + uint offset, const void *buf, int len, + u32 sel); +extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, + void *buf, int len, u32 sel); +#define brcms_b_copyfrom_shm(wlc_hw, offset, buf, len) \ + brcms_b_copyfrom_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL) +#define brcms_b_copyto_shm(wlc_hw, offset, buf, len) \ + brcms_b_copyto_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL) + +extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw); +extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on); +extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk); +extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk); +extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw); +extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags); +extern void brcms_b_reset(struct brcms_hardware *wlc_hw); +extern void brcms_b_init(struct brcms_hardware *wlc_hw, chanspec_t chanspec, + bool mute); +extern int brcms_b_up_prep(struct brcms_hardware *wlc_hw); +extern int brcms_b_up_finish(struct brcms_hardware *wlc_hw); +extern int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw); +extern int brcms_b_down_finish(struct brcms_hardware *wlc_hw); +extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode); + +/* chanspec, ucode interface */ +extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, + chanspec_t chanspec, + bool mute, struct txpwr_limits *txpwr); + +extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, + uint *blocks); +extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, + u16 val, int bands); +extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val); +extern u16 brcms_b_mhf_get(struct brcms_hardware *wlc_hw, u8 idx, int bands); +extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant); +extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw); +extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, + u8 antsel_type); +extern int brcms_b_state_get(struct brcms_hardware *wlc_hw, + struct brcms_b_state *state); +extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, + u16 v); +extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset); +extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, + int offset, int len, void *buf); +extern void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf, + uint *len); + +extern void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw, + u8 *ea); + +extern bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw); +extern void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, + bool shortslot); +extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, + u8 stf_mode); + +extern void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw); + +extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, + u32 override_bit); +extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, + u32 override_bit); + +extern void brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, + int match_reg_offset, + const u8 *addr); +extern void brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw, + void *bcn, int len, bool both); + +extern void brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr, + u32 *tsf_h_ptr); +extern void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin); +extern void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax); + +extern void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL, + u16 LRL); + +extern void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw); + + +/* API for BMAC driver (e.g. wlc_phy.c etc) */ + +extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw); +extern void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, + mbool req_bit); +extern void brcms_b_hw_up(struct brcms_hardware *wlc_hw); +extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate); +extern void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, + u32 antsel_avail); + +#endif /* _BRCM_BOTTOM_MAC_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/channel.c b/trunk/drivers/staging/brcm80211/brcmsmac/channel.c index 1aad680c7f62..f59693e1d8a2 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/channel.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/channel.c @@ -20,6 +20,7 @@ #include #include "pub.h" #include "phy/phy_hal.h" +#include "bmac.h" #include "main.h" #include "stf.h" #include "channel.h" @@ -30,14 +31,10 @@ #define VALID_CHANNEL20(wlc, val) brcms_c_valid_channel20((wlc)->cmi, val) struct brcms_cm_band { - /* struct locale_info flags */ - u8 locale_flags; - /* List of valid channels in the country */ - struct brcms_chanvec valid_channels; - /* List of restricted use channels */ - const struct brcms_chanvec *restricted_channels; - /* List of radar sensitive channels */ - const struct brcms_chanvec *radar_channels; + u8 locale_flags; /* struct locale_info flags */ + chanvec_t valid_channels; /* List of valid channels in the country */ + const chanvec_t *restricted_channels; /* List of restricted use channels */ + const chanvec_t *radar_channels; /* List of radar sensitive channels */ u8 PAD[8]; }; @@ -53,8 +50,7 @@ struct brcms_cm_info { /* per-band state (one per phy/radio) */ struct brcms_cm_band bandstate[MAXBANDS]; /* quiet channels currently for radar sensitivity or 11h support */ - /* channels on which we cannot transmit */ - struct brcms_chanvec quiet_channels; + chanvec_t quiet_channels; /* channels on which we cannot transmit */ }; static int brcms_c_channels_init(struct brcms_cm_info *wlc_cm, @@ -83,7 +79,7 @@ brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm); static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm); static bool brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, - u16 chspec); + chanspec_t chspec); static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val); static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm, uint bandunit, uint val); @@ -93,7 +89,7 @@ static const struct country_info * brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode); static void brcms_c_locale_get_channels(const struct locale_info *locale, - struct brcms_chanvec *valid_channels); + chanvec_t *valid_channels); static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx); static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx); static bool brcms_c_japan(struct brcms_c_info *wlc); @@ -101,8 +97,8 @@ static bool brcms_c_japan_ccode(const char *ccode); static void brcms_c_channel_min_txpower_limits_with_local_constraint( struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr, u8 local_constraint_qdbm); -static void brcms_c_locale_add_channels(struct brcms_chanvec *target, - const struct brcms_chanvec *channels); +static void brcms_c_locale_add_channels(chanvec_t *target, + const chanvec_t *channels); static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx); static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx); @@ -119,7 +115,7 @@ static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx); */ /* No channels */ -static const struct brcms_chanvec chanvec_none = { +static const chanvec_t chanvec_none = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -127,7 +123,7 @@ static const struct brcms_chanvec chanvec_none = { }; /* All 2.4 GHz HW channels */ -const struct brcms_chanvec chanvec_all_2G = { +const chanvec_t chanvec_all_2G = { {0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -135,7 +131,7 @@ const struct brcms_chanvec chanvec_all_2G = { }; /* All 5 GHz HW channels */ -const struct brcms_chanvec chanvec_all_5G = { +const chanvec_t chanvec_all_5G = { {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11, @@ -149,11 +145,10 @@ const struct brcms_chanvec chanvec_all_5G = { /* No radar */ #define radar_set_none chanvec_none -/* Channels 52 - 64, 100 - 140 */ -static const struct brcms_chanvec radar_set1 = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */ - 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */ - 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */ +static const chanvec_t radar_set1 = { /* Channels 52 - 64, 100 - 140 */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */ + 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */ + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */ 0x00, 0x00, 0x00, 0x00} }; @@ -164,7 +159,7 @@ static const struct brcms_chanvec radar_set1 = { #define restricted_set_none chanvec_none /* Channels 34, 38, 42, 46 */ -static const struct brcms_chanvec restricted_set_japan_legacy = { +static const chanvec_t restricted_set_japan_legacy = { {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -172,7 +167,7 @@ static const struct brcms_chanvec restricted_set_japan_legacy = { }; /* Channels 12, 13 */ -static const struct brcms_chanvec restricted_set_2g_short = { +static const chanvec_t restricted_set_2g_short = { {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -180,7 +175,7 @@ static const struct brcms_chanvec restricted_set_2g_short = { }; /* Channel 165 */ -static const struct brcms_chanvec restricted_chan_165 = { +static const chanvec_t restricted_chan_165 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, @@ -188,7 +183,7 @@ static const struct brcms_chanvec restricted_chan_165 = { }; /* Channels 36 - 48 & 149 - 165 */ -static const struct brcms_chanvec restricted_low_hi = { +static const chanvec_t restricted_low_hi = { {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00, @@ -196,7 +191,7 @@ static const struct brcms_chanvec restricted_low_hi = { }; /* Channels 12 - 14 */ -static const struct brcms_chanvec restricted_set_12_13_14 = { +static const chanvec_t restricted_set_12_13_14 = { {0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -220,19 +215,15 @@ static const struct brcms_chanvec restricted_set_12_13_14 = { #define LOCALE_CHAN_52_140_ALL (1<<14) #define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */ -#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \ - LOCALE_SET_5G_LOW2 | \ - LOCALE_SET_5G_LOW3) -#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3) -#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2) -#define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \ - LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1) -#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3) -#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4 +#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3) +#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3) +#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2) +#define LOCALE_CHAN_100_140 \ + (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1) +#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3) +#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4 -#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \ - LOCALE_CHAN_12_13 | \ - LOCALE_CHAN_14) +#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13 | LOCALE_CHAN_14) #define LOCALE_RADAR_SET_NONE 0 #define LOCALE_RADAR_SET_1 1 @@ -249,12 +240,12 @@ static const struct brcms_chanvec restricted_set_12_13_14 = { /* global memory to provide working buffer for expanded locale */ -static const struct brcms_chanvec *g_table_radar_set[] = { +static const chanvec_t *g_table_radar_set[] = { &chanvec_none, &radar_set1 }; -static const struct brcms_chanvec *g_table_restricted_chan[] = { +static const chanvec_t *g_table_restricted_chan[] = { &chanvec_none, /* restricted_set_none */ &restricted_set_2g_short, &restricted_chan_165, @@ -266,119 +257,119 @@ static const struct brcms_chanvec *g_table_restricted_chan[] = { &restricted_set_12_13_14 }; -static const struct brcms_chanvec locale_2g_01_11 = { +static const chanvec_t locale_2g_01_11 = { {0xfe, 0x0f, 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} }; -static const struct brcms_chanvec locale_2g_12_13 = { +static const chanvec_t locale_2g_12_13 = { {0x00, 0x30, 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} }; -static const struct brcms_chanvec locale_2g_14 = { +static const chanvec_t locale_2g_14 = { {0x00, 0x40, 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} }; -static const struct brcms_chanvec locale_5g_LOW_JP1 = { +static const chanvec_t locale_5g_LOW_JP1 = { {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_LOW_JP2 = { +static const chanvec_t locale_5g_LOW_JP2 = { {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_LOW1 = { +static const chanvec_t locale_5g_LOW1 = { {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_LOW2 = { +static const chanvec_t locale_5g_LOW2 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_LOW3 = { +static const chanvec_t locale_5g_LOW3 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_MID1 = { +static const chanvec_t locale_5g_MID1 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_MID2 = { +static const chanvec_t locale_5g_MID2 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_MID3 = { +static const chanvec_t locale_5g_MID3 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_HIGH1 = { +static const chanvec_t locale_5g_HIGH1 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_HIGH2 = { +static const chanvec_t locale_5g_HIGH2 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_HIGH3 = { +static const chanvec_t locale_5g_HIGH3 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_52_140_ALL = { +static const chanvec_t locale_5g_52_140_ALL = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; -static const struct brcms_chanvec locale_5g_HIGH4 = { +static const chanvec_t locale_5g_HIGH4 = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11} }; -static const struct brcms_chanvec *g_table_locale_base[] = { +static const chanvec_t *g_table_locale_base[] = { &locale_2g_01_11, &locale_2g_12_13, &locale_2g_14, @@ -397,25 +388,27 @@ static const struct brcms_chanvec *g_table_locale_base[] = { &locale_5g_HIGH4 }; -static void brcms_c_locale_add_channels(struct brcms_chanvec *target, - const struct brcms_chanvec *channels) +static void brcms_c_locale_add_channels(chanvec_t *target, + const chanvec_t *channels) { u8 i; - for (i = 0; i < sizeof(struct brcms_chanvec); i++) + for (i = 0; i < sizeof(chanvec_t); i++) { target->vec[i] |= channels->vec[i]; + } } static void brcms_c_locale_get_channels(const struct locale_info *locale, - struct brcms_chanvec *channels) + chanvec_t *channels) { u8 i; - memset(channels, 0, sizeof(struct brcms_chanvec)); + memset(channels, 0, sizeof(chanvec_t)); for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) { - if (locale->valid_channels & (1 << i)) + if (locale->valid_channels & (1 << i)) { brcms_c_locale_add_channels(channels, g_table_locale_base[i]); + } } } @@ -504,8 +497,7 @@ static const struct locale_mimo_info *g_mimo_5g_table[] = { #endif #define LC_5G(id) LOCALE_5G_IDX_ ## id -#define LOCALES(band2, band5, mimo2, mimo5) \ - {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)} +#define LOCALES(band2, band5, mimo2, mimo5) {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)} static const struct { char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */ @@ -594,33 +586,33 @@ struct chan20_info chan20_info[] = { static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx) { - if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) + if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) { return NULL; /* error condition */ - + } return g_locale_2g_table[locale_idx]; } static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx) { - if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) + if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) { return NULL; /* error condition */ - + } return g_locale_5g_table[locale_idx]; } static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx) { - if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) + if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) { return NULL; - + } return g_mimo_2g_table[locale_idx]; } static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx) { - if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) + if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) { return NULL; - + } return g_mimo_5g_table[locale_idx]; } @@ -646,13 +638,11 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) /* store the country code for passing up as a regulatory hint */ ccode = getvar(wlc->pub->vars, "ccode"); - if (ccode) + if (ccode) { strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); + } - /* - * internal country information which must match - * regulatory constraints in firmware - */ + /* internal country information which must match regulatory constraints in firmware */ memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ); strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1); country = brcms_c_country_lookup(wlc, country_abbrev); @@ -680,10 +670,8 @@ brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, return wlc_cm->bandstate[bandunit].locale_flags; } -/* - * set the driver's current country and regulatory information using - * a country code as the source. Lookup built in country information - * found with the country code. +/* set the driver's current country and regulatory information using a country code + * as the source. Lookup built in country information found with the country code. */ static int brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode) @@ -706,10 +694,7 @@ brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm, * otherwise use the ccode and regrev directly */ if (regrev == -1) { - /* - * map the country code to a built-in country - * code, regrev, and country_info - */ + /* map the country code to a built-in country code, regrev, and country_info */ country = brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode, &mapped_regrev); @@ -730,10 +715,8 @@ brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm, return 0; } -/* - * set the driver's current country and regulatory information - * using a country code as the source. Look up built in country - * information found with the country code. +/* set the driver's current country and regulatory information using a country code + * as the source. Look up built in country information found with the country code. */ static void brcms_c_set_country_common(struct brcms_cm_info *wlc_cm, @@ -772,10 +755,11 @@ brcms_c_set_country_common(struct brcms_cm_info *wlc_cm, brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); /* set or restore gmode as required by regulatory */ locale = brcms_c_get_locale_2g(country->locale_2G); - if (locale && (locale->flags & BRCMS_NO_OFDM)) + if (locale && (locale->flags & BRCMS_NO_OFDM)) { brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); - else + } else { brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); + } brcms_c_channels_init(wlc_cm, country); @@ -792,10 +776,7 @@ brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode) char mapped_ccode[BRCM_CNTRY_BUF_SZ]; uint mapped_regrev; - /* - * map the country code to a built-in country code, regrev, and - * country_info struct - */ + /* map the country code to a built-in country code, regrev, and country_info struct */ country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode, &mapped_regrev); @@ -868,18 +849,16 @@ brcms_c_country_lookup_direct(const char *ccode, uint regrev) /* Should just return 0 for single locale driver. */ /* Keep it this way in case we add more locales. (for now anyway) */ - /* - * all other country def arrays are for regrev == 0, so if - * regrev is non-zero, fail - */ + /* all other country def arrays are for regrev == 0, so if regrev is non-zero, fail */ if (regrev > 0) return NULL; /* find matched table entry from country code */ size = ARRAY_SIZE(cntry_locales); for (i = 0; i < size; i++) { - if (strcmp(ccode, cntry_locales[i].abbrev) == 0) + if (strcmp(ccode, cntry_locales[i].abbrev) == 0) { return &cntry_locales[i].country; + } } return NULL; } @@ -892,7 +871,7 @@ brcms_c_channels_init(struct brcms_cm_info *wlc_cm, uint i, j; struct brcms_band *band; const struct locale_info *li; - struct brcms_chanvec sup_chan; + chanvec_t sup_chan; const struct locale_mimo_info *li_mimo; band = wlc->band; @@ -916,16 +895,15 @@ brcms_c_channels_init(struct brcms_cm_info *wlc_cm, wlc_cm->bandstate[band->bandunit].radar_channels = g_table_radar_set[li->radar_channels]; - /* - * set the channel availability, masking out the channels - * that may not be supported on this phy. + /* set the channel availability, + * masking out the channels that may not be supported on this phy */ wlc_phy_chanspec_band_validch(band->pi, band->bandtype, &sup_chan); brcms_c_locale_get_channels(li, &wlc_cm->bandstate[band->bandunit]. valid_channels); - for (j = 0; j < sizeof(struct brcms_chanvec); j++) + for (j = 0; j < sizeof(chanvec_t); j++) wlc_cm->bandstate[band->bandunit].valid_channels. vec[j] &= sup_chan.vec[j]; } @@ -947,43 +925,36 @@ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm) /* search for the existence of any valid channel */ for (chan = 0; chan < MAXCHANNEL; chan++) { - if (VALID_CHANNEL20_DB(wlc, chan)) + if (VALID_CHANNEL20_DB(wlc, chan)) { break; + } } if (chan == MAXCHANNEL) chan = INVCHANNEL; - /* - * based on the channel search above, set or - * clear WL_RADIO_COUNTRY_DISABLE. - */ + /* based on the channel search above, set or clear WL_RADIO_COUNTRY_DISABLE */ if (chan == INVCHANNEL) { - /* - * country/locale with no valid channels, set - * the radio disable bit - */ + /* country/locale with no valid channels, set the radio disable bit */ mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" " "nbands %d bandlocked %d\n", wlc->pub->unit, __func__, wlc_cm->country_abbrev, NBANDS(wlc), wlc->bandlocked); - } else if (mboolisset(wlc->pub->radio_disabled, - WL_RADIO_COUNTRY_DISABLE)) { - /* - * country/locale with valid channel, clear - * the radio disable bit - */ + } else + if (mboolisset(wlc->pub->radio_disabled, + WL_RADIO_COUNTRY_DISABLE)) { + /* country/locale with valid channel, clear the radio disable bit */ mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); } - /* - * Now that the country abbreviation is set, if the radio supports 2G, - * then set channel 14 restrictions based on the new locale. + /* Now that the country abbreviation is set, if the radio supports 2G, then + * set channel 14 restrictions based on the new locale. */ - if (NBANDS(wlc) > 1 || BAND_2G(wlc->band->bandtype)) + if (NBANDS(wlc) > 1 || BAND_2G(wlc->band->bandtype)) { wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, brcms_c_japan(wlc) ? true : false); + } if (wlc->pub->up && chan != INVCHANNEL) { brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr); @@ -993,18 +964,15 @@ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm) } } -/* - * reset the quiet channels vector to the union - * of the restricted and radar channel sets - */ +/* reset the quiet channels vector to the union of the restricted and radar channel sets */ static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm) { struct brcms_c_info *wlc = wlc_cm->wlc; uint i, j; struct brcms_band *band; - const struct brcms_chanvec *chanvec; + const chanvec_t *chanvec; - memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec)); + memset(&wlc_cm->quiet_channels, 0, sizeof(chanvec_t)); band = wlc->band; for (i = 0; i < NBANDS(wlc); @@ -1012,21 +980,25 @@ static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm) /* initialize quiet channels for restricted channels */ chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels; - for (j = 0; j < sizeof(struct brcms_chanvec); j++) + for (j = 0; j < sizeof(chanvec_t); j++) wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j]; } } static bool -brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec) +brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chspec) { return N_ENAB(wlc_cm->wlc->pub) && CHSPEC_IS40(chspec) ? - (isset(wlc_cm->quiet_channels.vec, - LOWER_20_SB(CHSPEC_CHANNEL(chspec))) || - isset(wlc_cm->quiet_channels.vec, - UPPER_20_SB(CHSPEC_CHANNEL(chspec)))) : - isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec)); + (isset + (wlc_cm->quiet_channels.vec, + LOWER_20_SB(CHSPEC_CHANNEL(chspec))) + || isset(wlc_cm->quiet_channels.vec, + UPPER_20_SB(CHSPEC_CHANNEL(chspec)))) : isset(wlc_cm-> + quiet_channels. + vec, + CHSPEC_CHANNEL + (chspec)); } /* Is the channel valid for the current locale? (but don't consider channels not @@ -1067,42 +1039,50 @@ brcms_c_channel_min_txpower_limits_with_local_constraint( int j; /* CCK Rates */ - for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) + for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) { txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm); + } /* 20 MHz Legacy OFDM SISO */ - for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) + for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) { txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm); + } /* 20 MHz Legacy OFDM CDD */ - for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) + for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) { txpwr->ofdm_cdd[j] = min(txpwr->ofdm_cdd[j], local_constraint_qdbm); + } /* 40 MHz Legacy OFDM SISO */ - for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) + for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) { txpwr->ofdm_40_siso[j] = min(txpwr->ofdm_40_siso[j], local_constraint_qdbm); + } /* 40 MHz Legacy OFDM CDD */ - for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) + for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) { txpwr->ofdm_40_cdd[j] = min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm); + } /* 20MHz MCS 0-7 SISO */ - for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) + for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) { txpwr->mcs_20_siso[j] = min(txpwr->mcs_20_siso[j], local_constraint_qdbm); + } /* 20MHz MCS 0-7 CDD */ - for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) + for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) { txpwr->mcs_20_cdd[j] = min(txpwr->mcs_20_cdd[j], local_constraint_qdbm); + } /* 20MHz MCS 0-7 STBC */ - for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) + for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) { txpwr->mcs_20_stbc[j] = min(txpwr->mcs_20_stbc[j], local_constraint_qdbm); + } /* 20MHz MCS 8-15 MIMO */ for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++) @@ -1110,19 +1090,22 @@ brcms_c_channel_min_txpower_limits_with_local_constraint( min(txpwr->mcs_20_mimo[j], local_constraint_qdbm); /* 40MHz MCS 0-7 SISO */ - for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) + for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) { txpwr->mcs_40_siso[j] = min(txpwr->mcs_40_siso[j], local_constraint_qdbm); + } /* 40MHz MCS 0-7 CDD */ - for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) + for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) { txpwr->mcs_40_cdd[j] = min(txpwr->mcs_40_cdd[j], local_constraint_qdbm); + } /* 40MHz MCS 0-7 STBC */ - for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) + for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) { txpwr->mcs_40_stbc[j] = min(txpwr->mcs_40_stbc[j], local_constraint_qdbm); + } /* 40MHz MCS 8-15 MIMO */ for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++) @@ -1135,7 +1118,7 @@ brcms_c_channel_min_txpower_limits_with_local_constraint( } void -brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, +brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chanspec, u8 local_constraint_qdbm) { struct brcms_c_info *wlc = wlc_cm->wlc; @@ -1143,9 +1126,8 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); - brcms_c_channel_min_txpower_limits_with_local_constraint( - wlc_cm, &txpwr, local_constraint_qdbm - ); + brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, &txpwr, + local_constraint_qdbm); brcms_b_set_chanspec(wlc->hw, chanspec, (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0), @@ -1160,100 +1142,112 @@ static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr) char fraction[4][4] = { " ", ".25", ".5 ", ".75" }; sprintf(buf, "CCK "); - for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) + for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->cck[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->cck[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "20 MHz OFDM SISO "); - for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) + for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->ofdm[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->ofdm[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "20 MHz OFDM CDD "); - for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) + for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->ofdm_cdd[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->ofdm_cdd[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "40 MHz OFDM SISO "); - for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) + for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->ofdm_40_siso[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->ofdm_40_siso[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "40 MHz OFDM CDD "); - for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) + for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->ofdm_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->ofdm_40_cdd[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "20 MHz MCS0-7 SISO "); - for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) + for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->mcs_20_siso[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->mcs_20_siso[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "20 MHz MCS0-7 CDD "); - for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) + for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->mcs_20_cdd[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->mcs_20_cdd[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "20 MHz MCS0-7 STBC "); - for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) + for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->mcs_20_stbc[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->mcs_20_stbc[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "20 MHz MCS8-15 SDM "); - for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) + for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->mcs_20_mimo[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->mcs_20_mimo[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "40 MHz MCS0-7 SISO "); - for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) + for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->mcs_40_siso[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->mcs_40_siso[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "40 MHz MCS0-7 CDD "); - for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) + for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->mcs_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->mcs_40_cdd[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "40 MHz MCS0-7 STBC "); - for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) + for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->mcs_40_stbc[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->mcs_40_stbc[i] % BRCMS_TXPWR_DB_FACTOR]); + } printk(KERN_DEBUG "%s\n", buf); sprintf(buf, "40 MHz MCS8-15 SDM "); - for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) + for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) { sprintf(buf[strlen(buf)], " %2d%s", txpwr->mcs_40_mimo[i] / BRCMS_TXPWR_DB_FACTOR, fraction[txpwr->mcs_40_mimo[i] % @@ -1268,7 +1262,7 @@ static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr) #endif /* POWER_DBG */ void -brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, +brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec, struct txpwr_limits *txpwr) { struct brcms_c_info *wlc = wlc_cm->wlc; @@ -1279,8 +1273,8 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, const struct country_info *country; struct brcms_band *band; const struct locale_info *li; - int conducted_max = BRCMS_TXPWR_MAX; - int conducted_ofdm_max = BRCMS_TXPWR_MAX; + int conducted_max; + int conducted_ofdm_max; const struct locale_mimo_info *li_mimo; int maxpwr20, maxpwr40; int maxpwr_idx; @@ -1332,10 +1326,12 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, } /* OFDM txpwr limits for 2.4G or 5G bands */ - if (BAND_2G(band->bandtype)) + if (BAND_2G(band->bandtype)) { maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)]; - else + + } else { maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)]; + } maxpwr = maxpwr - delta; maxpwr = max(maxpwr, 0); @@ -1349,12 +1345,10 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, txpwr->ofdm[i] = (u8) maxpwr; for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { - /* - * OFDM 40 MHz SISO has the same power as the corresponding - * MCS0-7 rate unless overriden by the locale specific code. - * We set this value to 0 as a flag (presumably 0 dBm isn't - * a possibility) and then copy the MCS0-7 value to the 40 MHz - * value if it wasn't explicitly set. + /* OFDM 40 MHz SISO has the same power as the corresponding MCS0-7 rate unless + * overriden by the locale specific code. We set this value to 0 as a + * flag (presumably 0 dBm isn't a possibility) and then copy the MCS0-7 value + * to the 40 MHz value if it wasn't explicitly set. */ txpwr->ofdm_40_siso[i] = 0; @@ -1388,9 +1382,8 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, /* Fill in the MCS 0-7 (SISO) rates */ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { - /* - * 20 MHz has the same power as the corresponding OFDM rate - * unless overriden by the locale specific code. + /* 20 MHz has the same power as the corresponding OFDM rate unless + * overriden by the locale specific code. */ txpwr->mcs_20_siso[i] = txpwr->ofdm[i]; txpwr->mcs_40_siso[i] = 0; @@ -1402,17 +1395,15 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, txpwr->mcs_40_cdd[i] = (u8) maxpwr40; } - /* - * These locales have SISO expressed in the - * table and override CDD later - */ + /* These locales have SISO expressed in the table and override CDD later */ if (li_mimo == &locale_bn) { if (li_mimo == &locale_bn) { maxpwr20 = QDB(16); maxpwr40 = 0; - if (chan >= 3 && chan <= 11) + if (chan >= 3 && chan <= 11) { maxpwr40 = QDB(16); + } } for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { @@ -1446,10 +1437,10 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, } } - /* - * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO - * value if it wasn't provided explicitly. + /* Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO value if it wasn't + * provided explicitly. */ + for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { if (txpwr->mcs_40_siso[i] == 0) txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i]; @@ -1465,9 +1456,8 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, } } - /* - * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding - * STBC values if they weren't provided explicitly. + /* Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding STBC values if they weren't + * provided explicitly. */ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { if (txpwr->mcs_20_stbc[i] == 0) @@ -1497,12 +1487,11 @@ static bool brcms_c_japan_ccode(const char *ccode) } /* - * Validate the chanspec for this locale, for 40MHZ we need to also - * check that the sidebands are valid 20MZH channels in this locale - * and they are also a legal HT combination + * Validate the chanspec for this locale, for 40MHZ we need to also check that the sidebands + * are valid 20MZH channels in this locale and they are also a legal HT combination */ static bool -brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, +brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, chanspec_t chspec, bool dualband) { struct brcms_c_info *wlc = wlc_cm->wlc; @@ -1527,9 +1516,8 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, return VALID_CHANNEL20(wlc_cm->wlc, channel); } #ifdef SUPPORT_40MHZ - /* - * We know we are now checking a 40MHZ channel, so we should - * only be here for NPHYS + /* We know we are now checking a 40MHZ channel, so we should only be here + * for NPHYS */ if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) { u8 upper_sideband = 0, idx; @@ -1565,7 +1553,7 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, return false; } -bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec) +bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, chanspec_t chspec) { return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true); } diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/channel.h b/trunk/drivers/staging/brcm80211/brcmsmac/channel.h index 3e85844ec877..d22f2f5f592d 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/channel.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/channel.h @@ -40,14 +40,12 @@ */ /* macro to get 2.4 GHz channel group index for tx power */ -#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) -#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) +#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) /* cck index */ +#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) /* ofdm index */ /* macro to get 5 GHz channel group index for tx power */ -#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \ - (((c) < 62) ? 1 : \ - (((c) < 100) ? 2 : \ - (((c) < 149) ? 3 : 4)))) +#define CHANNEL_POWER_IDX_5G(c) \ + (((c) < 52) ? 0 : (((c) < 62) ? 1 : (((c) < 100) ? 2 : (((c) < 149) ? 3 : 4)))) /* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */ #define BRCMS_MAXPWR_TBL_SIZE 6 @@ -69,8 +67,9 @@ struct locale_info { u8 restricted_channels; /* Max tx pwr in qdBm for each sub-band */ s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE]; - /* Country IE advertised max tx pwr in dBm per sub-band */ - s8 pub_maxpwr[BAND_5G_PWR_LVLS]; + s8 pub_maxpwr[BAND_5G_PWR_LVLS]; /* Country IE advertised max tx pwr in dBm + * per sub-band + */ u8 flags; }; @@ -99,8 +98,8 @@ struct locale_mimo_info { u8 flags; }; -extern const struct brcms_chanvec chanvec_all_2G; -extern const struct brcms_chanvec chanvec_all_5G; +extern const chanvec_t chanvec_all_2G; +extern const chanvec_t chanvec_all_5G; /* * Country names and abbreviations with locale defined from ISO 3166 @@ -121,13 +120,13 @@ extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, uint bandunit); extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, - u16 chspec); + chanspec_t chspec); extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, - u16 chanspec, + chanspec_t chanspec, struct txpwr_limits *txpwr); extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, - u16 chanspec, + chanspec_t chanspec, u8 local_constraint_qdbm); #endif /* _WLC_CHANNEL_H */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/d11.h b/trunk/drivers/staging/brcm80211/brcmsmac/d11.h index 96f487aed9b3..e7ff0e6f28e0 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/d11.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/d11.h @@ -29,11 +29,11 @@ #define RX_FIFO 0 /* data and ctl frames */ #define RX_TXSTATUS_FIFO 3 /* RX fifo for tx status packages */ -/* TX FIFO numbers using WME Access Category */ -#define TX_AC_BK_FIFO 0 /* Background TX FIFO */ -#define TX_AC_BE_FIFO 1 /* Best-Effort TX FIFO */ -#define TX_AC_VI_FIFO 2 /* Video TX FIFO */ -#define TX_AC_VO_FIFO 3 /* Voice TX FIFO */ +/* TX FIFO numbers using WME Access Classes */ +#define TX_AC_BK_FIFO 0 /* Access Category Background TX FIFO */ +#define TX_AC_BE_FIFO 1 /* Access Category Best-Effort TX FIFO */ +#define TX_AC_VI_FIFO 2 /* Access Class Video TX FIFO */ +#define TX_AC_VO_FIFO 3 /* Access Class Voice TX FIFO */ #define TX_BCMC_FIFO 4 /* Broadcast/Multicast TX FIFO */ #define TX_ATIM_FIFO 5 /* TX fifo for ATIM window info */ @@ -73,8 +73,8 @@ struct pio2regs { /* a pair of pio channels(tx and rx) */ struct pio2regp { - struct pio2regs tx; - struct pio2regs rx; + pio2regs_t tx; + pio2regs_t rx; }; /* 4byte-wide pio register set per channel(xmt or rcv) */ @@ -85,8 +85,8 @@ struct pio4regs { /* a pair of pio channels(tx and rx) */ struct pio4regp { - struct pio4regs tx; - struct pio4regs rx; + pio4regs_t tx; + pio4regs_t rx; }; /* read: 32-bit register that can be read as 32-bit or as 2 16-bit @@ -101,10 +101,10 @@ union pmqreg { }; struct fifo64 { - struct dma64regs dmaxmt; /* dma tx */ - struct pio4regs piotx; /* pio tx */ - struct dma64regs dmarcv; /* dma rx */ - struct pio4regs piorx; /* pio rx */ + dma64regs_t dmaxmt; /* dma tx */ + pio4regs_t piotx; /* pio tx */ + dma64regs_t dmarcv; /* dma rx */ + pio4regs_t piorx; /* pio rx */ }; /* @@ -120,7 +120,7 @@ struct d11regs { u32 usectimer; /* 0x1c *//* for corerev >= 26 */ /* Interrupt Control *//* 0x20 */ - struct intctrlregs intctrlregs[8]; + intctrlregs_t intctrlregs[8]; u32 PAD[40]; /* 0x60 - 0xFC */ @@ -139,7 +139,7 @@ struct d11regs { u32 PAD[2]; /* 0x138 - 0x13C */ /* PMQ registers */ - union pmqreg pmqreg; /* 0x140 */ + pmqreg_t pmqreg; /* 0x140 */ u32 pmqpatl; /* 0x144 */ u32 pmqpath; /* 0x148 */ u32 PAD; /* 0x14C */ @@ -179,10 +179,10 @@ struct d11regs { u32 PAD[5]; /* 0x1ec - 0x1fc */ /* 0x200-0x37F dma/pio registers */ - struct fifo64 fifo64regs[6]; + fifo64_t fifo64regs[6]; /* FIFO diagnostic port access */ - struct dma32diag dmafifo; /* 0x380 - 0x38C */ + dma32diag_t dmafifo; /* 0x380 - 0x38C */ u32 aggfifocnt; /* 0x390 */ u32 aggfifodata; /* 0x394 */ @@ -457,7 +457,7 @@ struct d11regs { #define IRL_FC_MASK 0xff000000 /* frame count */ #define IRL_FC_SHIFT 24 /* frame count */ -/*== maccontrol register ==*/ +/* maccontrol register */ #define MCTL_GMODE (1U << 31) #define MCTL_DISCARD_PMQ (1 << 30) #define MCTL_WAKE (1 << 26) @@ -481,119 +481,75 @@ struct d11regs { #define MCTL_PSM_RUN (1 << 1) #define MCTL_EN_MAC (1 << 0) -/*== maccommand register ==*/ +/* maccommand register */ #define MCMD_BCN0VLD (1 << 0) #define MCMD_BCN1VLD (1 << 1) #define MCMD_DIRFRMQVAL (1 << 2) #define MCMD_CCA (1 << 3) #define MCMD_BG_NOISE (1 << 4) #define MCMD_SKIP_SHMINIT (1 << 5) /* only used for simulation */ -#define MCMD_SAMPLECOLL MCMD_SKIP_SHMINIT /* reuse for sample collect */ - -/*== macintstatus/macintmask ==*/ -/* gracefully suspended */ -#define MI_MACSSPNDD (1 << 0) -/* beacon template available */ -#define MI_BCNTPL (1 << 1) -/* TBTT indication */ -#define MI_TBTT (1 << 2) -/* beacon successfully tx'd */ -#define MI_BCNSUCCESS (1 << 3) -/* beacon canceled (IBSS) */ -#define MI_BCNCANCLD (1 << 4) -/* end of ATIM-window (IBSS) */ -#define MI_ATIMWINEND (1 << 5) -/* PMQ entries available */ -#define MI_PMQ (1 << 6) -/* non-specific gen-stat bits that are set by PSM */ -#define MI_NSPECGEN_0 (1 << 7) -/* non-specific gen-stat bits that are set by PSM */ -#define MI_NSPECGEN_1 (1 << 8) -/* MAC level Tx error */ -#define MI_MACTXERR (1 << 9) -/* non-specific gen-stat bits that are set by PSM */ -#define MI_NSPECGEN_3 (1 << 10) -/* PHY Tx error */ -#define MI_PHYTXERR (1 << 11) -/* Power Management Event */ -#define MI_PME (1 << 12) -/* General-purpose timer0 */ -#define MI_GP0 (1 << 13) -/* General-purpose timer1 */ -#define MI_GP1 (1 << 14) -/* (ORed) DMA-interrupts */ -#define MI_DMAINT (1 << 15) -/* MAC has completed a TX FIFO Suspend/Flush */ -#define MI_TXSTOP (1 << 16) -/* MAC has completed a CCA measurement */ -#define MI_CCA (1 << 17) -/* MAC has collected background noise samples */ -#define MI_BG_NOISE (1 << 18) -/* MBSS DTIM TBTT indication */ -#define MI_DTIM_TBTT (1 << 19) -/* Probe response queue needs attention */ -#define MI_PRQ (1 << 20) -/* Radio/PHY has been powered back up. */ -#define MI_PWRUP (1 << 21) +#define MCMD_SAMPLECOLL MCMD_SKIP_SHMINIT /* reuse for sample collect */ + +/* macintstatus/macintmask */ +#define MI_MACSSPNDD (1 << 0) /* MAC has gracefully suspended */ +#define MI_BCNTPL (1 << 1) /* beacon template available */ +#define MI_TBTT (1 << 2) /* TBTT indication */ +#define MI_BCNSUCCESS (1 << 3) /* beacon successfully tx'd */ +#define MI_BCNCANCLD (1 << 4) /* beacon canceled (IBSS) */ +#define MI_ATIMWINEND (1 << 5) /* end of ATIM-window (IBSS) */ +#define MI_PMQ (1 << 6) /* PMQ entries available */ +#define MI_NSPECGEN_0 (1 << 7) /* non-specific gen-stat bits that are set by PSM */ +#define MI_NSPECGEN_1 (1 << 8) /* non-specific gen-stat bits that are set by PSM */ +#define MI_MACTXERR (1 << 9) /* MAC level Tx error */ +#define MI_NSPECGEN_3 (1 << 10) /* non-specific gen-stat bits that are set by PSM */ +#define MI_PHYTXERR (1 << 11) /* PHY Tx error */ +#define MI_PME (1 << 12) /* Power Management Event */ +#define MI_GP0 (1 << 13) /* General-purpose timer0 */ +#define MI_GP1 (1 << 14) /* General-purpose timer1 */ +#define MI_DMAINT (1 << 15) /* (ORed) DMA-interrupts */ +#define MI_TXSTOP (1 << 16) /* MAC has completed a TX FIFO Suspend/Flush */ +#define MI_CCA (1 << 17) /* MAC has completed a CCA measurement */ +#define MI_BG_NOISE (1 << 18) /* MAC has collected background noise samples */ +#define MI_DTIM_TBTT (1 << 19) /* MBSS DTIM TBTT indication */ +#define MI_PRQ (1 << 20) /* Probe response queue needs attention */ +#define MI_PWRUP (1 << 21) /* Radio/PHY has been powered back up. */ #define MI_RESERVED3 (1 << 22) #define MI_RESERVED2 (1 << 23) #define MI_RESERVED1 (1 << 25) /* MAC detected change on RF Disable input*/ #define MI_RFDISABLE (1 << 28) -/* MAC has completed a TX */ -#define MI_TFS (1 << 29) -/* A phy status change wrt G mode */ -#define MI_PHYCHANGED (1 << 30) -/* general purpose timeout */ -#define MI_TO (1U << 31) +#define MI_TFS (1 << 29) /* MAC has completed a TX */ +#define MI_PHYCHANGED (1 << 30) /* A phy status change wrt G mode */ +#define MI_TO (1U << 31) /* general purpose timeout */ /* Mac capabilities registers */ -/*== machwcap ==*/ +/* machwcap */ #define MCAP_TKIPMIC 0x80000000 /* TKIP MIC hardware present */ -/*== pmqhost data ==*/ -/* data entry of head pmq entry */ -#define PMQH_DATA_MASK 0xffff0000 -/* PM entry for BSS config */ -#define PMQH_BSSCFG 0x00100000 -/* PM Mode OFF: power save off */ -#define PMQH_PMOFF 0x00010000 -/* PM Mode ON: power save on */ -#define PMQH_PMON 0x00020000 -/* Dis-associated or De-authenticated */ -#define PMQH_DASAT 0x00040000 -/* ATIM not acknowledged */ -#define PMQH_ATIMFAIL 0x00080000 -/* delete head entry */ -#define PMQH_DEL_ENTRY 0x00000001 -/* delete head entry to cur read pointer -1 */ -#define PMQH_DEL_MULT 0x00000002 -/* pmq overflow indication */ -#define PMQH_OFLO 0x00000004 -/* entries are present in pmq */ -#define PMQH_NOT_EMPTY 0x00000008 - -/*== phydebug ==*/ -/* phy is asserting carrier sense */ -#define PDBG_CRS (1 << 0) -/* phy is taking xmit byte from mac this cycle */ -#define PDBG_TXA (1 << 1) -/* mac is instructing the phy to transmit a frame */ -#define PDBG_TXF (1 << 2) -/* phy is signalling a transmit Error to the mac */ -#define PDBG_TXE (1 << 3) -/* phy detected the end of a valid frame preamble */ -#define PDBG_RXF (1 << 4) -/* phy detected the end of a valid PLCP header */ -#define PDBG_RXS (1 << 5) -/* rx start not asserted */ -#define PDBG_RXFRG (1 << 6) -/* mac is taking receive byte from phy this cycle */ -#define PDBG_RXV (1 << 7) -/* RF portion of the radio is disabled */ -#define PDBG_RFD (1 << 16) - -/*== objaddr register ==*/ +/* pmqhost data */ +#define PMQH_DATA_MASK 0xffff0000 /* data entry of head pmq entry */ +#define PMQH_BSSCFG 0x00100000 /* PM entry for BSS config */ +#define PMQH_PMOFF 0x00010000 /* PM Mode OFF: power save off */ +#define PMQH_PMON 0x00020000 /* PM Mode ON: power save on */ +#define PMQH_DASAT 0x00040000 /* Dis-associated or De-authenticated */ +#define PMQH_ATIMFAIL 0x00080000 /* ATIM not acknowledged */ +#define PMQH_DEL_ENTRY 0x00000001 /* delete head entry */ +#define PMQH_DEL_MULT 0x00000002 /* delete head entry to cur read pointer -1 */ +#define PMQH_OFLO 0x00000004 /* pmq overflow indication */ +#define PMQH_NOT_EMPTY 0x00000008 /* entries are present in pmq */ + +/* phydebug */ +#define PDBG_CRS (1 << 0) /* phy is asserting carrier sense */ +#define PDBG_TXA (1 << 1) /* phy is taking xmit byte from mac this cycle */ +#define PDBG_TXF (1 << 2) /* mac is instructing the phy to transmit a frame */ +#define PDBG_TXE (1 << 3) /* phy is signalling a transmit Error to the mac */ +#define PDBG_RXF (1 << 4) /* phy detected the end of a valid frame preamble */ +#define PDBG_RXS (1 << 5) /* phy detected the end of a valid PLCP header */ +#define PDBG_RXFRG (1 << 6) /* rx start not asserted */ +#define PDBG_RXV (1 << 7) /* mac is taking receive byte from phy this cycle */ +#define PDBG_RFD (1 << 16) /* RF portion of the radio is disabled */ + +/* objaddr register */ #define OBJADDR_SEL_MASK 0x000F0000 #define OBJADDR_UCM_SEL 0x00000000 #define OBJADDR_SHM_SEL 0x00010000 @@ -608,20 +564,20 @@ struct d11regs { #define WEP_PCMADDR 0x07d4 #define WEP_PCMDATA 0x07d6 -/*== frmtxstatus ==*/ +/* frmtxstatus */ #define TXS_V (1 << 0) /* valid bit */ #define TXS_STATUS_MASK 0xffff #define TXS_FID_MASK 0xffff0000 #define TXS_FID_SHIFT 16 -/*== frmtxstatus2 ==*/ +/* frmtxstatus2 */ #define TXS_SEQ_MASK 0xffff #define TXS_PTX_MASK 0xff0000 #define TXS_PTX_SHIFT 16 #define TXS_MU_MASK 0x01000000 #define TXS_MU_SHIFT 24 -/*== clk_ctl_st ==*/ +/* clk_ctl_st */ #define CCS_ERSRC_REQ_D11PLL 0x00000100 /* d11 core pll request */ #define CCS_ERSRC_REQ_PHYPLL 0x00000200 /* PHY pll request */ #define CCS_ERSRC_AVAIL_D11PLL 0x01000000 /* d11 core pll available */ @@ -646,27 +602,22 @@ struct d11regs { #define TXFIFO_SIZE_UNIT 256 /* one unit corresponds to 256 bytes */ #define MBSS16_TEMPLMEM_MINBLKS 65 /* one unit corresponds to 256 bytes */ -/*== phy versions (PhyVersion:Revision field) ==*/ -/* analog block version */ -#define PV_AV_MASK 0xf000 -/* analog block version bitfield offset */ -#define PV_AV_SHIFT 12 -/* phy type */ -#define PV_PT_MASK 0x0f00 -/* phy type bitfield offset */ -#define PV_PT_SHIFT 8 -/* phy version */ -#define PV_PV_MASK 0x000f +/* phy versions, PhyVersion:Revision field */ +#define PV_AV_MASK 0xf000 /* analog block version */ +#define PV_AV_SHIFT 12 /* analog block version bitfield offset */ +#define PV_PT_MASK 0x0f00 /* phy type */ +#define PV_PT_SHIFT 8 /* phy type bitfield offset */ +#define PV_PV_MASK 0x000f /* phy version */ #define PHY_TYPE(v) ((v & PV_PT_MASK) >> PV_PT_SHIFT) -/*== phy types (PhyVersion:PhyType field) ==*/ +/* phy types, PhyVersion:PhyType field */ #define PHY_TYPE_N 4 /* N-Phy value */ #define PHY_TYPE_SSN 6 /* SSLPN-Phy value */ #define PHY_TYPE_LCN 8 /* LCN-Phy value */ #define PHY_TYPE_LCNXN 9 /* LCNXN-Phy value */ #define PHY_TYPE_NULL 0xf /* Invalid Phy value */ -/*== analog types (PhyVersion:AnalogType field) ==*/ +/* analog types, PhyVersion:AnalogType field */ #define ANA_11N_013 5 /* 802.11a PLCP header def */ @@ -742,10 +693,9 @@ struct cck_phy_hdr { #define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU) #define BRCMS_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU) -/* - * The dot11a PLCP header is 5 bytes. To simplify the software (so that we - * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header - * has padding added in the ucode. +/* The dot11a PLCP header is 5 bytes. To simplify the software (so that we + * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header has + * padding added in the ucode. */ #define D11_PHY_HDR_LEN 6 @@ -795,17 +745,14 @@ struct d11txh { #define FT_HT 2 #define FT_N 3 -/* - * Position of MPDU inside A-MPDU; indicated with bits 10:9 - * of MacTxControlLow - */ +/* Position of MPDU inside A-MPDU; indicated with bits 10:9 of MacTxControlLow */ #define TXC_AMPDU_SHIFT 9 /* shift for ampdu settings */ #define TXC_AMPDU_NONE 0 /* Regular MPDU, not an A-MPDU */ #define TXC_AMPDU_FIRST 1 /* first MPDU of an A-MPDU */ #define TXC_AMPDU_MIDDLE 2 /* intermediate MPDU of an A-MPDU */ #define TXC_AMPDU_LAST 3 /* last (or single) MPDU of an A-MPDU */ -/*== MacTxControlLow ==*/ +/* MacTxControlLow */ #define TXC_AMIC 0x8000 #define TXC_SENDCTS 0x0800 #define TXC_AMPDU_MASK 0x0600 @@ -819,25 +766,18 @@ struct d11txh { #define TXC_LONGFRAME 0x0002 #define TXC_IMMEDACK 0x0001 -/*== MacTxControlHigh ==*/ -/* RTS fallback preamble type 1 = SHORT 0 = LONG */ -#define TXC_PREAMBLE_RTS_FB_SHORT 0x8000 -/* RTS main rate preamble type 1 = SHORT 0 = LONG */ -#define TXC_PREAMBLE_RTS_MAIN_SHORT 0x4000 -/* - * Main fallback rate preamble type - * 1 = SHORT for OFDM/GF for MIMO - * 0 = LONG for CCK/MM for MIMO - */ -#define TXC_PREAMBLE_DATA_FB_SHORT 0x2000 - +/* MacTxControlHigh */ +#define TXC_PREAMBLE_RTS_FB_SHORT 0x8000 /* RTS fallback preamble type 1 = SHORT 0 = LONG */ +#define TXC_PREAMBLE_RTS_MAIN_SHORT 0x4000 /* RTS main rate preamble type 1 = SHORT 0 = LONG */ +#define TXC_PREAMBLE_DATA_FB_SHORT 0x2000 /* Main fallback rate preamble type + * 1 = SHORT for OFDM/GF for MIMO + * 0 = LONG for CCK/MM for MIMO + */ /* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */ -/* use fallback rate for this AMPDU */ -#define TXC_AMPDU_FBR 0x1000 +#define TXC_AMPDU_FBR 0x1000 /* use fallback rate for this AMPDU */ #define TXC_SECKEY_MASK 0x0FF0 #define TXC_SECKEY_SHIFT 4 -/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */ -#define TXC_ALT_TXPWR 0x0008 +#define TXC_ALT_TXPWR 0x0008 /* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */ #define TXC_SECTYPE_MASK 0x0007 #define TXC_SECTYPE_SHIFT 0 @@ -877,7 +817,7 @@ struct d11txh { #define PHY_TXC1_MODE_SDM 3 /* PhyTxControl for HTphy that are different from Mimophy */ -#define PHY_TXC_HTANT_MASK 0x3fC0 /* bits 6-13 */ +#define PHY_TXC_HTANT_MASK 0x3fC0 /* bit 6, 7, 8, 9, 10, 11, 12, 13 */ /* XtraFrameTypes */ #define XFTS_RTS_FT_SHIFT 2 @@ -922,23 +862,23 @@ struct tx_status { #define TX_STATUS_RTS_RTX_MASK 0x0F00 #define TX_STATUS_RTS_RTX_SHIFT 8 #define TX_STATUS_MASK 0x00FE -#define TX_STATUS_PMINDCTD (1 << 7) /* PM mode indicated to AP */ -#define TX_STATUS_INTERMEDIATE (1 << 6) /* intermediate or 1st ampdu pkg */ -#define TX_STATUS_AMPDU (1 << 5) /* AMPDU status */ -#define TX_STATUS_SUPR_MASK 0x1C /* suppress status bits (4:2) */ +#define TX_STATUS_PMINDCTD (1 << 7) /* PM mode indicated to AP */ +#define TX_STATUS_INTERMEDIATE (1 << 6) /* intermediate or 1st ampdu pkg */ +#define TX_STATUS_AMPDU (1 << 5) /* AMPDU status */ +#define TX_STATUS_SUPR_MASK 0x1C /* suppress status bits (4:2) */ #define TX_STATUS_SUPR_SHIFT 2 -#define TX_STATUS_ACK_RCV (1 << 1) /* ACK received */ -#define TX_STATUS_VALID (1 << 0) /* Tx status valid */ +#define TX_STATUS_ACK_RCV (1 << 1) /* ACK received */ +#define TX_STATUS_VALID (1 << 0) /* Tx status valid */ #define TX_STATUS_NO_ACK 0 /* suppress status reason codes */ -#define TX_STATUS_SUPR_PMQ (1 << 2) /* PMQ entry */ -#define TX_STATUS_SUPR_FLUSH (2 << 2) /* flush request */ -#define TX_STATUS_SUPR_FRAG (3 << 2) /* previous frag failure */ -#define TX_STATUS_SUPR_TBTT (3 << 2) /* SHARED: Probe resp supr for TBTT */ -#define TX_STATUS_SUPR_BADCH (4 << 2) /* channel mismatch */ -#define TX_STATUS_SUPR_EXPTIME (5 << 2) /* lifetime expiry */ -#define TX_STATUS_SUPR_UF (6 << 2) /* underflow */ +#define TX_STATUS_SUPR_PMQ (1 << 2) /* PMQ entry */ +#define TX_STATUS_SUPR_FLUSH (2 << 2) /* flush request */ +#define TX_STATUS_SUPR_FRAG (3 << 2) /* previous frag failure */ +#define TX_STATUS_SUPR_TBTT (3 << 2) /* SHARED: Probe response supr for TBTT */ +#define TX_STATUS_SUPR_BADCH (4 << 2) /* channel mismatch */ +#define TX_STATUS_SUPR_EXPTIME (5 << 2) /* lifetime expiry */ +#define TX_STATUS_SUPR_UF (6 << 2) /* underflow */ /* Unexpected tx status for rate update */ #define TX_STATUS_UNEXP(status) \ @@ -999,8 +939,8 @@ struct tx_status { #define ADDR_BMP_RA (1 << 0) /* Receiver Address (RA) */ #define ADDR_BMP_TA (1 << 1) /* Transmitter Address (TA) */ #define ADDR_BMP_BSSID (1 << 2) /* BSSID */ -#define ADDR_BMP_AP (1 << 3) /* Infra-BSS Access Point */ -#define ADDR_BMP_STA (1 << 4) /* Infra-BSS Station */ +#define ADDR_BMP_AP (1 << 3) /* Infra-BSS Access Point (AP) */ +#define ADDR_BMP_STA (1 << 4) /* Infra-BSS Station (STA) */ #define ADDR_BMP_RESERVED1 (1 << 5) #define ADDR_BMP_RESERVED2 (1 << 6) #define ADDR_BMP_RESERVED3 (1 << 7) @@ -1072,10 +1012,9 @@ struct tx_status { #define T_BCN0_TPL_BASE (0x34 * 2) #define T_PRS_TPL_BASE (0x134 * 2) #define T_BCN1_TPL_BASE (0x234 * 2) -#define T_TX_FIFO_TXRAM_BASE (T_ACTS_TPL_BASE + \ - (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT)) +#define T_TX_FIFO_TXRAM_BASE (T_ACTS_TPL_BASE + (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT)) -#define T_BA_TPL_BASE T_QNULL_TPL_BASE /* template area for BA */ +#define T_BA_TPL_BASE T_QNULL_TPL_BASE /* template area for BA */ #define T_RAM_ACCESS_SZ 4 /* template ram is 4 byte access only */ @@ -1268,18 +1207,14 @@ struct tx_status { #define WATCHDOG_8TU_MAX 10 /* Manufacturing Test Variables */ -/* PER test mode */ -#define M_PKTENG_CTRL (0x6c * 2) -/* IFS for TX mode */ -#define M_PKTENG_IFS (0x6d * 2) -/* Lower word of tx frmcnt/rx lostcnt */ -#define M_PKTENG_FRMCNT_LO (0x6e * 2) -/* Upper word of tx frmcnt/rx lostcnt */ -#define M_PKTENG_FRMCNT_HI (0x6f * 2) +#define M_PKTENG_CTRL (0x6c * 2) /* PER test mode */ +#define M_PKTENG_IFS (0x6d * 2) /* IFS for TX mode */ +#define M_PKTENG_FRMCNT_LO (0x6e * 2) /* Lower word of tx frmcnt/rx lostcnt */ +#define M_PKTENG_FRMCNT_HI (0x6f * 2) /* Upper word of tx frmcnt/rx lostcnt */ /* Index variation in vbat ripple */ -#define M_LCN_PWR_IDX_MAX (0x67 * 2) /* highest index read by ucode */ -#define M_LCN_PWR_IDX_MIN (0x66 * 2) /* lowest index read by ucode */ +#define M_LCN_PWR_IDX_MAX (0x67 * 2) /* highest index read by ucode */ +#define M_LCN_PWR_IDX_MIN (0x66 * 2) /* lowest index read by ucode */ /* M_PKTENG_CTRL bit definitions */ #define M_PKTENG_MODE_TX 0x0001 @@ -1288,14 +1223,11 @@ struct tx_status { #define M_PKTENG_MODE_RX 0x0002 #define M_PKTENG_MODE_RX_WITH_ACK 0x0402 #define M_PKTENG_MODE_MASK 0x0003 -/* TX frames indicated in the frmcnt reg */ -#define M_PKTENG_FRMCNT_VLD 0x0100 +#define M_PKTENG_FRMCNT_VLD 0x0100 /* TX frames indicated in the frmcnt reg */ /* Sample Collect parameters (bitmap and type) */ -/* Trigger bitmap for sample collect */ -#define M_SMPL_COL_BMP (0x37d * 2) -/* Sample collect type */ -#define M_SMPL_COL_CTL (0x3b2 * 2) +#define M_SMPL_COL_BMP (0x37d * 2) /* Trigger bitmap for sample collect */ +#define M_SMPL_COL_CTL (0x3b2 * 2) /* Sample collect type */ #define ANTSEL_CLKDIV_4MHZ 6 #define MIMO_ANTSEL_BUSY 0x4000 /* bit 14 (busy) */ @@ -1327,37 +1259,27 @@ struct shm_acparams { #define MHF5 4 /* Hostflag 5 index */ /* Flags in M_HOST_FLAGS */ -/* Enable ucode antenna diversity help */ -#define MHF1_ANTDIV 0x0001 -/* Enable EDCF access control */ -#define MHF1_EDCF 0x0100 +#define MHF1_ANTDIV 0x0001 /* Enable ucode antenna diversity help */ +#define MHF1_EDCF 0x0100 /* Enable EDCF access control */ #define MHF1_IQSWAP_WAR 0x0200 -/* Disable Slow clock request, for corerev < 11 */ -#define MHF1_FORCEFASTCLK 0x0400 +#define MHF1_FORCEFASTCLK 0x0400 /* Disable Slow clock request, for corerev < 11 */ /* Flags in M_HOST_FLAGS2 */ -/* PR16165WAR : Enable ucode PCI slow clock WAR */ -#define MHF2_PCISLOWCLKWAR 0x0008 -/* Flush BCMC FIFO immediately */ -#define MHF2_TXBCMC_NOW 0x0040 -/* Enable ucode/hw power control */ -#define MHF2_HWPWRCTL 0x0080 +#define MHF2_PCISLOWCLKWAR 0x0008 /* PR16165WAR : Enable ucode PCI slow clock WAR */ +#define MHF2_TXBCMC_NOW 0x0040 /* Flush BCMC FIFO immediately */ +#define MHF2_HWPWRCTL 0x0080 /* Enable ucode/hw power control */ #define MHF2_NPHY40MHZ_WAR 0x0800 /* Flags in M_HOST_FLAGS3 */ -/* enabled mimo antenna selection */ -#define MHF3_ANTSEL_EN 0x0001 -/* antenna selection mode: 0: 2x3, 1: 2x4 */ -#define MHF3_ANTSEL_MODE 0x0002 +#define MHF3_ANTSEL_EN 0x0001 /* enabled mimo antenna selection */ +#define MHF3_ANTSEL_MODE 0x0002 /* antenna selection mode: 0: 2x3, 1: 2x4 */ #define MHF3_RESERVED1 0x0004 #define MHF3_RESERVED2 0x0008 #define MHF3_NPHY_MLADV_WAR 0x0010 /* Flags in M_HOST_FLAGS4 */ -/* force bphy Tx on core 0 (board level WAR) */ -#define MHF4_BPHY_TXCORE0 0x0080 -/* for 4313A0 FEM boards */ -#define MHF4_EXTPA_ENABLE 0x4000 +#define MHF4_BPHY_TXCORE0 0x0080 /* force bphy Tx on core 0 (board level WAR) */ +#define MHF4_EXTPA_ENABLE 0x4000 /* for 4313A0 FEM boards */ /* Flags in M_HOST_FLAGS5 */ #define MHF5_4313_GPIOCTRL 0x0001 @@ -1370,87 +1292,52 @@ struct shm_acparams { #define M_PHY_NOISE (0x037 * 2) #define PHY_NOISE_MASK 0x00ff -/* - * Receive Frame Data Header for 802.11b DCF-only frames - * - * RxFrameSize: Actual byte length of the frame data received - * PAD: padding (not used) - * PhyRxStatus_0: PhyRxStatus 15:0 - * PhyRxStatus_1: PhyRxStatus 31:16 - * PhyRxStatus_2: PhyRxStatus 47:32 - * PhyRxStatus_3: PhyRxStatus 63:48 - * PhyRxStatus_4: PhyRxStatus 79:64 - * PhyRxStatus_5: PhyRxStatus 95:80 - * RxStatus1: MAC Rx Status - * RxStatus2: extended MAC Rx status - * RxTSFTime: RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY - * RxChan: gain code, channel radio code, and phy type - */ +/* Receive Frame Data Header for 802.11b DCF-only frames */ struct d11rxhdr { - u16 RxFrameSize; + u16 RxFrameSize; /* Actual byte length of the frame data received */ u16 PAD; - u16 PhyRxStatus_0; - u16 PhyRxStatus_1; - u16 PhyRxStatus_2; - u16 PhyRxStatus_3; - u16 PhyRxStatus_4; - u16 PhyRxStatus_5; - u16 RxStatus1; - u16 RxStatus2; - u16 RxTSFTime; - u16 RxChan; + u16 PhyRxStatus_0; /* PhyRxStatus 15:0 */ + u16 PhyRxStatus_1; /* PhyRxStatus 31:16 */ + u16 PhyRxStatus_2; /* PhyRxStatus 47:32 */ + u16 PhyRxStatus_3; /* PhyRxStatus 63:48 */ + u16 PhyRxStatus_4; /* PhyRxStatus 79:64 */ + u16 PhyRxStatus_5; /* PhyRxStatus 95:80 */ + u16 RxStatus1; /* MAC Rx Status */ + u16 RxStatus2; /* extended MAC Rx status */ + u16 RxTSFTime; /* RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY */ + u16 RxChan; /* gain code, channel radio code, and phy type */ } __packed; #define RXHDR_LEN 24 /* sizeof struct d11rxhdr */ #define FRAMELEN(h) ((h)->RxFrameSize) -/* - * rxhdr: received frame header data - * tsf_l: TSF_L reading - * rssi: computed instanteneous rssi in BMAC - * rxpwr0: obsoleted, place holder for legacy ROM code. use rxpwr[] - * rxpwr1: obsoleted, place holder for legacy ROM code. use rxpwr[] - * do_rssi_ma: do per-pkt sampling for per-antenna ma in HIGH - * rxpwr: rssi for supported antennas - */ struct brcms_d11rxhdr { struct d11rxhdr rxhdr; - u32 tsf_l; - s8 rssi; - s8 rxpwr0; - s8 rxpwr1; - s8 do_rssi_ma; - s8 rxpwr[WL_RSSI_ANT_MAX]; + u32 tsf_l; /* TSF_L reading */ + s8 rssi; /* computed instanteneous rssi in BMAC */ + s8 rxpwr0; /* obsoleted, place holder for legacy ROM code. use rxpwr[] */ + s8 rxpwr1; /* obsoleted, place holder for legacy ROM code. use rxpwr[] */ + s8 do_rssi_ma; /* do per-pkt sampling for per-antenna ma in HIGH */ + s8 rxpwr[WL_RSSI_ANT_MAX]; /* rssi for supported antennas */ } __packed; /* PhyRxStatus_0: */ -/* NPHY only: CCK, OFDM, preN, N */ -#define PRXS0_FT_MASK 0x0003 -/* NPHY only: clip count adjustment steps by AGC */ -#define PRXS0_CLIP_MASK 0x000C +#define PRXS0_FT_MASK 0x0003 /* NPHY only: CCK, OFDM, preN, N */ +#define PRXS0_CLIP_MASK 0x000C /* NPHY only: clip count adjustment steps by AGC */ #define PRXS0_CLIP_SHIFT 2 -/* PHY received a frame with unsupported rate */ -#define PRXS0_UNSRATE 0x0010 -/* GPHY: rx ant, NPHY: upper sideband */ -#define PRXS0_RXANT_UPSUBBAND 0x0020 -/* CCK frame only: lost crs during cck frame reception */ -#define PRXS0_LCRS 0x0040 -/* Short Preamble */ -#define PRXS0_SHORTH 0x0080 -/* PLCP violation */ -#define PRXS0_PLCPFV 0x0100 -/* PLCP header integrity check failed */ -#define PRXS0_PLCPHCF 0x0200 -/* legacy PHY gain control */ -#define PRXS0_GAIN_CTL 0x4000 -/* NPHY: Antennas used for received frame, bitmask */ -#define PRXS0_ANTSEL_MASK 0xF000 +#define PRXS0_UNSRATE 0x0010 /* PHY received a frame with unsupported rate */ +#define PRXS0_RXANT_UPSUBBAND 0x0020 /* GPHY: rx ant, NPHY: upper sideband */ +#define PRXS0_LCRS 0x0040 /* CCK frame only: lost crs during cck frame reception */ +#define PRXS0_SHORTH 0x0080 /* Short Preamble */ +#define PRXS0_PLCPFV 0x0100 /* PLCP violation */ +#define PRXS0_PLCPHCF 0x0200 /* PLCP header integrity check failed */ +#define PRXS0_GAIN_CTL 0x4000 /* legacy PHY gain control */ +#define PRXS0_ANTSEL_MASK 0xF000 /* NPHY: Antennas used for received frame, bitmask */ #define PRXS0_ANTSEL_SHIFT 0x12 /* subfield PRXS0_FT_MASK */ #define PRXS0_CCK 0x0000 -/* valid only for G phy, use rxh->RxChan for A phy */ -#define PRXS0_OFDM 0x0001 +#define PRXS0_OFDM 0x0001 /* valid only for G phy, use rxh->RxChan for A phy */ #define PRXS0_PREN 0x0002 #define PRXS0_STDN 0x0003 @@ -1477,51 +1364,35 @@ struct brcms_d11rxhdr { #define PRXS0_UNUSED 0xF000 /* unused and not defined; set to 0 */ /* htphy PhyRxStatus_1: */ -/* core enables for {3..0}, 0=disabled, 1=enabled */ -#define PRXS1_HTPHY_CORE_MASK 0x000F -/* antenna configation */ -#define PRXS1_HTPHY_ANTCFG_MASK 0x00F0 -/* Mixmode PLCP Length low byte mask */ -#define PRXS1_HTPHY_MMPLCPLenL_MASK 0xFF00 +#define PRXS1_HTPHY_CORE_MASK 0x000F /* core enables for {3..0}, 0=disabled, 1=enabled */ +#define PRXS1_HTPHY_ANTCFG_MASK 0x00F0 /* antenna configation */ +#define PRXS1_HTPHY_MMPLCPLenL_MASK 0xFF00 /* Mixmode PLCP Length low byte mask */ /* htphy PhyRxStatus_2: */ -/* Mixmode PLCP Length high byte maskw */ -#define PRXS2_HTPHY_MMPLCPLenH_MASK 0x000F -/* Mixmode PLCP rate mask */ -#define PRXS2_HTPHY_MMPLCH_RATE_MASK 0x00F0 -/* Rx power on core 0 */ -#define PRXS2_HTPHY_RXPWR_ANT0 0xFF00 +#define PRXS2_HTPHY_MMPLCPLenH_MASK 0x000F /* Mixmode PLCP Length high byte maskw */ +#define PRXS2_HTPHY_MMPLCH_RATE_MASK 0x00F0 /* Mixmode PLCP rate mask */ +#define PRXS2_HTPHY_RXPWR_ANT0 0xFF00 /* Rx power on core 0 */ /* htphy PhyRxStatus_3: */ -/* Rx power on core 1 */ -#define PRXS3_HTPHY_RXPWR_ANT1 0x00FF -/* Rx power on core 2 */ -#define PRXS3_HTPHY_RXPWR_ANT2 0xFF00 +#define PRXS3_HTPHY_RXPWR_ANT1 0x00FF /* Rx power on core 1 */ +#define PRXS3_HTPHY_RXPWR_ANT2 0xFF00 /* Rx power on core 2 */ /* htphy PhyRxStatus_4: */ -/* Rx power on core 3 */ -#define PRXS4_HTPHY_RXPWR_ANT3 0x00FF -/* Coarse frequency offset */ -#define PRXS4_HTPHY_CFO 0xFF00 +#define PRXS4_HTPHY_RXPWR_ANT3 0x00FF /* Rx power on core 3 */ +#define PRXS4_HTPHY_CFO 0xFF00 /* Coarse frequency offset */ /* htphy PhyRxStatus_5: */ -/* Fine frequency offset */ -#define PRXS5_HTPHY_FFO 0x00FF -/* Advance Retard */ -#define PRXS5_HTPHY_AR 0xFF00 +#define PRXS5_HTPHY_FFO 0x00FF /* Fine frequency offset */ +#define PRXS5_HTPHY_AR 0xFF00 /* Advance Retard */ -#define HTPHY_MMPLCPLen(rxs) \ - ((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \ +#define HTPHY_MMPLCPLen(rxs) ((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \ (((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8)) /* Get Rx power on core 0 */ -#define HTPHY_RXPWR_ANT0(rxs) \ - ((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8) +#define HTPHY_RXPWR_ANT0(rxs) ((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8) /* Get Rx power on core 1 */ -#define HTPHY_RXPWR_ANT1(rxs) \ - (((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1) +#define HTPHY_RXPWR_ANT1(rxs) (((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1) /* Get Rx power on core 2 */ -#define HTPHY_RXPWR_ANT2(rxs) \ - ((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8) +#define HTPHY_RXPWR_ANT2(rxs) ((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8) /* ucode RxStatus1: */ #define RXS_BCNSENT 0x8000 @@ -1529,8 +1400,7 @@ struct brcms_d11rxhdr { #define RXS_SECKINDX_SHIFT 5 #define RXS_DECERR (1 << 4) #define RXS_DECATMPT (1 << 3) -/* PAD bytes to make IP data 4 bytes aligned */ -#define RXS_PBPRES (1 << 2) +#define RXS_PBPRES (1 << 2) /* PAD bytes to make IP data 4 bytes aligned */ #define RXS_RESPFRAMETX (1 << 1) #define RXS_FCSERR (1 << 0) @@ -1563,17 +1433,16 @@ struct brcms_d11rxhdr { #define M_PSM_SOFT_REGS 0x0 #define M_BOM_REV_MAJOR (M_PSM_SOFT_REGS + 0x0) #define M_BOM_REV_MINOR (M_PSM_SOFT_REGS + 0x2) -#define M_UCODE_DBGST (M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */ -#define M_UCODE_MACSTAT (M_PSM_SOFT_REGS + 0xE0) /* macstat counters */ +#define M_UCODE_DBGST (M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */ +#define M_UCODE_MACSTAT (M_PSM_SOFT_REGS + 0xE0) /* macstat counters */ -#define M_AGING_THRSH (0x3e * 2) /* max time waiting for medium before tx */ -#define M_MBURST_SIZE (0x40 * 2) /* max frames in a frameburst */ -#define M_MBURST_TXOP (0x41 * 2) /* max frameburst TXOP in unit of us */ -#define M_SYNTHPU_DLY (0x4a * 2) /* pre-wakeup for synthpu, default: 500 */ +#define M_AGING_THRSH (0x3e * 2) /* max time waiting for medium before tx */ +#define M_MBURST_SIZE (0x40 * 2) /* max frames in a frameburst */ +#define M_MBURST_TXOP (0x41 * 2) /* max frameburst TXOP in unit of us */ +#define M_SYNTHPU_DLY (0x4a * 2) /* pre-wakeup for synthpu, default: 500 */ #define M_PRETBTT (0x4b * 2) -/* offset to the target txpwr */ -#define M_ALT_TXPWR_IDX (M_PSM_SOFT_REGS + (0x3b * 2)) +#define M_ALT_TXPWR_IDX (M_PSM_SOFT_REGS + (0x3b * 2)) /* offset to the target txpwr */ #define M_PHY_TX_FLT_PTR (M_PSM_SOFT_REGS + (0x3d * 2)) #define M_CTS_DURATION (M_PSM_SOFT_REGS + (0x5c * 2)) #define M_LP_RCCAL_OVR (M_PSM_SOFT_REGS + (0x6b * 2)) @@ -1582,16 +1451,11 @@ struct brcms_d11rxhdr { #define M_RXSTATS_BLK_PTR (M_PSM_SOFT_REGS + (0x65 * 2)) /* ucode debug status codes */ -/* not valid really */ -#define DBGST_INACTIVE 0 -/* after zeroing SHM, before suspending at init */ -#define DBGST_INIT 1 -/* "normal" state */ -#define DBGST_ACTIVE 2 -/* suspended */ -#define DBGST_SUSPENDED 3 -/* asleep (PS mode) */ -#define DBGST_ASLEEP 4 +#define DBGST_INACTIVE 0 /* not valid really */ +#define DBGST_INIT 1 /* after zeroing SHM, before suspending at init */ +#define DBGST_ACTIVE 2 /* "normal" state */ +#define DBGST_SUSPENDED 3 /* suspended */ +#define DBGST_ASLEEP 4 /* asleep (PS mode) */ /* Scratch Reg defs */ enum _ePsmScratchPadRegDefinitions { @@ -1599,66 +1463,66 @@ enum _ePsmScratchPadRegDefinitions { S_RSV1, S_RSV2, - /* offset 0x03: scratch registers for Dot11-contants */ - S_DOT11_CWMIN, /* CW-minimum */ - S_DOT11_CWMAX, /* CW-maximum */ - S_DOT11_CWCUR, /* CW-current */ - S_DOT11_SRC_LMT, /* short retry count limit */ - S_DOT11_LRC_LMT, /* long retry count limit */ - S_DOT11_DTIMCOUNT, /* DTIM-count */ - - /* offset 0x09: Tx-side scratch registers */ - S_SEQ_NUM, /* hardware sequence number reg */ - S_SEQ_NUM_FRAG, /* seq num for frags (at the start of MSDU) */ - S_FRMRETX_CNT, /* frame retx count */ - S_SSRC, /* Station short retry count */ - S_SLRC, /* Station long retry count */ - S_EXP_RSP, /* Expected response frame */ - S_OLD_BREM, /* Remaining backoff ctr */ - S_OLD_CWWIN, /* saved-off CW-cur */ - S_TXECTL, /* TXE-Ctl word constructed in scr-pad */ - S_CTXTST, /* frm type-subtype as read from Tx-descr */ - - /* offset 0x13: Rx-side scratch registers */ - S_RXTST, /* Type and subtype in Rxframe */ + /* scratch registers for Dot11-contants */ + S_DOT11_CWMIN, /* CW-minimum 0x03 */ + S_DOT11_CWMAX, /* CW-maximum 0x04 */ + S_DOT11_CWCUR, /* CW-current 0x05 */ + S_DOT11_SRC_LMT, /* short retry count limit 0x06 */ + S_DOT11_LRC_LMT, /* long retry count limit 0x07 */ + S_DOT11_DTIMCOUNT, /* DTIM-count 0x08 */ + + /* Tx-side scratch registers */ + S_SEQ_NUM, /* hardware sequence number reg 0x09 */ + S_SEQ_NUM_FRAG, /* seq-num for frags (Set at the start os MSDU 0x0A */ + S_FRMRETX_CNT, /* frame retx count 0x0B */ + S_SSRC, /* Station short retry count 0x0C */ + S_SLRC, /* Station long retry count 0x0D */ + S_EXP_RSP, /* Expected response frame 0x0E */ + S_OLD_BREM, /* Remaining backoff ctr 0x0F */ + S_OLD_CWWIN, /* saved-off CW-cur 0x10 */ + S_TXECTL, /* TXE-Ctl word constructed in scr-pad 0x11 */ + S_CTXTST, /* frm type-subtype as read from Tx-descr 0x12 */ + + /* Rx-side scratch registers */ + S_RXTST, /* Type and subtype in Rxframe 0x13 */ /* Global state register */ - S_STREG, /* state storage actual bit maps below */ - - S_TXPWR_SUM, /* Tx power control: accumulator */ - S_TXPWR_ITER, /* Tx power control: iteration */ - S_RX_FRMTYPE, /* Rate and PHY type for frames */ - S_THIS_AGG, /* Size of this AGG (A-MSDU) */ - - S_KEYINDX, - S_RXFRMLEN, /* Receive MPDU length in bytes */ - - /* offset 0x1B: Receive TSF time stored in SCR */ - S_RXTSFTMRVAL_WD3, /* TSF value at the start of rx */ - S_RXTSFTMRVAL_WD2, /* TSF value at the start of rx */ - S_RXTSFTMRVAL_WD1, /* TSF value at the start of rx */ - S_RXTSFTMRVAL_WD0, /* TSF value at the start of rx */ - S_RXSSN, /* Received start seq number for A-MPDU BA */ - S_RXQOSFLD, /* Rx-QoS field (if present) */ - - /* offset 0x21: Scratch pad regs used in microcode as temp storage */ - S_TMP0, /* stmp0 */ - S_TMP1, /* stmp1 */ - S_TMP2, /* stmp2 */ - S_TMP3, /* stmp3 */ - S_TMP4, /* stmp4 */ - S_TMP5, /* stmp5 */ - S_PRQPENALTY_CTR, /* Probe response queue penalty counter */ - S_ANTCNT, /* unsuccessful attempts on current ant. */ - S_SYMBOL, /* flag for possible symbol ctl frames */ - S_RXTP, /* rx frame type */ - S_STREG2, /* extra state storage */ - S_STREG3, /* even more extra state storage */ - S_STREG4, /* ... */ - S_STREG5, /* remember to initialize it to zero */ + S_STREG, /* state storage actual bit maps below 0x14 */ + + S_TXPWR_SUM, /* Tx power control: accumulator 0x15 */ + S_TXPWR_ITER, /* Tx power control: iteration 0x16 */ + S_RX_FRMTYPE, /* Rate and PHY type for frames 0x17 */ + S_THIS_AGG, /* Size of this AGG (A-MSDU) 0x18 */ + + S_KEYINDX, /* 0x19 */ + S_RXFRMLEN, /* Receive MPDU length in bytes 0x1A */ + + /* Receive TSF time stored in SCR */ + S_RXTSFTMRVAL_WD3, /* TSF value at the start of rx 0x1B */ + S_RXTSFTMRVAL_WD2, /* TSF value at the start of rx 0x1C */ + S_RXTSFTMRVAL_WD1, /* TSF value at the start of rx 0x1D */ + S_RXTSFTMRVAL_WD0, /* TSF value at the start of rx 0x1E */ + S_RXSSN, /* Received start seq number for A-MPDU BA 0x1F */ + S_RXQOSFLD, /* Rx-QoS field (if present) 0x20 */ + + /* Scratch pad regs used in microcode as temp storage */ + S_TMP0, /* stmp0 0x21 */ + S_TMP1, /* stmp1 0x22 */ + S_TMP2, /* stmp2 0x23 */ + S_TMP3, /* stmp3 0x24 */ + S_TMP4, /* stmp4 0x25 */ + S_TMP5, /* stmp5 0x26 */ + S_PRQPENALTY_CTR, /* Probe response queue penalty counter 0x27 */ + S_ANTCNT, /* unsuccessful attempts on current ant. 0x28 */ + S_SYMBOL, /* flag for possible symbol ctl frames 0x29 */ + S_RXTP, /* rx frame type 0x2A */ + S_STREG2, /* extra state storage 0x2B */ + S_STREG3, /* even more extra state storage 0x2C */ + S_STREG4, /* ... 0x2D */ + S_STREG5, /* remember to initialize it to zero 0x2E */ S_ADJPWR_IDX, - S_CUR_PTR, /* Temp pointer for A-MPDU re-Tx SHM table */ + S_CUR_PTR, /* Temp pointer for A-MPDU re-Tx SHM table 0x32 */ S_REVID4, /* 0x33 */ S_INDX, /* 0x34 */ S_ADDR0, /* 0x35 */ @@ -1668,9 +1532,9 @@ enum _ePsmScratchPadRegDefinitions { S_ADDR4, /* 0x39 */ S_ADDR5, /* 0x3A */ S_TMP6, /* 0x3B */ - S_KEYINDX_BU, /* Backup for Key index */ - S_MFGTEST_TMP0, /* Temp regs used for RX test calculations */ - S_RXESN, /* Received end sequence number for A-MPDU BA */ + S_KEYINDX_BU, /* Backup for Key index 0x3C */ + S_MFGTEST_TMP0, /* Temp register used for RX test calculations 0x3D */ + S_RXESN, /* Received end sequence number for A-MPDU BA 0x3E */ S_STREG6, /* 0x3F */ }; @@ -1764,8 +1628,7 @@ struct macstat { #define SISF_FCLKA 0x0004 /* FastClkAvailable */ #define SISF_DB_PHY 0x0008 /* Dualband phy */ -/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg === */ -/* radio and LPPHY regs are separated */ +/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg, radio and LPPHY regs are separated === */ #define BPHY_REG_OFT_BASE 0x0 /* offsets for indirect access to bphy registers */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/dma.c b/trunk/drivers/staging/brcm80211/brcmsmac/dma.c index 05dad9fcc931..ea17671efb63 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/dma.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/dma.c @@ -18,14 +18,17 @@ #include #include +#if defined(__mips__) +#include +#endif + #include #include #include "types.h" #include "dma.h" /* - * Each descriptor ring must be 8kB aligned, and fit within a - * contiguous 8kB physical address. + * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical address. */ #define D64RINGALIGN_BITS 13 #define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) @@ -66,32 +69,21 @@ #define D64_XS1_XE_COREE 0x50000000 /* core error */ /* receive channel control */ -/* receive enable */ -#define D64_RC_RE 0x00000001 -/* receive frame offset */ -#define D64_RC_RO_MASK 0x000000fe +#define D64_RC_RE 0x00000001 /* receive enable */ +#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ #define D64_RC_RO_SHIFT 1 -/* direct fifo receive (pio) mode */ -#define D64_RC_FM 0x00000100 -/* separate rx header descriptor enable */ -#define D64_RC_SH 0x00000200 -/* overflow continue */ -#define D64_RC_OC 0x00000400 -/* parity check disable */ -#define D64_RC_PD 0x00000800 -/* address extension bits */ -#define D64_RC_AE 0x00030000 +#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ +#define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */ +#define D64_RC_OC 0x00000400 /* overflow continue */ +#define D64_RC_PD 0x00000800 /* parity check disable */ +#define D64_RC_AE 0x00030000 /* address extension bits */ #define D64_RC_AE_SHIFT 16 /* flags for dma controller */ -/* partity enable */ -#define DMA_CTRL_PEN (1 << 0) -/* rx overflow continue */ -#define DMA_CTRL_ROC (1 << 1) -/* allow rx scatter to multiple descriptors */ -#define DMA_CTRL_RXMULTI (1 << 2) -/* Unframed Rx/Tx data */ -#define DMA_CTRL_UNFRAMED (1 << 3) +#define DMA_CTRL_PEN (1 << 0) /* partity enable */ +#define DMA_CTRL_ROC (1 << 1) /* rx overflow continue */ +#define DMA_CTRL_RXMULTI (1 << 2) /* allow rx scatter to multiple descriptors */ +#define DMA_CTRL_UNFRAMED (1 << 3) /* Unframed Rx/Tx data */ /* receive descriptor table pointer */ #define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ @@ -139,13 +131,10 @@ #define D64_CTRL1_SOF ((u32)1 << 31) /* start of frame */ /* descriptor control flags 2 */ -/* buffer byte count. real data len must <= 16KB */ -#define D64_CTRL2_BC_MASK 0x00007fff -/* address extension bits */ -#define D64_CTRL2_AE 0x00030000 +#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count. real data len must <= 16KB */ +#define D64_CTRL2_AE 0x00030000 /* address extension bits */ #define D64_CTRL2_AE_SHIFT 16 -/* parity bit */ -#define D64_CTRL2_PARITY 0x00040000 +#define D64_CTRL2_PARITY 0x00040000 /* parity bit */ /* control flags in the range [27:20] are core-specific and not defined here */ #define D64_CTRL_CORE_MASK 0x0ff00000 @@ -155,16 +144,15 @@ #define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1 */ #define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */ -#define DMA64_DD_PARITY(dd) \ - parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2) +#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */ +#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */ +#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */ +#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */ -/* - * packet headroom necessary to accommodate the largest header - * in the system, (i.e TXOFF). By doing, we avoid the need to - * allocate an extra buffer for the header when bridging to WL. - * There is a compile time check in wlc.c which ensure that this - * value is at least as big as TXOFF. This value is used in - * dma_rxfill(). +/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF). + * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. + * There is a compile time check in wlc.c which ensure that this value is at least as big + * as TXOFF. This value is used in dma_rxfill (dma.c). */ #define BCMEXTRAHDROOM 172 @@ -192,29 +180,39 @@ #define DMA_NONE(args) +typedef unsigned long dmaaddr_t; +#define PHYSADDRHI(_pa) (0) +#define PHYSADDRHISET(_pa, _val) +#define PHYSADDRLO(_pa) ((_pa)) +#define PHYSADDRLOSET(_pa, _val) \ + do { \ + (_pa) = (_val); \ + } while (0) + #define d64txregs dregs.d64_u.txregs_64 #define d64rxregs dregs.d64_u.rxregs_64 #define txd64 dregs.d64_u.txd_64 #define rxd64 dregs.d64_u.rxd_64 -/* - * default dma message level (if input msg_level - * pointer is null in dma_attach()) - */ +/* default dma message level (if input msg_level pointer is null in dma_attach()) */ static uint dma_msg_level; #define MAXNAMEL 8 /* 8 char names */ #define DI_INFO(dmah) ((dma_info_t *)dmah) +#define R_SM(r) (*(r)) +#define W_SM(r, v) (*(r) = (v)) + /* One physical DMA segment */ struct dma_seg { - unsigned long addr; + dmaaddr_t addr; u32 length; }; struct dma_seg_map { - uint origsize; /* Size of the virtual packet */ + void *oshdmah; /* Opaque handle for OSL to store its information */ + uint origsize; /* Size of the virtual packet */ uint nsegs; struct dma_seg segs[MAX_DMA_SEGS]; }; @@ -224,9 +222,9 @@ struct dma_seg_map { * Descriptors are only read by the hardware, never written back. */ struct dma64desc { - u32 ctrl1; /* misc control bits & bufcount */ - u32 ctrl2; /* buffer count and address extension */ - u32 addrlow; /* memory address of the date buffer, bits 31:0 */ + u32 ctrl1; /* misc control bits & bufcount */ + u32 ctrl2; /* buffer count and address extension */ + u32 addrlow; /* memory address of the date buffer, bits 31:0 */ u32 addrhigh; /* memory address of the date buffer, bits 63:32 */ }; @@ -236,17 +234,15 @@ struct dma_info { uint *msg_level; /* message level pointer */ char name[MAXNAMEL]; /* callers name for diag msgs */ - struct pci_dev *pbus; /* bus handle */ + void *pbus; /* bus handle */ - bool dma64; /* this dma engine is operating in 64-bit mode */ - bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ + bool dma64; /* this dma engine is operating in 64-bit mode */ + bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ union { struct { - /* 64-bit dma tx engine registers */ - struct dma64regs *txregs_64; - /* 64-bit dma rx engine registers */ - struct dma64regs *rxregs_64; + dma64regs_t *txregs_64; /* 64-bit dma tx engine registers */ + dma64regs_t *rxregs_64; /* 64-bit dma rx engine registers */ /* pointer to dma64 tx descriptor ring */ struct dma64desc *txd_64; /* pointer to dma64 rx descriptor ring */ @@ -259,63 +255,48 @@ struct dma_info { u16 ntxd; /* # tx descriptors tunable */ u16 txin; /* index of next descriptor to reclaim */ u16 txout; /* index of next descriptor to post */ - /* pointer to parallel array of pointers to packets */ - struct sk_buff **txp; + void **txp; /* pointer to parallel array of pointers to packets */ struct dma_seg_map *txp_dmah; /* DMA MAP meta-data handle */ - /* Aligned physical address of descriptor ring */ - unsigned long txdpa; - /* Original physical address of descriptor ring */ - unsigned long txdpaorig; + dmaaddr_t txdpa; /* Aligned physical address of descriptor ring */ + dmaaddr_t txdpaorig; /* Original physical address of descriptor ring */ u16 txdalign; /* #bytes added to alloc'd mem to align txd */ u32 txdalloc; /* #bytes allocated for the ring */ u32 xmtptrbase; /* When using unaligned descriptors, the ptr register - * is not just an index, it needs all 13 bits to be - * an offset from the addr register. - */ + * is not just an index, it needs all 13 bits to be + * an offset from the addr register. + */ - u16 nrxd; /* # rx descriptors tunable */ - u16 rxin; /* index of next descriptor to reclaim */ - u16 rxout; /* index of next descriptor to post */ - /* pointer to parallel array of pointers to packets */ - struct sk_buff **rxp; + u16 nrxd; /* # rx descriptors tunable */ + u16 rxin; /* index of next descriptor to reclaim */ + u16 rxout; /* index of next descriptor to post */ + void **rxp; /* pointer to parallel array of pointers to packets */ struct dma_seg_map *rxp_dmah; /* DMA MAP meta-data handle */ - /* Aligned physical address of descriptor ring */ - unsigned long rxdpa; - /* Original physical address of descriptor ring */ - unsigned long rxdpaorig; + dmaaddr_t rxdpa; /* Aligned physical address of descriptor ring */ + dmaaddr_t rxdpaorig; /* Original physical address of descriptor ring */ u16 rxdalign; /* #bytes added to alloc'd mem to align rxd */ u32 rxdalloc; /* #bytes allocated for the ring */ u32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */ /* tunables */ - unsigned int rxbufsize; /* rx buffer size in bytes, not including - * the extra headroom + unsigned int rxbufsize; /* rx buffer size in bytes, + * not including the extra headroom */ - uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper - * stack, e.g. some rx pkt buffers will be - * bridged to tx side without byte copying. - * The extra headroom needs to be large enough - * to fit txheader needs. Some dongle driver may - * not need it. + uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper stack + * e.g. some rx pkt buffers will be bridged to tx side + * without byte copying. The extra headroom needs to be + * large enough to fit txheader needs. + * Some dongle driver may not need it. */ uint nrxpost; /* # rx buffers to keep posted */ unsigned int rxoffset; /* rxcontrol offset */ - /* add to get dma address of descriptor ring, low 32 bits */ - uint ddoffsetlow; - /* high 32 bits */ - uint ddoffsethigh; - /* add to get dma address of data buffer, low 32 bits */ - uint dataoffsetlow; - /* high 32 bits */ - uint dataoffsethigh; - /* descriptor base need to be aligned or not */ - bool aligndesc_4k; + uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */ + uint ddoffsethigh; /* high 32 bits */ + uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */ + uint dataoffsethigh; /* high 32 bits */ + bool aligndesc_4k; /* descriptor base need to be aligned or not */ }; -/* - * DMA Scatter-gather list is supported. Note this is limited to TX - * direction only - */ +/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */ #ifdef BCMDMASGLISTOSL #define DMASGLIST_ENAB true #else @@ -323,9 +304,7 @@ struct dma_info { #endif /* BCMDMASGLISTOSL */ /* descriptor bumping macros */ -/* faster than %, but n must be power of 2 */ -#define XXD(x, n) ((x) & ((n) - 1)) - +#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */ #define TXD(x) XXD((x), di->ntxd) #define RXD(x) XXD((x), di->nrxd) #define NEXTTXD(i) TXD((i) + 1) @@ -350,24 +329,110 @@ struct dma_info { static bool _dma_isaddrext(struct dma_info *di); static bool _dma_descriptor_align(struct dma_info *di); static bool _dma_alloc(struct dma_info *di, uint direction); +static void _dma_detach(struct dma_info *di); static void _dma_ddtable_init(struct dma_info *di, uint direction, - unsigned long pa); + dmaaddr_t pa); +static void _dma_rxinit(struct dma_info *di); +static void *_dma_rx(struct dma_info *di); +static bool _dma_rxfill(struct dma_info *di); +static void _dma_rxreclaim(struct dma_info *di); static void _dma_rxenable(struct dma_info *di); -static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall); +static void *_dma_getnextrxp(struct dma_info *di, bool forceall); +static void _dma_rx_param_get(struct dma_info *di, u16 *rxoffset, + u16 *rxbufsize); + +static void _dma_txblock(struct dma_info *di); +static void _dma_txunblock(struct dma_info *di); +static uint _dma_txactive(struct dma_info *di); +static uint _dma_rxactive(struct dma_info *di); +static uint _dma_txpending(struct dma_info *di); +static uint _dma_txcommitted(struct dma_info *di); + +static void *_dma_peeknexttxp(struct dma_info *di); +static void *_dma_peeknextrxp(struct dma_info *di); +static unsigned long _dma_getvar(struct dma_info *di, const char *name); +static void _dma_counterreset(struct dma_info *di); +static void _dma_fifoloopbackenable(struct dma_info *di); static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags); static u8 dma_align_sizetobits(uint size); static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size, u16 *alignbits, uint *alloced, - unsigned long *descpa); + dmaaddr_t *descpa); /* Prototypes for 64-bit routines */ static bool dma64_alloc(struct dma_info *di, uint direction); -static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall); +static bool dma64_txreset(struct dma_info *di); +static bool dma64_rxreset(struct dma_info *di); +static bool dma64_txsuspendedidle(struct dma_info *di); +static int dma64_txfast(struct dma_info *di, struct sk_buff *p0, bool commit); +static int dma64_txunframed(struct dma_info *di, void *p0, uint len, + bool commit); +static void *dma64_getpos(struct dma_info *di, bool direction); +static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range); +static void *dma64_getnextrxp(struct dma_info *di, bool forceall); +static void dma64_txrotate(struct dma_info *di); + static bool dma64_rxidle(struct dma_info *di); -static bool _dma64_addrext(struct dma64regs *dma64regs); +static void dma64_txinit(struct dma_info *di); +static bool dma64_txenabled(struct dma_info *di); +static void dma64_txsuspend(struct dma_info *di); +static void dma64_txresume(struct dma_info *di); +static bool dma64_txsuspended(struct dma_info *di); +static void dma64_txreclaim(struct dma_info *di, enum txd_range range); +static bool dma64_txstopped(struct dma_info *di); +static bool dma64_rxstopped(struct dma_info *di); +static bool dma64_rxenabled(struct dma_info *di); +static bool _dma64_addrext(dma64regs_t *dma64regs); static inline u32 parity32(u32 data); +const struct di_fcn_s dma64proc = { + (di_detach_t) _dma_detach, + (di_txinit_t) dma64_txinit, + (di_txreset_t) dma64_txreset, + (di_txenabled_t) dma64_txenabled, + (di_txsuspend_t) dma64_txsuspend, + (di_txresume_t) dma64_txresume, + (di_txsuspended_t) dma64_txsuspended, + (di_txsuspendedidle_t) dma64_txsuspendedidle, + (di_txfast_t) dma64_txfast, + (di_txunframed_t) dma64_txunframed, + (di_getpos_t) dma64_getpos, + (di_txstopped_t) dma64_txstopped, + (di_txreclaim_t) dma64_txreclaim, + (di_getnexttxp_t) dma64_getnexttxp, + (di_peeknexttxp_t) _dma_peeknexttxp, + (di_txblock_t) _dma_txblock, + (di_txunblock_t) _dma_txunblock, + (di_txactive_t) _dma_txactive, + (di_txrotate_t) dma64_txrotate, + + (di_rxinit_t) _dma_rxinit, + (di_rxreset_t) dma64_rxreset, + (di_rxidle_t) dma64_rxidle, + (di_rxstopped_t) dma64_rxstopped, + (di_rxenable_t) _dma_rxenable, + (di_rxenabled_t) dma64_rxenabled, + (di_rx_t) _dma_rx, + (di_rxfill_t) _dma_rxfill, + (di_rxreclaim_t) _dma_rxreclaim, + (di_getnextrxp_t) _dma_getnextrxp, + (di_peeknextrxp_t) _dma_peeknextrxp, + (di_rxparam_get_t) _dma_rx_param_get, + + (di_fifoloopbackenable_t) _dma_fifoloopbackenable, + (di_getvar_t) _dma_getvar, + (di_counterreset_t) _dma_counterreset, + (di_ctrlflags_t) _dma_ctrlflags, + NULL, + NULL, + NULL, + (di_rxactive_t) _dma_rxactive, + (di_txpending_t) _dma_txpending, + (di_txcommitted_t) _dma_txcommitted, + 39 +}; + struct dma_pub *dma_attach(char *name, struct si_pub *sih, void *dmaregstx, void *dmaregsrx, uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, @@ -391,15 +456,17 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64); /* init dma reg pointer */ - di->d64txregs = (struct dma64regs *) dmaregstx; - di->d64rxregs = (struct dma64regs *) dmaregsrx; - - /* - * Default flags (which can be changed by the driver calling - * dma_ctrlflags before enable): For backwards compatibility - * both Rx Overflow Continue and Parity are DISABLED. + di->d64txregs = (dma64regs_t *) dmaregstx; + di->d64rxregs = (dma64regs_t *) dmaregsrx; + di->dma.di_fn = (const struct di_fcn_s *)&dma64proc; + + /* Default flags (which can be changed by the driver calling dma_ctrlflags + * before enable): For backwards compatibility both Rx Overflow Continue + * and Parity are DISABLED. + * supports it. */ - _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); + di->dma.di_fn->ctrlflags(&di->dma, DMA_CTRL_ROC | DMA_CTRL_PEN, + 0); DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d " "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d " @@ -430,18 +497,23 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, /* * figure out the DMA physical address offset for dd and data - * PCI/PCIE: they map silicon backplace address to zero - * based memory, need offset - * Other bus: use zero SI_BUS BIGENDIAN kludge: use sdram - * swapped region for data buffer, not descriptor + * PCI/PCIE: they map silicon backplace address to zero based memory, need offset + * Other bus: use zero + * SI_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor */ di->ddoffsetlow = 0; di->dataoffsetlow = 0; - /* add offset for pcie with DMA64 bus */ - di->ddoffsetlow = 0; - di->ddoffsethigh = SI_PCIE_DMA_H32; - di->dataoffsetlow = di->ddoffsetlow; - di->dataoffsethigh = di->ddoffsethigh; + /* for pci bus, add offset */ + if (sih->bustype == PCI_BUS) { + /* pcie with DMA64 */ + di->ddoffsetlow = 0; + di->ddoffsethigh = SI_PCIE_DMA_H32; + di->dataoffsetlow = di->ddoffsetlow; + di->dataoffsethigh = di->ddoffsethigh; + } +#if defined(__mips__) && defined(IL_BIGENDIAN) + di->dataoffsetlow = di->dataoffsetlow + SI_SDRAM_SWAPPED; +#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */ /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */ if ((ai_coreid(sih) == SDIOD_CORE_ID) && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2))) @@ -452,16 +524,16 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, else di->addrext = _dma_isaddrext(di); - /* does the descriptor need to be aligned and if yes, on 4K/8K or not */ + /* does the descriptors need to be aligned and if yes, on 4K/8K or not */ di->aligndesc_4k = _dma_descriptor_align(di); if (di->aligndesc_4k) { di->dmadesc_align = D64RINGALIGN_BITS; - if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) + if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) { /* for smaller dd table, HW relax alignment reqmnt */ di->dmadesc_align = D64RINGALIGN_BITS - 1; - } else { + } + } else di->dmadesc_align = 4; /* 16 byte alignment */ - } DMA_NONE(("DMA descriptor align_needed %d, align %d\n", di->aligndesc_4k, di->dmadesc_align)); @@ -471,8 +543,7 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, size = ntxd * sizeof(void *); di->txp = kzalloc(size, GFP_ATOMIC); if (di->txp == NULL) { - DMA_ERROR(("%s: dma_attach: out of tx memory\n", - di->name)); + DMA_ERROR(("%s: dma_attach: out of tx memory\n", di->name)); goto fail; } } @@ -482,47 +553,35 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, size = nrxd * sizeof(void *); di->rxp = kzalloc(size, GFP_ATOMIC); if (di->rxp == NULL) { - DMA_ERROR(("%s: dma_attach: out of rx memory\n", - di->name)); + DMA_ERROR(("%s: dma_attach: out of rx memory\n", di->name)); goto fail; } } - /* - * allocate transmit descriptor ring, only need ntxd descriptors - * but it must be aligned - */ + /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ if (ntxd) { if (!_dma_alloc(di, DMA_TX)) goto fail; } - /* - * allocate receive descriptor ring, only need nrxd descriptors - * but it must be aligned - */ + /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ if (nrxd) { if (!_dma_alloc(di, DMA_RX)) goto fail; } if ((di->ddoffsetlow != 0) && !di->addrext) { - if (di->txdpa > SI_PCI_DMA_SZ) { - DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not " - "supported\n", di->name, (u32)di->txdpa)); + if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) { + DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->txdpa))); goto fail; } - if (di->rxdpa > SI_PCI_DMA_SZ) { - DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not " - "supported\n", di->name, (u32)di->rxdpa)); + if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) { + DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->rxdpa))); goto fail; } } - DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x " - "dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow, - di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh, - di->addrext)); + DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh, di->addrext)); /* allocate DMA mapping vectors */ if (DMASGLIST_ENAB) { @@ -544,7 +603,7 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih, return (struct dma_pub *) di; fail: - dma_detach((struct dma_pub *)di); + _dma_detach(di); return NULL; } @@ -560,35 +619,48 @@ static inline u32 parity32(u32 data) return data & 1; } +#define DMA64_DD_PARITY(dd) parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2) + static inline void dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring, - unsigned long pa, uint outidx, u32 *flags, u32 bufcount) + dmaaddr_t pa, uint outidx, u32 *flags, u32 bufcount) { u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; /* PCI bus with big(>1G) physical address, use address extension */ - if ((di->dataoffsetlow == 0) || !(pa & PCI32ADDR_HIGH)) { - ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow); - ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh); - ddring[outidx].ctrl1 = cpu_to_le32(*flags); - ddring[outidx].ctrl2 = cpu_to_le32(ctrl2); +#if defined(__mips__) && defined(IL_BIGENDIAN) + if ((di->dataoffsetlow == SI_SDRAM_SWAPPED) + || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { +#else + if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { +#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */ + + W_SM(&ddring[outidx].addrlow, + BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); + W_SM(&ddring[outidx].addrhigh, + BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh)); + W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); + W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); } else { /* address extension for 32-bit PCI */ u32 ae; - ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; - pa &= ~PCI32ADDR_HIGH; + ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; + PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; - ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow); - ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh); - ddring[outidx].ctrl1 = cpu_to_le32(*flags); - ddring[outidx].ctrl2 = cpu_to_le32(ctrl2); + W_SM(&ddring[outidx].addrlow, + BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); + W_SM(&ddring[outidx].addrhigh, + BUS_SWAP32(0 + di->dataoffsethigh)); + W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); + W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); } if (di->dma.dmactrlflags & DMA_CTRL_PEN) { - if (DMA64_DD_PARITY(&ddring[outidx])) - ddring[outidx].ctrl2 = - cpu_to_le32(ctrl2 | D64_CTRL2_PARITY); + if (DMA64_DD_PARITY(&ddring[outidx])) { + W_SM(&ddring[outidx].ctrl2, + BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY)); + } } } @@ -600,24 +672,18 @@ static bool _dma_alloc(struct dma_info *di, uint direction) void *dma_alloc_consistent(struct pci_dev *pdev, uint size, u16 align_bits, uint *alloced, unsigned long *pap) { - void *rc; - dma_addr_t dma_addr; - if (align_bits) { u16 align = (1 << align_bits); if (!IS_ALIGNED(PAGE_SIZE, align)) size += align; *alloced = size; } - rc = pci_alloc_consistent(pdev, size, &dma_addr); - *pap = dma_addr; - return rc; + return pci_alloc_consistent(pdev, size, (dma_addr_t *) pap); } /* !! may be called with core in reset */ -void dma_detach(struct dma_pub *pub) +static void _dma_detach(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; DMA_TRACE(("%s: dma_detach\n", di->name)); @@ -665,76 +731,87 @@ static bool _dma_descriptor_align(struct dma_info *di) return true; } -/* - * return true if this dma engine supports DmaExtendedAddrChanges, - * otherwise false - */ +/* return true if this dma engine supports DmaExtendedAddrChanges, otherwise false */ static bool _dma_isaddrext(struct dma_info *di) { /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ /* not all tx or rx channel are available */ if (di->d64txregs != NULL) { - if (!_dma64_addrext(di->d64txregs)) + if (!_dma64_addrext(di->d64txregs)) { DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have " "AE set\n", di->name)); + } return true; } else if (di->d64rxregs != NULL) { - if (!_dma64_addrext(di->d64rxregs)) + if (!_dma64_addrext(di->d64rxregs)) { DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have " "AE set\n", di->name)); + } return true; } - return false; } /* initialize descriptor table base address */ -static void -_dma_ddtable_init(struct dma_info *di, uint direction, unsigned long pa) +static void _dma_ddtable_init(struct dma_info *di, uint direction, dmaaddr_t pa) { if (!di->aligndesc_4k) { if (direction == DMA_TX) - di->xmtptrbase = pa; + di->xmtptrbase = PHYSADDRLO(pa); else - di->rcvptrbase = pa; + di->rcvptrbase = PHYSADDRLO(pa); } if ((di->ddoffsetlow == 0) - || !(pa & PCI32ADDR_HIGH)) { + || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { if (direction == DMA_TX) { - W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); - W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); + W_REG(&di->d64txregs->addrlow, + (PHYSADDRLO(pa) + di->ddoffsetlow)); + W_REG(&di->d64txregs->addrhigh, + (PHYSADDRHI(pa) + di->ddoffsethigh)); } else { - W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); - W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); + W_REG(&di->d64rxregs->addrlow, + (PHYSADDRLO(pa) + di->ddoffsetlow)); + W_REG(&di->d64rxregs->addrhigh, + (PHYSADDRHI(pa) + di->ddoffsethigh)); } } else { /* DMA64 32bits address extension */ u32 ae; /* shift the high bit(s) from pa to ae */ - ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; - pa &= ~PCI32ADDR_HIGH; + ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> + PCI32ADDR_HIGH_SHIFT; + PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; if (direction == DMA_TX) { - W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); - W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); + W_REG(&di->d64txregs->addrlow, + (PHYSADDRLO(pa) + di->ddoffsetlow)); + W_REG(&di->d64txregs->addrhigh, + di->ddoffsethigh); SET_REG(&di->d64txregs->control, D64_XC_AE, (ae << D64_XC_AE_SHIFT)); } else { - W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); - W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); + W_REG(&di->d64rxregs->addrlow, + (PHYSADDRLO(pa) + di->ddoffsetlow)); + W_REG(&di->d64rxregs->addrhigh, + di->ddoffsethigh); SET_REG(&di->d64rxregs->control, D64_RC_AE, (ae << D64_RC_AE_SHIFT)); } } } -void dma_rxinit(struct dma_pub *pub) +static void _dma_fifoloopbackenable(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; + DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name)); + OR_REG(&di->d64txregs->control, D64_XC_LE); +} + +static void _dma_rxinit(struct dma_info *di) +{ DMA_TRACE(("%s: dma_rxinit\n", di->name)); if (di->nrxd == 0) @@ -743,7 +820,8 @@ void dma_rxinit(struct dma_pub *pub) di->rxin = di->rxout = 0; /* clear rx descriptor ring */ - memset(di->rxd64, '\0', di->nrxd * sizeof(struct dma64desc)); + memset((void *)di->rxd64, '\0', + (di->nrxd * sizeof(struct dma64desc))); /* DMA engine with out alignment requirement requires table to be inited * before enabling the engine @@ -778,19 +856,25 @@ static void _dma_rxenable(struct dma_info *di) ((di->rxoffset << D64_RC_RO_SHIFT) | control)); } -/* - * !! rx entry routine +static void +_dma_rx_param_get(struct dma_info *di, u16 *rxoffset, u16 *rxbufsize) +{ + /* the normal values fit into 16 bits */ + *rxoffset = (u16) di->rxoffset; + *rxbufsize = (u16) di->rxbufsize; +} + +/* !! rx entry routine * returns a pointer to the next frame received, or NULL if there are no more - * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is - * supported with pkts chain + * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported + * with pkts chain * otherwise, it's treated as giant pkt and will be tossed. - * The DMA scattering starts with normal DMA header, followed by first - * buffer data. After it reaches the max size of buffer, the data continues - * in next DMA descriptor buffer WITHOUT DMA header + * The DMA scattering starts with normal DMA header, followed by first buffer data. + * After it reaches the max size of buffer, the data continues in next DMA descriptor + * buffer WITHOUT DMA header */ -struct sk_buff *dma_rx(struct dma_pub *pub) +static void *_dma_rx(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; struct sk_buff *p, *head, *tail; uint len; uint pkt_len; @@ -830,7 +914,7 @@ struct sk_buff *dma_rx(struct dma_pub *pub) D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc); - DMA_ERROR(("dma_rx, rxin %d rxout %d, hw_curr %d\n", + DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n", di->rxin, di->rxout, cur)); } #endif /* BCMDBG */ @@ -847,21 +931,19 @@ struct sk_buff *dma_rx(struct dma_pub *pub) return head; } -/* - * post receive buffers - * return false is refill failed completely and ring is empty this will stall - * the rx dma and user might want to call rxfill again asap. This unlikely - * happens on memory-rich NIC, but often on memory-constrained dongle +/* post receive buffers + * return false is refill failed completely and ring is empty + * this will stall the rx dma and user might want to call rxfill again asap + * This unlikely happens on memory-rich NIC, but often on memory-constrained dongle */ -bool dma_rxfill(struct dma_pub *pub) +static bool _dma_rxfill(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; struct sk_buff *p; u16 rxin, rxout; u32 flags = 0; uint n; uint i; - unsigned long pa; + dmaaddr_t pa; uint extra_offset = 0; bool ring_empty; @@ -884,10 +966,10 @@ bool dma_rxfill(struct dma_pub *pub) extra_offset = di->rxextrahdrroom; for (i = 0; i < n; i++) { - /* - * the di->rxbufsize doesn't include the extra headroom, - * we need to add it to the size to be allocated + /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the + size to be allocated */ + p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset); if (p == NULL) { @@ -939,10 +1021,49 @@ bool dma_rxfill(struct dma_pub *pub) return ring_empty; } -void dma_rxreclaim(struct dma_pub *pub) +/* like getnexttxp but no reclaim */ +static void *_dma_peeknexttxp(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; - struct sk_buff *p; + uint end, i; + + if (di->ntxd == 0) + return NULL; + + end = + B2I(((R_REG(&di->d64txregs->status0) & + D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK, + struct dma64desc); + + for (i = di->txin; i != end; i = NEXTTXD(i)) + if (di->txp[i]) + return di->txp[i]; + + return NULL; +} + +/* like getnextrxp but not take off the ring */ +static void *_dma_peeknextrxp(struct dma_info *di) +{ + uint end, i; + + if (di->nrxd == 0) + return NULL; + + end = + B2I(((R_REG(&di->d64rxregs->status0) & + D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK, + struct dma64desc); + + for (i = di->rxin; i != end; i = NEXTRXD(i)) + if (di->rxp[i]) + return di->rxp[i]; + + return NULL; +} + +static void _dma_rxreclaim(struct dma_info *di) +{ + void *p; DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); @@ -950,7 +1071,7 @@ void dma_rxreclaim(struct dma_pub *pub) brcmu_pkt_buf_free_skb(p); } -static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall) +static void *_dma_getnextrxp(struct dma_info *di, bool forceall) { if (di->nrxd == 0) return NULL; @@ -958,12 +1079,57 @@ static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall) return dma64_getnextrxp(di, forceall); } -void dma_counterreset(struct dma_pub *pub) +static void _dma_txblock(struct dma_info *di) +{ + di->dma.txavail = 0; +} + +static void _dma_txunblock(struct dma_info *di) +{ + di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; +} + +static uint _dma_txactive(struct dma_info *di) { - /* reset all software counters */ - pub->rxgiants = 0; - pub->rxnobuf = 0; - pub->txnobuf = 0; + return NTXDACTIVE(di->txin, di->txout); +} + +static uint _dma_txpending(struct dma_info *di) +{ + uint curr; + + curr = + B2I(((R_REG(&di->d64txregs->status0) & + D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK, + struct dma64desc); + + return NTXDACTIVE(curr, di->txout); +} + +static uint _dma_txcommitted(struct dma_info *di) +{ + uint ptr; + uint txin = di->txin; + + if (txin == di->txout) + return 0; + + ptr = B2I(R_REG(&di->d64txregs->ptr), struct dma64desc); + + return NTXDACTIVE(di->txin, ptr); +} + +static uint _dma_rxactive(struct dma_info *di) +{ + return NRXDACTIVE(di->rxin, di->rxout); +} + +static void _dma_counterreset(struct dma_info *di) +{ + /* reset all software counter */ + di->dma.rxgiants = 0; + di->dma.rxnobuf = 0; + di->dma.txnobuf = 0; } static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) @@ -985,15 +1151,16 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) control = R_REG(&di->d64txregs->control); W_REG(&di->d64txregs->control, control | D64_XC_PD); - if (R_REG(&di->d64txregs->control) & D64_XC_PD) + if (R_REG(&di->d64txregs->control) & D64_XC_PD) { /* We *can* disable it so it is supported, * restore control register */ W_REG(&di->d64txregs->control, control); - else + } else { /* Not supported, don't allow it to be enabled */ dmactrlflags &= ~DMA_CTRL_PEN; + } } di->dma.dmactrlflags = dmactrlflags; @@ -1002,10 +1169,8 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) } /* get the address of the var in order to change later */ -unsigned long dma_getvar(struct dma_pub *pub, const char *name) +static unsigned long _dma_getvar(struct dma_info *di, const char *name) { - struct dma_info *di = (struct dma_info *)pub; - if (!strcmp(name, "&txavail")) return (unsigned long)&(di->dma.txavail); return 0; @@ -1015,8 +1180,9 @@ static u8 dma_align_sizetobits(uint size) { u8 bitpos = 0; - while (size >>= 1) + while (size >>= 1) { bitpos++; + } return bitpos; } @@ -1028,7 +1194,7 @@ u8 dma_align_sizetobits(uint size) */ static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size, u16 *alignbits, uint *alloced, - unsigned long *descpa) + dmaaddr_t *descpa) { void *va; u32 desc_strtaddr; @@ -1052,9 +1218,8 @@ static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size, /* 64-bit DMA functions */ -void dma_txinit(struct dma_pub *pub) +static void dma64_txinit(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; u32 control = D64_XC_XE; DMA_TRACE(("%s: dma_txinit\n", di->name)); @@ -1066,7 +1231,7 @@ void dma_txinit(struct dma_pub *pub) di->dma.txavail = di->ntxd - 1; /* clear tx descriptor ring */ - memset(di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc))); + memset((void *)di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc))); /* DMA engine with out alignment requirement requires table to be inited * before enabling the engine @@ -1085,10 +1250,17 @@ void dma_txinit(struct dma_pub *pub) _dma_ddtable_init(di, DMA_TX, di->txdpa); } -void dma_txsuspend(struct dma_pub *pub) +static bool dma64_txenabled(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; + u32 xc; + + /* If the chip is dead, it is not enabled :-) */ + xc = R_REG(&di->d64txregs->control); + return (xc != 0xffffffff) && (xc & D64_XC_XE); +} +static void dma64_txsuspend(struct dma_info *di) +{ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); if (di->ntxd == 0) @@ -1097,10 +1269,8 @@ void dma_txsuspend(struct dma_pub *pub) OR_REG(&di->d64txregs->control, D64_XC_SE); } -void dma_txresume(struct dma_pub *pub) +static void dma64_txresume(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; - DMA_TRACE(("%s: dma_txresume\n", di->name)); if (di->ntxd == 0) @@ -1109,19 +1279,16 @@ void dma_txresume(struct dma_pub *pub) AND_REG(&di->d64txregs->control, ~D64_XC_SE); } -bool dma_txsuspended(struct dma_pub *pub) +static bool dma64_txsuspended(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; - return (di->ntxd == 0) || ((R_REG(&di->d64txregs->control) & D64_XC_SE) == D64_XC_SE); } -void dma_txreclaim(struct dma_pub *pub, enum txd_range range) +static void dma64_txreclaim(struct dma_info *di, enum txd_range range) { - struct dma_info *di = (struct dma_info *)pub; - struct sk_buff *p; + void *p; DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, (range == DMA_RANGE_ALL) ? "all" : @@ -1132,13 +1299,25 @@ void dma_txreclaim(struct dma_pub *pub, enum txd_range range) if (di->txin == di->txout) return; - while ((p = dma_getnexttxp(pub, range))) { + while ((p = dma64_getnexttxp(di, range))) { /* For unframed data, we don't have any packets to free */ if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED)) brcmu_pkt_buf_free_skb(p); } } +static bool dma64_txstopped(struct dma_info *di) +{ + return ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) == + D64_XS0_XS_STOPPED); +} + +static bool dma64_rxstopped(struct dma_info *di) +{ + return ((R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK) == + D64_RS0_RS_STOPPED); +} + static bool dma64_alloc(struct dma_info *di, uint direction) { u16 size; @@ -1158,38 +1337,39 @@ static bool dma64_alloc(struct dma_info *di, uint direction) va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, &alloced, &di->txdpaorig); if (va == NULL) { - DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd)" - " failed\n", di->name)); + DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name)); return false; } align = (1 << align_bits); di->txd64 = (struct dma64desc *) roundup((unsigned long)va, align); di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va); - di->txdpa = di->txdpaorig + di->txdalign; + PHYSADDRLOSET(di->txdpa, + PHYSADDRLO(di->txdpaorig) + di->txdalign); + PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig)); di->txdalloc = alloced; } else { va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, &alloced, &di->rxdpaorig); if (va == NULL) { - DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd)" - " failed\n", di->name)); + DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name)); return false; } align = (1 << align_bits); di->rxd64 = (struct dma64desc *) roundup((unsigned long)va, align); di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va); - di->rxdpa = di->rxdpaorig + di->rxdalign; + PHYSADDRLOSET(di->rxdpa, + PHYSADDRLO(di->rxdpaorig) + di->rxdalign); + PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig)); di->rxdalloc = alloced; } return true; } -bool dma_txreset(struct dma_pub *pub) +static bool dma64_txreset(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; u32 status; if (di->ntxd == 0) @@ -1224,9 +1404,8 @@ static bool dma64_rxidle(struct dma_info *di) (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK)); } -bool dma_rxreset(struct dma_pub *pub) +static bool dma64_rxreset(struct dma_info *di) { - struct dma_info *di = (struct dma_info *)pub; u32 status; if (di->nrxd == 0) @@ -1240,21 +1419,132 @@ bool dma_rxreset(struct dma_pub *pub) return status == D64_RS0_RS_DISABLED; } -/* - * !! tx entry routine +static bool dma64_rxenabled(struct dma_info *di) +{ + u32 rc; + + rc = R_REG(&di->d64rxregs->control); + return (rc != 0xffffffff) && (rc & D64_RC_RE); +} + +static bool dma64_txsuspendedidle(struct dma_info *di) +{ + + if (di->ntxd == 0) + return true; + + if (!(R_REG(&di->d64txregs->control) & D64_XC_SE)) + return 0; + + if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) == + D64_XS0_XS_IDLE) + return 1; + + return 0; +} + +/* Useful when sending unframed data. This allows us to get a progress report from the DMA. + * We return a pointer to the beginning of the DATA buffer of the current descriptor. + * If DMA is idle, we return NULL. + */ +static void *dma64_getpos(struct dma_info *di, bool direction) +{ + void *va; + bool idle; + u32 cd_offset; + + if (direction == DMA_TX) { + cd_offset = + R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK; + idle = !NTXDACTIVE(di->txin, di->txout); + va = di->txp[B2I(cd_offset, struct dma64desc)]; + } else { + cd_offset = + R_REG(&di->d64rxregs->status0) & D64_XS0_CD_MASK; + idle = !NRXDACTIVE(di->rxin, di->rxout); + va = di->rxp[B2I(cd_offset, struct dma64desc)]; + } + + /* If DMA is IDLE, return NULL */ + if (idle) { + DMA_TRACE(("%s: DMA idle, return NULL\n", __func__)); + va = NULL; + } + + return va; +} + +/* TX of unframed data + * + * Adds a DMA ring descriptor for the data pointed to by "buf". + * This is for DMA of a buffer of data and is unlike other dma TX functions + * that take a pointer to a "packet" + * Each call to this is results in a single descriptor being added for "len" bytes of + * data starting at "buf", it doesn't handle chained buffers. + */ +static int +dma64_txunframed(struct dma_info *di, void *buf, uint len, bool commit) +{ + u16 txout; + u32 flags = 0; + dmaaddr_t pa; /* phys addr */ + + txout = di->txout; + + /* return nonzero if out of tx descriptors */ + if (NEXTTXD(txout) == di->txin) + goto outoftxd; + + if (len == 0) + return 0; + + pa = pci_map_single(di->pbus, buf, len, PCI_DMA_TODEVICE); + + flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF); + + if (txout == (di->ntxd - 1)) + flags |= D64_CTRL1_EOT; + + dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); + + /* save the buffer pointer - used by dma_getpos */ + di->txp[txout] = buf; + + txout = NEXTTXD(txout); + /* bump the tx descriptor index */ + di->txout = txout; + + /* kick the chip */ + if (commit) { + W_REG(&di->d64txregs->ptr, + di->xmtptrbase + I2B(txout, struct dma64desc)); + } + + /* tx flow control */ + di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + + return 0; + + outoftxd: + DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __func__)); + di->dma.txavail = 0; + di->dma.txnobuf++; + return -1; +} + +/* !! tx entry routine * WARNING: call must check the return value for error. - * the error(toss frames) could be fatal and cause many subsequent hard - * to debug problems + * the error(toss frames) could be fatal and cause many subsequent hard to debug problems */ -int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit) +static int dma64_txfast(struct dma_info *di, struct sk_buff *p0, + bool commit) { - struct dma_info *di = (struct dma_info *)pub; struct sk_buff *p, *next; unsigned char *data; uint len; u16 txout; u32 flags = 0; - unsigned long pa; + dmaaddr_t pa; DMA_TRACE(("%s: dma_txfast\n", di->name)); @@ -1306,8 +1596,8 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit) /* With a DMA segment list, Descriptor table is filled * using the segment list instead of looping over - * buffers in multi-chain DMA. Therefore, EOF for SGLIST - * is when end of segment list is reached. + * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when + * end of segment list is reached. */ if ((!DMASGLIST_ENAB && next == NULL) || (DMASGLIST_ENAB && j == nsegs)) @@ -1331,8 +1621,8 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit) /* if last txd eof not set, fix it */ if (!(flags & D64_CTRL1_EOF)) - di->txd64[PREVTXD(txout)].ctrl1 = - cpu_to_le32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF); + W_SM(&di->txd64[PREVTXD(txout)].ctrl1, + BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF)); /* save the packet */ di->txp[PREVTXD(txout)] = p0; @@ -1368,12 +1658,11 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit) * If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and * return associated packet regardless of the value of hardware pointers. */ -struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) +static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range) { - struct dma_info *di = (struct dma_info *)pub; u16 start, end, i; u16 active_desc; - struct sk_buff *txp; + void *txp; DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, (range == DMA_RANGE_ALL) ? "all" : @@ -1390,7 +1679,7 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) if (range == DMA_RANGE_ALL) end = di->txout; else { - struct dma64regs *dregs = di->d64txregs; + dma64regs_t *dregs = di->d64txregs; end = (u16) (B2I(((R_REG(&dregs->status0) & D64_XS0_CD_MASK) - @@ -1413,11 +1702,16 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) goto bogus; for (i = start; i != end && !txp; i = NEXTTXD(i)) { - unsigned long pa; + dmaaddr_t pa; struct dma_seg_map *map = NULL; uint size, j, nsegs; - pa = cpu_to_le32(di->txd64[i].addrlow) - di->dataoffsetlow; + PHYSADDRLOSET(pa, + (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) - + di->dataoffsetlow)); + PHYSADDRHISET(pa, + (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) - + di->dataoffsethigh)); if (DMASGLIST_ENAB) { map = &di->txp_dmah[i]; @@ -1425,14 +1719,14 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) nsegs = map->nsegs; } else { size = - (cpu_to_le32(di->txd64[i].ctrl2) & + (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) & D64_CTRL2_BC_MASK); nsegs = 1; } for (j = nsegs; j > 0; j--) { - di->txd64[i].addrlow = 0xdeadbeef; - di->txd64[i].addrhigh = 0xdeadbeef; + W_SM(&di->txd64[i].addrlow, 0xdeadbeef); + W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); txp = di->txp[i]; di->txp[i] = NULL; @@ -1451,16 +1745,15 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) return txp; bogus: - DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d " - "force %d\n", start, end, di->txout, forceall)); + DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", start, end, di->txout, forceall)); return NULL; } -static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall) +static void *dma64_getnextrxp(struct dma_info *di, bool forceall) { uint i, curr; - struct sk_buff *rxp; - unsigned long pa; + void *rxp; + dmaaddr_t pa; i = di->rxin; @@ -1480,20 +1773,25 @@ static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall) rxp = di->rxp[i]; di->rxp[i] = NULL; - pa = cpu_to_le32(di->rxd64[i].addrlow) - di->dataoffsetlow; + PHYSADDRLOSET(pa, + (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) - + di->dataoffsetlow)); + PHYSADDRHISET(pa, + (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) - + di->dataoffsethigh)); /* clear this packet from the descriptor ring */ pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE); - di->rxd64[i].addrlow = 0xdeadbeef; - di->rxd64[i].addrhigh = 0xdeadbeef; + W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); + W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); di->rxin = NEXTRXD(i); return rxp; } -static bool _dma64_addrext(struct dma64regs *dma64regs) +static bool _dma64_addrext(dma64regs_t *dma64regs) { u32 w; OR_REG(&dma64regs->control, D64_XC_AE); @@ -1502,6 +1800,97 @@ static bool _dma64_addrext(struct dma64regs *dma64regs) return (w & D64_XC_AE) == D64_XC_AE; } +/* + * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). + */ +static void dma64_txrotate(struct dma_info *di) +{ + u16 ad; + uint nactive; + uint rot; + u16 old, new; + u32 w; + u16 first, last; + + nactive = _dma_txactive(di); + ad = (u16) (B2I((((R_REG(&di->d64txregs->status1) & + D64_XS1_AD_MASK) - di->xmtptrbase) & + D64_XS1_AD_MASK), struct dma64desc)); + rot = TXD(ad - di->txin); + + /* full-ring case is a lot harder - don't worry about this */ + if (rot >= (di->ntxd - nactive)) { + DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); + return; + } + + first = di->txin; + last = PREVTXD(di->txout); + + /* move entries starting at last and moving backwards to first */ + for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { + new = TXD(old + rot); + + /* + * Move the tx dma descriptor. + * EOT is set only in the last entry in the ring. + */ + w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT; + if (new == (di->ntxd - 1)) + w |= D64_CTRL1_EOT; + W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w)); + + w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2)); + W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w)); + + W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); + W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); + + /* zap the old tx dma descriptor address field */ + W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef)); + W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef)); + + /* move the corresponding txp[] entry */ + di->txp[new] = di->txp[old]; + + /* Move the map */ + if (DMASGLIST_ENAB) { + memcpy(&di->txp_dmah[new], &di->txp_dmah[old], + sizeof(struct dma_seg_map)); + memset(&di->txp_dmah[old], 0, + sizeof(struct dma_seg_map)); + } + + di->txp[old] = NULL; + } + + /* update txin and txout */ + di->txin = ad; + di->txout = TXD(di->txout + rot); + di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + + /* kick the chip */ + W_REG(&di->d64txregs->ptr, + di->xmtptrbase + I2B(di->txout, struct dma64desc)); +} + +uint dma_addrwidth(struct si_pub *sih, void *dmaregs) +{ + /* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */ + /* DMA engine is 64-bit capable */ + if ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) { + /* backplane are 64-bit capable */ + if (ai_backplane64(sih)) + /* If bus is System Backplane or PCIE then we can access 64-bits */ + if ((sih->bustype == SI_BUS) || + ((sih->bustype == PCI_BUS) && + (sih->buscoretype == PCIE_CORE_ID))) + return DMADDRWIDTH_64; + } + /* DMA hardware not supported by this driver*/ + return DMADDRWIDTH_64; +} + /* * Mac80211 initiated actions sometimes require packets in the DMA queue to be * modified. The modified portion of the packet is not under control of the DMA diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/dma.h b/trunk/drivers/staging/brcm80211/brcmsmac/dma.h index 2ce5963818d4..9c8b9a6a557e 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/dma.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/dma.h @@ -17,7 +17,6 @@ #ifndef _BRCM_DMA_H_ #define _BRCM_DMA_H_ -#include #include "types.h" /* forward structure declarations */ /* DMA structure: @@ -39,12 +38,12 @@ struct dma32diag { /* diag access */ /* dma registers per channel(xmt or rcv) */ struct dma64regs { - u32 control; /* enable, et al */ - u32 ptr; /* last descriptor posted to chip */ - u32 addrlow; /* desc ring base address low 32-bits (8K aligned) */ - u32 addrhigh; /* desc ring base address bits 63:32 (8K aligned) */ - u32 status0; /* current descriptor, xmt state */ - u32 status1; /* active descriptor, xmt error */ + u32 control; /* enable, et al */ + u32 ptr; /* last descriptor posted to chip */ + u32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ + u32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ + u32 status0; /* current descriptor, xmt state */ + u32 status1; /* active descriptor, xmt error */ }; /* map/unmap direction */ @@ -59,11 +58,110 @@ enum txd_range { DMA_RANGE_TRANSFERED }; +/* dma function type */ +typedef void (*di_detach_t) (struct dma_pub *dmah); +typedef bool(*di_txreset_t) (struct dma_pub *dmah); +typedef bool(*di_rxreset_t) (struct dma_pub *dmah); +typedef bool(*di_rxidle_t) (struct dma_pub *dmah); +typedef void (*di_txinit_t) (struct dma_pub *dmah); +typedef bool(*di_txenabled_t) (struct dma_pub *dmah); +typedef void (*di_rxinit_t) (struct dma_pub *dmah); +typedef void (*di_txsuspend_t) (struct dma_pub *dmah); +typedef void (*di_txresume_t) (struct dma_pub *dmah); +typedef bool(*di_txsuspended_t) (struct dma_pub *dmah); +typedef bool(*di_txsuspendedidle_t) (struct dma_pub *dmah); +typedef int (*di_txfast_t) (struct dma_pub *dmah, struct sk_buff *p, + bool commit); +typedef int (*di_txunframed_t) (struct dma_pub *dmah, void *p, uint len, + bool commit); +typedef void *(*di_getpos_t) (struct dma_pub *di, bool direction); +typedef void (*di_fifoloopbackenable_t) (struct dma_pub *dmah); +typedef bool(*di_txstopped_t) (struct dma_pub *dmah); +typedef bool(*di_rxstopped_t) (struct dma_pub *dmah); +typedef bool(*di_rxenable_t) (struct dma_pub *dmah); +typedef bool(*di_rxenabled_t) (struct dma_pub *dmah); +typedef void *(*di_rx_t) (struct dma_pub *dmah); +typedef bool(*di_rxfill_t) (struct dma_pub *dmah); +typedef void (*di_txreclaim_t) (struct dma_pub *dmah, enum txd_range range); +typedef void (*di_rxreclaim_t) (struct dma_pub *dmah); +typedef unsigned long (*di_getvar_t) (struct dma_pub *dmah, + const char *name); +typedef void *(*di_getnexttxp_t) (struct dma_pub *dmah, enum txd_range range); +typedef void *(*di_getnextrxp_t) (struct dma_pub *dmah, bool forceall); +typedef void *(*di_peeknexttxp_t) (struct dma_pub *dmah); +typedef void *(*di_peeknextrxp_t) (struct dma_pub *dmah); +typedef void (*di_rxparam_get_t) (struct dma_pub *dmah, u16 *rxoffset, + u16 *rxbufsize); +typedef void (*di_txblock_t) (struct dma_pub *dmah); +typedef void (*di_txunblock_t) (struct dma_pub *dmah); +typedef uint(*di_txactive_t) (struct dma_pub *dmah); +typedef void (*di_txrotate_t) (struct dma_pub *dmah); +typedef void (*di_counterreset_t) (struct dma_pub *dmah); +typedef uint(*di_ctrlflags_t) (struct dma_pub *dmah, uint mask, uint flags); +typedef char *(*di_dump_t) (struct dma_pub *dmah, struct brcmu_strbuf *b, + bool dumpring); +typedef char *(*di_dumptx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b, + bool dumpring); +typedef char *(*di_dumprx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b, + bool dumpring); +typedef uint(*di_rxactive_t) (struct dma_pub *dmah); +typedef uint(*di_txpending_t) (struct dma_pub *dmah); +typedef uint(*di_txcommitted_t) (struct dma_pub *dmah); + +/* dma opsvec */ +struct di_fcn_s { + di_detach_t detach; + di_txinit_t txinit; + di_txreset_t txreset; + di_txenabled_t txenabled; + di_txsuspend_t txsuspend; + di_txresume_t txresume; + di_txsuspended_t txsuspended; + di_txsuspendedidle_t txsuspendedidle; + di_txfast_t txfast; + di_txunframed_t txunframed; + di_getpos_t getpos; + di_txstopped_t txstopped; + di_txreclaim_t txreclaim; + di_getnexttxp_t getnexttxp; + di_peeknexttxp_t peeknexttxp; + di_txblock_t txblock; + di_txunblock_t txunblock; + di_txactive_t txactive; + di_txrotate_t txrotate; + + di_rxinit_t rxinit; + di_rxreset_t rxreset; + di_rxidle_t rxidle; + di_rxstopped_t rxstopped; + di_rxenable_t rxenable; + di_rxenabled_t rxenabled; + di_rx_t rx; + di_rxfill_t rxfill; + di_rxreclaim_t rxreclaim; + di_getnextrxp_t getnextrxp; + di_peeknextrxp_t peeknextrxp; + di_rxparam_get_t rxparam_get; + + di_fifoloopbackenable_t fifoloopbackenable; + di_getvar_t d_getvar; + di_counterreset_t counterreset; + di_ctrlflags_t ctrlflags; + di_dump_t dump; + di_dumptx_t dumptx; + di_dumprx_t dumprx; + di_rxactive_t rxactive; + di_txpending_t txpending; + di_txcommitted_t txcommitted; + uint endnum; +}; + /* * Exported data structure (read-only) */ /* export structure */ struct dma_pub { + const struct di_fcn_s *di_fn; /* DMA function pointers */ uint txavail; /* # free tx descriptors */ uint dmactrlflags; /* dma control flags */ @@ -79,42 +177,74 @@ extern struct dma_pub *dma_attach(char *name, struct si_pub *sih, uint nrxd, uint rxbufsize, int rxextheadroom, uint nrxpost, uint rxoffset, uint *msg_level); -void dma_rxinit(struct dma_pub *pub); -struct sk_buff *dma_rx(struct dma_pub *pub); -bool dma_rxfill(struct dma_pub *pub); -bool dma_rxreset(struct dma_pub *pub); -bool dma_txreset(struct dma_pub *pub); -void dma_txinit(struct dma_pub *pub); -int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit); -void dma_txsuspend(struct dma_pub *pub); -bool dma_txsuspended(struct dma_pub *pub); -void dma_txresume(struct dma_pub *pub); -void dma_txreclaim(struct dma_pub *pub, enum txd_range range); -void dma_rxreclaim(struct dma_pub *pub); -void dma_detach(struct dma_pub *pub); -unsigned long dma_getvar(struct dma_pub *pub, const char *name); -struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range); -void dma_counterreset(struct dma_pub *pub); - +extern const struct di_fcn_s dma64proc; + +#define dma_detach(di) (dma64proc.detach(di)) +#define dma_txreset(di) (dma64proc.txreset(di)) +#define dma_rxreset(di) (dma64proc.rxreset(di)) +#define dma_rxidle(di) (dma64proc.rxidle(di)) +#define dma_txinit(di) (dma64proc.txinit(di)) +#define dma_txenabled(di) (dma64proc.txenabled(di)) +#define dma_rxinit(di) (dma64proc.rxinit(di)) +#define dma_txsuspend(di) (dma64proc.txsuspend(di)) +#define dma_txresume(di) (dma64proc.txresume(di)) +#define dma_txsuspended(di) (dma64proc.txsuspended(di)) +#define dma_txsuspendedidle(di) (dma64proc.txsuspendedidle(di)) +#define dma_txfast(di, p, commit) (dma64proc.txfast(di, p, commit)) +#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit)) +#define dma_getpos(di, dir) (dma64proc.getpos(di, dir)) +#define dma_fifoloopbackenable(di) (dma64proc.fifoloopbackenable(di)) +#define dma_txstopped(di) (dma64proc.txstopped(di)) +#define dma_rxstopped(di) (dma64proc.rxstopped(di)) +#define dma_rxenable(di) (dma64proc.rxenable(di)) +#define dma_rxenabled(di) (dma64proc.rxenabled(di)) +#define dma_rx(di) (dma64proc.rx(di)) +#define dma_rxfill(di) (dma64proc.rxfill(di)) +#define dma_txreclaim(di, range) (dma64proc.txreclaim(di, range)) +#define dma_rxreclaim(di) (dma64proc.rxreclaim(di)) +#define dma_getvar(di, name) (dma64proc.d_getvar(di, name)) +#define dma_getnexttxp(di, range) (dma64proc.getnexttxp(di, range)) +#define dma_getnextrxp(di, forceall) (dma64proc.getnextrxp(di, forceall)) +#define dma_peeknexttxp(di) (dma64proc.peeknexttxp(di)) +#define dma_peeknextrxp(di) (dma64proc.peeknextrxp(di)) +#define dma_rxparam_get(di, off, bufs) (dma64proc.rxparam_get(di, off, bufs)) + +#define dma_txblock(di) (dma64proc.txblock(di)) +#define dma_txunblock(di) (dma64proc.txunblock(di)) +#define dma_txactive(di) (dma64proc.txactive(di)) +#define dma_rxactive(di) (dma64proc.rxactive(di)) +#define dma_txrotate(di) (dma64proc.txrotate(di)) +#define dma_counterreset(di) (dma64proc.counterreset(di)) +#define dma_ctrlflags(di, mask, flags) (dma64proc.ctrlflags((di), (mask), (flags))) +#define dma_txpending(di) (dma64proc.txpending(di)) +#define dma_txcommitted(di) (dma64proc.txcommitted(di)) + + +/* return addresswidth allowed + * This needs to be done after SB attach but before dma attach. + * SB attach provides ability to probe backplane and dma core capabilities + * This info is needed by DMA_ALLOC_CONSISTENT in dma attach + */ +extern uint dma_addrwidth(struct si_pub *sih, void *dmaregs); void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc) (void *pkt, void *arg_a), void *arg_a); /* - * DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but - * the packet length is not updated yet (by DMA) on the expected time. + * DMA(Bug) on some chips seems to declare that the packet is ready, but the + * packet length is not updated yet (by DMA) on the expected time. * Workaround is to hold processor till DMA updates the length, and stay off * the bus to allow DMA update the length in buffer */ static inline void dma_spin_for_len(uint len, struct sk_buff *head) { -#if defined(CONFIG_BCM47XX) +#if defined(__mips__) if (!len) { while (!(len = *(u16 *) KSEG1ADDR(head->data))) udelay(1); *(u16 *) (head->data) = cpu_to_le16((u16) len); } -#endif /* defined(CONFIG_BCM47XX) */ +#endif /* defined(__mips__) */ } #endif /* _BRCM_DMA_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.c index 237017186131..d6de44e430d3 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.c @@ -61,6 +61,8 @@ static void _brcms_timer(struct brcms_timer *t); static int ieee_hw_init(struct ieee80211_hw *hw); static int ieee_hw_rate_init(struct ieee80211_hw *hw); +static int wl_linux_watchdog(void *ctx); + /* Flags we support */ #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ FIF_ALLMULTI | \ @@ -83,8 +85,7 @@ static int __devinit brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static void brcms_remove(struct pci_dev *pdev); static void brcms_free(struct brcms_info *wl); -static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, - bool is_br); +static void brcms_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br); MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver."); @@ -93,10 +94,11 @@ MODULE_LICENSE("Dual BSD/GPL"); /* recognized PCI IDs */ static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, /* 43225 2G */ - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, /* 43224 DUAL */ - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, /* 4313 DUAL */ - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, /* 43224 Ven */ + {PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 43225 2G */ + {PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 43224 DUAL */ + {PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 4313 DUAL */ + /* 43224 Ven */ + {PCI_VENDOR_ID_BROADCOM, 0x0576, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, {0} }; @@ -214,10 +216,10 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) err = brcms_up(wl); UNLOCK(wl); - if (err != 0) + if (err != 0) { wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__, err); - + } return err; } @@ -304,9 +306,9 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) "\n", __func__, conf->power_level * 4, new_int); } - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { err = ieee_set_channel(hw, conf->channel, conf->channel_type); - + } if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { if (brcms_c_set (wl->wlc, BRCM_SET_SRL, @@ -375,7 +377,7 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_supported_band *bi; u32 br_mask, i; u16 rate; - struct brcm_rateset rs; + struct wl_rateset rs; int error; /* retrieve the current rates */ @@ -417,36 +419,32 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw, info->bssid); UNLOCK(wl); } - if (changed & BSS_CHANGED_BEACON) + if (changed & BSS_CHANGED_BEACON) { /* Beacon data changed, retrieve new beacon (beaconing modes) */ wiphy_err(wiphy, "%s: beacon changed\n", __func__); - + } if (changed & BSS_CHANGED_BEACON_ENABLED) { /* Beaconing should be enabled/disabled (beaconing modes) */ wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__, info->enable_beacon ? "true" : "false"); } - if (changed & BSS_CHANGED_CQM) { /* Connection quality monitor config changed */ wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d " " (implement)\n", __func__, info->cqm_rssi_thold, info->cqm_rssi_hyst); } - if (changed & BSS_CHANGED_IBSS) { /* IBSS join status changed */ wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__, info->ibss_joined ? "true" : "false"); } - if (changed & BSS_CHANGED_ARP_FILTER) { /* Hardware ARP filter address list or state changed */ wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d" " (implement)\n", __func__, info->arp_filter_enabled ? "true" : "false", info->arp_addr_cnt); } - if (changed & BSS_CHANGED_QOS) { /* * QoS for this association was enabled/disabled. @@ -604,10 +602,7 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT; - /* - * minstrel_ht initiates addBA on our behalf by calling - * ieee80211_start_tx_ba_session() - */ + /* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */ return 0; } @@ -645,10 +640,7 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, tid); return -EINVAL; } - /* - * Future improvement: - * Use the starting sequence number provided ... - */ + /* Future improvement: Use the starting sequence number provided ... */ *ssn = 0; ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; @@ -753,7 +745,7 @@ static int brcms_set_hint(struct brcms_info *wl, char *abbrev) */ static struct brcms_info *brcms_attach(u16 vendor, u16 device, unsigned long regs, - struct pci_dev *btparam, uint irq) + uint bustype, void *btparam, uint irq) { struct brcms_info *wl = NULL; int unit, err; @@ -764,8 +756,9 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device, unit = n_adapters_found; err = 0; - if (unit < 0) + if (unit < 0) { return NULL; + } /* allocate private info */ hw = pci_get_drvdata(btparam); /* btparam == pdev */ @@ -784,6 +777,14 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device, base_addr = regs; + if (bustype == PCI_BUS || bustype == RPC_BUS) { + /* Do nothing */ + } else { + bustype = PCI_BUS; + BCMMSG(wl->wiphy, "force to PCI\n"); + } + wl->bcm_bustype = bustype; + wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ); if (wl->regsva == NULL) { wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit); @@ -793,17 +794,17 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device, spin_lock_init(&wl->isr_lock); /* prepare ucode */ - if (brcms_request_fw(wl, btparam) < 0) { + if (brcms_request_fw(wl, (struct pci_dev *)btparam) < 0) { wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); brcms_release_fw(wl); - brcms_remove(btparam); + brcms_remove((struct pci_dev *)btparam); return NULL; } /* common load-time initialization */ - wl->wlc = brcms_c_attach(wl, vendor, device, unit, false, - wl->regsva, btparam, &err); + wl->wlc = brcms_c_attach((void *)wl, vendor, device, unit, false, + wl->regsva, wl->bcm_bustype, btparam, &err); brcms_release_fw(wl); if (!wl->wlc) { wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", @@ -814,9 +815,10 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device, wl->pub->ieee_hw = hw; - if (brcms_c_set_par(wl->wlc, IOV_MPC, 0) < 0) + if (brcms_c_set_par(wl->wlc, IOV_MPC, 0) < 0) { wiphy_err(wl->wiphy, "wl%d: Error setting MPC variable to 0\n", unit); + } /* register our interrupt handler */ if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { @@ -826,7 +828,7 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device, wl->irq = irq; /* register module */ - brcms_c_module_register(wl->pub, "linux", wl, NULL); + brcms_c_module_register(wl->pub, "linux", wl, wl_linux_watchdog, NULL); if (ieee_hw_init(hw)) { wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit, @@ -840,17 +842,19 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device, SET_IEEE80211_PERM_ADDR(hw, perm); err = ieee80211_register_hw(hw); - if (err) + if (err) { wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" "%d\n", __func__, err); + } if (wl->pub->srom_ccode[0]) err = brcms_set_hint(wl, wl->pub->srom_ccode); else err = brcms_set_hint(wl, "US"); - if (err) + if (err) { wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", __func__, err); + } n_adapters_found++; return wl; @@ -971,10 +975,6 @@ static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = { .hw_value = (rate100m / 5), \ } -/* - * The rate table is used for both 2.4G and 5G rates. The - * latter being a subset as it does not support CCK rates. - */ static struct ieee80211_rate legacy_ratetable[] = { RATE(10, 0), RATE(20, IEEE80211_RATE_SHORT_PREAMBLE), @@ -1016,13 +1016,11 @@ static struct ieee80211_supported_band brcms_band_5GHz_nphy = { .band = IEEE80211_BAND_5GHZ, .channels = brcms_5ghz_nphy_chantable, .n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable), - .bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET, - .n_bitrates = ARRAY_SIZE(legacy_ratetable) - - BRCMS_LEGACY_5G_RATE_OFFSET, + .bitrates = legacy_ratetable + 4, + .n_bitrates = ARRAY_SIZE(legacy_ratetable) - 4, .ht_cap = { - .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */ + /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */ + .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */ .ht_supported = true, .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, .ampdu_density = AMPDU_DEF_MPDU_DENSITY, @@ -1065,11 +1063,12 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw) /* Assume all bands use the same phy. True for 11n devices. */ if (NBANDS_PUB(wl->pub) > 1) { has_5g++; - if (phy_list[0] == 'n' || phy_list[0] == 'c') + if (phy_list[0] == 'n' || phy_list[0] == 'c') { hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &brcms_band_5GHz_nphy; - else + } else { return -EPERM; + } } return 0; } @@ -1088,8 +1087,7 @@ static int ieee_hw_init(struct ieee80211_hw *hw) hw->queues = N_TX_QUEUES; hw->max_rates = 2; /* Primary rate and 1 fallback rate */ - /* channel change time is dependent on chip and band */ - hw->channel_change_time = 7 * 1000; + hw->channel_change_time = 7 * 1000; /* channel change time is dependent on chip and band */ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); hw->rate_control_algorithm = "minstrel_ht"; @@ -1151,7 +1149,7 @@ brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) memset(hw->priv, 0, sizeof(*wl)); wl = brcms_attach(pdev->vendor, pdev->device, - pci_resource_start(pdev, 0), pdev, + pci_resource_start(pdev, 0), PCI_BUS, pdev, pdev->irq); if (!wl) { @@ -1338,8 +1336,9 @@ static void brcms_free(struct brcms_info *wl) /* kill dpc */ tasklet_kill(&wl->tasklet); - if (wl->pub) + if (wl->pub) { brcms_c_module_unregister(wl->pub, "linux", wl); + } /* free common resources */ if (wl->wlc) { @@ -1364,18 +1363,18 @@ static void brcms_free(struct brcms_info *wl) } /* - * unregister_netdev() calls get_stats() which may read chip - * registers so we cannot unmap the chip registers until - * after calling unregister_netdev() . + * unregister_netdev() calls get_stats() which may read chip registers + * so we cannot unmap the chip registers until after calling unregister_netdev() . */ - if (wl->regsva) + if (wl->regsva && wl->bcm_bustype != SDIO_BUS && + wl->bcm_bustype != JTAG_BUS) { iounmap((void *)wl->regsva); - + } wl->regsva = NULL; } /* flags the given rate in rateset as requested */ -static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br) +static void brcms_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br) { u32 i; @@ -1438,6 +1437,14 @@ void brcms_intrson(struct brcms_info *wl) INT_UNLOCK(wl, flags); } +/* + * precondition: perimeter lock has been acquired + */ +bool wl_alloc_dma_resources(struct brcms_info *wl, uint addrwidth) +{ + return true; +} + u32 brcms_intrsoff(struct brcms_info *wl) { unsigned long flags; @@ -1550,9 +1557,10 @@ static void brcms_dpc(unsigned long data) /* re-schedule dpc */ if (wl->resched) tasklet_schedule(&wl->tasklet); - else + else { /* re-enable interrupts */ brcms_intrson(wl); + } done: UNLOCK(wl); @@ -1627,8 +1635,7 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl, return t; } -/* - * adds only the kernel timer since it's going to be more accurate +/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate * as well as it's easier to make it periodic * * precondition: perimeter lock has been acquired @@ -1637,10 +1644,10 @@ void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *t, uint ms, int periodic) { #ifdef BCMDBG - if (t->set) + if (t->set) { wiphy_err(wl->wiphy, "%s: Already set. Name: %s, per %d\n", __func__, t->name, periodic); - + } #endif t->ms = ms; t->periodic = (bool) periodic; @@ -1660,9 +1667,9 @@ bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *t) { if (t->set) { t->set = false; - if (!del_timer(&t->timer)) + if (!del_timer(&t->timer)) { return false; - + } atomic_dec(&wl->callbacks); } @@ -1704,6 +1711,16 @@ void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *t) } +/* + * runs in software irq context + * + * precondition: perimeter lock is not acquired + */ +static int wl_linux_watchdog(void *ctx) +{ + return 0; +} + struct firmware_hdr { u32 offset; u32 len; @@ -1727,17 +1744,15 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx) hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data; for (entry = 0; entry < wl->fw.hdr_num_entries[i]; entry++, hdr++) { - u32 len = le32_to_cpu(hdr->len); - if (le32_to_cpu(hdr->idx) == idx) { - pdata = wl->fw.fw_bin[i]->data + - le32_to_cpu(hdr->offset); - *pbuf = kmalloc(len, GFP_ATOMIC); + if (hdr->idx == idx) { + pdata = wl->fw.fw_bin[i]->data + hdr->offset; + *pbuf = kmalloc(hdr->len, GFP_ATOMIC); if (*pbuf == NULL) { wiphy_err(wl->wiphy, "fail to alloc %d" - " bytes\n", len); + " bytes\n", hdr->len); goto fail; } - memcpy(*pbuf, pdata, len); + memcpy(*pbuf, pdata, hdr->len); return 0; } } @@ -1762,15 +1777,14 @@ int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx) hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data; for (entry = 0; entry < wl->fw.hdr_num_entries[i]; entry++, hdr++) { - if (le32_to_cpu(hdr->idx) == idx) { - pdata = wl->fw.fw_bin[i]->data + - le32_to_cpu(hdr->offset); - if (le32_to_cpu(hdr->len) != 4) { + if (hdr->idx == idx) { + pdata = wl->fw.fw_bin[i]->data + hdr->offset; + if (hdr->len != 4) { wiphy_err(wl->wiphy, "ERROR: fw hdr len\n"); return -ENOMSG; } - *data = le32_to_cpu(*((u32 *) pdata)); + *data = *((u32 *) pdata); return 0; } } @@ -1790,7 +1804,7 @@ static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev) char fw_name[100]; int i; - memset(&wl->fw, 0, sizeof(struct brcms_firmware)); + memset((void *)&wl->fw, 0, sizeof(struct brcms_firmware)); for (i = 0; i < MAX_FW_IMAGES; i++) { if (brcms_firmwares[i] == NULL) break; @@ -1876,8 +1890,7 @@ int brcms_check_firmwares(struct brcms_info *wl) ucode_hdr = (struct firmware_hdr *)fw_hdr->data; for (entry = 0; entry < wl->fw.hdr_num_entries[i] && !rc; entry++, ucode_hdr++) { - if (le32_to_cpu(ucode_hdr->offset) + - le32_to_cpu(ucode_hdr->len) > + if (ucode_hdr->offset + ucode_hdr->len > fw->size) { wiphy_err(wl->wiphy, "%s: conflicting bin/hdr\n", diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.h b/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.h index 7f290d7c0c41..40e3d375ea99 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.h @@ -20,15 +20,14 @@ #include #include -/* - * Starting index for 5G rates in the - * legacy rate table. - */ -#define BRCMS_LEGACY_5G_RATE_OFFSET 4 - /* softmac ioctl definitions */ #define BRCMS_SET_SHORTSLOT_OVERRIDE 146 + +/* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and + * sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be + * submitted to workqueue instead of being on kernel timer + */ struct brcms_timer { struct timer_list timer; struct brcms_info *wl; @@ -58,7 +57,7 @@ struct brcms_firmware { struct brcms_info { struct brcms_pub *pub; /* pointer to public wlc state */ - struct brcms_c_info *wlc; /* pointer to private common data */ + void *wlc; /* pointer to private common os-independent data */ u32 magic; int irq; @@ -66,7 +65,8 @@ struct brcms_info { spinlock_t lock; /* per-device perimeter lock */ spinlock_t isr_lock; /* per-device ISR synchronization lock */ - /* regsva for unmap in brcms_free() */ + /* bus type and regsva for unmap in brcms_free() */ + uint bcm_bustype; /* bus type */ void *regsva; /* opaque chip registers virtual address */ /* timer related fields */ @@ -92,6 +92,7 @@ extern int brcms_up(struct brcms_info *wl); extern void brcms_down(struct brcms_info *wl); extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, bool state, int prio); +extern bool wl_alloc_dma_resources(struct brcms_info *wl, uint dmaddrwidth); extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl); /* timer functions */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/main.c b/trunk/drivers/staging/brcm80211/brcmsmac/main.c index 339ab28477a1..1763c4535cd2 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/main.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/main.c @@ -15,24 +15,22 @@ */ #include -#include #include + #include #include -#include #include "rate.h" #include "scb.h" #include "phy/phy_hal.h" #include "channel.h" +#include "bmac.h" #include "antsel.h" #include "stf.h" #include "ampdu.h" #include "alloc.h" #include "mac80211_if.h" -#include "ucode_loader.h" #include "main.h" - /* * WPA(2) definitions */ @@ -53,10 +51,8 @@ */ #define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1) -/* watchdog timer, in unit of ms */ -#define TIMER_INTERVAL_WATCHDOG 1000 -/* radio monitor timer, in unit of ms */ -#define TIMER_INTERVAL_RADIOCHK 800 +#define TIMER_INTERVAL_WATCHDOG 1000 /* watchdog timer, in unit of ms */ +#define TIMER_INTERVAL_RADIOCHK 800 /* radio monitor timer, in unit of ms */ /* Max MPC timeout, in unit of watchdog */ #ifndef BRCMS_MPC_MAX_DELAYCNT @@ -67,16 +63,12 @@ #define BRCMS_MPC_MIN_DELAYCNT 1 #define BRCMS_MPC_THRESHOLD 3 /* MPC count threshold level */ -/* beacon interval, in unit of 1024TU */ -#define BEACON_INTERVAL_DEFAULT 100 -/* DTIM interval, in unit of beacon interval */ -#define DTIM_INTERVAL_DEFAULT 3 +#define BEACON_INTERVAL_DEFAULT 100 /* beacon interval, in unit of 1024TU */ +#define DTIM_INTERVAL_DEFAULT 3 /* DTIM interval, in unit of beacon interval */ /* Scale down delays to accommodate QT slow speed */ -/* beacon interval, in unit of 1024TU */ -#define BEACON_INTERVAL_DEF_QT 20 -/* DTIM interval, in unit of beacon interval */ -#define DTIM_INTERVAL_DEF_QT 1 +#define BEACON_INTERVAL_DEF_QT 20 /* beacon interval, in unit of 1024TU */ +#define DTIM_INTERVAL_DEF_QT 1 /* DTIM interval, in unit of beacon interval */ #define TBTT_ALIGN_LEEWAY_US 100 /* min leeway before first TBTT in us */ @@ -169,31 +161,34 @@ #define AC_VO 3 /* - * driver maintains internal 'tick'(wlc->pub->now) which increments in 1s - * OS timer(soft watchdog) it is not a wall clock and won't increment when - * driver is in "down" state this low resolution driver tick can be used - * for maintenance tasks such as phy calibration and scb update + * driver maintains internal 'tick'(wlc->pub->now) which increments in 1s OS timer(soft + * watchdog) it is not a wall clock and won't increment when driver is in "down" state + * this low resolution driver tick can be used for maintenance tasks such as phy + * calibration and scb update */ -/* - * To inform the ucode of the last mcast frame posted - * so that it can clear moredata bit - */ +/* To inform the ucode of the last mcast frame posted so that it can clear moredata bit */ #define BCMCFID(wlc, fid) brcms_b_write_shm((wlc)->hw, M_BCMC_FID, (fid)) -#define BRCMS_WAR16165(wlc) ((!AP_ENAB(wlc->pub)) && (wlc->war16165)) +#define BRCMS_WAR16165(wlc) (wlc->pub->sih->bustype == PCI_BUS && \ + (!AP_ENAB(wlc->pub)) && (wlc->war16165)) + +/* debug/trace */ +uint brcm_msg_level = +#if defined(BCMDBG) + LOG_ERROR_VAL; +#else + 0; +#endif /* BCMDBG */ /* Find basic rate for a given rate */ -#define BRCMS_BASIC_RATE(wlc, rspec) \ - (IS_MCS(rspec) \ - ? (wlc)->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK].leg_ofdm] \ - : (wlc)->band->basic_rate[rspec & RSPEC_RATE_MASK]) +#define BRCMS_BASIC_RATE(wlc, rspec) (IS_MCS(rspec) ? \ + (wlc)->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK].leg_ofdm] : \ + (wlc)->band->basic_rate[rspec & RSPEC_RATE_MASK]) -#define FRAMETYPE(r, mimoframe) \ - (IS_MCS(r) ? mimoframe : (IS_CCK(r) ? FT_CCK : FT_OFDM)) +#define FRAMETYPE(r, mimoframe) (IS_MCS(r) ? mimoframe : (IS_CCK(r) ? FT_CCK : FT_OFDM)) -/* rfdisable delay timer 500 ms, runs of ALP clock */ -#define RFDISABLE_DEFAULT 10000000 +#define RFDISABLE_DEFAULT 10000000 /* rfdisable delay timer 500 ms, runs of ALP clock */ #define BRCMS_TEMPSENSE_PERIOD 10 /* 10 second timeout */ @@ -201,11 +196,26 @@ #define EPI_VERSION_NUM 0x054b0b00 +#ifdef BCMDBG +/* pointer to most recently allocated wl/wlc */ +static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL); +#endif + +const u8 prio2fifo[NUMPRIO] = { + TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */ + TX_AC_BK_FIFO, /* 1 BK AC_BK Background */ + TX_AC_BK_FIFO, /* 2 -- AC_BK Background */ + TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */ + TX_AC_VI_FIFO, /* 4 CL AC_VI Video */ + TX_AC_VI_FIFO, /* 5 VI AC_VI Video */ + TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */ + TX_AC_VO_FIFO /* 7 NC AC_VO Voice */ +}; + /* precedences numbers for wlc queues. These are twice as may levels as * 802.1D priorities. * Odd numbers are used for HI priority traffic at same precedence levels - * These constants are used ONLY by wlc_prio2prec_map. Do not use them - * elsewhere. + * These constants are used ONLY by wlc_prio2prec_map. Do not use them elsewhere. */ #define _BRCMS_PREC_NONE 0 /* None = - */ #define _BRCMS_PREC_BK 2 /* BK - Background */ @@ -228,158 +238,58 @@ #define MBSS_PRB_ENAB(cfg) 0 #define SOFTBCN_ENAB(pub) (0) -#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */ -#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us */ -#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us */ -#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */ - -#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */ - -#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */ - -#define DMAREG(wlc_hw, direction, fifonum) \ - ((direction == DMA_TX) ? \ - &(wlc_hw->regs->fifo64regs[fifonum].dmaxmt) : \ - &(wlc_hw->regs->fifo64regs[fifonum].dmarcv)) - -#define APHY_SLOT_TIME 9 -#define BPHY_SLOT_TIME 20 - -/* - * The following table lists the buffer memory allocated to xmt fifos in HW. - * the size is in units of 256bytes(one block), total size is HW dependent - * ucode has default fifo partition, sw can overwrite if necessary - * - * This is documented in twiki under the topic UcodeTxFifo. Please ensure - * the twiki is updated before making changes. - */ - -/* Starting corerev for the fifo size table */ -#define XMTFIFOTBL_STARTREV 20 +/* 802.1D Priority to precedence queue mapping */ +const u8 wlc_prio2prec_map[] = { + _BRCMS_PREC_BE, /* 0 BE - Best-effort */ + _BRCMS_PREC_BK, /* 1 BK - Background */ + _BRCMS_PREC_NONE, /* 2 None = - */ + _BRCMS_PREC_EE, /* 3 EE - Excellent-effort */ + _BRCMS_PREC_CL, /* 4 CL - Controlled Load */ + _BRCMS_PREC_VI, /* 5 Vi - Video */ + _BRCMS_PREC_VO, /* 6 Vo - Voice */ + _BRCMS_PREC_NC, /* 7 NC - Network Control */ +}; /* Check if a particular BSS config is AP or STA */ #define BSSCFG_AP(cfg) (0) #define BSSCFG_STA(cfg) (1) #define BSSCFG_IBSS(cfg) (!(cfg)->BSS) -/* iterate through all valid bsscfg entries */ +/* As above for all non-NULL BSS configs */ #define FOREACH_BSS(wlc, idx, cfg) \ - for (idx = 0; (int) idx < BRCMS_MAXBSSCFG; idx++) { \ - cfg = (wlc)->bsscfg[idx]; \ - if (!cfg) \ - continue; -/* close marker for iterator code block */ -#define END_FOREACH_BSS() } + for (idx = 0; (int) idx < BRCMS_MAXBSSCFG; idx++) \ + if ((cfg = (wlc)->bsscfg[idx])) + +/* TX FIFO number to WME/802.1E Access Category */ +const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE }; + +/* WME/802.1E Access Category to TX FIFO number */ +static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 }; + +static bool in_send_q; /* Shared memory location index for various AC params */ #define wme_shmemacindex(ac) wme_ac2fifo[ac] +#ifdef BCMDBG +static const char * const fifo_names[] = { + "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" }; +#else +static const char fifo_names[6][0]; +#endif + +static const u8 acbitmap2maxprio[] = { + PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK, + PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, + PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, + PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO +}; + /* currently the best mechanism for determining SIFS is the band in use */ #define SIFS(band) ((band)->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME : \ BPHY_SIFS_TIME); -/* dup state between BMAC(struct brcms_hardware) and HIGH(struct brcms_c_info) - driver */ -struct brcms_b_state { - u32 machwcap; /* mac hw capibility */ - u32 preamble_ovr; /* preamble override */ -}; - /* local prototypes */ -static void brcms_b_clkctl_clk(struct brcms_hardware *wlc, uint mode); - -/* used by wlc_wakeucode_init() */ -static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, - const struct d11init *inits); -static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[], - const uint nbytes); -static void brcms_ucode_download(struct brcms_hardware *wlc); -static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw); - -/* used by brcms_c_down() */ -static void brcms_c_flushqueues(struct brcms_c_info *wlc); - -static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs); -static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw); -static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw); -static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw, - uint tx_fifo); -static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw, - uint tx_fifo); - -/* Low Level Prototypes */ - -struct brcms_b_state; - -static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, - uint unit, bool piomode, void *regsva, - struct pci_dev *btparam); - -/* up/down, reset, clk */ -static void brcms_b_reset(struct brcms_hardware *wlc_hw); -static int brcms_b_state_get(struct brcms_hardware *wlc_hw, - struct brcms_b_state *state); -static void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf, - uint *len); - -static void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw, - u8 *ea); - -static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw); -static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw); - -static void brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, - int match_reg_offset, - const u8 *addr); -static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin); -static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax); - -static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL, - u16 LRL); - -static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw); - -static void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, - u32 req_bit); -static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, - u32 antsel_avail); -static int brcms_b_bandtype(struct brcms_hardware *wlc_hw); -static void brcms_b_info_init(struct brcms_hardware *wlc_hw); -static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want); -static u16 brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, - u32 sel); -static void brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, - u16 v, u32 sel); -static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk); -static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme); -static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw); -static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw); -static bool brcms_c_validboardtype(struct brcms_hardware *wlc); -static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw); -static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw); -static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw); -static void brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init); -static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw); -static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool want, u32 flags); -static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw); -static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw); -static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc); -static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask); -static void brcms_c_gpio_init(struct brcms_c_info *wlc); -static void brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw, - u16 bcn[], int len); -static void brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw, - u16 bcn[], int len); -static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec); -static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit); -static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit, - u16 chanspec); -static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, - bool shortslot); -static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw); -static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw, - u8 rate); - static u16 brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, struct sk_buff *p, @@ -387,18 +297,17 @@ static u16 brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, uint nfrags, uint queue, uint next_frag_len, struct wsec_key *key, - u32 rspec_override); + ratespec_t rspec_override); static void brcms_c_bss_default_init(struct brcms_c_info *wlc); static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc); -static u32 mac80211_wlc_set_nrate(struct brcms_c_info *wlc, +static ratespec_t mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, u32 int_val); static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc); static void brcms_c_watchdog(void *arg); static void brcms_c_watchdog_by_timer(void *arg); static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate); -static int brcms_c_set_rateset(struct brcms_c_info *wlc, - struct brcms_c_rateset *rs_arg); +static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg); static u8 brcms_c_local_constraint_qdbm(struct brcms_c_info *wlc); /* send and receive */ @@ -409,27 +318,27 @@ static void brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc, struct brcms_txq_info *qi, bool on, int prio); static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc); -static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rate, +static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, ratespec_t rate, uint length, u8 *plcp); -static void brcms_c_compute_ofdm_plcp(u32 rate, uint length, u8 *plcp); -static void brcms_c_compute_mimo_plcp(u32 rate, uint length, u8 *plcp); -static u16 brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate, +static void brcms_c_compute_ofdm_plcp(ratespec_t rate, uint length, u8 *plcp); +static void brcms_c_compute_mimo_plcp(ratespec_t rate, uint length, u8 *plcp); +static u16 brcms_c_compute_frame_dur(struct brcms_c_info *wlc, ratespec_t rate, u8 preamble_type, uint next_frag_len); static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc, struct brcms_d11rxhdr *rxh); static void brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh, struct sk_buff *p); -static uint brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 rate, +static uint brcms_c_calc_frame_len(struct brcms_c_info *wlc, ratespec_t rate, u8 preamble_type, uint dur); -static uint brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rate, +static uint brcms_c_calc_ack_time(struct brcms_c_info *wlc, ratespec_t rate, u8 preamble_type); -static uint brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rate, +static uint brcms_c_calc_cts_time(struct brcms_c_info *wlc, ratespec_t rate, u8 preamble_type); /* interrupt, up/down, band */ static void brcms_c_setband(struct brcms_c_info *wlc, uint bandunit); -static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc); +static chanspec_t brcms_c_init_chanspec(struct brcms_c_info *wlc); static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc, - u16 chanspec); + chanspec_t chanspec); static void brcms_c_bsinit(struct brcms_c_info *wlc); static int brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM, bool writeToShm); @@ -440,7 +349,7 @@ static void brcms_c_radio_enable(struct brcms_c_info *wlc); static void brcms_c_radio_upd(struct brcms_c_info *wlc); /* scan, association, BSS */ -static uint brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rate, +static uint brcms_c_calc_ba_time(struct brcms_c_info *wlc, ratespec_t rate, u8 preamble_type); static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap); static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val); @@ -457,2872 +366,89 @@ static uint brcms_c_down_del_timer(struct brcms_c_info *wlc); static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc); static int _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, struct brcms_c_if *wlcif); -static void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, u16 bcn[], - int len, bool both); - -const u8 prio2fifo[NUMPRIO] = { - TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */ - TX_AC_BK_FIFO, /* 1 BK AC_BK Background */ - TX_AC_BK_FIFO, /* 2 -- AC_BK Background */ - TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */ - TX_AC_VI_FIFO, /* 4 CL AC_VI Video */ - TX_AC_VI_FIFO, /* 5 VI AC_VI Video */ - TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */ - TX_AC_VO_FIFO /* 7 NC AC_VO Voice */ -}; - -/* debug/trace */ -uint brcm_msg_level = -#if defined(BCMDBG) - LOG_ERROR_VAL; -#else - 0; -#endif /* BCMDBG */ - -/* TX FIFO number to WME/802.1E Access Category */ -const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE }; - -/* WME/802.1E Access Category to TX FIFO number */ -static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 }; - -static bool in_send_q; - -/* 802.1D Priority to precedence queue mapping */ -const u8 wlc_prio2prec_map[] = { - _BRCMS_PREC_BE, /* 0 BE - Best-effort */ - _BRCMS_PREC_BK, /* 1 BK - Background */ - _BRCMS_PREC_NONE, /* 2 None = - */ - _BRCMS_PREC_EE, /* 3 EE - Excellent-effort */ - _BRCMS_PREC_CL, /* 4 CL - Controlled Load */ - _BRCMS_PREC_VI, /* 5 Vi - Video */ - _BRCMS_PREC_VO, /* 6 Vo - Voice */ - _BRCMS_PREC_NC, /* 7 NC - Network Control */ -}; - -static u16 xmtfifo_sz[][NFIFO] = { - /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */ - {20, 192, 192, 21, 17, 5}, - /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */ - {9, 58, 22, 14, 14, 5}, - /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */ - {20, 192, 192, 21, 17, 5}, - /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */ - {20, 192, 192, 21, 17, 5}, - /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */ - {9, 58, 22, 14, 14, 5}, -}; - -static const u8 acbitmap2maxprio[] = { - PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK, - PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, - PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, - PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO -}; - -#ifdef BCMDBG -static const char * const fifo_names[] = { - "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" }; -#else -static const char fifo_names[6][0]; -#endif - -#ifdef BCMDBG -/* pointer to most recently allocated wl/wlc */ -static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL); -#endif -/* - * Update the slot timing for standard 11b/g (20us slots) - * or shortslot 11g (9us slots) - * The PSM needs to be suspended for this call. +/* conditions under which the PM bit should be set in outgoing frames and STAY_AWAKE is meaningful */ -static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, - bool shortslot) +bool brcms_c_ps_allowed(struct brcms_c_info *wlc) { - struct d11regs *regs; - - regs = wlc_hw->regs; + int idx; + struct brcms_bss_cfg *cfg; - if (shortslot) { - /* 11g short slot: 11a timing */ - W_REG(®s->ifs_slot, 0x0207); /* APHY_SLOT_TIME */ - brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME); - } else { - /* 11g long slot: 11b timing */ - W_REG(®s->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */ - brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME); - } -} + /* disallow PS when one of the following global conditions meets */ + if (!wlc->pub->associated) + return false; -static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw) -{ - struct wiphy *wiphy = wlc_hw->wlc->wiphy; + /* disallow PS when one of these meets when not scanning */ + if (AP_ACTIVE(wlc) || wlc->monitor) + return false; - /* init microcode host flags */ - brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs); + for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) { + cfg = wlc->bsscfg[idx]; + if (cfg && BSSCFG_STA(cfg) && cfg->associated) { + /* + * disallow PS when one of the following + * bsscfg specific conditions meets + */ + if (!cfg->BSS || !BRCMS_PORTOPEN(cfg)) + return false; - /* do band-specific ucode IHR, SHM, and SCR inits */ - if (D11REV_IS(wlc_hw->corerev, 23)) { - if (BRCMS_ISNPHY(wlc_hw->band)) - brcms_c_write_inits(wlc_hw, d11n0bsinitvals16); - else - wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" - " %d\n", __func__, wlc_hw->unit, - wlc_hw->corerev); - } else { - if (D11REV_IS(wlc_hw->corerev, 24)) { - if (BRCMS_ISLCNPHY(wlc_hw->band)) - brcms_c_write_inits(wlc_hw, - d11lcn0bsinitvals24); - else - wiphy_err(wiphy, "%s: wl%d: unsupported phy in" - " core rev %d\n", __func__, - wlc_hw->unit, wlc_hw->corerev); - } else { - wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", - __func__, wlc_hw->unit, wlc_hw->corerev); + if (!cfg->dtim_programmed) + return false; } } -} - -/* switch to new band but leave it inactive */ -static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - u32 macintmask; - - BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); - WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); - - /* disable interrupts */ - macintmask = brcms_intrsoff(wlc->wl); - - /* radio off */ - wlc_phy_switch_radio(wlc_hw->band->pi, OFF); - - brcms_b_core_phy_clk(wlc_hw, OFF); - - brcms_c_setxband(wlc_hw, bandunit); - - return macintmask; + return true; } -/* Process received frames */ -/* - * Return true if more frames need to be processed. false otherwise. - * Param 'bound' indicates max. # frames to process before break out. - */ -static bool -brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) +void brcms_c_reset(struct brcms_c_info *wlc) { - struct sk_buff *p; - struct sk_buff *head = NULL; - struct sk_buff *tail = NULL; - uint n = 0; - uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1; - struct brcms_d11rxhdr *wlc_rxhdr = NULL; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - /* gather received frames */ - while ((p = dma_rx(wlc_hw->di[fifo]))) { - - if (!tail) - head = tail = p; - else { - tail->prev = p; - tail = p; - } - - /* !give others some time to run! */ - if (++n >= bound_limit) - break; - } - - /* post more rbufs */ - dma_rxfill(wlc_hw->di[fifo]); - - /* process each frame */ - while ((p = head) != NULL) { - head = head->prev; - p->prev = NULL; - - wlc_rxhdr = (struct brcms_d11rxhdr *) p->data; + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); - /* - * compute the RSSI from d11rxhdr and record it in wlc_rxd11hr - */ - wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr); + /* slurp up hw mac counters before core reset */ + brcms_c_statsupd(wlc); - brcms_c_recv(wlc_hw->wlc, p); - } + /* reset our snapshot of macstat counters */ + memset((char *)wlc->core->macstat_snapshot, 0, + sizeof(struct macstat)); - return n >= bound_limit; + brcms_b_reset(wlc->hw); } -static bool -brcms_b_dotxstatus(struct brcms_hardware *wlc_hw, struct tx_status *txs, - u32 s2) +void brcms_c_fatal_error(struct brcms_c_info *wlc) { - /* discard intermediate indications for ucode with one legitimate case: - * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, - * but the subsequent tx of DATA failed. so it will start rts/cts from - * the beginning (resetting the rts transmission count) - */ - if (!(txs->status & TX_STATUS_AMPDU) - && (txs->status & TX_STATUS_INTERMEDIATE)) - return false; - - return brcms_c_dotxstatus(wlc_hw->wlc, txs, s2); -} - -/* process tx completion events in BMAC - * Return true if more tx status need to be processed. false otherwise. - */ -static bool -brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) -{ - bool morepending = false; - struct brcms_c_info *wlc = wlc_hw->wlc; - struct d11regs *regs; - struct tx_status txstatus, *txs; - u32 s1, s2; - uint n = 0; - /* - * Param 'max_tx_num' indicates max. # tx status to process before - * break out. - */ - uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1; - - BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); - - txs = &txstatus; - regs = wlc_hw->regs; - while (!(*fatal) - && (s1 = R_REG(®s->frmtxstatus)) & TXS_V) { - - if (s1 == 0xffffffff) { - wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", - wlc_hw->unit, __func__); - return morepending; - } - - s2 = R_REG(®s->frmtxstatus2); - - txs->status = s1 & TXS_STATUS_MASK; - txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT; - txs->sequence = s2 & TXS_SEQ_MASK; - txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT; - txs->lasttxtime = 0; - - *fatal = brcms_b_dotxstatus(wlc_hw, txs, s2); - - /* !give others some time to run! */ - if (++n >= max_tx_num) - break; - } - - if (*fatal) - return 0; - - if (n >= max_tx_num) - morepending = true; - - if (!pktq_empty(&wlc->pkt_queue->q)) - brcms_c_send_q(wlc); - - return morepending; + wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n", + wlc->pub->unit); + brcms_init(wlc->wl); } -/* second-level interrupt processing - * Return true if another dpc needs to be re-scheduled. false otherwise. - * Param 'bounded' indicates if applicable loops should be bounded. +/* Return the channel the driver should initialize during brcms_c_init. + * the channel may have to be changed from the currently configured channel + * if other configurations are in conflict (bandlocked, 11n mode disabled, + * invalid channel for current country, etc.) */ -bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) +static chanspec_t brcms_c_init_chanspec(struct brcms_c_info *wlc) { - u32 macintstatus; - struct brcms_hardware *wlc_hw = wlc->hw; - struct d11regs *regs = wlc_hw->regs; - bool fatal = false; - struct wiphy *wiphy = wlc->wiphy; - - if (DEVICEREMOVED(wlc)) { - wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, - __func__); - brcms_down(wlc->wl); - return false; - } - - /* grab and clear the saved software intstatus bits */ - macintstatus = wlc->macintstatus; - wlc->macintstatus = 0; - - BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n", - wlc_hw->unit, macintstatus); - - WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */ - - /* BCN template is available */ - /* ZZZ: Use AP_ACTIVE ? */ - if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub)) - && (macintstatus & MI_BCNTPL)) - brcms_c_update_beacon(wlc); - - /* tx status */ - if (macintstatus & MI_TFS) { - if (brcms_b_txstatus(wlc->hw, bounded, &fatal)) - wlc->macintstatus |= MI_TFS; - if (fatal) { - wiphy_err(wiphy, "MI_TFS: fatal\n"); - goto fatal; - } - } - - if (macintstatus & (MI_TBTT | MI_DTIM_TBTT)) - brcms_c_tbtt(wlc); - - /* ATIM window end */ - if (macintstatus & MI_ATIMWINEND) { - BCMMSG(wlc->wiphy, "end of ATIM window\n"); - OR_REG(®s->maccommand, wlc->qvalid); - wlc->qvalid = 0; - } + chanspec_t chanspec = + 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | + WL_CHANSPEC_BAND_2G; - /* - * received data or control frame, MI_DMAINT is - * indication of RX_FIFO interrupt - */ - if (macintstatus & MI_DMAINT) - if (brcms_b_recv(wlc_hw, RX_FIFO, bounded)) - wlc->macintstatus |= MI_DMAINT; + return chanspec; +} - /* TX FIFO suspend/flush completion */ - if (macintstatus & MI_TXSTOP) - brcms_b_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO); - - /* noise sample collected */ - if (macintstatus & MI_BG_NOISE) - wlc_phy_noise_sample_intr(wlc_hw->band->pi); - - if (macintstatus & MI_GP0) { - wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d " - "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now); - - printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n", - __func__, wlc_hw->sih->chip, - wlc_hw->sih->chiprev); - /* big hammer */ - brcms_init(wlc->wl); - } - - /* gptimer timeout */ - if (macintstatus & MI_TO) - W_REG(®s->gptimer, 0); - - if (macintstatus & MI_RFDISABLE) { - BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the" - " RF Disable Input\n", wlc_hw->unit); - brcms_rfkill_set_hw_state(wlc->wl); - } - - /* send any enq'd tx packets. Just makes sure to jump start tx */ - if (!pktq_empty(&wlc->pkt_queue->q)) - brcms_c_send_q(wlc); - - /* it isn't done and needs to be resched if macintstatus is non-zero */ - return wlc->macintstatus != 0; - - fatal: - brcms_init(wlc->wl); - return wlc->macintstatus != 0; -} - -int brcms_b_state_get(struct brcms_hardware *wlc_hw, - struct brcms_b_state *state) -{ - state->machwcap = wlc_hw->machwcap; - - return 0; -} - -static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) -{ - uint i; - char name[8]; - /* - * ucode host flag 2 needed for pio mode, independent of band and fifo - */ - u16 pio_mhf2 = 0; - struct brcms_hardware *wlc_hw = wlc->hw; - uint unit = wlc_hw->unit; - struct brcms_tunables *tune = wlc->pub->tunables; - struct wiphy *wiphy = wlc->wiphy; - - /* name and offsets for dma_attach */ - snprintf(name, sizeof(name), "wl%d", unit); - - if (wlc_hw->di[0] == 0) { /* Init FIFOs */ - int dma_attach_err = 0; - - /* - * FIFO 0 - * TX: TX_AC_BK_FIFO (TX AC Background data packets) - * RX: RX_FIFO (RX data packets) - */ - wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, - (wme ? DMAREG(wlc_hw, DMA_TX, 0) : - NULL), DMAREG(wlc_hw, DMA_RX, 0), - (wme ? tune->ntxd : 0), tune->nrxd, - tune->rxbufsz, -1, tune->nrxbufpost, - BRCMS_HWRXOFF, &brcm_msg_level); - dma_attach_err |= (NULL == wlc_hw->di[0]); - - /* - * FIFO 1 - * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets) - * (legacy) TX_DATA_FIFO (TX data packets) - * RX: UNUSED - */ - wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, - DMAREG(wlc_hw, DMA_TX, 1), NULL, - tune->ntxd, 0, 0, -1, 0, 0, - &brcm_msg_level); - dma_attach_err |= (NULL == wlc_hw->di[1]); - - /* - * FIFO 2 - * TX: TX_AC_VI_FIFO (TX AC Video data packets) - * RX: UNUSED - */ - wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, - DMAREG(wlc_hw, DMA_TX, 2), NULL, - tune->ntxd, 0, 0, -1, 0, 0, - &brcm_msg_level); - dma_attach_err |= (NULL == wlc_hw->di[2]); - /* - * FIFO 3 - * TX: TX_AC_VO_FIFO (TX AC Voice data packets) - * (legacy) TX_CTL_FIFO (TX control & mgmt packets) - */ - wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, - DMAREG(wlc_hw, DMA_TX, 3), - NULL, tune->ntxd, 0, 0, -1, - 0, 0, &brcm_msg_level); - dma_attach_err |= (NULL == wlc_hw->di[3]); -/* Cleaner to leave this as if with AP defined */ - - if (dma_attach_err) { - wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed" - "\n", unit); - return false; - } - - /* get pointer to dma engine tx flow control variable */ - for (i = 0; i < NFIFO; i++) - if (wlc_hw->di[i]) - wlc_hw->txavail[i] = - (uint *) dma_getvar(wlc_hw->di[i], - "&txavail"); - } - - /* initial ucode host flags */ - brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2); - - return true; -} - -static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw) -{ - uint j; - - for (j = 0; j < NFIFO; j++) { - if (wlc_hw->di[j]) { - dma_detach(wlc_hw->di[j]); - wlc_hw->di[j] = NULL; - } - } -} - -/* - * Initialize brcms_c_info default values ... - * may get overrides later in this function - * BMAC_NOTES, move low out and resolve the dangling ones - */ -static void brcms_b_info_init(struct brcms_hardware *wlc_hw) -{ - struct brcms_c_info *wlc = wlc_hw->wlc; - - /* set default sw macintmask value */ - wlc->defmacintmask = DEF_MACINTMASK; - - /* various 802.11g modes */ - wlc_hw->shortslot = false; - - wlc_hw->SFBL = RETRY_SHORT_FB; - wlc_hw->LFBL = RETRY_LONG_FB; - - /* default mac retry limits */ - wlc_hw->SRL = RETRY_SHORT_DEF; - wlc_hw->LRL = RETRY_LONG_DEF; - wlc_hw->chanspec = CH20MHZ_CHSPEC(1); -} - -void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw) -{ - /* delay before first read of ucode state */ - udelay(40); - - /* wait until ucode is no longer asleep */ - SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) == - DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly); -} - -void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw, u8 *ea) -{ - memcpy(ea, wlc_hw->etheraddr, ETH_ALEN); -} - -static int brcms_b_bandtype(struct brcms_hardware *wlc_hw) -{ - return wlc_hw->band->bandtype; -} - -/* control chip clock to save power, enable dynamic clock or force fast clock */ -static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) -{ - if (PMUCTL_ENAB(wlc_hw->sih)) { - /* new chips with PMU, CCS_FORCEHT will distribute the HT clock - * on backplane, but mac core will still run on ALP(not HT) when - * it enters powersave mode, which means the FCA bit may not be - * set. Should wakeup mac if driver wants it to run on HT. - */ - - if (wlc_hw->clk) { - if (mode == CLK_FAST) { - OR_REG(&wlc_hw->regs->clk_ctl_st, - CCS_FORCEHT); - - udelay(64); - - SPINWAIT(((R_REG - (&wlc_hw->regs-> - clk_ctl_st) & CCS_HTAVAIL) == 0), - PMU_MAX_TRANSITION_DLY); - WARN_ON(!(R_REG - (&wlc_hw->regs-> - clk_ctl_st) & CCS_HTAVAIL)); - } else { - if ((wlc_hw->sih->pmurev == 0) && - (R_REG - (&wlc_hw->regs-> - clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ))) - SPINWAIT(((R_REG - (&wlc_hw->regs-> - clk_ctl_st) & CCS_HTAVAIL) - == 0), - PMU_MAX_TRANSITION_DLY); - AND_REG(&wlc_hw->regs->clk_ctl_st, - ~CCS_FORCEHT); - } - } - wlc_hw->forcefastclk = (mode == CLK_FAST); - } else { - - /* old chips w/o PMU, force HT through cc, - * then use FCA to verify mac is running fast clock - */ - - wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode); - - /* check fast clock is available (if core is not in reset) */ - if (wlc_hw->forcefastclk && wlc_hw->clk) - WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) & - SISF_FCLKA)); - - /* - * keep the ucode wake bit on if forcefastclk is on since we - * do not want ucode to put us back to slow clock when it dozes - * for PM mode. Code below matches the wake override bit with - * current forcefastclk state. Only setting bit in wake_override - * instead of waking ucode immediately since old code had this - * behavior. Older code set wlc->forcefastclk but only had the - * wake happen if the wakup_ucode work (protected by an up - * check) was executed just below. - */ - if (wlc_hw->forcefastclk) - mboolset(wlc_hw->wake_override, - BRCMS_WAKE_OVERRIDE_FORCEFAST); - else - mboolclr(wlc_hw->wake_override, - BRCMS_WAKE_OVERRIDE_FORCEFAST); - } -} - -/* set initial host flags value */ -static void -brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - - memset(mhfs, 0, MHFMAX * sizeof(u16)); - - mhfs[MHF2] |= mhf2_init; - - /* prohibit use of slowclock on multifunction boards */ - if (wlc_hw->boardflags & BFL_NOPLLDOWN) - mhfs[MHF1] |= MHF1_FORCEFASTCLK; - - if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) { - mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR; - mhfs[MHF1] |= MHF1_IQSWAP_WAR; - } -} - -/* set or clear ucode host flag bits - * it has an optimization for no-change write - * it only writes through shared memory when the core has clock; - * pre-CLK changes should use wlc_write_mhf to get around the optimization - * - * - * bands values are: BRCM_BAND_AUTO <--- Current band only - * BRCM_BAND_5G <--- 5G band only - * BRCM_BAND_2G <--- 2G band only - * BRCM_BAND_ALL <--- All bands - */ -void -brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val, - int bands) -{ - u16 save; - u16 addr[MHFMAX] = { - M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, - M_HOST_FLAGS5 - }; - struct brcms_hw_band *band; - - if ((val & ~mask) || idx >= MHFMAX) - return; /* error condition */ - - switch (bands) { - /* Current band only or all bands, - * then set the band to current band - */ - case BRCM_BAND_AUTO: - case BRCM_BAND_ALL: - band = wlc_hw->band; - break; - case BRCM_BAND_5G: - band = wlc_hw->bandstate[BAND_5G_INDEX]; - break; - case BRCM_BAND_2G: - band = wlc_hw->bandstate[BAND_2G_INDEX]; - break; - default: - band = NULL; /* error condition */ - } - - if (band) { - save = band->mhfs[idx]; - band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val; - - /* optimization: only write through if changed, and - * changed band is the current band - */ - if (wlc_hw->clk && (band->mhfs[idx] != save) - && (band == wlc_hw->band)) - brcms_b_write_shm(wlc_hw, addr[idx], - (u16) band->mhfs[idx]); - } - - if (bands == BRCM_BAND_ALL) { - wlc_hw->bandstate[0]->mhfs[idx] = - (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val; - wlc_hw->bandstate[1]->mhfs[idx] = - (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val; - } -} - -static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs) -{ - u8 idx; - u16 addr[] = { - M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, - M_HOST_FLAGS5 - }; - - for (idx = 0; idx < MHFMAX; idx++) - brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]); -} - -/* set the maccontrol register to desired reset state and - * initialize the sw cache of the register - */ -static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw) -{ - /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */ - wlc_hw->maccontrol = 0; - wlc_hw->suspended_fifos = 0; - wlc_hw->wake_override = 0; - wlc_hw->mute_override = 0; - brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE); -} - -/* set or clear maccontrol bits */ -void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val) -{ - u32 maccontrol; - u32 new_maccontrol; - - if (val & ~mask) - return; /* error condition */ - maccontrol = wlc_hw->maccontrol; - new_maccontrol = (maccontrol & ~mask) | val; - - /* if the new maccontrol value is the same as the old, nothing to do */ - if (new_maccontrol == maccontrol) - return; - - /* something changed, cache the new value */ - wlc_hw->maccontrol = new_maccontrol; - - /* write the new values with overrides applied */ - brcms_c_mctrl_write(wlc_hw); -} - -/* - * write the software state of maccontrol and - * overrides to the maccontrol register - */ -static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw) -{ - u32 maccontrol = wlc_hw->maccontrol; - - /* OR in the wake bit if overridden */ - if (wlc_hw->wake_override) - maccontrol |= MCTL_WAKE; - - /* set AP and INFRA bits for mute if needed */ - if (wlc_hw->mute_override) { - maccontrol &= ~(MCTL_AP); - maccontrol |= MCTL_INFRA; - } - - W_REG(&wlc_hw->regs->maccontrol, maccontrol); -} - -void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, - u32 override_bit) -{ - if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) { - mboolset(wlc_hw->wake_override, override_bit); - return; - } - - mboolset(wlc_hw->wake_override, override_bit); - - brcms_c_mctrl_write(wlc_hw); - brcms_b_wait_for_wake(wlc_hw); - - return; -} - -void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, - u32 override_bit) -{ - mboolclr(wlc_hw->wake_override, override_bit); - - if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) - return; - - brcms_c_mctrl_write(wlc_hw); - - return; -} - -/* When driver needs ucode to stop beaconing, it has to make sure that - * MCTL_AP is clear and MCTL_INFRA is set - * Mode MCTL_AP MCTL_INFRA - * AP 1 1 - * STA 0 1 <--- This will ensure no beacons - * IBSS 0 0 - */ -static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw) -{ - wlc_hw->mute_override = 1; - - /* if maccontrol already has AP == 0 and INFRA == 1 without this - * override, then there is no change to write - */ - if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) - return; - - brcms_c_mctrl_write(wlc_hw); - - return; -} - -/* Clear the override on AP and INFRA bits */ -static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw) -{ - if (wlc_hw->mute_override == 0) - return; - - wlc_hw->mute_override = 0; - - /* if maccontrol already has AP == 0 and INFRA == 1 without this - * override, then there is no change to write - */ - if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) - return; - - brcms_c_mctrl_write(wlc_hw); -} - -/* - * Write a MAC address to the given match reg offset in the RXE match engine. - */ -void -brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, - const u8 *addr) -{ - struct d11regs *regs; - u16 mac_l; - u16 mac_m; - u16 mac_h; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n", - wlc_hw->unit); - - regs = wlc_hw->regs; - mac_l = addr[0] | (addr[1] << 8); - mac_m = addr[2] | (addr[3] << 8); - mac_h = addr[4] | (addr[5] << 8); - - /* enter the MAC addr into the RXE match registers */ - W_REG(®s->rcm_ctl, RCM_INC_DATA | match_reg_offset); - W_REG(®s->rcm_mat_data, mac_l); - W_REG(®s->rcm_mat_data, mac_m); - W_REG(®s->rcm_mat_data, mac_h); - -} - -void -brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len, - void *buf) -{ - struct d11regs *regs; - u32 word; - bool be_bit; - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - regs = wlc_hw->regs; - W_REG(®s->tplatewrptr, offset); - - /* if MCTL_BIGEND bit set in mac control register, - * the chip swaps data in fifo, as well as data in - * template ram - */ - be_bit = (R_REG(®s->maccontrol) & MCTL_BIGEND) != 0; - - while (len > 0) { - memcpy(&word, buf, sizeof(u32)); - - if (be_bit) - word = cpu_to_be32(word); - else - word = cpu_to_le32(word); - - W_REG(®s->tplatewrdata, word); - - buf = (u8 *) buf + sizeof(u32); - len -= sizeof(u32); - } -} - -void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin) -{ - wlc_hw->band->CWmin = newmin; - - W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN); - (void)R_REG(&wlc_hw->regs->objaddr); - W_REG(&wlc_hw->regs->objdata, newmin); -} - -void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax) -{ - wlc_hw->band->CWmax = newmax; - - W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX); - (void)R_REG(&wlc_hw->regs->objaddr); - W_REG(&wlc_hw->regs->objdata, newmax); -} - -void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) -{ - bool fastclk; - - /* request FAST clock if not on */ - fastclk = wlc_hw->forcefastclk; - if (!fastclk) - brcms_b_clkctl_clk(wlc_hw, CLK_FAST); - - wlc_phy_bw_state_set(wlc_hw->band->pi, bw); - - brcms_b_phy_reset(wlc_hw); - wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi)); - - /* restore the clk */ - if (!fastclk) - brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); -} - -static void -brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw, u16 bcn[], - int len) -{ - struct d11regs *regs = wlc_hw->regs; - - brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3, - bcn); - /* write beacon length to SCR */ - brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len); - /* mark beacon0 valid */ - OR_REG(®s->maccommand, MCMD_BCN0VLD); -} - -static void -brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw, u16 bcn[], - int len) -{ - struct d11regs *regs = wlc_hw->regs; - - brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3, - bcn); - /* write beacon length to SCR */ - brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len); - /* mark beacon1 valid */ - OR_REG(®s->maccommand, MCMD_BCN1VLD); -} - -static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw) -{ - u16 v; - struct brcms_c_info *wlc = wlc_hw->wlc; - /* update SYNTHPU_DLY */ - - if (BRCMS_ISLCNPHY(wlc->band)) - v = SYNTHPU_DLY_LPPHY_US; - else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) - v = SYNTHPU_DLY_NPHY_US; - else - v = SYNTHPU_DLY_BPHY_US; - - brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v); -} - -/* band-specific init */ -static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - - BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, - wlc_hw->band->bandunit); - - brcms_c_ucode_bsinit(wlc_hw); - - wlc_phy_init(wlc_hw->band->pi, chanspec); - - brcms_c_ucode_txant_set(wlc_hw); - - /* - * cwmin is band-specific, update hardware - * with value for current band - */ - brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin); - brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax); - - brcms_b_update_slot_timing(wlc_hw, - BAND_5G(wlc_hw->band-> - bandtype) ? true : wlc_hw-> - shortslot); - - /* write phytype and phyvers */ - brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype); - brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev); - - /* - * initialize the txphyctl1 rate table since - * shmem is shared between bands - */ - brcms_upd_ofdm_pctl1_table(wlc_hw); - - brcms_b_upd_synthpu(wlc_hw); -} - -static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) -{ - BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk); - - wlc_hw->phyclk = clk; - - if (OFF == clk) { /* clear gmode bit, put phy into reset */ - - ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE), - (SICF_PRST | SICF_FGC)); - udelay(1); - ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST); - udelay(1); - - } else { /* take phy out of reset */ - - ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC); - udelay(1); - ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0); - udelay(1); - - } -} - -/* Perform a soft reset of the PHY PLL */ -void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw) -{ - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - ai_corereg(wlc_hw->sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol_addr), ~0, 0); - udelay(1); - ai_corereg(wlc_hw->sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); - udelay(1); - ai_corereg(wlc_hw->sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol_data), 0x4, 4); - udelay(1); - ai_corereg(wlc_hw->sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); - udelay(1); -} - -/* light way to turn on phy clock without reset for NPHY only - * refer to brcms_b_core_phy_clk for full version - */ -void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk) -{ - /* support(necessary for NPHY and HYPHY) only */ - if (!BRCMS_ISNPHY(wlc_hw->band)) - return; - - if (ON == clk) - ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC); - else - ai_core_cflags(wlc_hw->sih, SICF_FGC, 0); - -} - -void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk) -{ - if (ON == clk) - ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE); - else - ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0); -} - -void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) -{ - struct brcms_phy_pub *pih = wlc_hw->band->pi; - u32 phy_bw_clkbits; - bool phy_in_reset = false; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - if (pih == NULL) - return; - - phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi); - - /* Specific reset sequence required for NPHY rev 3 and 4 */ - if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) && - NREV_LE(wlc_hw->band->phyrev, 4)) { - /* Set the PHY bandwidth */ - ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits); - - udelay(1); - - /* Perform a soft reset of the PHY PLL */ - brcms_b_core_phypll_reset(wlc_hw); - - /* reset the PHY */ - ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE), - (SICF_PRST | SICF_PCLKE)); - phy_in_reset = true; - } else { - ai_core_cflags(wlc_hw->sih, - (SICF_PRST | SICF_PCLKE | SICF_BWMASK), - (SICF_PRST | SICF_PCLKE | phy_bw_clkbits)); - } - - udelay(2); - brcms_b_core_phy_clk(wlc_hw, ON); - - if (pih) - wlc_phy_anacore(pih, ON); -} - -/* switch to and initialize new band */ -static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit, - u16 chanspec) { - struct brcms_c_info *wlc = wlc_hw->wlc; - u32 macintmask; - - /* Enable the d11 core before accessing it */ - if (!ai_iscoreup(wlc_hw->sih)) { - ai_core_reset(wlc_hw->sih, 0, 0); - brcms_c_mctrl_reset(wlc_hw); - } - - macintmask = brcms_c_setband_inact(wlc, bandunit); - - if (!wlc_hw->up) - return; - - brcms_b_core_phy_clk(wlc_hw, ON); - - /* band-specific initializations */ - brcms_b_bsinit(wlc, chanspec); - - /* - * If there are any pending software interrupt bits, - * then replace these with a harmless nonzero value - * so brcms_c_dpc() will re-enable interrupts when done. - */ - if (wlc->macintstatus) - wlc->macintstatus = MI_DMAINT; - - /* restore macintmask */ - brcms_intrsrestore(wlc->wl, macintmask); - - /* ucode should still be suspended.. */ - WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); -} - -/* low-level band switch utility routine */ -void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit) -{ - BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, - bandunit); - - wlc_hw->band = wlc_hw->bandstate[bandunit]; - - /* - * BMAC_NOTE: - * until we eliminate need for wlc->band refs in low level code - */ - wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit]; - - /* set gmode core flag */ - if (wlc_hw->sbclk && !wlc_hw->noreset) - ai_core_cflags(wlc_hw->sih, SICF_GMODE, - ((bandunit == 0) ? SICF_GMODE : 0)); -} - -static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw) -{ - - /* reject unsupported corerev */ - if (!VALID_COREREV(wlc_hw->corerev)) { - wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n", - wlc_hw->corerev); - return false; - } - - return true; -} - -/* Validate some board info parameters */ -static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw) -{ - uint boardrev = wlc_hw->boardrev; - - /* 4 bits each for board type, major, minor, and tiny version */ - uint brt = (boardrev & 0xf000) >> 12; - uint b0 = (boardrev & 0xf00) >> 8; - uint b1 = (boardrev & 0xf0) >> 4; - uint b2 = boardrev & 0xf; - - /* voards from other vendors are always considered valid */ - if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM) - return true; - - /* do some boardrev sanity checks when boardvendor is Broadcom */ - if (boardrev == 0) - return false; - - if (boardrev <= 0xff) - return true; - - if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9) - || (b2 > 9)) - return false; - - return true; -} - -static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw) -{ - const char *varname = "macaddr"; - char *macaddr; - - /* If macaddr exists, use it (Sromrev4, CIS, ...). */ - macaddr = getvar(wlc_hw->vars, varname); - if (macaddr != NULL) - return macaddr; - - if (NBANDS_HW(wlc_hw) > 1) - varname = "et1macaddr"; - else - varname = "il0macaddr"; - - macaddr = getvar(wlc_hw->vars, varname); - if (macaddr == NULL) - wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr " - "getvar(%s) not found\n", wlc_hw->unit, varname); - - return macaddr; -} - -/* - * Return true if radio is disabled, otherwise false. - * hw radio disable signal is an external pin, users activate it asynchronously - * this function could be called when driver is down and w/o clock - * it operates on different registers depending on corerev and boardflag. - */ -bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) -{ - bool v, clk, xtal; - u32 resetbits = 0, flags = 0; - - xtal = wlc_hw->sbclk; - if (!xtal) - brcms_b_xtal(wlc_hw, ON); - - /* may need to take core out of reset first */ - clk = wlc_hw->clk; - if (!clk) { - /* - * mac no longer enables phyclk automatically when driver - * accesses phyreg throughput mac. This can be skipped since - * only mac reg is accessed below - */ - flags |= SICF_PCLKE; - - /* - * AI chip doesn't restore bar0win2 on - * hibernation/resume, need sw fixup - */ - if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || - (wlc_hw->sih->chip == BCM43225_CHIP_ID)) - wlc_hw->regs = (struct d11regs *) - ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); - ai_core_reset(wlc_hw->sih, flags, resetbits); - brcms_c_mctrl_reset(wlc_hw); - } - - v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0); - - /* put core back into reset */ - if (!clk) - ai_core_disable(wlc_hw->sih, 0); - - if (!xtal) - brcms_b_xtal(wlc_hw, OFF); - - return v; -} - -static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo) -{ - struct dma_pub *di = wlc_hw->di[fifo]; - return dma_rxreset(di); -} - -/* d11 core reset - * ensure fask clock during reset - * reset dma - * reset d11(out of reset) - * reset phy(out of reset) - * clear software macintstatus for fresh new start - * one testing hack wlc_hw->noreset will bypass the d11/phy reset - */ -void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) -{ - struct d11regs *regs; - uint i; - bool fastclk; - u32 resetbits = 0; - - if (flags == BRCMS_USE_COREFLAGS) - flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0); - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - regs = wlc_hw->regs; - - /* request FAST clock if not on */ - fastclk = wlc_hw->forcefastclk; - if (!fastclk) - brcms_b_clkctl_clk(wlc_hw, CLK_FAST); - - /* reset the dma engines except first time thru */ - if (ai_iscoreup(wlc_hw->sih)) { - for (i = 0; i < NFIFO; i++) - if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) - wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: " - "dma_txreset[%d]: cannot stop dma\n", - wlc_hw->unit, __func__, i); - - if ((wlc_hw->di[RX_FIFO]) - && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) - wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset" - "[%d]: cannot stop dma\n", - wlc_hw->unit, __func__, RX_FIFO); - } - /* if noreset, just stop the psm and return */ - if (wlc_hw->noreset) { - wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */ - brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0); - return; - } - - /* - * mac no longer enables phyclk automatically when driver accesses - * phyreg throughput mac, AND phy_reset is skipped at early stage when - * band->pi is invalid. need to enable PHY CLK - */ - flags |= SICF_PCLKE; - - /* - * reset the core - * In chips with PMU, the fastclk request goes through d11 core - * reg 0x1e0, which is cleared by the core_reset. have to re-request it. - * - * This adds some delay and we can optimize it by also requesting - * fastclk through chipcommon during this period if necessary. But - * that has to work coordinate with other driver like mips/arm since - * they may touch chipcommon as well. - */ - wlc_hw->clk = false; - ai_core_reset(wlc_hw->sih, flags, resetbits); - wlc_hw->clk = true; - if (wlc_hw->band && wlc_hw->band->pi) - wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true); - - brcms_c_mctrl_reset(wlc_hw); - - if (PMUCTL_ENAB(wlc_hw->sih)) - brcms_b_clkctl_clk(wlc_hw, CLK_FAST); - - brcms_b_phy_reset(wlc_hw); - - /* turn on PHY_PLL */ - brcms_b_core_phypll_ctl(wlc_hw, true); - - /* clear sw intstatus */ - wlc_hw->wlc->macintstatus = 0; - - /* restore the clk setting */ - if (!fastclk) - brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); -} - -/* txfifo sizes needs to be modified(increased) since the newer cores - * have more memory. - */ -static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw) -{ - struct d11regs *regs = wlc_hw->regs; - u16 fifo_nu; - u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk; - u16 txfifo_def, txfifo_def1; - u16 txfifo_cmd; - - /* tx fifos start at TXFIFO_START_BLK from the Base address */ - txfifo_startblk = TXFIFO_START_BLK; - - /* sequence of operations: reset fifo, set fifo size, reset fifo */ - for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) { - - txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu]; - txfifo_def = (txfifo_startblk & 0xff) | - (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT); - txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) | - ((((txfifo_endblk - - 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT); - txfifo_cmd = - TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT); - - W_REG(®s->xmtfifocmd, txfifo_cmd); - W_REG(®s->xmtfifodef, txfifo_def); - W_REG(®s->xmtfifodef1, txfifo_def1); - - W_REG(®s->xmtfifocmd, txfifo_cmd); - - txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu]; - } - /* - * need to propagate to shm location to be in sync since ucode/hw won't - * do this - */ - brcms_b_write_shm(wlc_hw, M_FIFOSIZE0, - wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]); - brcms_b_write_shm(wlc_hw, M_FIFOSIZE1, - wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]); - brcms_b_write_shm(wlc_hw, M_FIFOSIZE2, - ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw-> - xmtfifo_sz[TX_AC_BK_FIFO])); - brcms_b_write_shm(wlc_hw, M_FIFOSIZE3, - ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw-> - xmtfifo_sz[TX_BCMC_FIFO])); -} - -/* This function is used for changing the tsf frac register - * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz - * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz - * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz - * HTPHY Formula is 2^26/freq(MHz) e.g. - * For spuron2 - 126MHz -> 2^26/126 = 532610.0 - * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082 - * For spuron: 123MHz -> 2^26/123 = 545600.5 - * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341 - * For spur off: 120MHz -> 2^26/120 = 559240.5 - * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889 - */ - -void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) -{ - struct d11regs *regs; - regs = wlc_hw->regs; - - if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || - (wlc_hw->sih->chip == BCM43225_CHIP_ID)) { - if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ - W_REG(®s->tsf_clk_frac_l, 0x2082); - W_REG(®s->tsf_clk_frac_h, 0x8); - } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */ - W_REG(®s->tsf_clk_frac_l, 0x5341); - W_REG(®s->tsf_clk_frac_h, 0x8); - } else { /* 120Mhz */ - W_REG(®s->tsf_clk_frac_l, 0x8889); - W_REG(®s->tsf_clk_frac_h, 0x8); - } - } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { - if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */ - W_REG(®s->tsf_clk_frac_l, 0x7CE0); - W_REG(®s->tsf_clk_frac_h, 0xC); - } else { /* 80Mhz */ - W_REG(®s->tsf_clk_frac_l, 0xCCCD); - W_REG(®s->tsf_clk_frac_h, 0xC); - } - } -} - -/* Initialize GPIOs that are controlled by D11 core */ -static void brcms_c_gpio_init(struct brcms_c_info *wlc) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - struct d11regs *regs; - u32 gc, gm; - - regs = wlc_hw->regs; - - /* use GPIO select 0 to get all gpio signals from the gpio out reg */ - brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0); - - /* - * Common GPIO setup: - * G0 = LED 0 = WLAN Activity - * G1 = LED 1 = WLAN 2.4 GHz Radio State - * G2 = LED 2 = WLAN 5 GHz Radio State - * G4 = radio disable input (HI enabled, LO disabled) - */ - - gc = gm = 0; - - /* Allocate GPIOs for mimo antenna diversity feature */ - if (wlc_hw->antsel_type == ANTSEL_2x3) { - /* Enable antenna diversity, use 2x3 mode */ - brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, - MHF3_ANTSEL_EN, BRCM_BAND_ALL); - brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, - MHF3_ANTSEL_MODE, BRCM_BAND_ALL); - - /* init superswitch control */ - wlc_phy_antsel_init(wlc_hw->band->pi, false); - - } else if (wlc_hw->antsel_type == ANTSEL_2x4) { - gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13); - /* - * The board itself is powered by these GPIOs - * (when not sending pattern) so set them high - */ - OR_REG(®s->psm_gpio_oe, - (BOARD_GPIO_12 | BOARD_GPIO_13)); - OR_REG(®s->psm_gpio_out, - (BOARD_GPIO_12 | BOARD_GPIO_13)); - - /* Enable antenna diversity, use 2x4 mode */ - brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, - MHF3_ANTSEL_EN, BRCM_BAND_ALL); - brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0, - BRCM_BAND_ALL); - - /* Configure the desired clock to be 4Mhz */ - brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV, - ANTSEL_CLKDIV_4MHZ); - } - - /* - * gpio 9 controls the PA. ucode is responsible - * for wiggling out and oe - */ - if (wlc_hw->boardflags & BFL_PACTRL) - gm |= gc |= BOARD_GPIO_PACTRL; - - /* apply to gpiocontrol register */ - ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY); -} - -static void brcms_ucode_download(struct brcms_hardware *wlc_hw) -{ - struct brcms_c_info *wlc; - wlc = wlc_hw->wlc; - - if (wlc_hw->ucode_loaded) - return; - - if (D11REV_IS(wlc_hw->corerev, 23)) { - if (BRCMS_ISNPHY(wlc_hw->band)) { - brcms_ucode_write(wlc_hw, bcm43xx_16_mimo, - bcm43xx_16_mimosz); - wlc_hw->ucode_loaded = true; - } else - wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " - "corerev %d\n", - __func__, wlc_hw->unit, wlc_hw->corerev); - } else if (D11REV_IS(wlc_hw->corerev, 24)) { - if (BRCMS_ISLCNPHY(wlc_hw->band)) { - brcms_ucode_write(wlc_hw, bcm43xx_24_lcn, - bcm43xx_24_lcnsz); - wlc_hw->ucode_loaded = true; - } else { - wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " - "corerev %d\n", - __func__, wlc_hw->unit, wlc_hw->corerev); - } - } -} - -static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[], - const uint nbytes) { - struct d11regs *regs = wlc_hw->regs; - uint i; - uint count; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - count = (nbytes / sizeof(u32)); - - W_REG(®s->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL)); - (void)R_REG(®s->objaddr); - for (i = 0; i < count; i++) - W_REG(®s->objdata, le32_to_cpu(ucode[i])); - -} - -static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, - const struct d11init *inits) -{ - int i; - u8 *base; - u8 *addr; - u16 size; - u32 value; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - base = (u8 *)wlc_hw->regs; - - for (i = 0; inits[i].addr != 0xffff; i++) { - size = le16_to_cpu(inits[i].size); - addr = base + le16_to_cpu(inits[i].addr); - value = le32_to_cpu(inits[i].value); - if (size == 2) - W_REG((u16 *)addr, value); - else if (size == 4) - W_REG((u32 *)addr, value); - else - break; - } -} - -static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw) -{ - u16 phyctl; - u16 phytxant = wlc_hw->bmac_phytxant; - u16 mask = PHY_TXC_ANT_MASK; - - /* set the Probe Response frame phy control word */ - phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS); - phyctl = (phyctl & ~mask) | phytxant; - brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl); - - /* set the Response (ACK/CTS) frame phy control word */ - phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD); - phyctl = (phyctl & ~mask) | phytxant; - brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl); -} - -void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant) -{ - /* update sw state */ - wlc_hw->bmac_phytxant = phytxant; - - /* push to ucode if up */ - if (!wlc_hw->up) - return; - brcms_c_ucode_txant_set(wlc_hw); - -} - -u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw) -{ - return (u16) wlc_hw->wlc->stf->txant; -} - -void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type) -{ - wlc_hw->antsel_type = antsel_type; - - /* Update the antsel type for phy module to use */ - wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type); -} - -void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) -{ - bool fatal = false; - uint unit; - uint intstatus, idx; - struct d11regs *regs = wlc_hw->regs; - struct wiphy *wiphy = wlc_hw->wlc->wiphy; - - unit = wlc_hw->unit; - - for (idx = 0; idx < NFIFO; idx++) { - /* read intstatus register and ignore any non-error bits */ - intstatus = - R_REG(®s->intctrlregs[idx].intstatus) & I_ERRORS; - if (!intstatus) - continue; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n", - unit, idx, intstatus); - - if (intstatus & I_RO) { - wiphy_err(wiphy, "wl%d: fifo %d: receive fifo " - "overflow\n", unit, idx); - fatal = true; - } - - if (intstatus & I_PC) { - wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n", - unit, idx); - fatal = true; - } - - if (intstatus & I_PD) { - wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit, - idx); - fatal = true; - } - - if (intstatus & I_DE) { - wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol " - "error\n", unit, idx); - fatal = true; - } - - if (intstatus & I_RU) - wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor " - "underflow\n", idx, unit); - - if (intstatus & I_XU) { - wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo " - "underflow\n", idx, unit); - fatal = true; - } - - if (fatal) { - brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */ - break; - } else - W_REG(®s->intctrlregs[idx].intstatus, - intstatus); - } -} - -void brcms_c_intrson(struct brcms_c_info *wlc) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - wlc->macintmask = wlc->defmacintmask; - W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); -} - -/* - * callback for siutils.c, which has only wlc handler, no wl they both check - * up, not only because there is no need to off/restore d11 interrupt but also - * because per-port code may require sync with valid interrupt. - */ -static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc) -{ - if (!wlc->hw->up) - return 0; - - return brcms_intrsoff(wlc->wl); -} - -static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask) -{ - if (!wlc->hw->up) - return; - - brcms_intrsrestore(wlc->wl, macintmask); -} - -u32 brcms_c_intrsoff(struct brcms_c_info *wlc) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - u32 macintmask; - - if (!wlc_hw->clk) - return 0; - - macintmask = wlc->macintmask; /* isr can still happen */ - - W_REG(&wlc_hw->regs->macintmask, 0); - (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */ - udelay(1); /* ensure int line is no longer driven */ - wlc->macintmask = 0; - - /* return previous macintmask; resolve race between us and our isr */ - return wlc->macintstatus ? 0 : macintmask; -} - -void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - if (!wlc_hw->clk) - return; - - wlc->macintmask = macintmask; - W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); -} - -static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw, - uint tx_fifo) -{ - u8 fifo = 1 << tx_fifo; - - /* Two clients of this code, 11h Quiet period and scanning. */ - - /* only suspend if not already suspended */ - if ((wlc_hw->suspended_fifos & fifo) == fifo) - return; - - /* force the core awake only if not already */ - if (wlc_hw->suspended_fifos == 0) - brcms_c_ucode_wake_override_set(wlc_hw, - BRCMS_WAKE_OVERRIDE_TXFIFO); - - wlc_hw->suspended_fifos |= fifo; - - if (wlc_hw->di[tx_fifo]) { - /* - * Suspending AMPDU transmissions in the middle can cause - * underflow which may result in mismatch between ucode and - * driver so suspend the mac before suspending the FIFO - */ - if (BRCMS_PHY_11N_CAP(wlc_hw->band)) - brcms_c_suspend_mac_and_wait(wlc_hw->wlc); - - dma_txsuspend(wlc_hw->di[tx_fifo]); - - if (BRCMS_PHY_11N_CAP(wlc_hw->band)) - brcms_c_enable_mac(wlc_hw->wlc); - } -} - -static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, u32 flags) -{ - u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; - - if (on) { - /* suspend tx fifos */ - brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO); - brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO); - brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO); - brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO); - - /* zero the address match register so we do not send ACKs */ - brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, - null_ether_addr); - } else { - /* resume tx fifos */ - if (!wlc_hw->wlc->tx_suspended) - brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO); - - brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO); - brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO); - brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO); - - /* Restore address */ - brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, - wlc_hw->etheraddr); - } - - wlc_phy_mute_upd(wlc_hw->band->pi, on, flags); - - if (on) - brcms_c_ucode_mute_override_set(wlc_hw); - else - brcms_c_ucode_mute_override_clear(wlc_hw); -} - -/* brcms_b_tx_fifo_suspended: - * Check the MAC's tx suspend status for a tx fifo. - * - * When the MAC acknowledges a tx suspend, it indicates that no more - * packets will be transmitted out the radio. This is independent of - * DMA channel suspension---the DMA may have finished suspending, or may still - * be pulling data into a tx fifo, by the time the MAC acks the suspend - * request. - */ -static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw, - uint tx_fifo) -{ - /* check that a suspend has been requested and is no longer pending */ - - /* - * for DMA mode, the suspend request is set in xmtcontrol of the DMA - * engine, and the tx fifo suspend at the lower end of the MAC is - * acknowledged in the chnstatus register. - * - * The tx fifo suspend completion is independent of the DMA suspend - * completion and may be acked before or after the DMA is suspended. - */ - if (dma_txsuspended(wlc_hw->di[tx_fifo]) && - (R_REG(&wlc_hw->regs->chnstatus) & - (1 << tx_fifo)) == 0) - return true; - - return false; -} - -static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw, - uint tx_fifo) -{ - /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case - * but need to be done here for PIO otherwise the watchdog will catch - * the inconsistency and fire - */ - /* Two clients of this code, 11h Quiet period and scanning. */ - if (wlc_hw->di[tx_fifo]) - dma_txresume(wlc_hw->di[tx_fifo]); - - /* allow core to sleep again */ - if (wlc_hw->suspended_fifos == 0) - return; - else { - wlc_hw->suspended_fifos &= ~(1 << tx_fifo); - if (wlc_hw->suspended_fifos == 0) - brcms_c_ucode_wake_override_clear(wlc_hw, - BRCMS_WAKE_OVERRIDE_TXFIFO); - } -} - -/* - * Read and clear macintmask and macintstatus and intstatus registers. - * This routine should be called with interrupts off - * Return: - * -1 if DEVICEREMOVED(wlc) evaluates to true; - * 0 if the interrupt is not for us, or we are in some special cases; - * device interrupt status bits otherwise. - */ -static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - struct d11regs *regs = wlc_hw->regs; - u32 macintstatus; - - /* macintstatus includes a DMA interrupt summary bit */ - macintstatus = R_REG(®s->macintstatus); - - BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit, - macintstatus); - - /* detect cardbus removed, in power down(suspend) and in reset */ - if (DEVICEREMOVED(wlc)) - return -1; - - /* DEVICEREMOVED succeeds even when the core is still resetting, - * handle that case here. - */ - if (macintstatus == 0xffffffff) - return 0; - - /* defer unsolicited interrupts */ - macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask); - - /* if not for us */ - if (macintstatus == 0) - return 0; - - /* interrupts are already turned off for CFE build - * Caution: For CFE Turning off the interrupts again has some undesired - * consequences - */ - /* turn off the interrupts */ - W_REG(®s->macintmask, 0); - (void)R_REG(®s->macintmask); /* sync readback */ - wlc->macintmask = 0; - - /* clear device interrupts */ - W_REG(®s->macintstatus, macintstatus); - - /* MI_DMAINT is indication of non-zero intstatus */ - if (macintstatus & MI_DMAINT) - /* - * only fifo interrupt enabled is I_RI in - * RX_FIFO. If MI_DMAINT is set, assume it - * is set and clear the interrupt. - */ - W_REG(®s->intctrlregs[RX_FIFO].intstatus, - DEF_RXINTMASK); - - return macintstatus; -} - -/* Update wlc->macintstatus and wlc->intstatus[]. */ -/* Return true if they are updated successfully. false otherwise */ -bool brcms_c_intrsupd(struct brcms_c_info *wlc) -{ - u32 macintstatus; - - /* read and clear macintstatus and intstatus registers */ - macintstatus = wlc_intstatus(wlc, false); - - /* device is removed */ - if (macintstatus == 0xffffffff) - return false; - - /* update interrupt status in software */ - wlc->macintstatus |= macintstatus; - - return true; -} - -/* - * First-level interrupt processing. - * Return true if this was our interrupt, false otherwise. - * *wantdpc will be set to true if further brcms_c_dpc() processing is required, - * false otherwise. - */ -bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - u32 macintstatus; - - *wantdpc = false; - - if (!wlc_hw->up || !wlc->macintmask) - return false; - - /* read and clear macintstatus and intstatus registers */ - macintstatus = wlc_intstatus(wlc, true); - - if (macintstatus == 0xffffffff) - wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code" - " path\n"); - - /* it is not for us */ - if (macintstatus == 0) - return false; - - *wantdpc = true; - - /* save interrupt status bits */ - wlc->macintstatus = macintstatus; - - return true; - -} - -void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - struct d11regs *regs = wlc_hw->regs; - u32 mc, mi; - struct wiphy *wiphy = wlc->wiphy; - - BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, - wlc_hw->band->bandunit); - - /* - * Track overlapping suspend requests - */ - wlc_hw->mac_suspend_depth++; - if (wlc_hw->mac_suspend_depth > 1) - return; - - /* force the core awake */ - brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND); - - mc = R_REG(®s->maccontrol); - - if (mc == 0xffffffff) { - wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, - __func__); - brcms_down(wlc->wl); - return; - } - WARN_ON(mc & MCTL_PSM_JMP_0); - WARN_ON(!(mc & MCTL_PSM_RUN)); - WARN_ON(!(mc & MCTL_EN_MAC)); - - mi = R_REG(®s->macintstatus); - if (mi == 0xffffffff) { - wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, - __func__); - brcms_down(wlc->wl); - return; - } - WARN_ON(mi & MI_MACSSPNDD); - - brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0); - - SPINWAIT(!(R_REG(®s->macintstatus) & MI_MACSSPNDD), - BRCMS_MAX_MAC_SUSPEND); - - if (!(R_REG(®s->macintstatus) & MI_MACSSPNDD)) { - wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS" - " and MI_MACSSPNDD is still not on.\n", - wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND); - wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, " - "psm_brc 0x%04x\n", wlc_hw->unit, - R_REG(®s->psmdebug), - R_REG(®s->phydebug), - R_REG(®s->psm_brc)); - } - - mc = R_REG(®s->maccontrol); - if (mc == 0xffffffff) { - wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, - __func__); - brcms_down(wlc->wl); - return; - } - WARN_ON(mc & MCTL_PSM_JMP_0); - WARN_ON(!(mc & MCTL_PSM_RUN)); - WARN_ON(mc & MCTL_EN_MAC); -} - -void brcms_c_enable_mac(struct brcms_c_info *wlc) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - struct d11regs *regs = wlc_hw->regs; - u32 mc, mi; - - BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, - wlc->band->bandunit); - - /* - * Track overlapping suspend requests - */ - wlc_hw->mac_suspend_depth--; - if (wlc_hw->mac_suspend_depth > 0) - return; - - mc = R_REG(®s->maccontrol); - WARN_ON(mc & MCTL_PSM_JMP_0); - WARN_ON(mc & MCTL_EN_MAC); - WARN_ON(!(mc & MCTL_PSM_RUN)); - - brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC); - W_REG(®s->macintstatus, MI_MACSSPNDD); - - mc = R_REG(®s->maccontrol); - WARN_ON(mc & MCTL_PSM_JMP_0); - WARN_ON(!(mc & MCTL_EN_MAC)); - WARN_ON(!(mc & MCTL_PSM_RUN)); - - mi = R_REG(®s->macintstatus); - WARN_ON(mi & MI_MACSSPNDD); - - brcms_c_ucode_wake_override_clear(wlc_hw, - BRCMS_WAKE_OVERRIDE_MACSUSPEND); -} - -static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw) -{ - u8 rate; - u8 rates[8] = { - BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M, - BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M - }; - u16 entry_ptr; - u16 pctl1; - uint i; - - if (!BRCMS_PHY_11N_CAP(wlc_hw->band)) - return; - - /* walk the phy rate table and update the entries */ - for (i = 0; i < ARRAY_SIZE(rates); i++) { - rate = rates[i]; - - entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate); - - /* read the SHM Rate Table entry OFDM PCTL1 values */ - pctl1 = - brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS); - - /* modify the value */ - pctl1 &= ~PHY_TXC1_MODE_MASK; - pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT); - - /* Update the SHM Rate Table entry OFDM PCTL1 values */ - brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS, - pctl1); - } -} - -static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw, - u8 rate) -{ - uint i; - u8 plcp_rate = 0; - struct plcp_signal_rate_lookup { - u8 rate; - u8 signal_rate; - }; - /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */ - const struct plcp_signal_rate_lookup rate_lookup[] = { - {BRCM_RATE_6M, 0xB}, - {BRCM_RATE_9M, 0xF}, - {BRCM_RATE_12M, 0xA}, - {BRCM_RATE_18M, 0xE}, - {BRCM_RATE_24M, 0x9}, - {BRCM_RATE_36M, 0xD}, - {BRCM_RATE_48M, 0x8}, - {BRCM_RATE_54M, 0xC} - }; - - for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) { - if (rate == rate_lookup[i].rate) { - plcp_rate = rate_lookup[i].signal_rate; - break; - } - } - - /* Find the SHM pointer to the rate table entry by looking in the - * Direct-map Table - */ - return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2)); -} - -void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode) -{ - wlc_hw->hw_stf_ss_opmode = stf_mode; - - if (wlc_hw->clk) - brcms_upd_ofdm_pctl1_table(wlc_hw); -} - -static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw) -{ - struct d11regs *regs; - u32 w, val; - struct wiphy *wiphy = wlc_hw->wlc->wiphy; - - BCMMSG(wiphy, "wl%d\n", wlc_hw->unit); - - regs = wlc_hw->regs; - - /* Validate dchip register access */ - - W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); - (void)R_REG(®s->objaddr); - w = R_REG(®s->objdata); - - /* Can we write and read back a 32bit register? */ - W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); - (void)R_REG(®s->objaddr); - W_REG(®s->objdata, (u32) 0xaa5555aa); - - W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); - (void)R_REG(®s->objaddr); - val = R_REG(®s->objdata); - if (val != (u32) 0xaa5555aa) { - wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " - "expected 0xaa5555aa\n", wlc_hw->unit, val); - return false; - } - - W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); - (void)R_REG(®s->objaddr); - W_REG(®s->objdata, (u32) 0x55aaaa55); - - W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); - (void)R_REG(®s->objaddr); - val = R_REG(®s->objdata); - if (val != (u32) 0x55aaaa55) { - wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " - "expected 0x55aaaa55\n", wlc_hw->unit, val); - return false; - } - - W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); - (void)R_REG(®s->objaddr); - W_REG(®s->objdata, w); - - /* clear CFPStart */ - W_REG(®s->tsf_cfpstart, 0); - - w = R_REG(®s->maccontrol); - if ((w != (MCTL_IHR_EN | MCTL_WAKE)) && - (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) { - wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = " - "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w, - (MCTL_IHR_EN | MCTL_WAKE), - (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE)); - return false; - } - - return true; -} - -#define PHYPLL_WAIT_US 100000 - -void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) -{ - struct d11regs *regs; - u32 tmp; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - tmp = 0; - regs = wlc_hw->regs; - - if (on) { - if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) { - OR_REG(®s->clk_ctl_st, - (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL | - CCS_ERSRC_REQ_PHYPLL)); - SPINWAIT((R_REG(®s->clk_ctl_st) & - (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT), - PHYPLL_WAIT_US); - - tmp = R_REG(®s->clk_ctl_st); - if ((tmp & (CCS_ERSRC_AVAIL_HT)) != - (CCS_ERSRC_AVAIL_HT)) - wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY" - " PLL failed\n", __func__); - } else { - OR_REG(®s->clk_ctl_st, - (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL)); - SPINWAIT((R_REG(®s->clk_ctl_st) & - (CCS_ERSRC_AVAIL_D11PLL | - CCS_ERSRC_AVAIL_PHYPLL)) != - (CCS_ERSRC_AVAIL_D11PLL | - CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US); - - tmp = R_REG(®s->clk_ctl_st); - if ((tmp & - (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) - != - (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) - wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on " - "PHY PLL failed\n", __func__); - } - } else { - /* - * Since the PLL may be shared, other cores can still - * be requesting it; so we'll deassert the request but - * not wait for status to comply. - */ - AND_REG(®s->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL); - tmp = R_REG(®s->clk_ctl_st); - } -} - -void brcms_c_coredisable(struct brcms_hardware *wlc_hw) -{ - bool dev_gone; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - dev_gone = DEVICEREMOVED(wlc_hw->wlc); - - if (dev_gone) - return; - - if (wlc_hw->noreset) - return; - - /* radio off */ - wlc_phy_switch_radio(wlc_hw->band->pi, OFF); - - /* turn off analog core */ - wlc_phy_anacore(wlc_hw->band->pi, OFF); - - /* turn off PHYPLL to save power */ - brcms_b_core_phypll_ctl(wlc_hw, false); - - /* No need to set wlc->pub->radio_active = OFF - * because this function needs down capability and - * radio_active is designed for BCMNODOWN. - */ - - /* remove gpio controls */ - if (wlc_hw->ucode_dbgsel) - ai_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY); - - wlc_hw->clk = false; - ai_core_disable(wlc_hw->sih, 0); - wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); -} - -/* power both the pll and external oscillator on/off */ -static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want) -{ - BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want); - - /* - * dont power down if plldown is false or - * we must poll hw radio disable - */ - if (!want && wlc_hw->pllreq) - return; - - if (wlc_hw->sih) - ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want); - - wlc_hw->sbclk = want; - if (!wlc_hw->sbclk) { - wlc_hw->clk = false; - if (wlc_hw->band && wlc_hw->band->pi) - wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); - } -} - -static void brcms_c_flushqueues(struct brcms_c_info *wlc) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - uint i; - - wlc->txpend16165war = 0; - - /* free any posted tx packets */ - for (i = 0; i < NFIFO; i++) - if (wlc_hw->di[i]) { - dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL); - TXPKTPENDCLR(wlc, i); - BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i); - } - - /* free any posted rx packets */ - dma_rxreclaim(wlc_hw->di[RX_FIFO]); -} - -u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset) -{ - return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL); -} - -void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v) -{ - brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL); -} - -static u16 -brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel) -{ - struct d11regs *regs = wlc_hw->regs; - u16 *objdata_lo = (u16 *)®s->objdata; - u16 *objdata_hi = objdata_lo + 1; - u16 v; - - W_REG(®s->objaddr, sel | (offset >> 2)); - (void)R_REG(®s->objaddr); - if (offset & 2) - v = R_REG(objdata_hi); - else - v = R_REG(objdata_lo); - - return v; -} - -static void -brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v, - u32 sel) -{ - struct d11regs *regs = wlc_hw->regs; - u16 *objdata_lo = (u16 *)®s->objdata; - u16 *objdata_hi = objdata_lo + 1; - - W_REG(®s->objaddr, sel | (offset >> 2)); - (void)R_REG(®s->objaddr); - if (offset & 2) - W_REG(objdata_hi, v); - else - W_REG(objdata_lo, v); -} - -/* Copy a buffer to shared memory of specified type . - * SHM 'offset' needs to be an even address and - * Buffer length 'len' must be an even number of bytes - * 'sel' selects the type of memory - */ -void -brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset, - const void *buf, int len, u32 sel) -{ - u16 v; - const u8 *p = (const u8 *)buf; - int i; - - if (len <= 0 || (offset & 1) || (len & 1)) - return; - - for (i = 0; i < len; i += 2) { - v = p[i] | (p[i + 1] << 8); - brcms_b_write_objmem(wlc_hw, offset + i, v, sel); - } -} - -/* Copy a piece of shared memory of specified type to a buffer . - * SHM 'offset' needs to be an even address and - * Buffer length 'len' must be an even number of bytes - * 'sel' selects the type of memory - */ -void -brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf, - int len, u32 sel) -{ - u16 v; - u8 *p = (u8 *) buf; - int i; - - if (len <= 0 || (offset & 1) || (len & 1)) - return; - - for (i = 0; i < len; i += 2) { - v = brcms_b_read_objmem(wlc_hw, offset + i, sel); - p[i] = v & 0xFF; - p[i + 1] = (v >> 8) & 0xFF; - } -} - -void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf, - uint *len) -{ - BCMMSG(wlc_hw->wlc->wiphy, "nvram vars totlen=%d\n", - wlc_hw->vars_size); - - *buf = wlc_hw->vars; - *len = wlc_hw->vars_size; -} - -void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL, u16 LRL) -{ - wlc_hw->SRL = SRL; - wlc_hw->LRL = LRL; - - /* write retry limit to SCR, shouldn't need to suspend */ - if (wlc_hw->up) { - W_REG(&wlc_hw->regs->objaddr, - OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); - (void)R_REG(&wlc_hw->regs->objaddr); - W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL); - W_REG(&wlc_hw->regs->objaddr, - OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); - (void)R_REG(&wlc_hw->regs->objaddr); - W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL); - } -} - -void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, u32 req_bit) -{ - if (set) { - if (mboolisset(wlc_hw->pllreq, req_bit)) - return; - - mboolset(wlc_hw->pllreq, req_bit); - - if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { - if (!wlc_hw->sbclk) - brcms_b_xtal(wlc_hw, ON); - } - } else { - if (!mboolisset(wlc_hw->pllreq, req_bit)) - return; - - mboolclr(wlc_hw->pllreq, req_bit); - - if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { - if (wlc_hw->sbclk) - brcms_b_xtal(wlc_hw, OFF); - } - } - - return; -} - -void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail) -{ - wlc_hw->antsel_avail = antsel_avail; -} - -/* - * conditions under which the PM bit should be set in outgoing frames - * and STAY_AWAKE is meaningful - */ -bool brcms_c_ps_allowed(struct brcms_c_info *wlc) -{ - int idx; - struct brcms_bss_cfg *cfg; - - /* disallow PS when one of the following global conditions meets */ - if (!wlc->pub->associated) - return false; - - /* disallow PS when one of these meets when not scanning */ - if (AP_ACTIVE(wlc) || wlc->monitor) - return false; - - for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) { - cfg = wlc->bsscfg[idx]; - if (cfg && BSSCFG_STA(cfg) && cfg->associated) { - /* - * disallow PS when one of the following - * bsscfg specific conditions meets - */ - if (!cfg->BSS || !BRCMS_PORTOPEN(cfg)) - return false; - - if (!cfg->dtim_programmed) - return false; - } - } - - return true; -} - -void brcms_b_reset(struct brcms_hardware *wlc_hw) -{ - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - /* reset the core */ - if (!DEVICEREMOVED(wlc_hw->wlc)) - brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); - - /* purge the dma rings */ - brcms_c_flushqueues(wlc_hw->wlc); - - brcms_c_reset_bmac_done(wlc_hw->wlc); -} - -void brcms_c_reset(struct brcms_c_info *wlc) -{ - BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); - - /* slurp up hw mac counters before core reset */ - brcms_c_statsupd(wlc); - - /* reset our snapshot of macstat counters */ - memset((char *)wlc->core->macstat_snapshot, 0, - sizeof(struct macstat)); - - brcms_b_reset(wlc->hw); -} - -void brcms_c_fatal_error(struct brcms_c_info *wlc) -{ - wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n", - wlc->pub->unit); - brcms_init(wlc->wl); -} - -/* Return the channel the driver should initialize during brcms_c_init. - * the channel may have to be changed from the currently configured channel - * if other configurations are in conflict (bandlocked, 11n mode disabled, - * invalid channel for current country, etc.) - */ -static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc) -{ - u16 chanspec = - 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | - WL_CHANSPEC_BAND_2G; - - return chanspec; -} - -struct scb global_scb; +struct scb global_scb; static void brcms_c_init_scb(struct brcms_c_info *wlc, struct scb *scb) -{ - int i; - scb->flags = SCB_WMECAP | SCB_HTCAP; - for (i = 0; i < NUMPRIO; i++) - scb->seqnum[i] = 0; -} - -/* d11 core init - * reset PSM - * download ucode/PCM - * let ucode run to suspended - * download ucode inits - * config other core registers - * init dma - */ -static void brcms_b_coreinit(struct brcms_c_info *wlc) -{ - struct brcms_hardware *wlc_hw = wlc->hw; - struct d11regs *regs; - u32 sflags; - uint bcnint_us; - uint i = 0; - bool fifosz_fixup = false; - int err = 0; - u16 buf[NFIFO]; - struct wiphy *wiphy = wlc->wiphy; - - regs = wlc_hw->regs; - - BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); - - /* reset PSM */ - brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE)); - - brcms_ucode_download(wlc_hw); - /* - * FIFOSZ fixup. driver wants to controls the fifo allocation. - */ - fifosz_fixup = true; - - /* let the PSM run to the suspended state, set mode to BSS STA */ - W_REG(®s->macintstatus, -1); - brcms_b_mctrl(wlc_hw, ~0, - (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE)); - - /* wait for ucode to self-suspend after auto-init */ - SPINWAIT(((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0), - 1000 * 1000); - if ((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0) - wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-" - "suspend!\n", wlc_hw->unit); - - brcms_c_gpio_init(wlc); - - sflags = ai_core_sflags(wlc_hw->sih, 0, 0); - - if (D11REV_IS(wlc_hw->corerev, 23)) { - if (BRCMS_ISNPHY(wlc_hw->band)) - brcms_c_write_inits(wlc_hw, d11n0initvals16); - else - wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" - " %d\n", __func__, wlc_hw->unit, - wlc_hw->corerev); - } else if (D11REV_IS(wlc_hw->corerev, 24)) { - if (BRCMS_ISLCNPHY(wlc_hw->band)) - brcms_c_write_inits(wlc_hw, d11lcn0initvals24); - else - wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" - " %d\n", __func__, wlc_hw->unit, - wlc_hw->corerev); - } else { - wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", - __func__, wlc_hw->unit, wlc_hw->corerev); - } - - /* For old ucode, txfifo sizes needs to be modified(increased) */ - if (fifosz_fixup == true) - brcms_b_corerev_fifofixup(wlc_hw); - - /* check txfifo allocations match between ucode and driver */ - buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0); - if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) { - i = TX_AC_BE_FIFO; - err = -1; - } - buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1); - if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) { - i = TX_AC_VI_FIFO; - err = -1; - } - buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2); - buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff; - buf[TX_AC_BK_FIFO] &= 0xff; - if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) { - i = TX_AC_BK_FIFO; - err = -1; - } - if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) { - i = TX_AC_VO_FIFO; - err = -1; - } - buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3); - buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff; - buf[TX_BCMC_FIFO] &= 0xff; - if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) { - i = TX_BCMC_FIFO; - err = -1; - } - if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) { - i = TX_ATIM_FIFO; - err = -1; - } - if (err != 0) - wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d" - " driver size %d index %d\n", buf[i], - wlc_hw->xmtfifo_sz[i], i); - - /* make sure we can still talk to the mac */ - WARN_ON(R_REG(®s->maccontrol) == 0xffffffff); - - /* band-specific inits done by wlc_bsinit() */ - - /* Set up frame burst size and antenna swap threshold init values */ - brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST); - brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT); - - /* enable one rx interrupt per received frame */ - W_REG(®s->intrcvlazy[0], (1 << IRL_FC_SHIFT)); - - /* set the station mode (BSS STA) */ - brcms_b_mctrl(wlc_hw, - (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP), - (MCTL_INFRA | MCTL_DISCARD_PMQ)); - - /* set up Beacon interval */ - bcnint_us = 0x8000 << 10; - W_REG(®s->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT)); - W_REG(®s->tsf_cfpstart, bcnint_us); - W_REG(®s->macintstatus, MI_GP1); - - /* write interrupt mask */ - W_REG(®s->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK); - - /* allow the MAC to control the PHY clock (dynamic on/off) */ - brcms_b_macphyclk_set(wlc_hw, ON); - - /* program dynamic clock control fast powerup delay register */ - wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih); - W_REG(®s->scc_fastpwrup_dly, wlc->fastpwrup_dly); - - /* tell the ucode the corerev */ - brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev); - - /* tell the ucode MAC capabilities */ - brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L, - (u16) (wlc_hw->machwcap & 0xffff)); - brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H, - (u16) ((wlc_hw-> - machwcap >> 16) & 0xffff)); - - /* write retry limits to SCR, this done after PSM init */ - W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); - (void)R_REG(®s->objaddr); - W_REG(®s->objdata, wlc_hw->SRL); - W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); - (void)R_REG(®s->objaddr); - W_REG(®s->objdata, wlc_hw->LRL); - - /* write rate fallback retry limits */ - brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL); - brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL); - - AND_REG(®s->ifs_ctl, 0x0FFF); - W_REG(®s->ifs_aifsn, EDCF_AIFSN_MIN); - - /* dma initializations */ - wlc->txpend16165war = 0; - - /* init the tx dma engines */ - for (i = 0; i < NFIFO; i++) { - if (wlc_hw->di[i]) - dma_txinit(wlc_hw->di[i]); - } - - /* init the rx dma engine(s) and post receive buffers */ - dma_rxinit(wlc_hw->di[RX_FIFO]); - dma_rxfill(wlc_hw->di[RX_FIFO]); -} - -void -brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec, - bool mute) { - u32 macintmask; - bool fastclk; - struct brcms_c_info *wlc = wlc_hw->wlc; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - /* request FAST clock if not on */ - fastclk = wlc_hw->forcefastclk; - if (!fastclk) - brcms_b_clkctl_clk(wlc_hw, CLK_FAST); - - /* disable interrupts */ - macintmask = brcms_intrsoff(wlc->wl); - - /* set up the specified band and chanspec */ - brcms_c_setxband(wlc_hw, CHSPEC_BANDUNIT(chanspec)); - wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); - - /* do one-time phy inits and calibration */ - wlc_phy_cal_init(wlc_hw->band->pi); - - /* core-specific initialization */ - brcms_b_coreinit(wlc); - - /* suspend the tx fifos and mute the phy for preism cac time */ - if (mute) - brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM); - - /* band-specific inits */ - brcms_b_bsinit(wlc, chanspec); - - /* restore macintmask */ - brcms_intrsrestore(wlc->wl, macintmask); - - /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac - * is suspended and brcms_c_enable_mac() will clear this override bit. - */ - mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND); - - /* - * initialize mac_suspend_depth to 1 to match ucode - * initial suspended state - */ - wlc_hw->mac_suspend_depth = 1; - - /* restore the clk */ - if (!fastclk) - brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); +{ + int i; + scb->flags = SCB_WMECAP | SCB_HTCAP; + for (i = 0; i < NUMPRIO; i++) + scb->seqnum[i] = 0; } void brcms_c_init(struct brcms_c_info *wlc) { - struct d11regs *regs; - u16 chanspec; + d11regs_t *regs; + chanspec_t chanspec; int i; struct brcms_bss_cfg *bsscfg; bool mute = false; @@ -3331,10 +457,8 @@ void brcms_c_init(struct brcms_c_info *wlc) regs = wlc->regs; - /* - * This will happen if a big-hammer was executed. In - * that case, we want to go back to the channel that - * we were on and not new channel + /* This will happen if a big-hammer was executed. In that case, we want to go back + * to the channel that we were on and not new channel */ if (wlc->pub->associated) chanspec = wlc->home_chanspec; @@ -3350,14 +474,14 @@ void brcms_c_init(struct brcms_c_info *wlc) brcms_c_reprate_init(wlc); /* write ethernet address to core */ - FOREACH_BSS(wlc, i, bsscfg) + FOREACH_BSS(wlc, i, bsscfg) { brcms_c_set_mac(bsscfg); brcms_c_set_bssid(bsscfg); - END_FOREACH_BSS() + } /* Update tsf_cfprep if associated and up */ if (wlc->pub->associated) { - FOREACH_BSS(wlc, i, bsscfg) + FOREACH_BSS(wlc, i, bsscfg) { if (bsscfg->up) { u32 bi; @@ -3375,7 +499,7 @@ void brcms_c_init(struct brcms_c_info *wlc) break; } - END_FOREACH_BSS() + } } brcms_c_bandinit_ordered(wlc, chanspec); @@ -3394,10 +518,7 @@ void brcms_c_init(struct brcms_c_info *wlc) brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true); brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true); - /* - * Update some shared memory locations related to - * max AMPDU size allowed to received - */ + /* Update some shared memory locations related to max AMPDU size allowed to received */ brcms_c_ampdu_shm_upd(wlc->ampdu); /* band-specific inits */ @@ -3442,9 +563,10 @@ void brcms_c_init(struct brcms_c_info *wlc) /* Uninitialized; read from HW */ int ac; - for (ac = 0; ac < AC_COUNT; ac++) + for (ac = 0; ac < AC_COUNT; ac++) { wlc->wme_retries[ac] = brcms_c_read_shm(wlc, M_AC_TXLMT_ADDR(ac)); + } } } @@ -3468,11 +590,9 @@ void brcms_c_mac_promisc(struct brcms_c_info *wlc) { u32 promisc_bits = 0; - /* - * promiscuous mode just sets MCTL_PROMISC - * Note: APs get all BSS traffic without the need to set - * the MCTL_PROMISC bit since all BSS data traffic is - * directed at the AP + /* promiscuous mode just sets MCTL_PROMISC + * Note: APs get all BSS traffic without the need to set the MCTL_PROMISC bit + * since all BSS data traffic is directed at the AP */ if (PROMISC_ENAB(wlc->pub) && !AP_ENAB(wlc->pub)) promisc_bits |= MCTL_PROMISC; @@ -3521,9 +641,10 @@ int brcms_c_set_mac(struct brcms_bss_cfg *cfg) int err = 0; struct brcms_c_info *wlc = cfg->wlc; - if (cfg == wlc->cfg) + if (cfg == wlc->cfg) { /* enter the MAC addr into the RXE match registers */ brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, cfg->cur_etheraddr); + } brcms_c_ampdu_macaddr_upd(wlc); @@ -3538,24 +659,14 @@ void brcms_c_set_bssid(struct brcms_bss_cfg *cfg) struct brcms_c_info *wlc = cfg->wlc; /* if primary config, we need to update BSSID in RXE match registers */ - if (cfg == wlc->cfg) + if (cfg == wlc->cfg) { brcms_c_set_addrmatch(wlc, RCM_BSSID_OFFSET, cfg->BSSID); + } #ifdef SUPPORT_HWKEYS - else if (BSSCFG_STA(cfg) && cfg->BSS) + else if (BSSCFG_STA(cfg) && cfg->BSS) { brcms_c_rcmta_add_bssid(wlc, cfg); - -#endif -} - -void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) -{ - wlc_hw->shortslot = shortslot; - - if (BAND_2G(brcms_b_bandtype(wlc_hw)) && wlc_hw->up) { - brcms_c_suspend_mac_and_wait(wlc_hw->wlc); - brcms_b_update_slot_timing(wlc_hw, shortslot); - brcms_c_enable_mac(wlc_hw->wlc); } +#endif } /* @@ -3577,7 +688,7 @@ void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot) wlc->shortslot = shortslot; /* update the capability based on current shortslot mode */ - FOREACH_BSS(wlc, idx, cfg) + FOREACH_BSS(wlc, idx, cfg) { if (!cfg->associated) continue; cfg->current_bss->capability &= @@ -3585,7 +696,7 @@ void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot) if (wlc->shortslot) cfg->current_bss->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - END_FOREACH_BSS() + } brcms_b_set_shortslot(wlc->hw, shortslot); } @@ -3617,11 +728,8 @@ static u8 brcms_c_local_constraint_qdbm(struct brcms_c_info *wlc) return local; } -/* - * propagate home chanspec to all bsscfgs in - * case bsscfg->current_bss->chanspec is referenced - */ -void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec) +/* propagate home chanspec to all bsscfgs in case bsscfg->current_bss->chanspec is referenced */ +void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec) { if (wlc->home_chanspec != chanspec) { int idx; @@ -3629,19 +737,18 @@ void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec) wlc->home_chanspec = chanspec; - FOREACH_BSS(wlc, idx, cfg) + FOREACH_BSS(wlc, idx, cfg) { if (!cfg->associated) continue; cfg->current_bss->chanspec = chanspec; - END_FOREACH_BSS() - + } } } static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc, - u16 chanspec) + chanspec_t chanspec) { /* Save our copy of the chanspec */ wlc->chanspec = chanspec; @@ -3660,55 +767,11 @@ static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc, } -void -brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec, - bool mute, struct txpwr_limits *txpwr) -{ - uint bandunit; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec); - - wlc_hw->chanspec = chanspec; - - /* Switch bands if necessary */ - if (NBANDS_HW(wlc_hw) > 1) { - bandunit = CHSPEC_BANDUNIT(chanspec); - if (wlc_hw->band->bandunit != bandunit) { - /* brcms_b_setband disables other bandunit, - * use light band switch if not up yet - */ - if (wlc_hw->up) { - wlc_phy_chanspec_radio_set(wlc_hw-> - bandstate[bandunit]-> - pi, chanspec); - brcms_b_setband(wlc_hw, bandunit, chanspec); - } else { - brcms_c_setxband(wlc_hw, bandunit); - } - } - } - - wlc_phy_initcal_enable(wlc_hw->band->pi, !mute); - - if (!wlc_hw->up) { - if (wlc_hw->clk) - wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, - chanspec); - wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); - } else { - wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec); - wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec); - - /* Update muting of the channel */ - brcms_b_mute(wlc_hw, mute, 0); - } -} - -void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec) +void brcms_c_set_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec) { uint bandunit; bool switchband = false; - u16 old_chanspec = wlc->chanspec; + chanspec_t old_chanspec = wlc->chanspec; if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) { wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n", @@ -3760,10 +823,10 @@ void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec) brcms_c_ucode_mac_upd(wlc); } -u32 brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc, - struct brcms_c_rateset *rs) +ratespec_t brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc, + wlc_rateset_t *rs) { - u32 lowest_basic_rspec; + ratespec_t lowest_basic_rspec; uint i; /* Use the lowest basic rate */ @@ -3775,26 +838,22 @@ u32 brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc, } } #if NCONF - /* - * pick siso/cdd as default for OFDM (note no basic - * rate MCSs are supported yet) - */ - if (IS_OFDM(lowest_basic_rspec)) + /* pick siso/cdd as default for OFDM (note no basic rate MCSs are supported yet) */ + if (IS_OFDM(lowest_basic_rspec)) { lowest_basic_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT); - + } #endif return lowest_basic_rspec; } -/* - * This function changes the phytxctl for beacon based on current - * beacon ratespec AND txant setting as per this table: +/* This function changes the phytxctl for beacon based on current beacon ratespec AND txant + * setting as per this table: * ratespec CCK ant = wlc->stf->txant * OFDM ant = 3 */ void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, - u32 bcn_rspec) + ratespec_t bcn_rspec) { u16 phyctl; u16 phytxant = wlc->stf->phytxant; @@ -3809,11 +868,9 @@ void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, brcms_c_write_shm(wlc, M_BCN_PCTLWD, phyctl); } -/* - * centralized protection config change function to simplify debugging, no - * consistency checking this should be called only on changes to avoid overhead - * in periodic function - */ +/* centralized protection config change function to simplify debugging, no consistency checking + * this should be called only on changes to avoid overhead in periodic function +*/ void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val) { BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val); @@ -3900,18 +957,16 @@ static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc) */ if (wlc->home_chanspec == BRCMS_BAND_PI_RADIO_CHANSPEC) { if (wlc->pub->associated) { - /* - * BMAC_NOTE: This is something that should be fixed - * in ucode inits. I think that the ucode inits set - * up the bcn templates and shm values with a bogus - * beacon. This should not be done in the inits. If - * ucode needs to set up a beacon for testing, the - * test routines should write it down, not expect the - * inits to populate a bogus beacon. + /* BMAC_NOTE: This is something that should be fixed in ucode inits. + * I think that the ucode inits set up the bcn templates and shm values + * with a bogus beacon. This should not be done in the inits. If ucode needs + * to set up a beacon for testing, the test routines should write it down, + * not expect the inits to populate a bogus beacon. */ - if (BRCMS_PHY_11N_CAP(wlc->band)) + if (BRCMS_PHY_11N_CAP(wlc->band)) { brcms_c_write_shm(wlc, M_BCN_TXTSF_OFFSET, wlc->band->bcntsfoff); + } } } else { /* disable an active IBSS if we are not on the home channel */ @@ -3923,16 +978,16 @@ static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc) } static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc, - u16 chanspec) + chanspec_t chanspec) { - struct brcms_c_rateset default_rateset; + wlc_rateset_t default_rateset; uint parkband; uint i, band_order[2]; BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); /* - * We might have been bandlocked during down and the chip - * power-cycled (hibernate). Figure out the right band to park on + * We might have been bandlocked during down and the chip power-cycled (hibernate). + * figure out the right band to park on */ if (wlc->bandlocked || NBANDS(wlc) == 1) { /* updated in brcms_c_bandlock() */ @@ -4009,10 +1064,7 @@ static void brcms_c_setband(struct brcms_c_info *wlc, brcms_c_bsinit(wlc); } -/* - * Initialize a WME Parameter Info Element with default - * STA parameters from WMM Spec, Table 12 - */ +/* Initialize a WME Parameter Info Element with default STA parameters from WMM Spec, Table 12 */ void brcms_c_wme_initparams_sta(struct brcms_c_info *wlc, struct wme_param_ie *pe) { @@ -4238,8 +1290,7 @@ void brcms_c_info_init(struct brcms_c_info *wlc, int unit) wlc->pub->_wme = AUTO; #ifdef BCMSDIODEV_ENABLED - /* enable priority flow control for sdio dongle */ - wlc->pub->_priofc = true; + wlc->pub->_priofc = true; /* enable priority flow control for sdio dongle */ #endif wlc->pub->_ampdu = AMPDU_AGG_HOST; @@ -4252,7 +1303,7 @@ void brcms_c_info_init(struct brcms_c_info *wlc, int unit) static bool brcms_c_state_bmac_sync(struct brcms_c_info *wlc) { - struct brcms_b_state state_bmac = {0}; + struct brcms_b_state state_bmac; if (brcms_b_state_get(wlc->hw, &state_bmac) != 0) return false; @@ -4296,366 +1347,19 @@ static uint brcms_c_attach_module(struct brcms_c_info *wlc) return err; } -struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc) +struct brcms_pub *brcms_c_pub(void *wlc) { - return wlc->pub; + return ((struct brcms_c_info *) wlc)->pub; } #define CHIP_SUPPORTS_11N(wlc) 1 -/* low level attach - * run backplane attach, init nvram - * run phy attach - * initialize software state for each core and band - * put the whole chip in reset(driver down state), no clock - */ -int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, uint unit, - bool piomode, void *regsva, struct pci_dev *btparam) -{ - struct brcms_hardware *wlc_hw; - struct d11regs *regs; - char *macaddr = NULL; - char *vars; - uint err = 0; - uint j; - bool wme = false; - struct shared_phy_params sha_params; - struct wiphy *wiphy = wlc->wiphy; - char *var; - unsigned long res; - - BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor, - device); - - wme = true; - - wlc_hw = wlc->hw; - wlc_hw->wlc = wlc; - wlc_hw->unit = unit; - wlc_hw->band = wlc_hw->bandstate[0]; - wlc_hw->_piomode = piomode; - - /* populate struct brcms_hardware with default values */ - brcms_b_info_init(wlc_hw); - - /* - * Do the hardware portion of the attach. Also initialize software - * state that depends on the particular hardware we are running. - */ - wlc_hw->sih = ai_attach(regsva, btparam, - &wlc_hw->vars, &wlc_hw->vars_size); - if (wlc_hw->sih == NULL) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n", - unit); - err = 11; - goto fail; - } - vars = wlc_hw->vars; - - /* - * Get vendid/devid nvram overwrites, which could be different - * than those the BIOS recognizes for devices on PCMCIA_BUS, - * SDIO_BUS, and SROMless devices on PCI_BUS. - */ - var = getvar(vars, "vendid"); - if (var && !kstrtoul(var, 0, &res)) { - vendor = (u16)res; - wiphy_err(wiphy, "Overriding vendor id = 0x%x\n", - vendor); - } - var = getvar(vars, "devid"); - if (var && !kstrtoul(var, 0, &res)) { - u16 devid = (u16)res; - if (devid != 0xffff) { - device = devid; - wiphy_err(wiphy, "Overriding device id = 0x%x" - "\n", device); - } - } - - /* verify again the device is supported */ - if (!brcms_c_chipmatch(vendor, device)) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " - "vendor/device (0x%x/0x%x)\n", - unit, vendor, device); - err = 12; - goto fail; - } - - wlc_hw->vendorid = vendor; - wlc_hw->deviceid = device; - - /* set bar0 window to point at D11 core */ - wlc_hw->regs = (struct d11regs *) ai_setcore(wlc_hw->sih, D11_CORE_ID, - 0); - wlc_hw->corerev = ai_corerev(wlc_hw->sih); - - regs = wlc_hw->regs; - - wlc->regs = wlc_hw->regs; - - /* validate chip, chiprev and corerev */ - if (!brcms_c_isgoodchip(wlc_hw)) { - err = 13; - goto fail; - } - - /* initialize power control registers */ - ai_clkctl_init(wlc_hw->sih); - - /* request fastclock and force fastclock for the rest of attach - * bring the d11 core out of reset. - * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk - * is still false; But it will be called again inside wlc_corereset, - * after d11 is out of reset. - */ - brcms_b_clkctl_clk(wlc_hw, CLK_FAST); - brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); - - if (!brcms_b_validate_chip_access(wlc_hw)) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access " - "failed\n", unit); - err = 14; - goto fail; - } - - /* get the board rev, used just below */ - j = getintvar(vars, "boardrev"); - /* promote srom boardrev of 0xFF to 1 */ - if (j == BOARDREV_PROMOTABLE) - j = BOARDREV_PROMOTED; - wlc_hw->boardrev = (u16) j; - if (!brcms_c_validboardtype(wlc_hw)) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom " - "board type (0x%x)" " or revision level (0x%x)\n", - unit, wlc_hw->sih->boardtype, wlc_hw->boardrev); - err = 15; - goto fail; - } - wlc_hw->sromrev = (u8) getintvar(vars, "sromrev"); - wlc_hw->boardflags = (u32) getintvar(vars, "boardflags"); - wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2"); - - if (wlc_hw->boardflags & BFL_NOPLLDOWN) - brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED); - - if (ai_pci_war16165(wlc_hw->sih)) - wlc->war16165 = true; - - /* check device id(srom, nvram etc.) to set bands */ - if (wlc_hw->deviceid == BCM43224_D11N_ID || - wlc_hw->deviceid == BCM43224_D11N_ID_VEN1) - /* Dualband boards */ - wlc_hw->_nbands = 2; - else - wlc_hw->_nbands = 1; - - if ((wlc_hw->sih->chip == BCM43225_CHIP_ID)) - wlc_hw->_nbands = 1; - - /* BMAC_NOTE: remove init of pub values when brcms_c_attach() - * unconditionally does the init of these values - */ - wlc->vendorid = wlc_hw->vendorid; - wlc->deviceid = wlc_hw->deviceid; - wlc->pub->sih = wlc_hw->sih; - wlc->pub->corerev = wlc_hw->corerev; - wlc->pub->sromrev = wlc_hw->sromrev; - wlc->pub->boardrev = wlc_hw->boardrev; - wlc->pub->boardflags = wlc_hw->boardflags; - wlc->pub->boardflags2 = wlc_hw->boardflags2; - wlc->pub->_nbands = wlc_hw->_nbands; - - wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc); - - if (wlc_hw->physhim == NULL) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach " - "failed\n", unit); - err = 25; - goto fail; - } - - /* pass all the parameters to wlc_phy_shared_attach in one struct */ - sha_params.sih = wlc_hw->sih; - sha_params.physhim = wlc_hw->physhim; - sha_params.unit = unit; - sha_params.corerev = wlc_hw->corerev; - sha_params.vars = vars; - sha_params.vid = wlc_hw->vendorid; - sha_params.did = wlc_hw->deviceid; - sha_params.chip = wlc_hw->sih->chip; - sha_params.chiprev = wlc_hw->sih->chiprev; - sha_params.chippkg = wlc_hw->sih->chippkg; - sha_params.sromrev = wlc_hw->sromrev; - sha_params.boardtype = wlc_hw->sih->boardtype; - sha_params.boardrev = wlc_hw->boardrev; - sha_params.boardvendor = wlc_hw->sih->boardvendor; - sha_params.boardflags = wlc_hw->boardflags; - sha_params.boardflags2 = wlc_hw->boardflags2; - sha_params.buscorerev = wlc_hw->sih->buscorerev; - - /* alloc and save pointer to shared phy state area */ - wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params); - if (!wlc_hw->phy_sh) { - err = 16; - goto fail; - } - - /* initialize software state for each core and band */ - for (j = 0; j < NBANDS_HW(wlc_hw); j++) { - /* - * band0 is always 2.4Ghz - * band1, if present, is 5Ghz - */ - - /* So if this is a single band 11a card, use band 1 */ - if (IS_SINGLEBAND_5G(wlc_hw->deviceid)) - j = BAND_5G_INDEX; - - brcms_c_setxband(wlc_hw, j); - - wlc_hw->band->bandunit = j; - wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; - wlc->band->bandunit = j; - wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; - wlc->core->coreidx = ai_coreidx(wlc_hw->sih); - - wlc_hw->machwcap = R_REG(®s->machwcap); - wlc_hw->machwcap_backup = wlc_hw->machwcap; - - /* init tx fifo size */ - wlc_hw->xmtfifo_sz = - xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)]; - - /* Get a phy for this band */ - wlc_hw->band->pi = - wlc_phy_attach(wlc_hw->phy_sh, regs, - brcms_b_bandtype(wlc_hw), vars, - wlc->wiphy); - if (wlc_hw->band->pi == NULL) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_" - "attach failed\n", unit); - err = 17; - goto fail; - } - - wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap); - - wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype, - &wlc_hw->band->phyrev, - &wlc_hw->band->radioid, - &wlc_hw->band->radiorev); - wlc_hw->band->abgphy_encore = - wlc_phy_get_encore(wlc_hw->band->pi); - wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi); - wlc_hw->band->core_flags = - wlc_phy_get_coreflags(wlc_hw->band->pi); - - /* verify good phy_type & supported phy revision */ - if (BRCMS_ISNPHY(wlc_hw->band)) { - if (NCONF_HAS(wlc_hw->band->phyrev)) - goto good_phy; - else - goto bad_phy; - } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { - if (LCNCONF_HAS(wlc_hw->band->phyrev)) - goto good_phy; - else - goto bad_phy; - } else { - bad_phy: - wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported " - "phy type/rev (%d/%d)\n", unit, - wlc_hw->band->phytype, wlc_hw->band->phyrev); - err = 18; - goto fail; - } - - good_phy: - /* - * BMAC_NOTE: wlc->band->pi should not be set below and should - * be done in the high level attach. However we can not make - * that change until all low level access is changed to - * wlc_hw->band->pi. Instead do the wlc->band->pi init below, - * keeping wlc_hw->band->pi as well for incremental update of - * low level fns, and cut over low only init when all fns - * updated. - */ - wlc->band->pi = wlc_hw->band->pi; - wlc->band->phytype = wlc_hw->band->phytype; - wlc->band->phyrev = wlc_hw->band->phyrev; - wlc->band->radioid = wlc_hw->band->radioid; - wlc->band->radiorev = wlc_hw->band->radiorev; - - /* default contention windows size limits */ - wlc_hw->band->CWmin = APHY_CWMIN; - wlc_hw->band->CWmax = PHY_CWMAX; - - if (!brcms_b_attach_dmapio(wlc, j, wme)) { - err = 19; - goto fail; - } - } - - /* disable core to match driver "down" state */ - brcms_c_coredisable(wlc_hw); - - /* Match driver "down" state */ - ai_pci_down(wlc_hw->sih); - - /* register sb interrupt callback functions */ - ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff, - (void *)brcms_c_wlintrsrestore, NULL, wlc); - - /* turn off pll and xtal to match driver "down" state */ - brcms_b_xtal(wlc_hw, OFF); - - /* ******************************************************************* - * The hardware is in the DOWN state at this point. D11 core - * or cores are in reset with clocks off, and the board PLLs - * are off if possible. - * - * Beyond this point, wlc->sbclk == false and chip registers - * should not be touched. - ********************************************************************* - */ - - /* init etheraddr state variables */ - macaddr = brcms_c_get_macaddr(wlc_hw); - if (macaddr == NULL) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n", - unit); - err = 21; - goto fail; - } - if (!mac_pton(macaddr, wlc_hw->etheraddr) || - is_broadcast_ether_addr(wlc_hw->etheraddr) || - is_zero_ether_addr(wlc_hw->etheraddr)) { - wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n", - unit, macaddr); - err = 22; - goto fail; - } - - BCMMSG(wlc->wiphy, - "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n", - wlc_hw->deviceid, wlc_hw->_nbands, - wlc_hw->sih->boardtype, macaddr); - - return err; - - fail: - wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit, - err); - return err; -} - /* * The common driver entry routine. Error codes should be unique */ -struct brcms_c_info * -brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, - bool piomode, void *regsva, struct pci_dev *btparam, uint *perr) +void *brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, + bool piomode, void *regsva, uint bustype, void *btparam, + uint *perr) { struct brcms_c_info *wlc; uint err = 0; @@ -4695,14 +1399,12 @@ brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, * inside, no more in rest of the attach) */ err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva, - btparam); + bustype, btparam); if (err) goto fail; - /* - * for some states, due to different info pointer(e,g, wlc, wlc_hw) or - * master/slave split, HIGH driver(both monolithic and HIGH_ONLY) needs - * to sync states FROM BMAC portion driver + /* for some states, due to different info pointer(e,g, wlc, wlc_hw) or master/slave split, + * HIGH driver(both monolithic and HIGH_ONLY) needs to sync states FROM BMAC portion driver */ if (!brcms_c_state_bmac_sync(wlc)) { err = 20; @@ -4790,10 +1492,7 @@ brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, (bool) N_ENAB(wlc->pub)); } - /* - * update antenna config due to - * wlc->stf->txant/txchain/ant_rx_ovr change - */ + /* update antenna config due to wlc->stf->txant/txchain/ant_rx_ovr change */ brcms_c_stf_phy_txant_upd(wlc); /* attach each modules */ @@ -4893,7 +1592,7 @@ brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, if (perr) *perr = 0; - return wlc; + return (void *)wlc; fail: wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n", @@ -4921,17 +1620,14 @@ static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc) } else { s8 gain, fract; /* Older sroms specified gain in whole dbm only. In order - * be able to specify qdbm granularity and remain backward - * compatible the whole dbms are now encoded in only - * low 6 bits and remaining qdbms are encoded in the hi 2 bits. - * 6 bit signed number ranges from -32 - 31. - * - * Examples: - * 0x1 = 1 db, + * be able to specify qdbm granularity and remain backward compatible + * the whole dbms are now encoded in only low 6 bits and remaining qdbms + * are encoded in the hi 2 bits. 6 bit signed number ranges from + * -32 - 31. Examples: 0x1 = 1 db, * 0xc1 = 1.75 db (1 + 3 quarters), * 0x3f = -1 (-1 + 0 quarters), - * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm. - * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm. + * 0x7f = -.75 (-1 in low 6 bits + 1 quarters in hi 2 bits) = -3 qdbm. + * 0xbf = -.50 (-1 in low 6 bits + 2 quarters in hi 2 bits) = -2 qdbm. */ gain = wlc->band->antgain & 0x3f; gain <<= 2; /* Sign extend */ @@ -5010,58 +1706,6 @@ static void brcms_c_detach_module(struct brcms_c_info *wlc) brcms_c_stf_detach(wlc); } -/* - * low level detach - */ -int brcms_b_detach(struct brcms_c_info *wlc) -{ - uint i; - struct brcms_hw_band *band; - struct brcms_hardware *wlc_hw = wlc->hw; - int callbacks; - - callbacks = 0; - - if (wlc_hw->sih) { - /* - * detach interrupt sync mechanism since interrupt is disabled - * and per-port interrupt object may has been freed. this must - * be done before sb core switch - */ - ai_deregister_intr_callback(wlc_hw->sih); - ai_pci_sleep(wlc_hw->sih); - } - - brcms_b_detach_dmapio(wlc_hw); - - band = wlc_hw->band; - for (i = 0; i < NBANDS_HW(wlc_hw); i++) { - if (band->pi) { - /* Detach this band's phy */ - wlc_phy_detach(band->pi); - band->pi = NULL; - } - band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)]; - } - - /* Free shared phy state */ - kfree(wlc_hw->phy_sh); - - wlc_phy_shim_detach(wlc_hw->physhim); - - /* free vars */ - kfree(wlc_hw->vars); - wlc_hw->vars = NULL; - - if (wlc_hw->sih) { - ai_detach(wlc_hw->sih); - wlc_hw->sih = NULL; - } - - return callbacks; - -} - /* * Return a count of the number of driver callbacks still pending. * @@ -5121,16 +1765,14 @@ static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc) if (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO || wlc->pub->hw_off) return; - if (brcms_b_radio_read_hwdisabled(wlc->hw)) + if (brcms_b_radio_read_hwdisabled(wlc->hw)) { mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE); - else + } else { mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE); + } } -/* - * return true if Minimum Power Consumption should - * be entered, false otherwise - */ +/* return true if Minimum Power Consumption should be entered, false otherwise */ bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc) { return false; @@ -5162,10 +1804,9 @@ void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc) } /* - * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in - * wlc->pub->radio_disabled to go ON, always call radio_upd - * synchronously to go OFF, postpone radio_upd to later when - * context is safe(e.g. watchdog) + * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in wlc->pub->radio_disabled + * to go ON, always call radio_upd synchronously + * to go OFF, postpone radio_upd to later when context is safe(e.g. watchdog) */ radio_state = (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF : @@ -5183,16 +1824,14 @@ void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc) wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; wlc->mpc_dur += OSL_SYSUPTIME() - wlc->mpc_laston_ts; } - /* - * Below logic is meant to capture the transition from mpc off - * to mpc on for reasons other than wlc->mpc_delay_off keeping - * the mpc off. In that case reset wlc->mpc_delay_off to - * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off + /* Below logic is meant to capture the transition from mpc off to mpc on for reasons + * other than wlc->mpc_delay_off keeping the mpc off. In that case reset + * wlc->mpc_delay_off to wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off */ if ((wlc->prev_non_delay_mpc == false) && - (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) + (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) { wlc->mpc_delay_off = wlc->mpc_dlycnt; - + } wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc); } @@ -5202,19 +1841,18 @@ void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc) */ static void brcms_c_radio_upd(struct brcms_c_info *wlc) { - if (wlc->pub->radio_disabled) + if (wlc->pub->radio_disabled) { brcms_c_radio_disable(wlc); - else + } else { brcms_c_radio_enable(wlc); + } } /* maintain LED behavior in down state */ static void brcms_c_down_led_upd(struct brcms_c_info *wlc) { - /* - * maintain LEDs while in down state, turn on sbclk if - * not available yet. Turn on sbclk if necessary - */ + /* maintain LEDs while in down state, turn on sbclk if not available yet */ + /* turn on sbclk if necessary */ if (!AP_ENAB(wlc->pub)) { brcms_c_pllreq(wlc, true, BRCMS_PLLREQ_FLIP); @@ -5227,8 +1865,7 @@ bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc) { brcms_c_radio_hwdisable_upd(wlc); - return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? - true : false; + return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? true : false; } void brcms_c_radio_disable(struct brcms_c_info *wlc) @@ -5296,29 +1933,6 @@ bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc) return brcms_del_timer(wlc->wl, wlc->radio_timer); } -/* common low-level watchdog code */ -void brcms_b_watchdog(void *arg) -{ - struct brcms_c_info *wlc = (struct brcms_c_info *) arg; - struct brcms_hardware *wlc_hw = wlc->hw; - - BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); - - if (!wlc_hw->up) - return; - - /* increment second count */ - wlc_hw->now++; - - /* Check for FIFO error interrupts */ - brcms_b_fifoerrors(wlc_hw); - - /* make sure RX dma has buffers */ - dma_rxfill(wlc->hw->di[RX_FIFO]); - - wlc_phy_watchdog(wlc_hw->band->pi); -} - static void brcms_c_watchdog_by_timer(void *arg) { brcms_c_watchdog(arg); @@ -5368,127 +1982,32 @@ static void brcms_c_watchdog(void *arg) brcms_b_watchdog(wlc); - /* - * occasionally sample mac stat counters to - * detect 16-bit counter wrap - */ - if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0) - brcms_c_statsupd(wlc); - - /* Manage TKIP countermeasures timers */ - FOREACH_BSS(wlc, i, cfg) - if (cfg->tk_cm_dt) - cfg->tk_cm_dt--; - if (cfg->tk_cm_bt) - cfg->tk_cm_bt--; - END_FOREACH_BSS() - - if (BRCMS_ISNPHY(wlc->band) && !wlc->pub->tempsense_disable && - ((wlc->pub->now - wlc->tempsense_lasttime) >= - BRCMS_TEMPSENSE_PERIOD)) { - wlc->tempsense_lasttime = wlc->pub->now; - brcms_c_tempsense_upd(wlc); - } -} - -/* Initialize just the hardware when coming out of POR or S3/S5 system states */ -void brcms_b_hw_up(struct brcms_hardware *wlc_hw) -{ - if (wlc_hw->wlc->pub->hw_up) - return; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - /* - * Enable pll and xtal, initialize the power control registers, - * and force fastclock for the remainder of brcms_c_up(). - */ - brcms_b_xtal(wlc_hw, ON); - ai_clkctl_init(wlc_hw->sih); - brcms_b_clkctl_clk(wlc_hw, CLK_FAST); - - ai_pci_fixcfg(wlc_hw->sih); - - /* - * AI chip doesn't restore bar0win2 on - * hibernation/resume, need sw fixup - */ - if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || - (wlc_hw->sih->chip == BCM43225_CHIP_ID)) - wlc_hw->regs = (struct d11regs *) - ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); - - /* - * Inform phy that a POR reset has occurred so - * it does a complete phy init - */ - wlc_phy_por_inform(wlc_hw->band->pi); - - wlc_hw->ucode_loaded = false; - wlc_hw->wlc->pub->hw_up = true; - - if ((wlc_hw->boardflags & BFL_FEM) - && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) { - if (! - (wlc_hw->boardrev >= 0x1250 - && (wlc_hw->boardflags & BFL_FEM_BT))) - ai_epa_4313war(wlc_hw->sih); - } -} - -int brcms_b_up_prep(struct brcms_hardware *wlc_hw) -{ - uint coremask; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - /* - * Enable pll and xtal, initialize the power control registers, - * and force fastclock for the remainder of brcms_c_up(). - */ - brcms_b_xtal(wlc_hw, ON); - ai_clkctl_init(wlc_hw->sih); - brcms_b_clkctl_clk(wlc_hw, CLK_FAST); - - /* - * Configure pci/pcmcia here instead of in brcms_c_attach() - * to allow mfg hotswap: down, hotswap (chip power cycle), up. - */ - coremask = (1 << wlc_hw->wlc->core->coreidx); - - ai_pci_setup(wlc_hw->sih, coremask); - - /* - * Need to read the hwradio status here to cover the case where the - * system is loaded with the hw radio disabled. We do not want to - * bring the driver up in this case. - */ - if (brcms_b_radio_read_hwdisabled(wlc_hw)) { - /* put SB PCI in down state again */ - ai_pci_down(wlc_hw->sih); - brcms_b_xtal(wlc_hw, OFF); - return -ENOMEDIUM; - } - - ai_pci_up(wlc_hw->sih); - - /* reset the d11 core */ - brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); - - return 0; -} + /* occasionally sample mac stat counters to detect 16-bit counter wrap */ + if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0) + brcms_c_statsupd(wlc); -int brcms_b_up_finish(struct brcms_hardware *wlc_hw) -{ - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + /* Manage TKIP countermeasures timers */ + FOREACH_BSS(wlc, i, cfg) { + if (cfg->tk_cm_dt) { + cfg->tk_cm_dt--; + } + if (cfg->tk_cm_bt) { + cfg->tk_cm_bt--; + } + } - wlc_hw->up = true; - wlc_phy_hw_state_upd(wlc_hw->band->pi, true); + /* Call any registered watchdog handlers */ + for (i = 0; i < BRCMS_MAXMODULES; i++) { + if (wlc->modulecb[i].watchdog_fn) + wlc->modulecb[i].watchdog_fn(wlc->modulecb[i].hdl); + } - /* FULLY enable dynamic power control and d11 core interrupt */ - brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); - brcms_intrson(wlc_hw->wlc->wl); - return 0; + if (BRCMS_ISNPHY(wlc->band) && !wlc->pub->tempsense_disable && + ((wlc->pub->now - wlc->tempsense_lasttime) >= + BRCMS_TEMPSENSE_PERIOD)) { + wlc->tempsense_lasttime = wlc->pub->now; + brcms_c_tempsense_upd(wlc); + } } /* make interface operational */ @@ -5508,20 +2027,20 @@ int brcms_c_up(struct brcms_c_info *wlc) if ((wlc->pub->boardflags & BFL_FEM) && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) { if (wlc->pub->boardrev >= 0x1250 - && (wlc->pub->boardflags & BFL_FEM_BT)) + && (wlc->pub->boardflags & BFL_FEM_BT)) { brcms_c_mhf(wlc, MHF5, MHF5_4313_GPIOCTRL, MHF5_4313_GPIOCTRL, BRCM_BAND_ALL); - else + } else { brcms_c_mhf(wlc, MHF4, MHF4_EXTPA_ENABLE, MHF4_EXTPA_ENABLE, BRCM_BAND_ALL); + } } /* - * Need to read the hwradio status here to cover the case where the - * system is loaded with the hw radio disabled. We do not want to bring - * the driver up in this case. If radio is disabled, abort up, lower - * power, start radio timer and return 0(for NDIS) don't call - * radio_update to avoid looping brcms_c_up. + * Need to read the hwradio status here to cover the case where the system + * is loaded with the hw radio disabled. We do not want to bring the driver up in this case. + * if radio is disabled, abort up, lower power, start radio timer and return 0(for NDIS) + * don't call radio_update to avoid looping brcms_c_up. * * brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only */ @@ -5535,7 +2054,7 @@ int brcms_c_up(struct brcms_c_info *wlc) mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE); - FOREACH_BSS(wlc, idx, bsscfg) + FOREACH_BSS(wlc, idx, bsscfg) { if (!BSSCFG_STA(bsscfg) || !bsscfg->enable || !bsscfg->BSS) continue; @@ -5543,7 +2062,7 @@ int brcms_c_up(struct brcms_c_info *wlc) ": rfdisable -> " "bsscfg_disable()\n", wlc->pub->unit, idx); - END_FOREACH_BSS() + } } } } @@ -5559,10 +2078,11 @@ int brcms_c_up(struct brcms_c_info *wlc) brcms_c_radio_monitor_stop(wlc); /* Set EDCF hostflags */ - if (EDCF_ENAB(wlc->pub)) + if (EDCF_ENAB(wlc->pub)) { brcms_c_mhf(wlc, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL); - else + } else { brcms_c_mhf(wlc, MHF1, MHF1_EDCF, 0, BRCM_BAND_ALL); + } if (BRCMS_WAR16165(wlc)) brcms_c_mhf(wlc, MHF2, MHF2_PCISLOWCLKWAR, MHF2_PCISLOWCLKWAR, @@ -5599,18 +2119,14 @@ int brcms_c_up(struct brcms_c_info *wlc) return 0; } -/* - * Initialize the base precedence map for dequeueing - * from txq based on WME settings - */ +/* Initialize the base precedence map for dequeueing from txq based on WME settings */ static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc) { wlc->tx_prec_map = BRCMS_PREC_BMP_ALL; memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16)); - /* - * For non-WME, both fifos have overlapping MAXPRIO. So just - * disable all precedences if either is full. + /* For non-WME, both fifos have overlapping MAXPRIO. So just disable all precedences + * if either is full. */ if (!EDCF_ENAB(wlc->pub)) { wlc->fifo2prec_map[TX_DATA_FIFO] = BRCMS_PREC_BMP_ALL; @@ -5630,77 +2146,6 @@ static uint brcms_c_down_del_timer(struct brcms_c_info *wlc) return callbacks; } -int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw) -{ - bool dev_gone; - uint callbacks = 0; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - if (!wlc_hw->up) - return callbacks; - - dev_gone = DEVICEREMOVED(wlc_hw->wlc); - - /* disable interrupts */ - if (dev_gone) - wlc_hw->wlc->macintmask = 0; - else { - /* now disable interrupts */ - brcms_intrsoff(wlc_hw->wlc->wl); - - /* ensure we're running on the pll clock again */ - brcms_b_clkctl_clk(wlc_hw, CLK_FAST); - } - /* down phy at the last of this stage */ - callbacks += wlc_phy_down(wlc_hw->band->pi); - - return callbacks; -} - -int brcms_b_down_finish(struct brcms_hardware *wlc_hw) -{ - uint callbacks = 0; - bool dev_gone; - - BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); - - if (!wlc_hw->up) - return callbacks; - - wlc_hw->up = false; - wlc_phy_hw_state_upd(wlc_hw->band->pi, false); - - dev_gone = DEVICEREMOVED(wlc_hw->wlc); - - if (dev_gone) { - wlc_hw->sbclk = false; - wlc_hw->clk = false; - wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); - - /* reclaim any posted packets */ - brcms_c_flushqueues(wlc_hw->wlc); - } else { - - /* Reset and disable the core */ - if (ai_iscoreup(wlc_hw->sih)) { - if (R_REG(&wlc_hw->regs->maccontrol) & - MCTL_EN_MAC) - brcms_c_suspend_mac_and_wait(wlc_hw->wlc); - callbacks += brcms_reset(wlc_hw->wlc->wl); - brcms_c_coredisable(wlc_hw); - } - - /* turn off primary xtal and pll */ - if (!wlc_hw->noreset) { - ai_pci_down(wlc_hw->sih); - brcms_b_xtal(wlc_hw, OFF); - } - } - - return callbacks; -} - /* * Mark the interface nonoperational, stop the software mechanisms, * disable the hardware, free any transient buffer state. @@ -5756,8 +2201,9 @@ uint brcms_c_down(struct brcms_c_info *wlc) brcms_c_txflowcontrol_reset(wlc); /* flush tx queues */ - for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) + for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) { brcmu_pktq_flush(&qi->q, true, NULL, NULL); + } callbacks += brcms_b_down_finish(wlc->hw); @@ -5773,18 +2219,17 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) { int ret = 0; uint i; - struct brcms_c_rateset rs; + wlc_rateset_t rs; /* Default to 54g Auto */ /* Advertise and use shortslot (-1/0/1 Auto/Off/On) */ s8 shortslot = BRCMS_SHORTSLOT_AUTO; - bool shortslot_restrict = false; /* Restrict association to stations - * that support shortslot - */ + bool shortslot_restrict = false; /* Restrict association to stations that support shortslot + */ bool ofdm_basic = false; /* Make 6, 12, and 24 basic rates */ /* Advertise and use short preambles (-1/0/1 Auto/Off/On) */ int preamble = BRCMS_PLCP_LONG; - bool preamble_restrict = false; /* Restrict association to stations - * that support short preambles + bool preamble_restrict = false; /* Restrict association to stations that support short + * preambles */ struct brcms_band *band; @@ -5813,10 +2258,10 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode); /* Clear supported rates filter */ - memset(&wlc->sup_rates_override, 0, sizeof(struct brcms_c_rateset)); + memset(&wlc->sup_rates_override, 0, sizeof(wlc_rateset_t)); /* Clear rateset override */ - memset(&rs, 0, sizeof(struct brcms_c_rateset)); + memset(&rs, 0, sizeof(wlc_rateset_t)); switch (gmode) { case GMODE_LEGACY_B: @@ -5842,8 +2287,7 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) break; case GMODE_PERFORMANCE: - if (AP_ENAB(wlc->pub)) - /* Put all rates into the Supported Rates element */ + if (AP_ENAB(wlc->pub)) /* Put all rates into the Supported Rates element */ brcms_c_rateset_copy(&cck_ofdm_rates, &wlc->sup_rates_override); @@ -5871,19 +2315,21 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) band->rspec_override = 0; brcms_c_reprate_init(wlc); } - if (band->mrspec_override && !IS_CCK(band->mrspec_override)) + if (band->mrspec_override && !IS_CCK(band->mrspec_override)) { band->mrspec_override = 0; + } } band->gmode = gmode; wlc->shortslot_override = shortslot; - if (AP_ENAB(wlc->pub)) + if (AP_ENAB(wlc->pub)) { /* wlc->ap->shortslot_restrict = shortslot_restrict; */ wlc->PLCPHdr_override = (preamble != BRCMS_PLCP_LONG) ? BRCMS_PLCP_SHORT : BRCMS_PLCP_AUTO; + } if ((AP_ENAB(wlc->pub) && preamble != BRCMS_PLCP_LONG) || preamble == BRCMS_PLCP_SHORT) @@ -6000,13 +2446,12 @@ int brcms_c_set_nmode(struct brcms_c_info *wlc, s32 nmode) return err; } -static int -brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs_arg) +static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg) { - struct brcms_c_rateset rs, new; + wlc_rateset_t rs, new; uint bandunit; - memcpy(&rs, rs_arg, sizeof(struct brcms_c_rateset)); + memcpy(&rs, rs_arg, sizeof(wlc_rateset_t)); /* check for bad count value */ if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES)) @@ -6014,7 +2459,7 @@ brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs_arg) /* try the current band */ bandunit = wlc->band->bandunit; - memcpy(&new, &rs, sizeof(struct brcms_c_rateset)); + memcpy(&new, &rs, sizeof(wlc_rateset_t)); if (brcms_c_rate_hwrs_filter_sort_validate (&new, &wlc->bandstate[bandunit]->hw_rateset, true, wlc->stf->txstreams)) @@ -6023,7 +2468,7 @@ brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs_arg) /* try the other band */ if (IS_MBAND_UNLOCKED(wlc)) { bandunit = OTHERBANDUNIT(wlc); - memcpy(&new, &rs, sizeof(struct brcms_c_rateset)); + memcpy(&new, &rs, sizeof(wlc_rateset_t)); if (brcms_c_rate_hwrs_filter_sort_validate(&new, &wlc-> bandstate[bandunit]-> @@ -6036,10 +2481,9 @@ brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs_arg) good: /* apply new rateset */ - memcpy(&wlc->default_bss->rateset, &new, - sizeof(struct brcms_c_rateset)); + memcpy(&wlc->default_bss->rateset, &new, sizeof(wlc_rateset_t)); memcpy(&wlc->bandstate[bandunit]->defrateset, &new, - sizeof(struct brcms_c_rateset)); + sizeof(wlc_rateset_t)); return 0; } @@ -6111,12 +2555,9 @@ _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, /* default argument is generic integer */ pval = arg ? (int *)arg : NULL; - /* - * This will prevent misaligned access. The (void *) cast prevents a - * memcpy alignment issue on e.g. Sparc64 platforms. - */ + /* This will prevent the misaligned access */ if (pval && (u32) len >= sizeof(val)) - memcpy((void *)&val, (void *)pval, sizeof(val)); + memcpy(&val, pval, sizeof(val)); else val = 0; @@ -6134,7 +2575,7 @@ _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, switch (cmd) { case BRCM_SET_CHANNEL:{ - u16 chspec = CH20MHZ_CHSPEC(val); + chanspec_t chspec = CH20MHZ_CHSPEC(val); if (val < 0 || val > MAXCHANNEL) { bcmerror = -EINVAL; @@ -6174,9 +2615,9 @@ _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL); - for (ac = 0; ac < AC_COUNT; ac++) + for (ac = 0; ac < AC_COUNT; ac++) { BRCMS_WME_RETRY_SHORT_SET(wlc, ac, wlc->SRL); - + } brcms_c_wme_retries_write(wlc); } else bcmerror = -EINVAL; @@ -6189,18 +2630,17 @@ _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL); - for (ac = 0; ac < AC_COUNT; ac++) + for (ac = 0; ac < AC_COUNT; ac++) { BRCMS_WME_RETRY_LONG_SET(wlc, ac, wlc->LRL); - + } brcms_c_wme_retries_write(wlc); } else bcmerror = -EINVAL; break; case BRCM_GET_CURR_RATESET:{ - struct brcm_rateset *ret_rs = - (struct brcm_rateset *) arg; - struct brcms_c_rateset *rs; + wl_rateset_t *ret_rs = (wl_rateset_t *) arg; + wlc_rateset_t *rs; if (wlc->pub->associated) rs = ¤t_bss->rateset; @@ -6219,9 +2659,8 @@ _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, } case BRCM_SET_RATESET:{ - struct brcms_c_rateset rs; - struct brcm_rateset *in_rs = - (struct brcm_rateset *) arg; + wlc_rateset_t rs; + wl_rateset_t *in_rs = (wl_rateset_t *) arg; if (len < (int)(in_rs->count + sizeof(in_rs->count))) { bcmerror = -EOVERFLOW; @@ -6233,7 +2672,7 @@ _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, break; } - memset(&rs, 0, sizeof(struct brcms_c_rateset)); + memset(&rs, 0, sizeof(wlc_rateset_t)); /* Copy only legacy rateset section */ rs.count = in_rs->count; @@ -6241,13 +2680,14 @@ _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, /* merge rateset coming in with the current mcsset */ if (N_ENAB(wlc->pub)) { - struct brcms_bss_info *mcsset_bss; if (bsscfg->associated) - mcsset_bss = current_bss; + memcpy(rs.mcs, + ¤t_bss->rateset.mcs[0], + MCSSET_LEN); else - mcsset_bss = wlc->default_bss; - memcpy(rs.mcs, &mcsset_bss->rateset.mcs[0], - MCSSET_LEN); + memcpy(rs.mcs, + &wlc->default_bss->rateset.mcs[0], + MCSSET_LEN); } bcmerror = brcms_c_set_rateset(wlc, &rs); @@ -6308,12 +2748,13 @@ _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, } else { /* driver is down, so just update the brcms_c_info * value */ - if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO) + if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO) { wlc->shortslot = false; - else + } else { wlc->shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON); + } } break; @@ -6331,8 +2772,8 @@ _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len, * register watchdog and down handlers. */ int brcms_c_module_register(struct brcms_pub *pub, - const char *name, struct brcms_info *hdl, - int (*d_fn)(void *handle)) + const char *name, void *hdl, + watchdog_fn_t w_fn, down_fn_t d_fn) { struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc; int i; @@ -6343,6 +2784,7 @@ int brcms_c_module_register(struct brcms_pub *pub, strncpy(wlc->modulecb[i].name, name, sizeof(wlc->modulecb[i].name) - 1); wlc->modulecb[i].hdl = hdl; + wlc->modulecb[i].watchdog_fn = w_fn; wlc->modulecb[i].down_fn = d_fn; return 0; } @@ -6352,8 +2794,8 @@ int brcms_c_module_register(struct brcms_pub *pub, } /* unregister module callbacks */ -int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, - struct brcms_info *hdl) +int +brcms_c_module_unregister(struct brcms_pub *pub, const char *name, void *hdl) { struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc; int i; @@ -6373,10 +2815,7 @@ int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, return -ENODATA; } -/* - * Write WME tunable parameters for retransmit/max rate - * from wlc struct to ucode - */ +/* Write WME tunable parameters for retransmit/max rate from wlc struct to ucode */ static void brcms_c_wme_retries_write(struct brcms_c_info *wlc) { int ac; @@ -6385,9 +2824,10 @@ static void brcms_c_wme_retries_write(struct brcms_c_info *wlc) if (!wlc->clk) return; - for (ac = 0; ac < AC_COUNT; ac++) + for (ac = 0; ac < AC_COUNT; ac++) { brcms_c_write_shm(wlc, M_AC_TXLMT_ADDR(ac), wlc->wme_retries[ac]); + } } #ifdef BCMDBG @@ -6489,8 +2929,9 @@ void brcms_c_statsupd(struct brcms_c_info *wlc) /* merge counters from dma module */ for (i = 0; i < NFIFO; i++) { - if (wlc->hw->di[i]) + if (wlc->hw->di[i]) { dma_counterreset(wlc->hw->di[i]); + } } } @@ -6641,29 +3082,6 @@ void brcms_c_print_rxh(struct d11rxhdr *rxh) } #endif /* defined(BCMDBG) */ -u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate) -{ - u16 table_ptr; - u8 phy_rate, index; - - /* get the phy specific rate encoding for the PLCP SIGNAL field */ - if (IS_OFDM(rate)) - table_ptr = M_RT_DIRMAP_A; - else - table_ptr = M_RT_DIRMAP_B; - - /* for a given rate, the LS-nibble of the PLCP SIGNAL field is - * the index into the rate table. - */ - phy_rate = rate_info[rate] & BRCMS_RATE_MASK; - index = phy_rate & 0xf; - - /* Find the SHM pointer to the rate table entry by looking in the - * Direct-map Table - */ - return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2)); -} - static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate) { return brcms_b_rate_shm_offset(wlc->hw, rate); @@ -6680,8 +3098,8 @@ static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate) * * Returns true if packet consumed (queued), false if not. */ -bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, - struct sk_buff *pkt, int prec) +bool +brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, void *pkt, int prec) { return brcms_c_prec_enq_head(wlc, q, pkt, prec, false); } @@ -6733,9 +3151,10 @@ brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q, return true; } -void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, - struct sk_buff *sdu, uint prec) +void brcms_c_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu, + uint prec) { + struct brcms_c_info *wlc = (struct brcms_c_info *) ctx; struct brcms_txq_info *qi = wlc->pkt_queue; /* Check me */ struct pktq *q = &qi->q; int prio; @@ -6755,20 +3174,20 @@ void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, brcmu_pkt_buf_free_skb(sdu); } - /* - * Check if flow control needs to be turned on after enqueuing the - * packet. Don't turn on flow control if EDCF is enabled. Driver - * would make the decision on what to drop instead of relying on - * stack to make the right decision + /* Check if flow control needs to be turned on after enqueuing the packet + * Don't turn on flow control if EDCF is enabled. Driver would make the decision on what + * to drop instead of relying on stack to make the right decision */ if (!EDCF_ENAB(wlc->pub) || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) { - if (pktq_len(q) >= wlc->pub->tunables->datahiwat) + if (pktq_len(q) >= wlc->pub->tunables->datahiwat) { brcms_c_txflowcontrol(wlc, qi, ON, ALLPRIO); + } } else if (wlc->pub->_priofc) { if (pktq_plen(q, wlc_prio2prec_map[prio]) >= - wlc->pub->tunables->datahiwat) + wlc->pub->tunables->datahiwat) { brcms_c_txflowcontrol(wlc, qi, ON, prio); + } } } @@ -6778,21 +3197,20 @@ brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, { u8 prio; uint fifo; + void *pkt; struct scb *scb = &global_scb; struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data); - /* - * 802.11 standard requires management traffic - * to go at highest priority - */ + /* 802.11 standard requires management traffic to go at highest priority */ prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority : MAXPRIO; fifo = prio2fifo[prio]; + pkt = sdu; if (unlikely (brcms_c_d11hdrs_mac80211( - wlc, hw, sdu, scb, 0, 1, fifo, 0, NULL, 0))) + wlc, hw, pkt, scb, 0, 1, fifo, 0, NULL, 0))) return -EINVAL; - brcms_c_txq_enq(wlc, scb, sdu, BRCMS_PRIO_TO_PREC(prio)); + brcms_c_txq_enq(wlc, scb, pkt, BRCMS_PRIO_TO_PREC(prio)); brcms_c_send_q(wlc); return 0; } @@ -6826,18 +3244,17 @@ void brcms_c_send_q(struct brcms_c_info *wlc) count = 1; err = brcms_c_prep_pdu(wlc, pkt[0], &fifo); if (!err) { - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { brcms_c_txfifo(wlc, fifo, pkt[i], true, 1); + } } } if (err == -EBUSY) { brcmu_pktq_penq_head(q, prec, pkt[0]); - /* - * If send failed due to any other reason than a - * change in HW FIFO condition, quit. Otherwise, - * read the new prec_map! + /* If send failed due to any other reason than a change in + * HW FIFO condition, quit. Otherwise, read the new prec_map! */ if (prec_map == wlc->tx_prec_map) break; @@ -6845,22 +3262,21 @@ void brcms_c_send_q(struct brcms_c_info *wlc) } } - /* - * Check if flow control needs to be turned off after - * sending the packet - */ + /* Check if flow control needs to be turned off after sending the packet */ if (!EDCF_ENAB(wlc->pub) || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) { if (brcms_c_txflowcontrol_prio_isset(wlc, qi, ALLPRIO) - && (pktq_len(q) < wlc->pub->tunables->datahiwat / 2)) + && (pktq_len(q) < wlc->pub->tunables->datahiwat / 2)) { brcms_c_txflowcontrol(wlc, qi, OFF, ALLPRIO); + } } else if (wlc->pub->_priofc) { int prio; for (prio = MAXPRIO; prio >= 0; prio--) { if (brcms_c_txflowcontrol_prio_isset(wlc, qi, prio) && (pktq_plen(q, wlc_prio2prec_map[prio]) < - wlc->pub->tunables->datahiwat / 2)) + wlc->pub->tunables->datahiwat / 2)) { brcms_c_txflowcontrol(wlc, qi, OFF, prio); + } } } in_send_q = false; @@ -6896,19 +3312,20 @@ brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p, txh = (struct d11txh *) (p->data); - /* When a BC/MC frame is being committed to the BCMC fifo - * via DMA (NOT PIO), update ucode or BSS info as appropriate. + /* When a BC/MC frame is being committed to the BCMC fifo via DMA (NOT PIO), update + * ucode or BSS info as appropriate. */ - if (fifo == TX_BCMC_FIFO) + if (fifo == TX_BCMC_FIFO) { frameid = le16_to_cpu(txh->TxFrameID); + } + if (BRCMS_WAR16165(wlc)) brcms_c_war16165(wlc, true); - /* - * Bump up pending count for if not using rpc. If rpc is - * used, this will be handled in brcms_b_txfifo() + /* Bump up pending count for if not using rpc. If rpc is used, this will be handled + * in brcms_b_txfifo() */ if (commit) { TXPKTPENDINC(wlc, fifo, txpktpend); @@ -6920,49 +3337,48 @@ brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p, if (frameid != INVALIDFID) BCMCFID(wlc, frameid); - if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) + if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) { wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n"); + } } void -brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec, +brcms_c_compute_plcp(struct brcms_c_info *wlc, ratespec_t rspec, uint length, u8 *plcp) { - if (IS_MCS(rspec)) + if (IS_MCS(rspec)) { brcms_c_compute_mimo_plcp(rspec, length, plcp); - else if (IS_OFDM(rspec)) + } else if (IS_OFDM(rspec)) { brcms_c_compute_ofdm_plcp(rspec, length, plcp); - else + } else { brcms_c_compute_cck_plcp(wlc, rspec, length, plcp); + } return; } /* Rate: 802.11 rate code, length: PSDU length in octets */ -static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp) +static void brcms_c_compute_mimo_plcp(ratespec_t rspec, uint length, u8 *plcp) { u8 mcs = (u8) (rspec & RSPEC_RATE_MASK); plcp[0] = mcs; if (RSPEC_IS40MHZ(rspec) || (mcs == 32)) plcp[0] |= MIMO_PLCP_40MHZ; BRCMS_SET_MIMO_PLCP_LEN(plcp, length); - plcp[3] = RSPEC_MIMOPLCP3(rspec); /* rspec already holds this byte */ - plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */ - plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */ + plcp[3] = RSPEC_MIMOPLCP3(rspec); /* rspec already holds this byte */ + plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */ + plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */ plcp[5] = 0; } /* Rate: 802.11 rate code, length: PSDU length in octets */ static void -brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp) +brcms_c_compute_ofdm_plcp(ratespec_t rspec, u32 length, u8 *plcp) { u8 rate_signal; u32 tmp = 0; int rate = RSPEC2RATE(rspec); - /* - * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb - * transmitted first - */ + /* encode rate per 802.11a-1999 sec 17.3.4.1, with lsb transmitted first */ rate_signal = rate_info[rate] & BRCMS_RATE_MASK; memset(plcp, 0, D11_PHY_HDR_LEN); D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal); @@ -7010,9 +3426,8 @@ static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500, break; default: - wiphy_err(wlc->wiphy, - "brcms_c_cck_plcp_set: unsupported rate %d\n", - rate_500); + wiphy_err(wlc->wiphy, "brcms_c_cck_plcp_set: unsupported rate %d" + "\n", rate_500); rate_500 = BRCM_RATE_1M; usec = length << 3; break; @@ -7030,7 +3445,7 @@ static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500, } /* Rate: 802.11 rate code, length: PSDU length in octets */ -static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec, +static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, ratespec_t rspec, uint length, u8 *plcp) { int rate = RSPEC2RATE(rspec); @@ -7049,7 +3464,7 @@ static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec, * preamble_type use short/GF or long/MM PLCP header */ static u16 -brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate, +brcms_c_compute_frame_dur(struct brcms_c_info *wlc, ratespec_t rate, u8 preamble_type, uint next_frag_len) { u16 dur, sifs; @@ -7084,22 +3499,20 @@ brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate, */ u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, - u32 rts_rate, - u32 frame_rate, u8 rts_preamble_type, + ratespec_t rts_rate, + ratespec_t frame_rate, u8 rts_preamble_type, u8 frame_preamble_type, uint frame_len, bool ba) { u16 dur, sifs; sifs = SIFS(wlc->band); - if (!cts_only) { - /* RTS/CTS */ + if (!cts_only) { /* RTS/CTS */ dur = 3 * sifs; dur += (u16) brcms_c_calc_cts_time(wlc, rts_rate, rts_preamble_type); - } else { - /* CTS-TO-SELF */ + } else { /* CTS-TO-SELF */ dur = 2 * sifs; } @@ -7117,7 +3530,7 @@ brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, return dur; } -u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec) +u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec) { u16 phyctl1 = 0; u16 bw; @@ -7143,11 +3556,8 @@ u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec) phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8); } else if (IS_CCK(rspec) && !BRCMS_ISLCNPHY(wlc->band) && !BRCMS_ISSSLPNPHY(wlc->band)) { - /* - * In CCK mode LPPHY overloads OFDM Modulation bits with CCK - * Data Rate. Eventually MIMOPHY would also be converted to - * this format - */ + /* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */ + /* Eventually MIMOPHY would also be converted to this format */ /* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */ phyctl1 = (bw | (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT)); } else { /* legacy OFDM/CCK */ @@ -7167,38 +3577,38 @@ u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec) return phyctl1; } -u32 -brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec, +ratespec_t +brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, ratespec_t rspec, bool use_rspec, u16 mimo_ctlchbw) { - u32 rts_rspec = 0; + ratespec_t rts_rspec = 0; - if (use_rspec) + if (use_rspec) { /* use frame rate as rts rate */ rts_rspec = rspec; - else if (wlc->band->gmode && wlc->protection->_g && !IS_CCK(rspec)) + + } else if (wlc->band->gmode && wlc->protection->_g && !IS_CCK(rspec)) { /* Use 11Mbps as the g protection RTS target rate and fallback. * Use the BRCMS_BASIC_RATE() lookup to find the best basic rate * under the target in case 11 Mbps is not Basic. - * 6 and 9 Mbps are not usually selected by rate selection, but - * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11 - * is more robust. + * 6 and 9 Mbps are not usually selected by rate selection, but even + * if the OFDM rate we are protecting is 6 or 9 Mbps, 11 is more robust. */ rts_rspec = BRCMS_BASIC_RATE(wlc, BRCM_RATE_11M); - else + } else { /* calculate RTS rate and fallback rate based on the frame rate * RTS must be sent at a basic rate since it is a * control frame, sec 9.6 of 802.11 spec */ rts_rspec = BRCMS_BASIC_RATE(wlc, rspec); + } if (BRCMS_PHY_11N_CAP(wlc->band)) { /* set rts txbw to correct side band */ rts_rspec &= ~RSPEC_BW_MASK; - /* - * if rspec/rspec_fallback is 40MHz, then send RTS on both - * 20MHz channel (DUP), otherwise send RTS on control channel + /* if rspec/rspec_fallback is 40MHz, then send RTS on both 20MHz channel + * (DUP), otherwise send RTS on control channel */ if (RSPEC_IS40MHZ(rspec) && !IS_CCK(rts_rspec)) rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT); @@ -7227,7 +3637,7 @@ static u16 brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, struct sk_buff *p, struct scb *scb, uint frag, uint nfrags, uint queue, uint next_frag_len, - struct wsec_key *key, u32 rspec_override) + struct wsec_key *key, ratespec_t rspec_override) { struct ieee80211_hdr *h; struct d11txh *txh; @@ -7235,7 +3645,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, int len, phylen, rts_phylen; u16 mch, phyctl, xfts, mainrates; u16 seq = 0, mcl = 0, status = 0, frameid = 0; - u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }, rts_rspec[2] = { + ratespec_t rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }, rts_rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M}; bool use_rts = false; bool use_cts = false; @@ -7275,8 +3685,9 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, * the packet itself, thus phylen = packet length + ICV_LEN + FCS_LEN * in this case */ - if (key) + if (key) { phylen += key->icv_len; + } /* Get tx_info */ tx_info = IEEE80211_SKB_CB(p); @@ -7297,8 +3708,9 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, frameid = bcmc_fid_generate(wlc, NULL, txh); } else { /* Increment the counter for first fragment */ - if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) { SCB_SEQNUM(scb, p->priority)++; + } /* extract fragment number from frame first */ seq = le16_to_cpu(seq) & FRAGNUM_MASK; @@ -7318,12 +3730,10 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, txrate[0] = tx_info->control.rates; txrate[1] = txrate[0] + 1; - /* - * if rate control algorithm didn't give us a fallback - * rate, use the primary rate - */ - if (txrate[1]->idx < 0) + /* if rate control algorithm didn't give us a fallback rate, use the primary rate */ + if (txrate[1]->idx < 0) { txrate[1] = txrate[0]; + } for (k = 0; k < hw->max_rates; k++) { is_mcs[k] = @@ -7345,11 +3755,8 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, } else { rate_val[k] = txrate[k]->idx; } - - /* - * Currently only support same setting for primay and - * fallback rates. Unify flags for each rate into a - * single value for the frame + /* Currently only support same setting for primay and fallback rates. + * Unify flags for each rate into a single value for the frame */ use_rts |= txrate[k]-> @@ -7363,11 +3770,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, rate_val[k]); - /* - * (1) RATE: - * determine and validate primary rate - * and fallback rates - */ + /* (1) RATE: determine and validate primary rate and fallback rates */ if (!RSPEC_ACTIVE(rspec[k])) { rspec[k] = BRCM_RATE_1M; } else { @@ -7383,10 +3786,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, if (N_ENAB(wlc->pub)) { for (k = 0; k < hw->max_rates; k++) { - /* - * apply siso/cdd to single stream mcs's or ofdm - * if rspec is auto selected - */ + /* apply siso/cdd to single stream mcs's or ofdm if rspec is auto selected */ if (((IS_MCS(rspec[k]) && IS_SINGLE_STREAM(rspec[k] & RSPEC_RATE_MASK)) || IS_OFDM(rspec[k])) @@ -7399,20 +3799,17 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, && BRCMS_STF_SS_STBC_TX(wlc, scb)) { u8 stc; - /* Nss for single stream is always 1 */ - stc = 1; - rspec[k] |= (PHY_TXC1_MODE_STBC << - RSPEC_STF_SHIFT) | - (stc << RSPEC_STC_SHIFT); + stc = 1; /* Nss for single stream is always 1 */ + rspec[k] |= + (PHY_TXC1_MODE_STBC << + RSPEC_STF_SHIFT) | (stc << + RSPEC_STC_SHIFT); } else rspec[k] |= (phyctl1_stf << RSPEC_STF_SHIFT); } - /* - * Is the phy configured to use 40MHZ frames? If - * so then pick the desired txbw - */ + /* Is the phy configured to use 40MHZ frames? If so then pick the desired txbw */ if (CHSPEC_WLC_BW(wlc->chanspec) == BRCMS_40_MHZ) { /* default txbw is 20in40 SB */ mimo_ctlchbw = mimo_txbw = @@ -7421,8 +3818,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, if (IS_MCS(rspec[k])) { /* mcs 32 must be 40b/w DUP */ - if ((rspec[k] & RSPEC_RATE_MASK) - == 32) { + if ((rspec[k] & RSPEC_RATE_MASK) == 32) { mimo_txbw = PHY_TXC1_BW_40MHZ_DUP; /* use override */ @@ -7434,19 +3830,18 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, } else if (IS_OFDM(rspec[k])) { if (wlc->ofdm_40txbw != AUTO) mimo_txbw = wlc->ofdm_40txbw; - } else if (wlc->cck_40txbw != AUTO) { - mimo_txbw = wlc->cck_40txbw; + } else { + if (wlc->cck_40txbw != AUTO) + mimo_txbw = wlc->cck_40txbw; } } else { - /* - * mcs32 is 40 b/w only. - * This is possible for probe packets on - * a STA during SCAN + /* mcs32 is 40 b/w only. + * This is possible for probe packets on a STA during SCAN */ - if ((rspec[k] & RSPEC_RATE_MASK) == 32) + if ((rspec[k] & RSPEC_RATE_MASK) == 32) { /* mcs 0 */ rspec[k] = RSPEC_MIMORATE; - + } mimo_txbw = PHY_TXC1_BW_20MHZ; } @@ -7482,14 +3877,12 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, if (IS_MCS(rspec[k])) { preamble_type[k] = mimo_preamble_type; - /* - * if SGI is selected, then forced mm - * for single stream - */ + /* if SGI is selected, then forced mm for single stream */ if ((rspec[k] & RSPEC_SHORT_GI) && IS_SINGLE_STREAM(rspec[k] & - RSPEC_RATE_MASK)) + RSPEC_RATE_MASK)) { preamble_type[k] = BRCMS_MM_PREAMBLE; + } } /* should be better conditionalized */ @@ -7609,14 +4002,12 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, /* TxFrameID */ txh->TxFrameID = cpu_to_le16(frameid); - /* - * TxStatus, Note the case of recreating the first frag of a suppressed - * frame then we may need to reset the retry cnt's via the status reg + /* TxStatus, Note the case of recreating the first frag of a suppressed frame + * then we may need to reset the retry cnt's via the status reg */ txh->TxStatus = cpu_to_le16(status); - /* - * extra fields for ucode AMPDU aggregation, the new fields are added to + /* extra fields for ucode AMPDU aggregation, the new fields are added to * the END of previous structure so that it's compatible in driver. */ txh->MaxNMpdus = cpu_to_le16(0); @@ -7719,22 +4110,16 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, #ifdef SUPPORT_40MHZ /* add null delimiter count */ - if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && IS_MCS(rspec)) + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && IS_MCS(rspec)) { txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen); - + } #endif - /* - * Now that RTS/RTS FB preamble types are updated, write - * the final value - */ + /* Now that RTS/RTS FB preamble types are updated, write the final value */ txh->MacTxControlHigh = cpu_to_le16(mch); - /* - * MainRates (both the rts and frag plcp rates have - * been calculated now) - */ + /* MainRates (both the rts and frag plcp rates have been calculated now) */ txh->MainRates = cpu_to_le16(mainrates); /* XtraFrameTypes */ @@ -7774,9 +4159,9 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, } /* - * For mcs frames, if mixedmode(overloaded with long preamble) - * is going to be set, fill in non-zero MModeLen and/or - * MModeFbrLen it will be unnecessary if they are separated + * For mcs frames, if mixedmode(overloaded with long preamble) is going to be set, + * fill in non-zero MModeLen and/or MModeFbrLen + * it will be unnecessary if they are separated */ if (IS_MCS(rspec[0]) && (preamble_type[0] == BRCMS_MM_PREAMBLE)) { @@ -7798,7 +4183,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, uint frag_dur, dur, dur_fallback; /* WME: Update TXOP threshold */ - if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) && frag == 0) { + if ((!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) && (frag == 0)) { frag_dur = brcms_c_calc_frame_time(wlc, rspec[0], preamble_type[0], phylen); @@ -7835,44 +4220,40 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, } /* NEED to set TxFesTimeNormal (hard) */ txh->TxFesTimeNormal = cpu_to_le16((u16) dur); - /* - * NEED to set fallback rate version of - * TxFesTimeNormal (hard) - */ + /* NEED to set fallback rate version of TxFesTimeNormal (hard) */ txh->TxFesTimeFallback = cpu_to_le16((u16) dur_fallback); - /* - * update txop byte threshold (txop minus intraframe - * overhead) - */ + /* update txop byte threshold (txop minus intraframe overhead) */ if (wlc->edcf_txop[ac] >= (dur - frag_dur)) { - uint newfragthresh; - - newfragthresh = - brcms_c_calc_frame_len(wlc, - rspec[0], preamble_type[0], - (wlc->edcf_txop[ac] - - (dur - frag_dur))); - /* range bound the fragthreshold */ - if (newfragthresh < DOT11_MIN_FRAG_LEN) - newfragthresh = - DOT11_MIN_FRAG_LEN; - else if (newfragthresh > - wlc->usr_fragthresh) + { + uint newfragthresh; + newfragthresh = - wlc->usr_fragthresh; - /* update the fragthresh and do txc update */ - if (wlc->fragthresh[queue] != - (u16) newfragthresh) - wlc->fragthresh[queue] = - (u16) newfragthresh; - } else { + brcms_c_calc_frame_len(wlc, + rspec[0], preamble_type[0], + (wlc->edcf_txop[ac] - + (dur - frag_dur))); + /* range bound the fragthreshold */ + if (newfragthresh < DOT11_MIN_FRAG_LEN) + newfragthresh = + DOT11_MIN_FRAG_LEN; + else if (newfragthresh > + wlc->usr_fragthresh) + newfragthresh = + wlc->usr_fragthresh; + /* update the fragthresh and do txc update */ + if (wlc->fragthresh[queue] != + (u16) newfragthresh) { + wlc->fragthresh[queue] = + (u16) newfragthresh; + } + } + } else wiphy_err(wlc->wiphy, "wl%d: %s txop invalid " "for rate %d\n", wlc->pub->unit, fifo_names[queue], RSPEC2RATE(rspec[0])); - } if (dur > wlc->edcf_txop[ac]) wiphy_err(wlc->wiphy, "wl%d: %s: %s txop " @@ -7891,12 +4272,10 @@ void brcms_c_tbtt(struct brcms_c_info *wlc) { struct brcms_bss_cfg *cfg = wlc->cfg; - if (!cfg->BSS) - /* - * DirFrmQ is now valid...defer setting until end - * of ATIM window - */ + if (!cfg->BSS) { + /* DirFrmQ is now valid...defer setting until end of ATIM window */ wlc->qvalid |= MCMD_DIRFRMQVAL; + } } static void brcms_c_war16165(struct brcms_c_info *wlc, bool tx) @@ -7930,13 +4309,12 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs, u32 frm_tx2) struct ieee80211_tx_rate *txrate; int i; - /* Compiler reference to avoid unused variable warning */ - (void)(frm_tx2); + (void)(frm_tx2); /* Compiler reference to avoid unused variable warning */ /* discard intermediate indications for ucode with one legitimate case: - * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, - * but the subsequent tx of DATA failed. so it will start rts/cts - * from the beginning (resetting the rts transmission count) + * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent + * tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts + * transmission count) */ if (!(txs->status & TX_STATUS_AMPDU) && (txs->status & TX_STATUS_INTERMEDIATE)) { @@ -8028,22 +4406,13 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs, u32 frm_tx2) ieee80211_tx_info_clear_status(tx_info); if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) { - /* - * rate selection requested a fallback rate - * and we used it - */ + /* rate selection requested a fallback rate and we used it */ txrate[0].count = fbl; txrate[1].count = tx_frame_count - fbl; } else { - /* - * rate selection did not request fallback rate, or - * we didn't need it - */ + /* rate selection did not request fallback rate, or we didn't need it */ txrate[0].count = tx_frame_count; - /* - * rc80211_minstrel.c:minstrel_tx_status() expects - * unused rates to be marked with idx = -1 - */ + /* rc80211_minstrel.c:minstrel_tx_status() expects unused rates to be marked with idx = -1 */ txrate[1].idx = -1; txrate[1].count = 0; } @@ -8097,8 +4466,9 @@ brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend) /* Clear MHF2_TXBCMC_NOW flag if BCMC fifo has drained */ if (AP_ENAB(wlc->pub) && - !TXPKTPENDGET(wlc, TX_BCMC_FIFO)) + !TXPKTPENDGET(wlc, TX_BCMC_FIFO)) { brcms_c_mhf(wlc, MHF2, MHF2_TXBCMC_NOW, 0, BRCM_BAND_AUTO); + } /* figure out which bsscfg is being worked on... */ } @@ -8117,19 +4487,6 @@ void brcms_c_bcn_li_upd(struct brcms_c_info *wlc) (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn); } -void -brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr, - u32 *tsf_h_ptr) -{ - struct d11regs *regs = wlc_hw->regs; - - /* read the tsf timer low, then high to get an atomic read */ - *tsf_l_ptr = R_REG(®s->tsf_timerlow); - *tsf_h_ptr = R_REG(®s->tsf_timerhigh); - - return; -} - /* * recover 64bit TSF value from the 16bit TSF value in the rx header * given the assumption that the TSF passed in header is within 65ms @@ -8176,7 +4533,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, struct brcms_d11rxhdr *wlc_rxh = (struct brcms_d11rxhdr *) rxh; int preamble; int channel; - u32 rspec; + ratespec_t rspec; unsigned char *plcp; /* fill in TSF and flag its presence */ @@ -8195,12 +4552,11 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, rx_status->freq = ieee80211_dsss_chan_to_freq(channel); } - rx_status->signal = wlc_rxh->rssi; + rx_status->signal = wlc_rxh->rssi; /* signal */ /* noise */ /* qual */ - rx_status->antenna = - (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0; + rx_status->antenna = (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0; /* ant */ plcp = p->data; @@ -8252,14 +4608,6 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__); } - /* - * For 5GHz, we should decrease the index as it is - * a subset of the 2.4G rates. See bitrates field - * of brcms_band_5GHz_nphy (in mac80211_if.c). - */ - if (rx_status->band == IEEE80211_BAND_5GHZ) - rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET; - /* Determine short preamble and rate_idx */ preamble = 0; if (IS_CCK(rspec)) { @@ -8366,8 +4714,9 @@ void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p) } /* check received pkt has at least frame control field */ - if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) + if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) { goto toss; + } is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK; @@ -8409,7 +4758,7 @@ void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p) * len = 3(nsyms + nstream + 3) - 3 */ u16 -brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, +brcms_c_calc_lsig_len(struct brcms_c_info *wlc, ratespec_t ratespec, uint mac_len) { uint nsyms, len = 0, kNdps; @@ -8422,16 +4771,14 @@ brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, /* MCS_TXS(mcs) returns num tx streams - 1 */ int tot_streams = (MCS_TXS(mcs) + 1) + RSPEC_STC(ratespec); - /* - * the payload duration calculation matches that - * of regular ofdm - */ + /* the payload duration calculation matches that of regular ofdm */ /* 1000Ndbps = kbps * 4 */ kNdps = MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec), RSPEC_ISSGI(ratespec)) * 4; if (RSPEC_STC(ratespec) == 0) + /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */ nsyms = CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS) * 1000, kNdps); @@ -8442,24 +4789,17 @@ brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS) * 1000, 2 * kNdps); - /* (+3) account for HT-SIG(2) and HT-STF(1) */ - nsyms += (tot_streams + 3); - /* - * 3 bytes/symbol @ legacy 6Mbps rate - * (-3) excluding service bits and tail bits - */ - len = (3 * nsyms) - 3; + nsyms += (tot_streams + 3); /* (+3) account for HT-SIG(2) and HT-STF(1) */ + /* 3 bytes/symbol @ legacy 6Mbps rate */ + len = (3 * nsyms) - 3; /* (-3) excluding service bits and tail bits */ } return (u16) len; } -/* - * calculate frame duration of a given rate and length, return - * time in usec unit - */ +/* calculate frame duration of a given rate and length, return time in usec unit */ uint -brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec, +brcms_c_calc_frame_time(struct brcms_c_info *wlc, ratespec_t ratespec, u8 preamble_type, uint mac_len) { uint nsyms, dur = 0, Ndps, kNdps; @@ -8487,6 +4827,7 @@ brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec, RSPEC_ISSGI(ratespec)) * 4; if (RSPEC_STC(ratespec) == 0) + /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */ nsyms = CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS) * 1000, kNdps); @@ -8513,10 +4854,7 @@ brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec, if (BAND_2G(wlc->band->bandtype)) dur += DOT11_OFDM_SIGNAL_EXTENSION; } else { - /* - * calc # bits * 2 so factor of 2 in rate (1/2 mbps) - * will divide out - */ + /* calc # bits * 2 so factor of 2 in rate (1/2 mbps) will divide out */ mac_len = mac_len * 8 * 2; /* calc ceiling of bits/rate = microseconds of air time */ dur = (mac_len + rate - 1) / rate; @@ -8530,7 +4868,7 @@ brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec, /* The opposite of brcms_c_calc_frame_time */ static uint -brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec, +brcms_c_calc_frame_len(struct brcms_c_info *wlc, ratespec_t ratespec, u8 preamble_type, uint dur) { uint nsyms, mac_len, Ndps, kNdps; @@ -8576,15 +4914,13 @@ brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec, } static uint -brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec, +brcms_c_calc_ba_time(struct brcms_c_info *wlc, ratespec_t rspec, u8 preamble_type) { BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, " "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type); - /* - * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that - * is less than or equal to the rate of the immediately previous - * frame in the FES + /* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than + * or equal to the rate of the immediately previous frame in the FES */ rspec = BRCMS_BASIC_RATE(wlc, rspec); /* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */ @@ -8594,17 +4930,15 @@ brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec, } static uint -brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec, +brcms_c_calc_ack_time(struct brcms_c_info *wlc, ratespec_t rspec, u8 preamble_type) { uint dur = 0; BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n", wlc->pub->unit, rspec, preamble_type); - /* - * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that - * is less than or equal to the rate of the immediately previous - * frame in the FES + /* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than + * or equal to the rate of the immediately previous frame in the FES */ rspec = BRCMS_BASIC_RATE(wlc, rspec); /* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */ @@ -8615,7 +4949,7 @@ brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec, } static uint -brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec, +brcms_c_calc_cts_time(struct brcms_c_info *wlc, ratespec_t rspec, u8 preamble_type) { BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n", @@ -8624,8 +4958,7 @@ brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec, } /* derive wlc->band->basic_rate[] table from 'rateset' */ -void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, - struct brcms_c_rateset *rateset) +void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, wlc_rateset_t *rateset) { u8 rate; u8 mandatory; @@ -8699,10 +5032,7 @@ void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, continue; if (IS_OFDM(rate)) { - /* - * In 11g and 11a, the OFDM mandatory rates - * are 6, 12, and 24 Mbps - */ + /* In 11g and 11a, the OFDM mandatory rates are 6, 12, and 24 Mbps */ if (rate >= BRCM_RATE_24M) mandatory = BRCM_RATE_24M; else if (rate >= BRCM_RATE_12M) @@ -8710,7 +5040,7 @@ void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, else mandatory = BRCM_RATE_6M; } else { - /* In 11b, all CCK rates are mandatory 1 - 11 Mbps */ + /* In 11b, all the CCK rates are mandatory 1 - 11 Mbps */ mandatory = rate; } @@ -8752,10 +5082,9 @@ static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate, brcms_c_write_shm(wlc, (basic_table + index * 2), basic_ptr); } -static const struct brcms_c_rateset * -brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc) +static const wlc_rateset_t *brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc) { - const struct brcms_c_rateset *rs_dflt; + const wlc_rateset_t *rs_dflt; if (BRCMS_PHY_11N_CAP(wlc->band)) { if (BAND_5G(wlc->band->bandtype)) @@ -8772,8 +5101,8 @@ brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc) void brcms_c_set_ratetable(struct brcms_c_info *wlc) { - const struct brcms_c_rateset *rs_dflt; - struct brcms_c_rateset rs; + const wlc_rateset_t *rs_dflt; + wlc_rateset_t rs; u8 rate, basic_rate; uint i; @@ -8790,11 +5119,12 @@ void brcms_c_set_ratetable(struct brcms_c_info *wlc) * which a response ACK/CTS should be sent. */ basic_rate = BRCMS_BASIC_RATE(wlc, rate); - if (basic_rate == 0) + if (basic_rate == 0) { /* This should only happen if we are using a * restricted rateset. */ basic_rate = rs.rates[0] & BRCMS_RATE_MASK; + } brcms_c_write_rate_shm(wlc, rate, basic_rate); } @@ -8804,19 +5134,20 @@ void brcms_c_set_ratetable(struct brcms_c_info *wlc) * Return true if the specified rate is supported by the specified band. * BRCM_BAND_AUTO indicates the current band. */ -bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band, +bool brcms_c_valid_rate(struct brcms_c_info *wlc, ratespec_t rspec, int band, bool verbose) { - struct brcms_c_rateset *hw_rateset; + wlc_rateset_t *hw_rateset; uint i; - if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype)) + if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype)) { hw_rateset = &wlc->band->hw_rateset; - else if (NBANDS(wlc) > 1) + } else if (NBANDS(wlc) > 1) { hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset; - else + } else { /* other band specified and we are a single band device */ return false; + } /* check if this is a mimo rate */ if (IS_MCS(rspec)) { @@ -8830,9 +5161,10 @@ bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band, if (hw_rateset->rates[i] == RSPEC2RATE(rspec)) return true; error: - if (verbose) + if (verbose) { wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x " "not in hw_rateset\n", wlc->pub->unit, rspec); + } return false; } @@ -8863,8 +5195,8 @@ static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap) void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len) { - const struct brcms_c_rateset *rs_dflt; - struct brcms_c_rateset rs; + const wlc_rateset_t *rs_dflt; + wlc_rateset_t rs; u8 rate; u16 entry_ptr; u8 plcp[D11_PHY_HDR_LEN]; @@ -8878,10 +5210,7 @@ void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len) brcms_c_rateset_copy(rs_dflt, &rs); brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams); - /* - * walk the phy rate table and update MAC core SHM - * basic rate table entries - */ + /* walk the phy rate table and update MAC core SHM basic rate table entries */ for (i = 0; i < rs.count; i++) { rate = rs.rates[i] & BRCMS_RATE_MASK; @@ -8890,10 +5219,7 @@ void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len) /* Calculate the Probe Response PLCP for the given rate */ brcms_c_compute_plcp(wlc, rate, frame_len, plcp); - /* - * Calculate the duration of the Probe Response - * frame plus SIFS for the MAC - */ + /* Calculate the duration of the Probe Response frame plus SIFS for the MAC */ dur = (u16) brcms_c_calc_frame_time(wlc, rate, BRCMS_LONG_PREAMBLE, frame_len); dur += sifs; @@ -8916,12 +5242,12 @@ void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len) * * *len on input contains the max length of the packet available. * - * The *len value is set to the number of bytes in buf used, and starts - * with the PLCP and included up to, but not including, the 4 byte FCS. + * The *len value is set to the number of bytes in buf used, and starts with the PLCP + * and included up to, but not including, the 4 byte FCS. */ static void brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type, - u32 bcn_rspec, + ratespec_t bcn_rspec, struct brcms_bss_cfg *cfg, u16 *buf, int *len) { static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; @@ -8933,27 +5259,23 @@ brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type, hdr_len = DOT11_MAC_HDR_LEN; else hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN; + body_len = *len - hdr_len; /* calc buffer size provided for frame body */ - /* calc buffer size provided for frame body */ - body_len = *len - hdr_len; - /* return actual size */ - *len = hdr_len + body_len; + *len = hdr_len + body_len; /* return actual size */ /* format PHY and MAC headers */ memset((char *)buf, 0, hdr_len); plcp = (struct cck_phy_hdr *) buf; - /* - * PLCP for Probe Response frames are filled in from - * core's rate table - */ - if (type == IEEE80211_STYPE_BEACON && !MBSS_BCN_ENAB(cfg)) + /* PLCP for Probe Response frames are filled in from core's rate table */ + if (type == IEEE80211_STYPE_BEACON && !MBSS_BCN_ENAB(cfg)) { /* fill in PLCP */ brcms_c_compute_plcp(wlc, bcn_rspec, (DOT11_MAC_HDR_LEN + body_len + FCS_LEN), (u8 *) plcp); + } /* "Regular" and 16 MBSS but not for 4 MBSS */ /* Update the phytxctl for the beacon based on the rspec */ if (!SOFTBCN_ENAB(cfg)) @@ -8984,32 +5306,10 @@ int brcms_c_get_header_len() return TXOFF; } -/* mac is assumed to be suspended at this point */ -void -brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw, u16 bcn[], - int len, bool both) -{ - struct d11regs *regs = wlc_hw->regs; - - if (both) { - brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len); - brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len); - } else { - /* bcn 0 */ - if (!(R_REG(®s->maccommand) & MCMD_BCN0VLD)) - brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len); - /* bcn 1 */ - else if (! - (R_REG(®s->maccommand) & MCMD_BCN1VLD)) - brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len); - } -} - -/* - * Update a beacon for a particular BSS - * For MBSS, this updates the software template and sets "latest" to - * the index of the template updated. Otherwise, it updates the hardware - * template. +/* Update a beacon for a particular BSS + * For MBSS, this updates the software template and sets "latest" to the index of the + * template updated. + * Otherwise, it updates the hardware template. */ void brcms_c_bss_update_beacon(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg) @@ -9019,24 +5319,24 @@ void brcms_c_bss_update_beacon(struct brcms_c_info *wlc, /* Clear the soft intmask */ wlc->defmacintmask &= ~MI_BCNTPL; - if (!cfg->up) - /* Only allow updates on an UP bss */ + if (!cfg->up) { /* Only allow updates on an UP bss */ return; + } /* Optimize: Some of if/else could be combined */ if (!MBSS_BCN_ENAB(cfg) && HWBCN_ENAB(cfg)) { /* Hardware beaconing for this config */ u16 bcn[BCN_TMPL_LEN / 2]; u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD; - struct d11regs *regs = wlc->regs; + d11regs_t *regs = wlc->regs; /* Check if both templates are in use, if so sched. an interrupt * that will call back into this routine */ - if ((R_REG(®s->maccommand) & both_valid) == both_valid) + if ((R_REG(®s->maccommand) & both_valid) == both_valid) { /* clear any previous status */ W_REG(®s->macintstatus, MI_BCNTPL); - + } /* Check that after scheduling the interrupt both of the * templates are still busy. if not clear the int. & remask */ @@ -9063,10 +5363,10 @@ void brcms_c_update_beacon(struct brcms_c_info *wlc) struct brcms_bss_cfg *bsscfg; /* update AP or IBSS beacons */ - FOREACH_BSS(wlc, idx, bsscfg) + FOREACH_BSS(wlc, idx, bsscfg) { if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS)) brcms_c_bss_update_beacon(wlc, bsscfg); - END_FOREACH_BSS() + } } /* Write ssid into shared memory */ @@ -9092,10 +5392,10 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) struct brcms_bss_cfg *bsscfg; /* update AP or IBSS probe responses */ - FOREACH_BSS(wlc, idx, bsscfg) + FOREACH_BSS(wlc, idx, bsscfg) { if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS)) brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); - END_FOREACH_BSS() + } } void @@ -9106,10 +5406,7 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, u16 prb_resp[BCN_TMPL_LEN / 2]; int len = BCN_TMPL_LEN; - /* - * write the probe response to hardware, or save in - * the config structure - */ + /* write the probe response to hardware, or save in the config structure */ if (!MBSS_PRB_ENAB(cfg)) { /* create the probe response template */ @@ -9130,18 +5427,17 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, brcms_c_shm_ssid_upd(wlc, cfg); /* - * Write PLCP headers and durations for probe response frames - * at all rates. Use the actual frame length covered by the - * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() - * by subtracting the PLCP len and adding the FCS. + * Write PLCP headers and durations for probe response frames at all rates. + * Use the actual frame length covered by the PLCP header for the call to + * brcms_c_mod_prb_rsp_rate_table() by subtracting the PLCP len + * and adding the FCS. */ len += (-D11_PHY_HDR_LEN + FCS_LEN); brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len); if (suspend) brcms_c_enable_mac(wlc); - } else { - /* Generating probe resp in sw; update local template */ + } else { /* Generating probe resp in sw; update local template */ /* error: No software probe response support without MBSS */ } } @@ -9180,9 +5476,9 @@ void brcms_c_reprate_init(struct brcms_c_info *wlc) int i; struct brcms_bss_cfg *bsscfg; - FOREACH_BSS(wlc, i, bsscfg) + FOREACH_BSS(wlc, i, bsscfg) { brcms_c_bsscfg_reprate_init(bsscfg); - END_FOREACH_BSS() + } } /* per bsscfg init tx reported rate mechanism */ @@ -9192,7 +5488,7 @@ void brcms_c_bsscfg_reprate_init(struct brcms_bss_cfg *bsscfg) memset((char *)bsscfg->txrspec, 0, sizeof(bsscfg->txrspec)); } -void brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs) +void brcms_default_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs) { brcms_c_rateset_default(rs, NULL, wlc->band->phytype, wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL, @@ -9203,7 +5499,7 @@ void brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs) static void brcms_c_bss_default_init(struct brcms_c_info *wlc) { - u16 chanspec; + chanspec_t chanspec; struct brcms_band *band; struct brcms_bss_info *bi = wlc->default_bss; @@ -9233,21 +5529,22 @@ static void brcms_c_bss_default_init(struct brcms_c_info *wlc) bi->flags |= BRCMS_BSS_HT; } -static u32 +static ratespec_t mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, u32 int_val) { u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT; u8 rate = int_val & NRATE_RATE_MASK; - u32 rspec; + ratespec_t rspec; bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE); bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT); bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY) == NRATE_OVERRIDE_MCS_ONLY); int bcmerror = 0; - if (!ismcs) - return (u32) rate; + if (!ismcs) { + return (ratespec_t) rate; + } /* validate the combination of rate/mcs/stf is allowed */ if (N_ENAB(wlc->pub) && ismcs) { @@ -9279,10 +5576,7 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, stf = PHY_TXC1_MODE_SDM; } } else { - /* - * MCS 0-7 may use SISO, CDD, and for - * phy_rev >= 3 STBC - */ + /* MCS 0-7 may use SISO, CDD, and for phy_rev >= 3 STBC */ if ((stf > PHY_TXC1_MODE_STBC) || (!BRCMS_STBC_CAP_PHY(wlc) && (stf == PHY_TXC1_MODE_STBC))) { @@ -9341,8 +5635,9 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, rspec |= RSPEC_SHORT_GI; if ((rate != 0) - && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true)) + && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true)) { return rate; + } return rspec; done: @@ -9419,17 +5714,6 @@ void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val, int bands) brcms_b_mhf(wlc->hw, idx, mask, val, bands); } -int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, - uint *blocks) -{ - if (fifo >= NFIFO) - return -EINVAL; - - *blocks = wlc_hw->xmtfifo_sz[fifo]; - - return 0; -} - int brcms_c_xmtfifo_sz_get(struct brcms_c_info *wlc, uint fifo, uint *blocks) { return brcms_b_xmtfifo_sz_get(wlc->hw, fifo, blocks); @@ -9441,8 +5725,8 @@ void brcms_c_write_template_ram(struct brcms_c_info *wlc, int offset, int len, brcms_b_write_template_ram(wlc->hw, offset, len, buf); } -void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, u16 bcn[], int len, - bool both) +void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, void *bcn, int len, + bool both) { brcms_b_write_hw_bcntemplates(wlc->hw, bcn, len, both); } @@ -9456,7 +5740,7 @@ brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset, memcpy(wlc->cfg->BSSID, addr, ETH_ALEN); } -void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, u32 req_bit) +void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, mbool req_bit) { brcms_b_pllreq(wlc->hw, set, req_bit); } @@ -9473,10 +5757,11 @@ brcms_c_txflowcontrol_prio_isset(struct brcms_c_info *wlc, { uint prio_mask; - if (prio == ALLPRIO) + if (prio == ALLPRIO) { prio_mask = TXQ_STOP_FOR_PRIOFC_MASK; - else + } else { prio_mask = NBITVAL(prio); + } return (q->stopped & prio_mask) == prio_mask; } @@ -9491,10 +5776,11 @@ void brcms_c_txflowcontrol(struct brcms_c_info *wlc, BCMMSG(wlc->wiphy, "flow control kicks in\n"); - if (prio == ALLPRIO) + if (prio == ALLPRIO) { prio_bits = TXQ_STOP_FOR_PRIOFC_MASK; - else + } else { prio_bits = NBITVAL(prio); + } cur_bits = qi->stopped & prio_bits; @@ -9502,22 +5788,23 @@ void brcms_c_txflowcontrol(struct brcms_c_info *wlc, * Otherwise update the bit and continue */ if (on) { - if (cur_bits == prio_bits) + if (cur_bits == prio_bits) { return; - + } mboolset(qi->stopped, prio_bits); } else { - if (cur_bits == 0) + if (cur_bits == 0) { return; - + } mboolclr(qi->stopped, prio_bits); } /* If there is a flow control override we will not change the external * flow control state. */ - if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK) + if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK) { return; + } brcms_c_txflowcontrol_signal(wlc, qi, on, prio); } @@ -9539,8 +5826,9 @@ brcms_c_txflowcontrol_override(struct brcms_c_info *wlc, /* if there was a previous override bit on, then setting this * makes no difference. */ - if (prev_override) + if (prev_override) { return; + } brcms_c_txflowcontrol_signal(wlc, qi, ON, ALLPRIO); } else { @@ -9549,8 +5837,9 @@ brcms_c_txflowcontrol_override(struct brcms_c_info *wlc, * flow control if it was the only bit set. For any other * override setting, just return */ - if (prev_override != override) + if (prev_override != override) { return; + } if (qi->stopped == 0) { brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO); @@ -9694,8 +5983,9 @@ void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) /* wait for queue and DMA fifos to run dry */ while (!pktq_empty(&wlc->pkt_queue->q) || - TXPKTPENDTOT(wlc) > 0) + TXPKTPENDTOT(wlc) > 0) { brcms_msleep(wlc->wl, 1); + } } int brcms_c_set_par(struct brcms_c_info *wlc, enum wlc_par_id par_id, @@ -9803,11 +6093,10 @@ char *getvar(char *vars, const char *name) int getintvar(char *vars, const char *name) { char *val; - unsigned long res; val = getvar(vars, name); - if (val && !kstrtoul(val, 0, &res)) - return res; + if (val == NULL) + return 0; - return 0; + return simple_strtoul(val, NULL, 0); } diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/main.h b/trunk/drivers/staging/brcm80211/brcmsmac/main.h index 433e6a94c5d8..f204b1f47475 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/main.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/main.h @@ -49,7 +49,8 @@ /* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */ #define BRCMS_MAX_MAC_SUSPEND 83000 -/* responses for probe requests older that this are tossed, zero to disable */ +/* Probe Response timeout - responses for probe requests older that this are tossed, zero to disable + */ #define BRCMS_PRB_RESP_TIMEOUT 0 /* Disable probe response timeout */ /* transmit buffer max headroom for protocol headers */ @@ -122,9 +123,7 @@ #define BOARDREV_PROMOTABLE 0xFF /* from */ #define BOARDREV_PROMOTED 1 /* to */ -/* - * if wpa is in use then portopen is true when the - * group key is plumbed otherwise it is always true +/* if wpa is in use then portopen is true when the group key is plumbed otherwise it is always true */ #define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) #define BRCMS_SW_KEYS(wlc, bsscfg) ((((wlc)->wsec_swkeys) || \ @@ -164,13 +163,13 @@ extern const u8 prio2fifo[]; #define RETRY_SHORT_DEF 7 /* Default Short retry Limit */ #define RETRY_SHORT_MAX 255 /* Maximum Short retry Limit */ #define RETRY_LONG_DEF 4 /* Default Long retry count */ -#define RETRY_SHORT_FB 3 /* Short count for fallback rate */ -#define RETRY_LONG_FB 2 /* Long count for fallback rate */ +#define RETRY_SHORT_FB 3 /* Short retry count for fallback rate */ +#define RETRY_LONG_FB 2 /* Long retry count for fallback rate */ #define MAXTXPKTS 6 /* max # pkts pending */ /* frameburst */ -#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */ +#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */ #define MAXFRAMEBURST_TXOP 10000 /* Frameburst TXOP in usec */ /* Per-AC retry limit register definitions; uses defs.h bitfield macros */ @@ -229,12 +228,11 @@ extern const u8 prio2fifo[]; /* * Detect Card removed. - * Even checking an sbconfig register read will not false trigger when the core - * is in reset it breaks CF address mechanism. Accessing gphy phyversion will - * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible - * reg with fixed 0/1 pattern (some platforms return all 0). - * If clocks are present, call the sb routine which will figure out if the - * device is removed. + * Even checking an sbconfig register read will not false trigger when the core is in reset. + * it breaks CF address mechanism. Accessing gphy phyversion will cause SB error if aphy + * is in reset on 4306B0-DB. Need a simple accessible reg with fixed 0/1 pattern + * (some platforms return all 0). + * If clocks are present, call the sb routine which will figure out if the device is removed. */ #define DEVICEREMOVED(wlc) \ ((wlc->hw->clk) ? \ @@ -244,87 +242,52 @@ extern const u8 prio2fifo[]; #define BRCMS_UNIT(wlc) ((wlc)->pub->unit) -#define brcms_b_copyfrom_shm(wlc_hw, offset, buf, len) \ - brcms_b_copyfrom_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL) - -#define brcms_b_copyto_shm(wlc_hw, offset, buf, len) \ - brcms_b_copyto_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL) - -/* - * 802.11 protection information - * - * _g: use g spec protection, driver internal. - * g_override: override for use of g spec protection. - * gmode_user: user config gmode, operating band->gmode is different. - * overlap: Overlap BSS/IBSS protection for both 11g and 11n. - * nmode_user: user config nmode, operating pub->nmode is different. - * n_cfg: use OFDM protection on MIMO frames. - * n_cfg_override: override for use of N protection. - * nongf: non-GF present protection. - * nongf_override: override for use of GF protection. - * n_pam_override: override for preamble: MM or GF. - * n_obss: indicated OBSS Non-HT STA present. -*/ struct brcms_protection { - bool _g; - s8 g_override; - u8 gmode_user; - s8 overlap; - s8 nmode_user; - s8 n_cfg; - s8 n_cfg_override; - bool nongf; - s8 nongf_override; - s8 n_pam_override; - bool n_obss; + bool _g; /* use g spec protection, driver internal */ + s8 g_override; /* override for use of g spec protection */ + u8 gmode_user; /* user config gmode, operating band->gmode is different */ + s8 overlap; /* Overlap BSS/IBSS protection for both 11g and 11n */ + s8 nmode_user; /* user config nmode, operating pub->nmode is different */ + s8 n_cfg; /* use OFDM protection on MIMO frames */ + s8 n_cfg_override; /* override for use of N protection */ + bool nongf; /* non-GF present protection */ + s8 nongf_override; /* override for use of GF protection */ + s8 n_pam_override; /* override for preamble: MM or GF */ + bool n_obss; /* indicated OBSS Non-HT STA present */ }; -/* - * anything affecting the single/dual streams/antenna operation - * - * hw_txchain: HW txchain bitmap cfg. - * txchain: txchain bitmap being used. - * txstreams: number of txchains being used. - * hw_rxchain: HW rxchain bitmap cfg. - * rxchain: rxchain bitmap being used. - * rxstreams: number of rxchains being used. - * ant_rx_ovr: rx antenna override. - * txant: userTx antenna setting. - * phytxant: phyTx antenna setting in txheader. - * ss_opmode: singlestream Operational mode, 0:siso; 1:cdd. - * ss_algosel_auto: if true, use wlc->stf->ss_algo_channel; - * else use wlc->band->stf->ss_mode_band. - * ss_algo_channel: ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC. - * no_cddstbc: stf override, 1: no CDD (or STBC) allowed. - * rxchain_restore_delay: delay time to restore default rxchain. - * ldpc: AUTO/ON/OFF ldpc cap supported. - * txcore[MAX_STREAMS_SUPPORTED + 1]: bitmap of selected core for each Nsts. - * spatial_policy: - */ +/* anything affects the single/dual streams/antenna operation */ struct brcms_stf { - u8 hw_txchain; - u8 txchain; - u8 txstreams; - u8 hw_rxchain; - u8 rxchain; - u8 rxstreams; - u8 ant_rx_ovr; - s8 txant; - u16 phytxant; - u8 ss_opmode; - bool ss_algosel_auto; - u16 ss_algo_channel; - u8 no_cddstbc; - u8 rxchain_restore_delay; - s8 ldpc; - u8 txcore[MAX_STREAMS_SUPPORTED + 1]; + u8 hw_txchain; /* HW txchain bitmap cfg */ + u8 txchain; /* txchain bitmap being used */ + u8 txstreams; /* number of txchains being used */ + + u8 hw_rxchain; /* HW rxchain bitmap cfg */ + u8 rxchain; /* rxchain bitmap being used */ + u8 rxstreams; /* number of rxchains being used */ + + u8 ant_rx_ovr; /* rx antenna override */ + s8 txant; /* userTx antenna setting */ + u16 phytxant; /* phyTx antenna setting in txheader */ + + u8 ss_opmode; /* singlestream Operational mode, 0:siso; 1:cdd */ + bool ss_algosel_auto; /* if true, use wlc->stf->ss_algo_channel; */ + /* else use wlc->band->stf->ss_mode_band; */ + u16 ss_algo_channel; /* ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC */ + u8 no_cddstbc; /* stf override, 1: no CDD (or STBC) allowed */ + + u8 rxchain_restore_delay; /* delay time to restore default rxchain */ + + s8 ldpc; /* AUTO/ON/OFF ldpc cap supported */ + u8 txcore[MAX_STREAMS_SUPPORTED + 1]; /* bitmap of selected core for each Nsts */ s8 spatial_policy; }; #define BRCMS_STF_SS_STBC_TX(wlc, scb) \ - (((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) \ - || (SCB_STBC_CAP((scb)) && (wlc)->band->band_stf_stbc_tx == AUTO && \ - isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC)))) + (((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) || \ + (SCB_STBC_CAP((scb)) && \ + (wlc)->band->band_stf_stbc_tx == AUTO && \ + isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC)))) #define BRCMS_STBC_CAP_PHY(wlc) (BRCMS_ISNPHY(wlc->band) && \ NREV_GE(wlc->band->phyrev, 3)) @@ -343,12 +306,9 @@ struct brcms_stf { #define BRCMS_BSS_HT 0x0020 /* BSS is HT (MIMO) capable */ /* Flags used in brcms_c_txq_info.stopped */ -/* per prio flow control bits */ -#define TXQ_STOP_FOR_PRIOFC_MASK 0x000000FF -/* stop txq enqueue for packet drain */ -#define TXQ_STOP_FOR_PKT_DRAIN 0x00000100 -/* stop txq enqueue for ampdu flow control */ -#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL 0x00000200 +#define TXQ_STOP_FOR_PRIOFC_MASK 0x000000FF /* per prio flow control bits */ +#define TXQ_STOP_FOR_PKT_DRAIN 0x00000100 /* stop txq enqueue for packet drain */ +#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL 0x00000200 /* stop txq enqueue for ampdu flow control */ #define BRCMS_HT_WEP_RESTRICT 0x01 /* restrict HT with WEP */ #define BRCMS_HT_TKIP_RESTRICT 0x02 /* restrict HT with TKIP */ @@ -356,8 +316,8 @@ struct brcms_stf { /* Maximum # of keys that wl driver supports in S/W. * Keys supported in H/W is less than or equal to WSEC_MAX_KEYS. */ -#define WSEC_MAX_KEYS 54 /* Max # of keys (50 + 4 default keys) */ -#define BRCMS_DEFAULT_KEYS 4 /* Default # of keys */ +#define WSEC_MAX_KEYS 54 /* Max # of keys (50 + 4 default keys) */ +#define BRCMS_DEFAULT_KEYS 4 /* Default # of keys */ /* * Max # of keys currently supported: @@ -381,14 +341,14 @@ struct wsec_key { u8 ea[ETH_ALEN]; /* per station */ u8 idx; /* key index in wsec_keys array */ u8 id; /* key ID [0-3] */ - u8 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ - u8 rcmta; /* rcmta entry index, same as idx by default */ - u16 flags; /* misc flags */ - u8 algo_hw; /* cache for hw register */ - u8 aes_mode; /* cache for hw register */ - s8 iv_len; /* IV length */ - s8 icv_len; /* ICV length */ - u32 len; /* key length..don't move this var */ + u8 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ + u8 rcmta; /* rcmta entry index, same as idx by default */ + u16 flags; /* misc flags */ + u8 algo_hw; /* cache for hw register */ + u8 aes_mode; /* cache for hw register */ + s8 iv_len; /* IV length */ + s8 icv_len; /* ICV length */ + u32 len; /* key length..don't move this var */ /* data is 4byte aligned */ u8 data[WLAN_MAX_KEY_LEN]; /* key data */ struct wsec_iv rxiv[BRCMS_NUMRXIVS]; /* Rx IV (one per TID) */ @@ -426,29 +386,27 @@ struct brcms_band { struct scb *hwrs_scb; /* permanent scb for hw rateset */ - /* band-specific copy of default_bss.rateset */ - struct brcms_c_rateset defrateset; + wlc_rateset_t defrateset; /* band-specific copy of default_bss.rateset */ - u32 rspec_override; /* 802.11 rate override */ - u32 mrspec_override; /* multicast rate override */ + ratespec_t rspec_override; /* 802.11 rate override */ + ratespec_t mrspec_override; /* multicast rate override */ u8 band_stf_ss_mode; /* Configured STF type, 0:siso; 1:cdd */ s8 band_stf_stbc_tx; /* STBC TX 0:off; 1:force on; -1:auto */ - /* rates supported by chip (phy-specific) */ - struct brcms_c_rateset hw_rateset; + wlc_rateset_t hw_rateset; /* rates supported by chip (phy-specific) */ u8 basic_rate[BRCM_MAXRATE + 1]; /* basic rates indexed by rate */ bool mimo_cap_40; /* 40 MHz cap enabled on this band */ s8 antgain; /* antenna gain from srom */ - u16 CWmin; /* minimum size of contention window, in unit of aSlotTime */ - u16 CWmax; /* maximum size of contention window, in unit of aSlotTime */ + u16 CWmin; /* The minimum size of contention window, in unit of aSlotTime */ + u16 CWmax; /* The maximum size of contention window, in unit of aSlotTime */ u16 bcntsfoff; /* beacon tsf offset */ }; -struct pkt_cb { - /* function to call when tx frame completes */ - /* tx completion callback takes 3 args */ - void (*fn)(struct brcms_c_info *wlc, uint txstatus, void *arg); +/* tx completion callback takes 3 args */ +typedef void (*pkcb_fn_t) (struct brcms_c_info *wlc, uint txstatus, void *arg); +struct pkt_cb { + pkcb_fn_t fn; /* function to call when tx frame completes */ void *arg; /* void arg for fn */ u8 nextidx; /* index of next call back if threading */ bool entered; /* recursion check */ @@ -456,39 +414,24 @@ struct pkt_cb { /* module control blocks */ struct modulecb { - /* module name : NULL indicates empty array member */ - char name[32]; - /* iovar table */ - const struct brcmu_iovar *iovars; - /* handle passed when handler 'doiovar' is called */ - struct brcms_info *hdl; - - /* IOVar handler - * - * handle - a pointer value registered with the function - * vi - iovar_info that was looked up - * actionid - action ID, calculated by IOV_GVAL() and IOV_SVAL() - * based on varid. - * name - the actual iovar name - * params/plen - parameters and length for a get, input only. - * arg/len - buffer and length for value to be set or retrieved, - * input or output. - * vsize - value size, valid for integer type only. - * wlcif - interface context (brcms_c_if pointer) - * - * All pointers may point into the same buffer. - */ - int (*iovar_fn)(void *handle, const struct brcmu_iovar *vi, - u32 actionid, const char *name, void *params, - uint plen, void *arg, int alen, int vsize, - struct brcms_c_if *wlcif); - - int (*down_fn)(void *handle); /* down handler. Note: the int returned - * by the down function is a count of the - * number of timers that could not be - * freed. - */ + char name[32]; /* module name : NULL indicates empty array member */ + const struct brcmu_iovar *iovars; /* iovar table */ + void *hdl; /* handle passed when handler 'doiovar' is called */ + watchdog_fn_t watchdog_fn; /* watchdog handler */ + iovar_fn_t iovar_fn; /* iovar handler */ + down_fn_t down_fn; /* down handler. Note: the int returned + * by the down function is a count of the + * number of timers that could not be + * freed. + */ +}; +/* dump control blocks */ +struct dumpcb_s { + const char *name; /* dump name */ + dump_fn_t dump_fn; /* 'wl dump' handler */ + void *dump_fn_arg; + struct dumpcb_s *next; }; struct edcf_acparam { @@ -510,11 +453,11 @@ struct wme_param_ie { /* virtual interface */ struct brcms_c_if { struct brcms_c_if *next; - u8 type; /* BSS or WDS */ - u8 index; /* assigned in wl_add_if(), index of the wlif if any, - * not necessarily corresponding to bsscfg._idx or - * AID2PVBMAP(scb). - */ + u8 type; /* BSS or WDS */ + u8 index; /* assigned in wl_add_if(), index of the wlif if any, + * not necessarily corresponding to bsscfg._idx or + * AID2PVBMAP(scb). + */ u8 flags; /* flags for the interface */ struct brcms_if *wlif; /* pointer to wlif */ struct brcms_txq_info *qi; /* pointer to associated tx queue */ @@ -570,9 +513,9 @@ struct brcms_hardware { struct si_pub *sih; /* SI handle (cookie for siutils calls) */ char *vars; /* "environment" name=value */ uint vars_size; /* size of vars, free vars on detach */ - struct d11regs *regs; /* pointer to device registers */ - struct phy_shim_info *physhim; /* phy shim layer handler */ - struct shared_phy *phy_sh; /* pointer to shared phy state */ + d11regs_t *regs; /* pointer to device registers */ + void *physhim; /* phy shim layer handler */ + void *phy_sh; /* pointer to shared phy state */ struct brcms_hw_band *band;/* pointer to active per-band state */ /* band state per phy/radio */ struct brcms_hw_band *bandstate[MAXBANDS]; @@ -586,22 +529,22 @@ struct brcms_hardware { bool up; /* d11 hardware up and running */ uint now; /* # elapsed seconds */ uint _nbands; /* # bands supported */ - u16 chanspec; /* bmac chanspec shadow */ + chanspec_t chanspec; /* bmac chanspec shadow */ uint *txavail[NFIFO]; /* # tx descriptors available */ u16 *xmtfifo_sz; /* fifo size in 256B for each xmt fifo */ - u32 pllreq; /* pll requests to keep PLL on */ + mbool pllreq; /* pll requests to keep PLL on */ u8 suspended_fifos; /* Which TX fifo to remain awake for */ u32 maccontrol; /* Cached value of maccontrol */ uint mac_suspend_depth; /* current depth of mac_suspend levels */ - u32 wake_override; /* bit flags to force MAC to WAKE mode */ + u32 wake_override; /* Various conditions to force MAC to WAKE mode */ u32 mute_override; /* Prevent ucode from sending beacons */ u8 etheraddr[ETH_ALEN]; /* currently configured ethernet address */ u32 led_gpio_mask; /* LED GPIO Mask */ bool noreset; /* true= do not reset hw, used by WLC_OUT */ - bool forcefastclk; /* true if h/w is forcing to use fast clk */ + bool forcefastclk; /* true if the h/w is forcing the use of fast clk */ bool clk; /* core is out of reset and has clock */ bool sbclk; /* sb has clock */ struct bmac_pmq *bmac_pmq; /* bmac PM states derived from ucode PMQ */ @@ -635,267 +578,194 @@ struct brcms_txq_info { }; /* - * Principal common driver data structure. - * - * pub: pointer to driver public state. - * wl: pointer to specific private state. - * regs: pointer to device registers. - * hw: HW related state. - * clkreq_override: setting for clkreq for PCIE : Auto, 0, 1. - * fastpwrup_dly: time in us needed to bring up d11 fast clock. - * macintstatus: bit channel between isr and dpc. - * macintmask: sw runtime master macintmask value. - * defmacintmask: default "on" macintmask value. - * device_present: (removable) device is present. - * clk: core is out of reset and has clock. - * core: pointer to active io core. - * band: pointer to active per-band state. - * corestate: per-core state (one per hw core). - * bandstate: per-band state (one per phy/radio). - * war16165: PCI slow clock 16165 war flag. - * tx_suspended: data fifos need to remain suspended. - * txpend16165war: PCI slow clock 16165 war flag. - * qvalid: DirFrmQValid and BcMcFrmQValid. - * txpwr_local_max: regulatory local txpwr max. - * txpwr_local_constraint: local power contraint in dB. - * ampdu: ampdu module handler. - * asi: antsel module handler. - * cmi: channel manager module handler. - * vars_size: size of vars, free vars on detach. - * vendorid: PCI vendor id. - * deviceid: PCI device id. - * ucode_rev: microcode revision. - * machwcap: MAC capabilities, BMAC shadow. - * perm_etheraddr: original sprom local ethernet address. - * bandlocked: disable auto multi-band switching. - * bandinit_pending: track band init in auto band. - * radio_monitor: radio timer is running. - * going_down: down path intermediate variable. - * mpc: enable minimum power consumption. - * mpc_dlycnt: # of watchdog cnt before turn disable radio. - * mpc_offcnt: # of watchdog cnt that radio is disabled. - * mpc_delay_off: delay radio disable by # of watchdog cnt. - * prev_non_delay_mpc: prev state brcms_c_is_non_delay_mpc. - * wdtimer: timer for watchdog routine. - * radio_timer: timer for hw radio button monitor routine. - * monitor: monitor (MPDU sniffing) mode. - * bcnmisc_ibss: bcns promisc mode override for IBSS. - * bcnmisc_scan: bcns promisc mode override for scan. - * bcnmisc_monitor: bcns promisc mode override for monitor. - * _rifs: enable per-packet rifs. - * sgi_tx: sgi tx. - * bcn_li_bcn: beacon listen interval in # beacons. - * bcn_li_dtim: beacon listen interval in # dtims. - * WDarmed: watchdog timer is armed. - * WDlast: last time wlc_watchdog() was called. - * wme_dp: AC bitmap. Discard (oldest first) policy per AC. - * edcf_txop[AC_COUNT]: current txop for each ac. - * wme_param_ie: on STA contains parameters in use locally, and on AP - * contains parameters advertised - * wme_retries: per-AC retry limits. - * tx_prec_map: Precedence map based on HW FIFO space. - * fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME. - * bsscfg: set of BSS configurations, idx 0 is default and always valid. - * cfg: the primary bsscfg (can be AP or STA). - * tx_queues: common TX Queue list. - * wsec_keys[WSEC_MAX_KEYS]: dynamic key storage. - * wsec_def_keys[BRCMS_DEFAULT_KEYS]: default key storage. - * wsec_swkeys: indicates that all keys should be treated as - * sw keys (used for debugging). - * modulecb: - * mimoft: SIGN or 11N. - * cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode. - * ofdm_40txbw: 11N, ofdm tx b/w override when in 40MHZ mode. - * mimo_40txbw: 11N, mimo tx b/w override when in 40MHZ mode. - * ht_cap: HT CAP IE being advertised by this node. - * default_bss: configured BSS parameters. - * mc_fid_counter: BC/MC FIFO frame ID counter. - * country_default: saved country for leaving 802.11d auto-country mode. - * autocountry_default: initial country for 802.11d auto-country mode. - * prb_resp_timeout: do not send prb resp if request older - * than this, 0 = disable. - * sup_rates_override: use only these rates in 11g supported rates if specified. - * home_chanspec: shared home chanspec. - * chanspec: target operational channel. - * usr_fragthresh: user configured fragmentation threshold. - * fragthresh[NFIFO]: per-fifo fragmentation thresholds. - * RTSThresh: 802.11 dot11RTSThreshold. - * SRL: 802.11 dot11ShortRetryLimit. - * LRL: 802.11 dot11LongRetryLimit. - * SFBL: Short Frame Rate Fallback Limit. - * LFBL: Long Frame Rate Fallback Limit. - * shortslot: currently using 11g ShortSlot timing. - * shortslot_override: 11g ShortSlot override. - * include_legacy_erp: include Legacy ERP info elt ID 47 as well as g ID 42. - * PLCPHdr_override: 802.11b Preamble Type override. - * stf: - * bcn_rspec: save bcn ratespec purpose. - * tempsense_lasttime; - * tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM. - * tx_duty_cycle_cck: maximum allowed duty cycle for CCK. - * next_bsscfg_ID; - * pkt_queue: txq for transmit packets. - * mpc_dur: total time (ms) in mpc mode except for the portion since - * radio is turned off last time. - * mpc_laston_ts: timestamp (ms) when radio is turned off last time. - * wiphy: + * Principal common (os-independent) software data structure. */ struct brcms_c_info { - struct brcms_pub *pub; - struct brcms_info *wl; - struct d11regs *regs; + struct brcms_pub *pub; /* pointer to wlc public state */ + struct brcms_info *wl; /* pointer to os-specific private state */ + d11regs_t *regs; /* pointer to device registers */ + + /* HW related state used primarily by BMAC */ struct brcms_hardware *hw; /* clock */ - int clkreq_override; - u16 fastpwrup_dly; + int clkreq_override; /* setting for clkreq for PCIE : Auto, 0, 1 */ + u16 fastpwrup_dly; /* time in us needed to bring up d11 fast clock */ /* interrupt */ - u32 macintstatus; - u32 macintmask; - u32 defmacintmask; + u32 macintstatus; /* bit channel between isr and dpc */ + u32 macintmask; /* sw runtime master macintmask value */ + u32 defmacintmask; /* default "on" macintmask value */ /* up and down */ - bool device_present; + bool device_present; /* (removable) device is present */ - bool clk; + bool clk; /* core is out of reset and has clock */ /* multiband */ - struct brcms_core *core; - struct brcms_band *band; - struct brcms_core *corestate; + struct brcms_core *core; /* pointer to active io core */ + struct brcms_band *band; /* pointer to active per-band state */ + struct brcms_core *corestate; /* per-core state (one per hw core) */ + /* per-band state (one per phy/radio): */ struct brcms_band *bandstate[MAXBANDS]; - bool war16165; + bool war16165; /* PCI slow clock 16165 war flag */ - bool tx_suspended; + bool tx_suspended; /* data fifos need to remain suspended */ uint txpend16165war; /* packet queue */ - uint qvalid; + uint qvalid; /* DirFrmQValid and BcMcFrmQValid */ /* Regulatory power limits */ - s8 txpwr_local_max; - u8 txpwr_local_constraint; + s8 txpwr_local_max; /* regulatory local txpwr max */ + u8 txpwr_local_constraint; /* local power contraint in dB */ - struct ampdu_info *ampdu; - struct antsel_info *asi; - struct brcms_cm_info *cmi; + struct ampdu_info *ampdu; /* ampdu module handler */ + struct antsel_info *asi; /* antsel module handler */ + struct brcms_cm_info *cmi; /* channel manager module handler */ - uint vars_size; + uint vars_size; /* size of vars, free vars on detach */ - u16 vendorid; - u16 deviceid; - uint ucode_rev; + u16 vendorid; /* PCI vendor id */ + u16 deviceid; /* PCI device id */ + uint ucode_rev; /* microcode revision */ - u32 machwcap; + u32 machwcap; /* MAC capabilities, BMAC shadow */ - u8 perm_etheraddr[ETH_ALEN]; + u8 perm_etheraddr[ETH_ALEN]; /* original sprom local ethernet address */ - bool bandlocked; - bool bandinit_pending; + bool bandlocked; /* disable auto multi-band switching */ + bool bandinit_pending; /* track band init in auto band */ - bool radio_monitor; - bool going_down; + bool radio_monitor; /* radio timer is running */ + bool going_down; /* down path intermediate variable */ - bool mpc; - u8 mpc_dlycnt; - u8 mpc_offcnt; - u8 mpc_delay_off; - u8 prev_non_delay_mpc; + bool mpc; /* enable minimum power consumption */ + u8 mpc_dlycnt; /* # of watchdog cnt before turn disable radio */ + u8 mpc_offcnt; /* # of watchdog cnt that radio is disabled */ + u8 mpc_delay_off; /* delay radio disable by # of watchdog cnt */ + u8 prev_non_delay_mpc; /* prev state brcms_c_is_non_delay_mpc */ + /* timer for watchdog routine */ struct brcms_timer *wdtimer; + /* timer for hw radio button monitor routine */ struct brcms_timer *radio_timer; /* promiscuous */ - bool monitor; - bool bcnmisc_ibss; - bool bcnmisc_scan; - bool bcnmisc_monitor; + bool monitor; /* monitor (MPDU sniffing) mode */ + bool bcnmisc_ibss; /* bcns promisc mode override for IBSS */ + bool bcnmisc_scan; /* bcns promisc mode override for scan */ + bool bcnmisc_monitor; /* bcns promisc mode override for monitor */ /* driver feature */ - bool _rifs; - s8 sgi_tx; + bool _rifs; /* enable per-packet rifs */ + s8 sgi_tx; /* sgi tx */ /* AP-STA synchronization, power save */ - u8 bcn_li_bcn; - u8 bcn_li_dtim; + u8 bcn_li_bcn; /* beacon listen interval in # beacons */ + u8 bcn_li_dtim; /* beacon listen interval in # dtims */ - bool WDarmed; - u32 WDlast; + bool WDarmed; /* watchdog timer is armed */ + u32 WDlast; /* last time wlc_watchdog() was called */ /* WME */ - u8 wme_dp; - u16 edcf_txop[AC_COUNT]; + ac_bitmap_t wme_dp; /* Discard (oldest first) policy per AC */ + u16 edcf_txop[AC_COUNT]; /* current txop for each ac */ + /* + * WME parameter info element, which on STA contains parameters in use + * locally, and on AP contains parameters advertised to STA in beacons + * and assoc responses. + */ struct wme_param_ie wme_param_ie; - u16 wme_retries[AC_COUNT]; - u16 tx_prec_map; - u16 fifo2prec_map[NFIFO]; + u16 wme_retries[AC_COUNT]; /* per-AC retry limits */ + u16 tx_prec_map; /* Precedence map based on HW FIFO space */ + u16 fifo2prec_map[NFIFO]; /* pointer to fifo2_prec map based on WME */ + + /* + * BSS Configurations set of BSS configurations, idx 0 is default and + * always valid + */ struct brcms_bss_cfg *bsscfg[BRCMS_MAXBSSCFG]; - struct brcms_bss_cfg *cfg; + struct brcms_bss_cfg *cfg; /* the primary bsscfg (can be AP or STA) */ /* tx queue */ - struct brcms_txq_info *tx_queues; + struct brcms_txq_info *tx_queues; /* common TX Queue list */ /* security */ - struct wsec_key *wsec_keys[WSEC_MAX_KEYS]; + struct wsec_key *wsec_keys[WSEC_MAX_KEYS]; /* dynamic key storage */ + /* default key storage */ struct wsec_key *wsec_def_keys[BRCMS_DEFAULT_KEYS]; - bool wsec_swkeys; + bool wsec_swkeys; /* indicates that all keys should be + * treated as sw keys (used for debugging) + */ struct modulecb *modulecb; - u8 mimoft; - s8 cck_40txbw; - s8 ofdm_40txbw; - s8 mimo_40txbw; + u8 mimoft; /* SIGN or 11N */ + s8 cck_40txbw; /* 11N, cck tx b/w override when in 40MHZ mode */ + s8 ofdm_40txbw; /* 11N, ofdm tx b/w override when in 40MHZ mode */ + s8 mimo_40txbw; /* 11N, mimo tx b/w override when in 40MHZ mode */ + /* HT CAP IE being advertised by this node: */ struct ieee80211_ht_cap ht_cap; - struct brcms_bss_info *default_bss; + struct brcms_bss_info *default_bss; /* configured BSS parameters */ - u16 mc_fid_counter; + u16 mc_fid_counter; /* BC/MC FIFO frame ID counter */ + /* saved country for leaving 802.11d auto-country mode */ char country_default[BRCM_CNTRY_BUF_SZ]; + /* initial country for 802.11d auto-country mode */ char autocountry_default[BRCM_CNTRY_BUF_SZ]; - u16 prb_resp_timeout; - struct brcms_c_rateset sup_rates_override; + u16 prb_resp_timeout; /* do not send prb resp if request older than this, + * 0 = disable + */ + + wlc_rateset_t sup_rates_override; /* use only these rates in 11g supported rates if + * specifed + */ - u16 home_chanspec; + chanspec_t home_chanspec; /* shared home chanspec */ /* PHY parameters */ - u16 chanspec; - u16 usr_fragthresh; - u16 fragthresh[NFIFO]; - u16 RTSThresh; - u16 SRL; - u16 LRL; - u16 SFBL; - u16 LFBL; + chanspec_t chanspec; /* target operational channel */ + u16 usr_fragthresh; /* user configured fragmentation threshold */ + u16 fragthresh[NFIFO]; /* per-fifo fragmentation thresholds */ + u16 RTSThresh; /* 802.11 dot11RTSThreshold */ + u16 SRL; /* 802.11 dot11ShortRetryLimit */ + u16 LRL; /* 802.11 dot11LongRetryLimit */ + u16 SFBL; /* Short Frame Rate Fallback Limit */ + u16 LFBL; /* Long Frame Rate Fallback Limit */ /* network config */ - bool shortslot; - s8 shortslot_override; - bool include_legacy_erp; + bool shortslot; /* currently using 11g ShortSlot timing */ + s8 shortslot_override; /* 11g ShortSlot override */ + bool include_legacy_erp; /* include Legacy ERP info elt ID 47 as well as g ID 42 */ struct brcms_protection *protection; - s8 PLCPHdr_override; + s8 PLCPHdr_override; /* 802.11b Preamble Type override */ struct brcms_stf *stf; - u32 bcn_rspec; + ratespec_t bcn_rspec; /* save bcn ratespec purpose */ uint tempsense_lasttime; - u16 tx_duty_cycle_ofdm; - u16 tx_duty_cycle_cck; + u16 tx_duty_cycle_ofdm; /* maximum allowed duty cycle for OFDM */ + u16 tx_duty_cycle_cck; /* maximum allowed duty cycle for CCK */ u16 next_bsscfg_ID; - struct brcms_txq_info *pkt_queue; - u32 mpc_dur; - u32 mpc_laston_ts; + struct brcms_txq_info *pkt_queue; /* txq for transmit packets */ + u32 mpc_dur; /* total time (ms) in mpc mode except for the + * portion since radio is turned off last time + */ + u32 mpc_laston_ts; /* timestamp (ms) when radio is turned off last + * time + */ struct wiphy *wiphy; }; @@ -912,136 +782,88 @@ struct antsel_info { struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */ }; -/* - * BSS configuration state - * - * wlc: wlc to which this bsscfg belongs to. - * up: is this configuration up operational - * enable: is this configuration enabled - * associated: is BSS in ASSOCIATED state - * BSS: infraustructure or adhoc - * dtim_programmed: - * SSID_len: the length of SSID - * SSID: SSID string - * bcmc_scb: one bcmc_scb per band - * _idx: the index of this bsscfg, assigned at wlc_bsscfg_alloc() - * - * MAC filter - * ---------- - * nmac: # of entries on maclist array - * macmode: allow/deny stations on maclist array - * maclist: list of source MAC addrs to match - - * security - * -------- - * wsec: wireless security bitvec - * auth: 802.11 authentication: Open, Shared Key, WPA - * openshared: try Open auth first, then Shared Key - * wsec_restrict: drop unencrypted packets if wsec is enabled - * eap_restrict: restrict data until 802.1X auth succeeds - * WPA_auth: WPA authenticated key management - * wpa2_preauth: default is true, wpa_cap sets value - * wsec_portopen: indicates keys are plumbed - * wpa_none_txiv: global txiv for WPA_NONE, tkip and aes - * wsec_index: 0-3: default tx key, -1: not set - * bss_def_keys: default key storage - * - * TKIP countermeasures - * -------------------- - * tkip_countermeasures: flags TKIP no-assoc period - * tk_cm_dt: detect timer - * tk_cm_bt: blocking timer - * tk_cm_bt_tmstmp: Timestamp when TKIP BT is activated - * tk_cm_activate: activate countermeasures after EAPOL-Key sent - * - * BSSID: BSSID (associated) - * cur_etheraddr: h/w address - * bcmc_fid: the last BCMC FID queued to TX_BCMC_FIFO - * bcmc_fid_shm: the last BCMC FID written to shared mem - * flags: BSSCFG flags; see below - * bcn: AP beacon - * bcn_len: AP beacon length - * ar_disassoc: disassociated in associated recreation - * auth_atmptd: auth type (open/shared) attempted - * - * pmkid_cand: PMKID candidate list - * npmkid_cand: num PMKID candidates - * pmkid: PMKID cache - * npmkid: num cached PMKIDs - * current_bss: BSS parms in ASSOCIATED state - * - * PM states - * --------- - * PMawakebcn: bcn recvd during current waking state - * PMpending: waiting for tx status with PM indicated set - * priorPMstate: Detecting PM state transitions - * PSpoll: flags there is an outstanding PS-Poll frame - * - * rcmta: BSSID entry in RCMTA, use the wsec key to manage the RCMTA entries. - * - * ID: 'unique' ID of this bsscfg, assigned at bsscfg allocation - * - * txrspecidx: index into tx rate circular buffer - * txrspec: circular buffer of prev MPDUs tx rates - */ +/* BSS configuration state */ struct brcms_bss_cfg { - struct brcms_c_info *wlc; - bool up; - bool enable; - bool associated; - bool BSS; + struct brcms_c_info *wlc; /* wlc to which this bsscfg belongs to. */ + bool up; /* is this configuration up operational */ + bool enable; /* is this configuration enabled */ + bool associated; /* is BSS in ASSOCIATED state */ + bool BSS; /* infraustructure or adhac */ bool dtim_programmed; - u8 SSID_len; - u8 SSID[IEEE80211_MAX_SSID_LEN]; - struct scb *bcmc_scb[MAXBANDS]; - s8 _idx; - uint nmac; - int macmode; - struct ether_addr *maclist; - u32 wsec; - s16 auth; - s16 openshared; - bool wsec_restrict; - bool eap_restrict; - u16 WPA_auth; - bool wpa2_preauth; - bool wsec_portopen; + + u8 SSID_len; /* the length of SSID */ + u8 SSID[IEEE80211_MAX_SSID_LEN]; /* SSID string */ + struct scb *bcmc_scb[MAXBANDS]; /* one bcmc_scb per band */ + s8 _idx; /* the index of this bsscfg, + * assigned at wlc_bsscfg_alloc() + */ + /* MAC filter */ + uint nmac; /* # of entries on maclist array */ + int macmode; /* allow/deny stations on maclist array */ + struct ether_addr *maclist; /* list of source MAC addrs to match */ + + /* security */ + u32 wsec; /* wireless security bitvec */ + s16 auth; /* 802.11 authentication: Open, Shared Key, WPA */ + s16 openshared; /* try Open auth first, then Shared Key */ + bool wsec_restrict; /* drop unencrypted packets if wsec is enabled */ + bool eap_restrict; /* restrict data until 802.1X auth succeeds */ + u16 WPA_auth; /* WPA: authenticated key management */ + bool wpa2_preauth; /* default is true, wpa_cap sets value */ + bool wsec_portopen; /* indicates keys are plumbed */ + /* global txiv for WPA_NONE, tkip and aes */ struct wsec_iv wpa_none_txiv; - int wsec_index; + int wsec_index; /* 0-3: default tx key, -1: not set */ + /* default key storage: */ struct wsec_key *bss_def_keys[BRCMS_DEFAULT_KEYS]; - bool tkip_countermeasures; - u32 tk_cm_dt; - u32 tk_cm_bt; - u32 tk_cm_bt_tmstmp; - bool tk_cm_activate; - u8 BSSID[ETH_ALEN]; - u8 cur_etheraddr[ETH_ALEN]; - u16 bcmc_fid; - u16 bcmc_fid_shm; - u32 flags; - u8 *bcn; - uint bcn_len; - bool ar_disassoc; - int auth_atmptd; - struct pmkid_cand pmkid_cand[MAXPMKID]; - uint npmkid_cand; - struct pmkid pmkid[MAXPMKID]; - uint npmkid; - struct brcms_bss_info *current_bss; - bool PMawakebcn; - bool PMpending; - bool priorPMstate; - bool PSpoll; + + /* TKIP countermeasures */ + bool tkip_countermeasures; /* flags TKIP no-assoc period */ + u32 tk_cm_dt; /* detect timer */ + u32 tk_cm_bt; /* blocking timer */ + u32 tk_cm_bt_tmstmp; /* Timestamp when TKIP BT is activated */ + bool tk_cm_activate; /* activate countermeasures after EAPOL-Key sent */ + + u8 BSSID[ETH_ALEN]; /* BSSID (associated) */ + u8 cur_etheraddr[ETH_ALEN]; /* h/w address */ + u16 bcmc_fid; /* the last BCMC FID queued to TX_BCMC_FIFO */ + u16 bcmc_fid_shm; /* the last BCMC FID written to shared mem */ + + u32 flags; /* BSSCFG flags; see below */ + + u8 *bcn; /* AP beacon */ + uint bcn_len; /* AP beacon length */ + bool ar_disassoc; /* disassociated in associated recreation */ + + int auth_atmptd; /* auth type (open/shared) attempted */ + + pmkid_cand_t pmkid_cand[MAXPMKID]; /* PMKID candidate list */ + uint npmkid_cand; /* num PMKID candidates */ + pmkid_t pmkid[MAXPMKID]; /* PMKID cache */ + uint npmkid; /* num cached PMKIDs */ + + struct brcms_bss_info *current_bss; /* BSS parms in ASSOCIATED state */ + + /* PM states */ + bool PMawakebcn; /* bcn recvd during current waking state */ + bool PMpending; /* waiting for tx status with PM indicated set */ + bool priorPMstate; /* Detecting PM state transitions */ + bool PSpoll; /* whether there is an outstanding PS-Poll frame */ + + /* BSSID entry in RCMTA, use the wsec key management infrastructure to + * manage the RCMTA entries. + */ struct wsec_key *rcmta; + + /* 'unique' ID of this bsscfg, assigned at bsscfg allocation */ u16 ID; - uint txrspecidx; - u32 txrspec[NTXRATE][2]; + + uint txrspecidx; /* index into tx rate circular buffer */ + ratespec_t txrspec[NTXRATE][2]; /* circular buffer of prev MPDUs tx rates */ }; -#define CHANNEL_BANDUNIT(wlc, ch) \ - (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX) -#define OTHERBANDUNIT(wlc) \ - ((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX)) +#define CHANNEL_BANDUNIT(wlc, ch) (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX) +#define OTHERBANDUNIT(wlc) ((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX)) #define IS_MBAND_UNLOCKED(wlc) \ ((NBANDS(wlc) > 1) && !(wlc)->bandlocked) @@ -1049,15 +871,14 @@ struct brcms_bss_cfg { #define BRCMS_BAND_PI_RADIO_CHANSPEC wlc_phy_chanspec_get(wlc->band->pi) /* sum the individual fifo tx pending packet counts */ -#define TXPKTPENDTOT(wlc) \ - ((wlc)->core->txpktpend[0] + (wlc)->core->txpktpend[1] + \ - (wlc)->core->txpktpend[2] + (wlc)->core->txpktpend[3]) -#define TXPKTPENDGET(wlc, fifo) ((wlc)->core->txpktpend[(fifo)]) -#define TXPKTPENDINC(wlc, fifo, val) ((wlc)->core->txpktpend[(fifo)] += (val)) -#define TXPKTPENDDEC(wlc, fifo, val) ((wlc)->core->txpktpend[(fifo)] -= (val)) -#define TXPKTPENDCLR(wlc, fifo) ((wlc)->core->txpktpend[(fifo)] = 0) -#define TXAVAIL(wlc, fifo) (*(wlc)->core->txavail[(fifo)]) -#define GETNEXTTXP(wlc, _queue) \ +#define TXPKTPENDTOT(wlc) ((wlc)->core->txpktpend[0] + (wlc)->core->txpktpend[1] + \ + (wlc)->core->txpktpend[2] + (wlc)->core->txpktpend[3]) +#define TXPKTPENDGET(wlc, fifo) ((wlc)->core->txpktpend[(fifo)]) +#define TXPKTPENDINC(wlc, fifo, val) ((wlc)->core->txpktpend[(fifo)] += (val)) +#define TXPKTPENDDEC(wlc, fifo, val) ((wlc)->core->txpktpend[(fifo)] -= (val)) +#define TXPKTPENDCLR(wlc, fifo) ((wlc)->core->txpktpend[(fifo)] = 0) +#define TXAVAIL(wlc, fifo) (*(wlc)->core->txavail[(fifo)]) +#define GETNEXTTXP(wlc, _queue) \ dma_getnexttxp((wlc)->hw->di[(_queue)], DMA_RANGE_TRANSMITTED) #define BRCMS_IS_MATCH_SSID(wlc, ssid1, ssid2, len1, len2) \ @@ -1073,15 +894,17 @@ extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, bool commit, s8 txpktpend); extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend); -extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, - struct sk_buff *sdu, uint prec); +extern void brcms_c_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu, + uint prec); extern void brcms_c_info_init(struct brcms_c_info *wlc, int unit); extern void brcms_c_print_txstatus(struct tx_status *txs); extern int brcms_c_xmtfifo_sz_get(struct brcms_c_info *wlc, uint fifo, uint *blocks); extern void brcms_c_write_template_ram(struct brcms_c_info *wlc, int offset, int len, void *buf); -extern void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, u32 req_bit); +extern void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, void *bcn, + int len, bool both); +extern void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, mbool req_bit); extern void brcms_c_reset_bmac_done(struct brcms_c_info *wlc); #if defined(BCMDBG) @@ -1094,7 +917,7 @@ extern void brcms_c_print_txdesc(struct d11txh *txh); extern void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit); extern void brcms_c_coredisable(struct brcms_hardware *wlc_hw); -extern bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rate, +extern bool brcms_c_valid_rate(struct brcms_c_info *wlc, ratespec_t rate, int band, bool verbose); extern void brcms_c_ap_upd(struct brcms_c_info *wlc); @@ -1120,14 +943,14 @@ extern void brcms_c_send_q(struct brcms_c_info *wlc); extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifo); -extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, +extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, ratespec_t ratespec, uint mac_len); -extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, - u32 rspec, +extern ratespec_t brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, + ratespec_t rspec, bool use_rspec, u16 mimo_ctlchbw); extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, - u32 rts_rate, - u32 frame_rate, + ratespec_t rts_rate, + ratespec_t frame_rate, u8 rts_preamble_type, u8 frame_preamble_type, uint frame_len, bool ba); @@ -1157,17 +980,19 @@ extern void brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, extern bool brcms_c_ismpc(struct brcms_c_info *wlc); extern bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc); extern void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc); +extern bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, + void *pkt, int prec); extern bool brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q, struct sk_buff *pkt, int prec, bool head); -extern u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec); -extern void brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rate, +extern u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec); +extern void brcms_c_compute_plcp(struct brcms_c_info *wlc, ratespec_t rate, uint length, u8 *plcp); extern uint brcms_c_calc_frame_time(struct brcms_c_info *wlc, - u32 ratespec, + ratespec_t ratespec, u8 preamble_type, uint mac_len); extern void brcms_c_set_chanspec(struct brcms_c_info *wlc, - u16 chanspec); + chanspec_t chanspec); extern bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit); @@ -1183,61 +1008,18 @@ extern void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend); extern void brcms_c_set_ratetable(struct brcms_c_info *wlc); extern int brcms_c_set_mac(struct brcms_bss_cfg *cfg); extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, - u32 bcn_rate); + ratespec_t bcn_rate); extern void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len); -extern u32 brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc, - struct brcms_c_rateset *rs); +extern ratespec_t brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc, + wlc_rateset_t *rs); extern void brcms_c_radio_disable(struct brcms_c_info *wlc); extern void brcms_c_bcn_li_upd(struct brcms_c_info *wlc); extern void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, - u16 chanspec); + chanspec_t chanspec); extern bool brcms_c_ps_allowed(struct brcms_c_info *wlc); extern bool brcms_c_stay_awake(struct brcms_c_info *wlc); extern void brcms_c_wme_initparams_sta(struct brcms_c_info *wlc, struct wme_param_ie *pe); -extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, - u8 antsel_type); - -/* chanspec, ucode interface */ -extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, - u16 chanspec, - bool mute, struct txpwr_limits *txpwr); - -extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, - u16 v); -extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset); - -extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, - u16 val, int bands); - -extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags); - -extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val); - -extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw); -extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw); -extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw); -extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, - u32 override_bit); -extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, - u32 override_bit); -extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, - int offset, int len, void *buf); -extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate); -extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, - uint offset, const void *buf, int len, - u32 sel); -extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, - void *buf, int len, u32 sel); -extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode); -extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw); -extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk); -extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk); -extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on); -extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant); -extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, - u8 stf_mode); - #endif /* _BRCM_MAIN_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/nicpci.c b/trunk/drivers/staging/brcm80211/brcmsmac/nicpci.c index 2d46e701dd25..3d71c590fcef 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/nicpci.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/nicpci.c @@ -213,7 +213,9 @@ struct pcicore_info { /* debug/trace */ #define PCI_ERROR(args) -#define PCIE_PUB(sih) ((sih)->buscoretype == PCIE_CORE_ID) +#define PCIE_PUB(sih) \ + (((sih)->bustype == PCI_BUS) && \ + ((sih)->buscoretype == PCIE_CORE_ID)) /* routines to access mdio slave device registers */ static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk); @@ -245,8 +247,7 @@ static void pcie_war_pci_setup(struct pcicore_info *pi); /* Initialize the PCI core. * It's caller's responsibility to make sure that this is done only once */ -struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev, - void *regs) +void *pcicore_init(struct si_pub *sih, void *pdev, void *regs) { struct pcicore_info *pi; @@ -272,7 +273,7 @@ struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev, return pi; } -void pcicore_deinit(struct pcicore_info *pch) +void pcicore_deinit(void *pch) { kfree(pch); } @@ -280,7 +281,7 @@ void pcicore_deinit(struct pcicore_info *pch) /* return cap_offset if requested capability exists in the PCI config space */ /* Note that it's caller's responsibility to make sure it's a pci bus */ u8 -pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, +pcicore_find_pci_capability(void *dev, u8 req_cap_id, unsigned char *buf, u32 *buflen) { u8 cap_id; @@ -398,7 +399,6 @@ static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) while (i < pcie_serdes_spinwait) { if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) break; - udelay(1000); i++; } @@ -485,8 +485,9 @@ pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val) } /* ***** Support functions ***** */ -static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val) +static u8 pcie_clkreq(void *pch, u32 mask, u32 val) { + struct pcicore_info *pi = pch; u32 reg_val; u8 offset; @@ -536,30 +537,30 @@ static void pcie_clkreq_upd(struct pcicore_info *pi, uint state) switch (state) { case SI_DOATTACH: if (PCIE_ASPM(sih)) - pcie_clkreq(pi, 1, 0); + pcie_clkreq((void *)pi, 1, 0); break; case SI_PCIDOWN: if (sih->buscorerev == 6) { /* turn on serdes PLL down */ ai_corereg(sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol_addr), + offsetof(chipcregs_t, chipcontrol_addr), ~0, 0); ai_corereg(sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol_data), + offsetof(chipcregs_t, chipcontrol_data), ~0x40, 0); } else if (pi->pcie_pr42767) { - pcie_clkreq(pi, 1, 1); + pcie_clkreq((void *)pi, 1, 1); } break; case SI_PCIUP: if (sih->buscorerev == 6) { /* turn off serdes PLL down */ ai_corereg(sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol_addr), + offsetof(chipcregs_t, chipcontrol_addr), ~0, 0); ai_corereg(sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol_data), + offsetof(chipcregs_t, chipcontrol_data), ~0x40, 0x40); } else if (PCIE_ASPM(sih)) { /* disable clkreq */ - pcie_clkreq(pi, 1, 0); + pcie_clkreq((void *)pi, 1, 0); } break; } @@ -673,7 +674,7 @@ static void pcie_war_noplldown(struct pcicore_info *pi) u16 *reg16; /* turn off serdes PLL down */ - ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol), + ai_corereg(pi->sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol), CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN); /* clear srom shadow backdoor */ @@ -729,8 +730,9 @@ static void pcie_war_pci_setup(struct pcicore_info *pi) } /* ***** Functions called during driver state changes ***** */ -void pcicore_attach(struct pcicore_info *pi, char *pvars, int state) +void pcicore_attach(void *pch, char *pvars, int state) { + struct pcicore_info *pi = pch; struct si_pub *sih = pi->sih; /* Determine if this board needs override */ @@ -752,16 +754,20 @@ void pcicore_attach(struct pcicore_info *pi, char *pvars, int state) } -void pcicore_hwup(struct pcicore_info *pi) +void pcicore_hwup(void *pch) { + struct pcicore_info *pi = pch; + if (!pi || !PCIE_PUB(pi->sih)) return; pcie_war_pci_setup(pi); } -void pcicore_up(struct pcicore_info *pi, int state) +void pcicore_up(void *pch, int state) { + struct pcicore_info *pi = pch; + if (!pi || !PCIE_PUB(pi->sih)) return; @@ -774,8 +780,9 @@ void pcicore_up(struct pcicore_info *pi, int state) /* When the device is going to enter D3 state * (or the system is going to enter S3/S4 states) */ -void pcicore_sleep(struct pcicore_info *pi) +void pcicore_sleep(void *pch) { + struct pcicore_info *pi = pch; u32 w; if (!pi || !PCIE_ASPM(pi->sih)) @@ -788,8 +795,10 @@ void pcicore_sleep(struct pcicore_info *pi) pi->pcie_pr42767 = false; } -void pcicore_down(struct pcicore_info *pi, int state) +void pcicore_down(void *pch, int state) { + struct pcicore_info *pi = pch; + if (!pi || !PCIE_PUB(pi->sih)) return; @@ -800,12 +809,20 @@ void pcicore_down(struct pcicore_info *pi, int state) } /* precondition: current core is sii->buscoretype */ -static void pcicore_fixcfg(struct pcicore_info *pi, u16 *reg16) +void pcicore_fixcfg(void *pch, void *regs) { + struct pcicore_info *pi = pch; struct si_info *sii = SI_INFO(pi->sih); - u16 val16; + struct sbpciregs *pciregs = regs; + struct sbpcieregs *pcieregs = regs; + u16 val16, *reg16 = NULL; uint pciidx; + /* check 'pi' is correct and fix it if not */ + if (sii->pub.buscoretype == PCIE_CORE_ID) + reg16 = &pcieregs->sprom[SRSH_PI_OFFSET]; + else if (sii->pub.buscoretype == PCI_CORE_ID) + reg16 = &pciregs->sprom[SRSH_PI_OFFSET]; pciidx = ai_coreidx(&sii->pub); val16 = R_REG(reg16); if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) { @@ -815,19 +832,11 @@ static void pcicore_fixcfg(struct pcicore_info *pi, u16 *reg16) } } -void pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs *pciregs) -{ - pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]); -} - -void pcicore_fixcfg_pcie(struct pcicore_info *pi, struct sbpcieregs *pcieregs) -{ - pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]); -} - /* precondition: current core is pci core */ -void pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs *pciregs) +void pcicore_pci_setup(void *pch, void *regs) { + struct pcicore_info *pi = pch; + struct sbpciregs *pciregs = regs; u32 w; OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST); diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/nicpci.h b/trunk/drivers/staging/brcm80211/brcmsmac/nicpci.h index 3082db0d4f45..f71f842a2156 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/nicpci.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/nicpci.h @@ -70,24 +70,16 @@ #define SRSH_PI_MASK 0xf000 /* bit 15:12 */ #define SRSH_PI_SHIFT 12 /* bit 15:12 */ -struct sbpciregs; -struct sbpcieregs; - -extern struct pcicore_info *pcicore_init(struct si_pub *sih, - struct pci_dev *pdev, void *regs); -extern void pcicore_deinit(struct pcicore_info *pch); -extern void pcicore_attach(struct pcicore_info *pch, char *pvars, int state); -extern void pcicore_hwup(struct pcicore_info *pch); -extern void pcicore_up(struct pcicore_info *pch, int state); -extern void pcicore_sleep(struct pcicore_info *pch); -extern void pcicore_down(struct pcicore_info *pch, int state); -extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, - unsigned char *buf, u32 *buflen); -extern void pcicore_fixcfg_pci(struct pcicore_info *pch, - struct sbpciregs *pciregs); -extern void pcicore_fixcfg_pcie(struct pcicore_info *pch, - struct sbpcieregs *pciregs); -extern void pcicore_pci_setup(struct pcicore_info *pch, - struct sbpciregs *pciregs); +extern void *pcicore_init(struct si_pub *sih, void *pdev, void *regs); +extern void pcicore_deinit(void *pch); +extern void pcicore_attach(void *pch, char *pvars, int state); +extern void pcicore_hwup(void *pch); +extern void pcicore_up(void *pch, int state); +extern void pcicore_sleep(void *pch); +extern void pcicore_down(void *pch, int state); +extern u8 pcicore_find_pci_capability(void *dev, u8 req_cap_id, + unsigned char *buf, u32 *buflen); +extern void pcicore_fixcfg(void *pch, void *regs); +extern void pcicore_pci_setup(void *pch, void *regs); #endif /* _BRCM_NICPCI_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/otp.c b/trunk/drivers/staging/brcm80211/brcmsmac/otp.c index 1e0093c71ca3..34253cf37812 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/otp.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/otp.c @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -25,14 +24,10 @@ #define OTPS_GUP_MASK 0x00000f00 #define OTPS_GUP_SHIFT 8 -/* h/w subregion is programmed */ -#define OTPS_GUP_HW 0x00000100 -/* s/w subregion is programmed */ -#define OTPS_GUP_SW 0x00000200 -/* chipid/pkgopt subregion is programmed */ -#define OTPS_GUP_CI 0x00000400 -/* fuse subregion is programmed */ -#define OTPS_GUP_FUSE 0x00000800 +#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */ +#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */ +#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */ +#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */ /* Fields in otpprog in rev >= 21 */ #define OTPP_COL_MASK 0x000000ff @@ -64,15 +59,23 @@ #define MAXNUMRDES 9 /* Maximum OTP redundancy entries */ +/* OTP common function type */ +typedef int (*otp_status_t) (void *oh); +typedef int (*otp_size_t) (void *oh); +typedef void *(*otp_init_t) (struct si_pub *sih); +typedef u16(*otp_read_bit_t) (void *oh, chipcregs_t *cc, uint off); +typedef int (*otp_read_region_t) (struct si_pub *sih, int region, u16 *data, + uint *wlen); +typedef int (*otp_nvread_t) (void *oh, char *data, uint *len); + /* OTP function struct */ struct otp_fn_s { - int (*size)(struct otpinfo *oi); - u16 (*read_bit)(struct otpinfo *oi, struct chipcregs *cc, uint off); - struct otpinfo *(*init)(struct si_pub *sih); - int (*read_region)(struct otpinfo *oi, int region, u16 *data, - uint *wlen); - int (*nvread)(struct otpinfo *oi, char *data, uint *len); - int (*status)(struct otpinfo *oi); + otp_size_t size; + otp_read_bit_t read_bit; + otp_init_t init; + otp_read_region_t read_region; + otp_nvread_t nvread; + otp_status_t status; }; struct otpinfo { @@ -148,24 +151,31 @@ static struct otpinfo otpinfo; #define OTP4315_SWREG_SZ 178 /* 178 bytes */ #define OTP_SZ_FU_144 (144/8) /* 144 bits */ -static int ipxotp_status(struct otpinfo *oi) +static int ipxotp_status(void *oh) { + struct otpinfo *oi = (struct otpinfo *) oh; return (int)(oi->status); } /* Return size in bytes */ -static int ipxotp_size(struct otpinfo *oi) +static int ipxotp_size(void *oh) { + struct otpinfo *oi = (struct otpinfo *) oh; return (int)oi->wsize * 2; } -static u16 ipxotp_otpr(struct otpinfo *oi, struct chipcregs *cc, uint wn) +static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn) { + struct otpinfo *oi; + + oi = (struct otpinfo *) oh; + return R_REG(&cc->sromotp[wn]); } -static u16 ipxotp_read_bit(struct otpinfo *oi, struct chipcregs *cc, uint off) +static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off) { + struct otpinfo *oi = (struct otpinfo *) oh; uint k, row, col; u32 otpp, st; @@ -182,20 +192,19 @@ static u16 ipxotp_read_bit(struct otpinfo *oi, struct chipcregs *cc, uint off) ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); k++) ; - if (k >= OTPP_TRIES) + if (k >= OTPP_TRIES) { return 0xffff; - - if (st & OTPP_READERR) + } + if (st & OTPP_READERR) { return 0xffff; - + } st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT; return (int)st; } -/* - * Calculate max HW/SW region byte size by subtracting fuse region - * and checksum size, osizew is oi->wsize (OTP size - GU size) in words +/* Calculate max HW/SW region byte size by subtracting fuse region and checksum size, + * osizew is oi->wsize (OTP size - GU size) in words */ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew) { @@ -216,23 +225,17 @@ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew) return ret; } -static void _ipxotp_init(struct otpinfo *oi, struct chipcregs *cc) +static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc) { uint k; u32 otpp, st; - /* - * record word offset of General Use Region - * for various chipcommon revs - */ + /* record word offset of General Use Region for various chipcommon revs */ if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 || oi->sih->ccrev == 27) { oi->otpgu_base = REVA4_OTPGU_BASE; } else if (oi->sih->ccrev == 36) { - /* - * OTP size greater than equal to 2KB (128 words), - * otpgu_base is similar to rev23 - */ + /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */ if (oi->wsize >= 128) oi->otpgu_base = REVB8_OTPGU_BASE; else @@ -250,8 +253,9 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs *cc) ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); k++) ; - if (k >= OTPP_TRIES) + if (k >= OTPP_TRIES) { return; + } /* Read OTP lock bits and subregion programmed indication bits */ oi->status = R_REG(&cc->otpstatus); @@ -267,9 +271,8 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs *cc) } /* - * h/w region base and fuse region limit are fixed to - * the top and the bottom of the general use region. - * Everything else can be flexible. + * h/w region base and fuse region limit are fixed to the top and + * the bottom of the general use region. Everything else can be flexible. */ oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF; oi->hwlim = oi->wsize; @@ -293,10 +296,10 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs *cc) oi->flim = oi->wsize; } -static struct otpinfo *ipxotp_init(struct si_pub *sih) +static void *ipxotp_init(struct si_pub *sih) { uint idx; - struct chipcregs *cc; + chipcregs_t *cc; struct otpinfo *oi; /* Make sure we're running IPX OTP */ @@ -348,14 +351,14 @@ static struct otpinfo *ipxotp_init(struct si_pub *sih) ai_setcoreidx(sih, idx); - return oi; + return (void *)oi; } -static int -ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) +static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen) { + struct otpinfo *oi = (struct otpinfo *) oh; uint idx; - struct chipcregs *cc; + chipcregs_t *cc; uint base, i, sz; /* Validate region selection */ @@ -429,27 +432,27 @@ ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) /* Read the data */ for (i = 0; i < sz; i++) - data[i] = ipxotp_otpr(oi, cc, base + i); + data[i] = ipxotp_otpr(oh, cc, base + i); ai_setcoreidx(oi->sih, idx); *wlen = sz; return 0; } -static int ipxotp_nvread(struct otpinfo *oi, char *data, uint *len) +static int ipxotp_nvread(void *oh, char *data, uint *len) { return -ENOTSUPP; } static struct otp_fn_s ipxotp_fn = { - (int (*)(struct otpinfo *)) ipxotp_size, - (u16 (*)(struct otpinfo *, struct chipcregs *, uint)) ipxotp_read_bit, + (otp_size_t) ipxotp_size, + (otp_read_bit_t) ipxotp_read_bit, - (struct otpinfo *(*)(struct si_pub *)) ipxotp_init, - (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region, - (int (*)(struct otpinfo *, char *, uint *)) ipxotp_nvread, + (otp_init_t) ipxotp_init, + (otp_read_region_t) ipxotp_read_region, + (otp_nvread_t) ipxotp_nvread, - (int (*)(struct otpinfo *)) ipxotp_status + (otp_status_t) ipxotp_status }; /* @@ -461,29 +464,34 @@ static struct otp_fn_s ipxotp_fn = { * otp_nvread() */ -int otp_status(struct otpinfo *oi) +int otp_status(void *oh) { - return oi->fn->status(oi); + struct otpinfo *oi = (struct otpinfo *) oh; + + return oi->fn->status(oh); } -int otp_size(struct otpinfo *oi) +int otp_size(void *oh) { - return oi->fn->size(oi); + struct otpinfo *oi = (struct otpinfo *) oh; + + return oi->fn->size(oh); } -u16 otp_read_bit(struct otpinfo *oi, uint offset) +u16 otp_read_bit(void *oh, uint offset) { + struct otpinfo *oi = (struct otpinfo *) oh; uint idx = ai_coreidx(oi->sih); - struct chipcregs *cc = ai_setcoreidx(oi->sih, SI_CC_IDX); - u16 readBit = (u16) oi->fn->read_bit(oi, cc, offset); + chipcregs_t *cc = ai_setcoreidx(oi->sih, SI_CC_IDX); + u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset); ai_setcoreidx(oi->sih, idx); return readBit; } -struct otpinfo *otp_init(struct si_pub *sih) +void *otp_init(struct si_pub *sih) { struct otpinfo *oi; - struct otpinfo *ret = NULL; + void *ret = NULL; oi = &otpinfo; memset(oi, 0, sizeof(struct otpinfo)); @@ -493,8 +501,9 @@ struct otpinfo *otp_init(struct si_pub *sih) if (OTPTYPE_IPX(oi->ccrev)) oi->fn = &ipxotp_fn; - if (oi->fn == NULL) + if (oi->fn == NULL) { return NULL; + } oi->sih = sih; @@ -504,8 +513,9 @@ struct otpinfo *otp_init(struct si_pub *sih) } int -otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) { - struct otpinfo *oi; +otp_read_region(struct si_pub *sih, int region, u16 *data, + uint *wlen) { + void *oh; int err = 0; if (ai_is_otp_disabled(sih)) { @@ -513,19 +523,22 @@ otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) { goto out; } - oi = otp_init(sih); - if (oi == NULL) { + oh = otp_init(sih); + if (oh == NULL) { err = -EBADE; goto out; } - err = ((oi)->fn->read_region)(oi, region, data, wlen); + err = (((struct otpinfo *) oh)->fn->read_region) + (oh, region, data, wlen); out: return err; } -int otp_nvread(struct otpinfo *oi, char *data, uint *len) +int otp_nvread(void *oh, char *data, uint *len) { - return oi->fn->nvread(oi, data, len); + struct otpinfo *oi = (struct otpinfo *) oh; + + return oi->fn->nvread(oh, data, len); } diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/otp.h b/trunk/drivers/staging/brcm80211/brcmsmac/otp.h index 938100e25482..f6d3a56acf1e 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/otp.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/otp.h @@ -24,8 +24,7 @@ #define OTP_SW_RGN 2 #define OTP_CI_RGN 4 #define OTP_FUSE_RGN 8 -/* From h/w region to end of OTP including checksum */ -#define OTP_ALL_RGN 0xf +#define OTP_ALL_RGN 0xf /* From h/w region to end of OTP including checksum */ /* OTP Size */ #define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */ @@ -36,15 +35,13 @@ /* OTP usage */ #define OTP4325_FM_DISABLED_OFFSET 188 -struct otpinfo; - /* Exported functions */ -extern int otp_status(struct otpinfo *oi); -extern int otp_size(struct otpinfo *oi); -extern u16 otp_read_bit(struct otpinfo *oi, uint offset); -extern struct otpinfo *otp_init(struct si_pub *sih); +extern int otp_status(void *oh); +extern int otp_size(void *oh); +extern u16 otp_read_bit(void *oh, uint offset); +extern void *otp_init(struct si_pub *sih); extern int otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen); -extern int otp_nvread(struct otpinfo *oi, char *data, uint *len); +extern int otp_nvread(void *oh, char *data, uint *len); #endif /* _BRCM_OTP_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c index 5307bd8c258d..17012fbe9c97 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c @@ -119,11 +119,11 @@ const u8 ofdm_rate_lookup[] = { BRCM_RATE_9M }; -#define PHY_WREG_LIMIT 24 +#define PHY_WREG_LIMIT 24 static void wlc_set_phy_uninitted(struct brcms_phy *pi); static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi); -static void wlc_phy_timercb_phycal(struct brcms_phy *pi); +static void wlc_phy_timercb_phycal(void *arg); static bool wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant); @@ -136,13 +136,11 @@ static void wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch); static void wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, - struct txpwr_limits *tp, - u16 chanspec); - + struct txpwr_limits *tp, chanspec_t); static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi); static s8 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, - u32 band, u8 rate); + u32 band, u8 rate); static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band); static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi); static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi); @@ -174,13 +172,12 @@ char *phy_getvar(struct brcms_phy *pi, const char *name) int phy_getintvar(struct brcms_phy *pi, const char *name) { char *val; - unsigned long res; val = PHY_GETVAR(pi, name); - if (val && !kstrtoul(val, 0, &res)) - return res; + if (val == NULL) + return 0; - return 0; + return simple_strtoul(val, NULL, 0); } void wlc_phyreg_enter(struct brcms_phy_pub *pih) @@ -206,7 +203,7 @@ void wlc_radioreg_enter(struct brcms_phy_pub *pih) void wlc_radioreg_exit(struct brcms_phy_pub *pih) { struct brcms_phy *pi = (struct brcms_phy *) pih; - u16 dummy; + volatile u16 dummy; dummy = R_REG(&pi->regs->phyversion); pi->phy_wreg = 0; @@ -279,9 +276,11 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) W_REG(&pi->regs->phy4wdatalo, val); } - if (++pi->phy_wreg >= pi->phy_wreg_limit) { - (void)R_REG(&pi->regs->maccontrol); - pi->phy_wreg = 0; + if (pi->sh->bustype == PCI_BUS) { + if (++pi->phy_wreg >= pi->phy_wreg_limit) { + (void)R_REG(&pi->regs->maccontrol); + pi->phy_wreg = 0; + } } } @@ -364,7 +363,7 @@ void write_phy_channel_reg(struct brcms_phy *pi, uint val) u16 read_phy_reg(struct brcms_phy *pi, u16 addr) { - struct d11regs *regs; + d11regs_t *regs; regs = pi->regs; @@ -376,11 +375,11 @@ u16 read_phy_reg(struct brcms_phy *pi, u16 addr) void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) { - struct d11regs *regs; + d11regs_t *regs; regs = pi->regs; -#ifdef CONFIG_BCM47XX +#ifdef __mips__ W_REG_FLUSH(®s->phyregaddr, addr); W_REG(®s->phyregdata, val); if (addr == 0x72) @@ -388,16 +387,18 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) #else W_REG((u32 *)(®s->phyregaddr), addr | (val << 16)); - if (++pi->phy_wreg >= pi->phy_wreg_limit) { - pi->phy_wreg = 0; - (void)R_REG(®s->phyversion); + if (pi->sh->bustype == PCI_BUS) { + if (++pi->phy_wreg >= pi->phy_wreg_limit) { + pi->phy_wreg = 0; + (void)R_REG(®s->phyversion); + } } #endif } void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) { - struct d11regs *regs; + d11regs_t *regs; regs = pi->regs; @@ -409,7 +410,7 @@ void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) { - struct d11regs *regs; + d11regs_t *regs; regs = pi->regs; @@ -421,7 +422,7 @@ void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) { - struct d11regs *regs; + d11regs_t *regs; regs = pi->regs; @@ -463,8 +464,9 @@ static void wlc_set_phy_uninitted(struct brcms_phy *pi) } pi->radiopwr = 0xffff; for (i = 0; i < STATIC_NUM_RF; i++) { - for (j = 0; j < STATIC_NUM_BB; j++) + for (j = 0; j < STATIC_NUM_BB; j++) { pi->stats_11b_txpower[i][j] = -1; + } } } @@ -473,8 +475,9 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) struct shared_phy *sh; sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC); - if (sh == NULL) + if (sh == NULL) { return NULL; + } sh->sih = shp->sih; sh->physhim = shp->physhim; @@ -492,6 +495,7 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) sh->boardvendor = shp->boardvendor; sh->boardflags = shp->boardflags; sh->boardflags2 = shp->boardflags2; + sh->bustype = shp->bustype; sh->buscorerev = shp->buscorerev; sh->fast_timer = PHY_SW_TIMER_FAST; @@ -504,7 +508,7 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) } struct brcms_phy_pub * -wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype, +wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype, char *vars, struct wiphy *wiphy) { struct brcms_phy *pi; @@ -519,22 +523,25 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype, sflags = ai_core_sflags(sh->sih, 0, 0); if (BAND_5G(bandtype)) { - if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) + if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) { return NULL; + } } pi = sh->phy_head; if ((sflags & SISF_DB_PHY) && pi) { + wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); pi->refcnt++; return &pi->pubpi_ro; } pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC); - if (pi == NULL) + if (pi == NULL) { return NULL; + } pi->wiphy = wiphy; - pi->regs = regs; + pi->regs = (d11regs_t *) regs; pi->sh = sh; pi->phy_init_por = true; pi->phy_wreg_limit = PHY_WREG_LIMIT; @@ -547,8 +554,10 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype, pi->phycal_tempdelta = 0; - if (BAND_2G(bandtype) && (sflags & SISF_2G_PHY)) + if (BAND_2G(bandtype) && (sflags & SISF_2G_PHY)) { + pi->pubpi.coreflags = SICF_GMODE; + } wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); phyversion = R_REG(&pi->regs->phyversion); @@ -563,25 +572,28 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype, pi->pubpi.phy_corenum = PHY_CORE_NUM_2; pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT; - if (!VALID_PHYTYPE(pi->pubpi.phy_type)) + if (!VALID_PHYTYPE(pi->pubpi.phy_type)) { goto err; - + } if (BAND_5G(bandtype)) { - if (!ISNPHY(pi)) + if (!ISNPHY(pi)) { goto err; - } else if (!ISNPHY(pi) && !ISLCNPHY(pi)) { - goto err; + } + } else { + if (!ISNPHY(pi) && !ISLCNPHY(pi)) { + goto err; + } } wlc_phy_anacore((struct brcms_phy_pub *) pi, ON); idcode = wlc_phy_get_radio_ver(pi); pi->pubpi.radioid = - (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT; + (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT; pi->pubpi.radiorev = - (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT; + (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT; pi->pubpi.radiover = - (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT; + (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT; if (!VALID_RADIO(pi, pi->pubpi.radioid)) goto err; @@ -591,7 +603,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype, pi->bw = WL_CHANSPEC_BW_20; pi->radio_chanspec = - BAND_2G(bandtype) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36); + BAND_2G(bandtype) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36); pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; pi->rxiq_antsel = ANT_RX_DIV_DEF; @@ -613,7 +625,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype, pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; pi->phy_txcore_enable_temp = - PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP; + PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP; pi->phy_tempsense_offset = 0; pi->phy_txcore_heatedup = false; @@ -636,10 +648,11 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype, if (ISNPHY(pi)) { pi->phycal_timer = wlapi_init_timer(pi->sh->physhim, - wlc_phy_timercb_phycal, - pi, "phycal"); - if (!pi->phycal_timer) + wlc_phy_timercb_phycal, + pi, "phycal"); + if (!pi->phycal_timer) { goto err; + } if (!wlc_phy_attach_nphy(pi)) goto err; @@ -648,6 +661,8 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype, if (!wlc_phy_attach_lcnphy(pi)) goto err; + } else { + } pi->refcnt++; @@ -660,7 +675,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype, return &pi->pubpi_ro; -err: + err: kfree(pi); return NULL; } @@ -670,8 +685,9 @@ void wlc_phy_detach(struct brcms_phy_pub *pih) struct brcms_phy *pi = (struct brcms_phy *) pih; if (pih) { - if (--pi->refcnt) + if (--pi->refcnt) { return; + } if (pi->phycal_timer) { wlapi_free_timer(pi->sh->physhim, pi->phycal_timer); @@ -684,7 +700,7 @@ void wlc_phy_detach(struct brcms_phy_pub *pih) pi->sh->phy_head->next = NULL; if (pi->pi_fptr.detach) - (pi->pi_fptr.detach)(pi); + (pi->pi_fptr.detach) (pi); kfree(pi); } @@ -715,8 +731,9 @@ u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih) return pi->pubpi.coreflags; } -static void wlc_phy_timercb_phycal(struct brcms_phy *pi) +static void wlc_phy_timercb_phycal(void *arg) { + struct brcms_phy *pi = (struct brcms_phy *) arg; uint delay = 5; if (PHY_PERICAL_MPHASE_PENDING(pi)) { @@ -845,10 +862,10 @@ void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate) pi->sh->up = newstate; } -void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) +void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec) { u32 mc; - void (*phy_init)(struct brcms_phy *) = NULL; + initfn_t phy_init = NULL; struct brcms_phy *pi = (struct brcms_phy *) pih; if (pi->init_in_progress) @@ -862,8 +879,9 @@ void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init")) return; - if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) + if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) { pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; + } if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA), "HW error SISF_FCLKA\n")) @@ -871,8 +889,9 @@ void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) phy_init = pi->pi_fptr.init; - if (phy_init == NULL) + if (phy_init == NULL) { return; + } wlc_phy_anacore(pih, ON); @@ -884,7 +903,7 @@ void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON); - (*phy_init)(pi); + (*phy_init) (pi); pi->phy_init_por = false; @@ -902,7 +921,7 @@ void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) void wlc_phy_cal_init(struct brcms_phy_pub *pih) { struct brcms_phy *pi = (struct brcms_phy *) pih; - void (*cal_init)(struct brcms_phy *) = NULL; + initfn_t cal_init = NULL; if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0, "HW error: MAC enabled during phy cal\n")) @@ -911,7 +930,7 @@ void wlc_phy_cal_init(struct brcms_phy_pub *pih) if (!pi->initialized) { cal_init = pi->pi_fptr.calinit; if (cal_init) - (*cal_init)(pi); + (*cal_init) (pi); pi->initialized = true; } @@ -971,9 +990,11 @@ void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val) } if (width == 32) { + write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16)); write_phy_reg(pi, pi->tbl_data_lo, (u16) val); } else { + write_phy_reg(pi, pi->tbl_data_lo, (u16) val); } } @@ -1004,12 +1025,15 @@ wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, } if (tbl_width == 32) { + write_phy_reg(pi, tblDataHi, (u16) (ptbl_32b[idx] >> 16)); write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]); } else if (tbl_width == 16) { + write_phy_reg(pi, tblDataLo, ptbl_16b[idx]); } else { + write_phy_reg(pi, tblDataLo, ptbl_8b[idx]); } } @@ -1040,11 +1064,14 @@ wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, } if (tbl_width == 32) { + ptbl_32b[idx] = read_phy_reg(pi, tblDataLo); ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16); } else if (tbl_width == 16) { + ptbl_16b[idx] = read_phy_reg(pi, tblDataLo); } else { + ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo); } } @@ -1057,9 +1084,10 @@ wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, uint i = 0; do { - if (radioregs[i].do_init) + if (radioregs[i].do_init) { write_radio_reg(pi, radioregs[i].address, (u16) radioregs[i].init); + } i++; } while (radioregs[i].address != 0xffff); @@ -1103,8 +1131,8 @@ wlc_phy_init_radio_regs(struct brcms_phy *pi, struct radio_regs *radioregs, void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) { -#define DUMMY_PKT_LEN 20 - struct d11regs *regs = pi->regs; +#define DUMMY_PKT_LEN 20 + d11regs_t *regs = pi->regs; int i, count; u8 ofdmpkt[DUMMY_PKT_LEN] = { 0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, @@ -1128,8 +1156,9 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) W_REG(®s->wepctl, 0); W_REG(®s->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0); - if (ISNPHY(pi) || ISLCNPHY(pi)) + if (ISNPHY(pi) || ISLCNPHY(pi)) { W_REG(®s->txe_phyctl1, 0x1A02); + } W_REG(®s->txe_wm_0, 0); W_REG(®s->txe_wm_1, 0); @@ -1156,14 +1185,16 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) i = 0; count = ofdm ? 30 : 250; while ((i++ < count) - && (R_REG(®s->txe_status) & (1 << 7))) + && (R_REG(®s->txe_status) & (1 << 7))) { udelay(10); + } i = 0; while ((i++ < 10) - && ((R_REG(®s->txe_status) & (1 << 10)) == 0)) + && ((R_REG(®s->txe_status) & (1 << 10)) == 0)) { udelay(10); + } i = 0; @@ -1176,26 +1207,28 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) } } -void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set) +void wlc_phy_hold_upd(struct brcms_phy_pub *pih, mbool id, bool set) { struct brcms_phy *pi = (struct brcms_phy *) pih; - if (set) + if (set) { mboolset(pi->measure_hold, id); - else + } else { mboolclr(pi->measure_hold, id); + } return; } -void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags) +void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, mbool flags) { struct brcms_phy *pi = (struct brcms_phy *) pih; - if (mute) + if (mute) { mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE); - else + } else { mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE); + } if (!mute && (flags & PHY_MUTE_FOR_PREISM)) pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer; @@ -1236,6 +1269,7 @@ void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on) if (ISNPHY(pi)) { wlc_phy_switch_radio_nphy(pi, on); + } else if (ISLCNPHY(pi)) { if (on) { and_phy_reg(pi, 0x44c, @@ -1277,25 +1311,26 @@ void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw) pi->bw = bw; } -void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch) +void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, chanspec_t newch) { struct brcms_phy *pi = (struct brcms_phy *) ppi; pi->radio_chanspec = newch; } -u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi) +chanspec_t wlc_phy_chanspec_get(struct brcms_phy_pub *ppi) { struct brcms_phy *pi = (struct brcms_phy *) ppi; return pi->radio_chanspec; } -void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec) +void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, chanspec_t chanspec) { struct brcms_phy *pi = (struct brcms_phy *) ppi; u16 m_cur_channel; - void (*chanspec_set)(struct brcms_phy *, u16) = NULL; + chansetfn_t chanspec_set = NULL; + m_cur_channel = CHSPEC_CHANNEL(chanspec); if (CHSPEC_IS5G(chanspec)) m_cur_channel |= D11_CURCHANNEL_5G; @@ -1305,7 +1340,7 @@ void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec) chanspec_set = pi->pi_fptr.chanset; if (chanspec_set) - (*chanspec_set)(pi, chanspec); + (*chanspec_set) (pi, chanspec); } @@ -1325,16 +1360,17 @@ int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq) return range; } -int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, u16 chanspec) +int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, chanspec_t chanspec) { int range = -1; uint channel = CHSPEC_CHANNEL(chanspec); uint freq = wlc_phy_channel2freq(channel); - if (ISNPHY(pi)) + if (ISNPHY(pi)) { range = wlc_phy_get_chan_freq_range_nphy(pi, channel); - else if (ISLCNPHY(pi)) + } else if (ISLCNPHY(pi)) { range = wlc_phy_chanspec_freq2bandrange_lpssn(freq); + } return range; } @@ -1360,13 +1396,13 @@ int wlc_phy_channel2freq(uint channel) void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, - struct brcms_chanvec *channels) + chanvec_t *channels) { struct brcms_phy *pi = (struct brcms_phy *) ppi; uint i; uint channel; - memset(channels, 0, sizeof(struct brcms_chanvec)); + memset(channels, 0, sizeof(chanvec_t)); for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { channel = chan_info_all[i].chan; @@ -1381,12 +1417,12 @@ wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, } } -u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band) +chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band) { struct brcms_phy *pi = (struct brcms_phy *) ppi; uint i; uint channel; - u16 chspec; + chanspec_t chspec; for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { channel = chan_info_all[i].chan; @@ -1404,8 +1440,9 @@ u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band) continue; channel = UPPER_20_SB(channel); - chspec = channel | WL_CHANSPEC_BW_40 | - WL_CHANSPEC_CTL_SB_LOWER; + chspec = + channel | WL_CHANSPEC_BW_40 | + WL_CHANSPEC_CTL_SB_LOWER; if (band == BRCM_BAND_2G) chspec |= WL_CHANSPEC_BAND_2G; else @@ -1422,7 +1459,7 @@ u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band) return chspec; } - return (u16) INVCHANSPEC; + return (chanspec_t) INVCHANSPEC; } int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override) @@ -1502,8 +1539,10 @@ int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override) if (!SCAN_INPROG_PHY(pi)) { bool suspend; - suspend = (0 == (R_REG(&pi->regs->maccontrol) & - MCTL_EN_MAC)); + suspend = + (0 == + (R_REG(&pi->regs->maccontrol) & + MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); @@ -1545,8 +1584,9 @@ wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr, txp_rate_idx = TXP_FIRST_OFDM; for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { - if (channel == chan_info_all[i].chan) + if (channel == chan_info_all[i].chan) { break; + } } if (pi->hwtxpwr) { @@ -1580,8 +1620,7 @@ wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan, pactrl = 0; max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES : - ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + - 1) : (TXP_LAST_OFDM + 1); + ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1); for (rate = 0; rate < max_num_rate; rate++) { @@ -1630,9 +1669,9 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) u8 tx_pwr_max_rate_ind = 0; u8 max_num_rate; u8 start_rate = 0; - u16 chspec; + chanspec_t chspec; u32 band = CHSPEC2BAND(pi->radio_chanspec); - void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL; + initfn_t txpwr_recalc_fn = NULL; chspec = pi->radio_chanspec; if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) @@ -1651,8 +1690,8 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) for (i = TXP_FIRST_SISO_MCS_20; i <= TXP_LAST_SISO_MCS_20; i++) { pi->tx_srom_max_rate_2g[i - 8] = - pi->tx_srom_max_2g - - ((offset_mcs & 0xf) * 2); + pi->tx_srom_max_2g - + ((offset_mcs & 0xf) * 2); offset_mcs >>= 4; } } else { @@ -1660,8 +1699,8 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) for (i = TXP_FIRST_SISO_MCS_20; i <= TXP_LAST_SISO_MCS_20; i++) { pi->tx_srom_max_rate_2g[i - 8] = - pi->tx_srom_max_2g - - ((offset_mcs & 0xf) * 2); + pi->tx_srom_max_2g - + ((offset_mcs & 0xf) * 2); offset_mcs >>= 4; } } @@ -1680,12 +1719,11 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) tx_pwr_target[rate] = pi->tx_user_target[rate]; - if (pi->user_txpwr_at_rfport) + if (pi->user_txpwr_at_rfport) { tx_pwr_target[rate] += - wlc_user_txpwr_antport_to_rfport(pi, - target_chan, - band, - rate); + wlc_user_txpwr_antport_to_rfport(pi, target_chan, + band, rate); + } { @@ -1696,7 +1734,7 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]); maxtxpwr = - (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; + (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; @@ -1709,7 +1747,7 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) } tx_pwr_target[rate] = - min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]); + min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]); if (tx_pwr_target[rate] > tx_pwr_max) tx_pwr_max_rate_ind = rate; @@ -1726,22 +1764,23 @@ void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) pi->tx_power_target[rate] = tx_pwr_target[rate]; - if (!pi->hwpwrctrl || ISNPHY(pi)) + if (!pi->hwpwrctrl || ISNPHY(pi)) { pi->tx_power_offset[rate] = - pi->tx_power_max - pi->tx_power_target[rate]; - else + pi->tx_power_max - pi->tx_power_target[rate]; + } else { pi->tx_power_offset[rate] = - pi->tx_power_target[rate] - pi->tx_power_min; + pi->tx_power_target[rate] - pi->tx_power_min; + } } txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc; if (txpwr_recalc_fn) - (*txpwr_recalc_fn)(pi); + (*txpwr_recalc_fn) (pi); } void wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, - u16 chanspec) + chanspec_t chanspec) { u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM]; u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL; @@ -1776,7 +1815,7 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, txpwr_ptr1 = txpwr->mcs_40_siso; txpwr_ptr2 = txpwr->ofdm_40_siso; rate_start_index = - WL_TX_POWER_OFDM40_SISO_FIRST; + WL_TX_POWER_OFDM40_SISO_FIRST; break; case 3: @@ -1786,21 +1825,18 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, break; } - for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; - rate2++) { + for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; rate2++) { tmp_txpwr_limit[rate2] = 0; tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = - txpwr_ptr1[rate2]; + txpwr_ptr1[rate2]; } - wlc_phy_mcs_to_ofdm_powers_nphy( - tmp_txpwr_limit, 0, - BRCMS_NUM_RATES_OFDM - - 1, BRCMS_NUM_RATES_OFDM); + wlc_phy_mcs_to_ofdm_powers_nphy(tmp_txpwr_limit, 0, + BRCMS_NUM_RATES_OFDM - 1, BRCMS_NUM_RATES_OFDM); for (rate1 = rate_start_index, rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++) pi->txpwr_limit[rate1] = - min(txpwr_ptr2[rate2], - tmp_txpwr_limit[rate2]); + min(txpwr_ptr2[rate2], + tmp_txpwr_limit[rate2]); } for (k = 0; k < 4; k++) { @@ -1830,22 +1866,19 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST; break; } - for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; - rate2++) { + for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; rate2++) { tmp_txpwr_limit[rate2] = 0; tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = - txpwr_ptr1[rate2]; + txpwr_ptr1[rate2]; } - wlc_phy_ofdm_to_mcs_powers_nphy( - tmp_txpwr_limit, 0, - BRCMS_NUM_RATES_OFDM - - 1, BRCMS_NUM_RATES_OFDM); + wlc_phy_ofdm_to_mcs_powers_nphy(tmp_txpwr_limit, 0, + BRCMS_NUM_RATES_OFDM - 1, BRCMS_NUM_RATES_OFDM); for (rate1 = rate_start_index, rate2 = 0; rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; rate1++, rate2++) pi->txpwr_limit[rate1] = - min(txpwr_ptr2[rate2], - tmp_txpwr_limit[rate2]); + min(txpwr_ptr2[rate2], + tmp_txpwr_limit[rate2]); } for (k = 0; k < 2; k++) { @@ -1889,10 +1922,10 @@ wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32; pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] = - min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST], - pi->txpwr_limit[WL_TX_POWER_MCS_32]); + min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST], + pi->txpwr_limit[WL_TX_POWER_MCS_32]); pi->txpwr_limit[WL_TX_POWER_MCS_32] = - pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST]; + pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST]; } } @@ -1942,7 +1975,7 @@ void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end) void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr, - u16 chanspec) + chanspec_t chanspec) { struct brcms_phy *pi = (struct brcms_phy *) ppi; @@ -1983,8 +2016,9 @@ void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt) void wlc_phy_txpower_update_shm(struct brcms_phy *pi) { int j; - if (ISNPHY(pi)) + if (ISNPHY(pi)) { return; + } if (!pi->sh->clk) return; @@ -2006,9 +2040,9 @@ void wlc_phy_txpower_update_shm(struct brcms_phy *pi) const u8 ucode_ofdm_rates[] = { 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c }; - offset = wlapi_bmac_rate_shm_offset( - pi->sh->physhim, - ucode_ofdm_rates[j - TXP_FIRST_OFDM]); + offset = wlapi_bmac_rate_shm_offset(pi->sh->physhim, + ucode_ofdm_rates[j - + TXP_FIRST_OFDM]); wlapi_bmac_write_shm(pi->sh->physhim, offset + 6, pi->tx_power_offset[j]); wlapi_bmac_write_shm(pi->sh->physhim, offset + 14, @@ -2022,11 +2056,11 @@ void wlc_phy_txpower_update_shm(struct brcms_phy *pi) for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) pi->tx_power_offset[i] = - (u8) roundup(pi->tx_power_offset[i], 8); + (u8) roundup(pi->tx_power_offset[i], 8); wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET, - (u16) - ((pi->tx_power_offset[TXP_FIRST_OFDM] - + 7) >> 3)); + (u16) ((pi-> + tx_power_offset[TXP_FIRST_OFDM] + + 7) >> 3)); } } @@ -2034,38 +2068,48 @@ bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi) { struct brcms_phy *pi = (struct brcms_phy *) ppi; - if (ISNPHY(pi)) + if (ISNPHY(pi)) { return pi->nphy_txpwrctrl; - else + } else { return pi->hwpwrctrl; + } } void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl) { struct brcms_phy *pi = (struct brcms_phy *) ppi; + bool cur_hwpwrctrl = pi->hwpwrctrl; bool suspend; - if (!pi->hwpwrctrl_capable) + if (!pi->hwpwrctrl_capable) { return; + } pi->hwpwrctrl = hwpwrctrl; pi->nphy_txpwrctrl = hwpwrctrl; pi->txpwrctrl = hwpwrctrl; if (ISNPHY(pi)) { - suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + suspend = + (0 == + (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); - if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) + if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) { wlc_phy_txpwr_fixpower_nphy(pi); - else + } else { + mod_phy_reg(pi, 0x1e7, (0x7f << 0), pi->saved_txpwr_idx); + } if (!suspend) wlapi_enable_mac(pi->sh->physhim); + } else if (hwpwrctrl != cur_hwpwrctrl) { + + return; } } @@ -2081,6 +2125,8 @@ void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi) } } +static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi); + static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi) { s16 tx0_status, tx1_status; @@ -2091,31 +2137,42 @@ static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi) estPower1 = read_phy_reg(pi, 0x118); estPower2 = read_phy_reg(pi, 0x119); - if ((estPower1 & (0x1 << 8)) == (0x1 << 8)) - pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0; - else + if ((estPower1 & (0x1 << 8)) + == (0x1 << 8)) { + pwr0 = (u8) (estPower1 & (0xff << 0)) + >> 0; + } else { pwr0 = 0x80; + } - if ((estPower2 & (0x1 << 8)) == (0x1 << 8)) - pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0; - else + if ((estPower2 & (0x1 << 8)) + == (0x1 << 8)) { + pwr1 = (u8) (estPower2 & (0xff << 0)) + >> 0; + } else { pwr1 = 0x80; + } tx0_status = read_phy_reg(pi, 0x1ed); tx1_status = read_phy_reg(pi, 0x1ee); - if ((tx0_status & (0x1 << 15)) == (0x1 << 15)) - adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0; - else + if ((tx0_status & (0x1 << 15)) + == (0x1 << 15)) { + adj_pwr0 = (u8) (tx0_status & (0xff << 0)) + >> 0; + } else { adj_pwr0 = 0x80; - if ((tx1_status & (0x1 << 15)) == (0x1 << 15)) - adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0; - else + } + if ((tx1_status & (0x1 << 15)) + == (0x1 << 15)) { + adj_pwr1 = (u8) (tx1_status & (0xff << 0)) + >> 0; + } else { adj_pwr1 = 0x80; + } - est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | - adj_pwr1); - + est_pwr = + (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | adj_pwr1); return est_pwr; } @@ -2136,7 +2193,7 @@ wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power, power->flags |= (WL_TX_POWER_F_MIMO); if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) power->flags |= - (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW); + (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW); } else if (ISLCNPHY(pi)) { power->rf_cores = 1; power->flags |= (WL_TX_POWER_F_SISO); @@ -2199,18 +2256,16 @@ wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power, power->tx_power_max[1] = pi->tx_power_max; power->tx_power_max_rate_ind[0] = - pi->tx_power_max_rate_ind; + pi->tx_power_max_rate_ind; power->tx_power_max_rate_ind[1] = - pi->tx_power_max_rate_ind; + pi->tx_power_max_rate_ind; if (wlc_phy_tpc_isenabled_lcnphy(pi)) power->flags |= - (WL_TX_POWER_F_HW | - WL_TX_POWER_F_ENABLED); + (WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED); else power->flags &= - ~(WL_TX_POWER_F_HW | - WL_TX_POWER_F_ENABLED); + ~(WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED); wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0], (s8 *) &power->est_Pout_cck); @@ -2249,13 +2304,16 @@ void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val) BRCM_BAND_ALL); } - if (ISNPHY(pi)) + if (ISNPHY(pi)) { + return; + } if (!pi->sh->clk) return; - suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + suspend = + (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); @@ -2299,7 +2357,7 @@ wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant) pwr_ant[i] = cmplx_pwr_dbm[i]; } pi->nphy_noise_index = - MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); + MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); return true; } @@ -2311,16 +2369,20 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) bool sampling_in_progress = (pi->phynoise_state != 0); bool wait_for_intr = true; - if (NORADIO_ENAB(pi->pubpi)) + if (NORADIO_ENAB(pi->pubpi)) { return; + } switch (reason) { case PHY_NOISE_SAMPLE_MON: + pi->phynoise_chan_watchdog = ch; pi->phynoise_state |= PHY_NOISE_STATE_MON; + break; case PHY_NOISE_SAMPLE_EXTERNAL: + pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL; break; @@ -2336,13 +2398,15 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) if (pi->phy_fixed_noise) { if (ISNPHY(pi)) { pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] = - PHY_NOISE_FIXED_VAL_NPHY; + PHY_NOISE_FIXED_VAL_NPHY; pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] = - PHY_NOISE_FIXED_VAL_NPHY; + PHY_NOISE_FIXED_VAL_NPHY; pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); + noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; } else { + noise_dbm = PHY_NOISE_FIXED_VAL; } @@ -2405,14 +2469,15 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) wlapi_enable_mac(pi->sh->physhim); for (i = 0; i < pi->pubpi.phy_corenum; i++) - cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >> - log_num_samps; + cmplx_pwr[i] = + (est[i].i_pwr + + est[i].q_pwr) >> log_num_samps; wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); for (i = 0; i < pi->pubpi.phy_corenum; i++) { pi->nphy_noise_win[i][pi->nphy_noise_index] = - noise_dbm_ant[i]; + noise_dbm_ant[i]; if (noise_dbm_ant[i] > noise_dbm) noise_dbm = noise_dbm_ant[i]; @@ -2424,7 +2489,7 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) } } -done: + done: if (!wait_for_intr) wlc_phy_noise_cb(pi, ch, noise_dbm); @@ -2448,15 +2513,16 @@ static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm) if (pi->phynoise_state & PHY_NOISE_STATE_MON) { if (pi->phynoise_chan_watchdog == channel) { pi->sh->phy_noise_window[pi->sh->phy_noise_index] = - noise_dbm; + noise_dbm; pi->sh->phy_noise_index = - MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ); + MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ); } pi->phynoise_state &= ~PHY_NOISE_STATE_MON; } - if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) + if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) { pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL; + } } @@ -2472,16 +2538,15 @@ static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi) memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); - for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, - core++) { + for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, core++) { lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx)); hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx + 1)); cmplx_pwr[core] = (hi << 16) + lo; cmplx_pwr_tot += cmplx_pwr[core]; - if (cmplx_pwr[core] == 0) + if (cmplx_pwr[core] == 0) { noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY; - else + } else cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE; } @@ -2490,13 +2555,13 @@ static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi) for (core = 0; core < pi->pubpi.phy_corenum; core++) { pi->nphy_noise_win[core][pi->nphy_noise_index] = - noise_dbm_ant[core]; + noise_dbm_ant[core]; if (noise_dbm_ant[core] > noise_dbm) noise_dbm = noise_dbm_ant[core]; } pi->nphy_noise_index = - MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); + MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); return noise_dbm; @@ -2613,9 +2678,9 @@ void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core) } } -void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, - struct brcms_d11rxhdr *wlc_rxhdr) +void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx) { + struct brcms_d11rxhdr *wlc_rxhdr = (struct brcms_d11rxhdr *) ctx; struct d11rxhdr *rxh = &wlc_rxhdr->rxhdr; int rssi = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_JSSI_MASK; uint radioid = pih->radioid; @@ -2650,6 +2715,7 @@ void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, } if (ISLCNPHY(pi)) { + if (rssi > 127) rssi -= 256; } else if (radioid == BCM2055_ID || radioid == BCM2056_ID @@ -2657,7 +2723,7 @@ void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, rssi = wlc_phy_rssi_compute_nphy(pi, wlc_rxhdr); } -end: + end: wlc_rxhdr->rssi = (s8) rssi; } @@ -2691,20 +2757,23 @@ void wlc_phy_watchdog(struct brcms_phy_pub *pih) if (!pi->watchdog_override) return; - if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) + if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) { wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi, PHY_NOISE_SAMPLE_MON, CHSPEC_CHANNEL(pi-> radio_chanspec)); + } - if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) + if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) { pi->phynoise_state = 0; + } if ((!pi->phycal_txpower) || ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) { - if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) + if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) { pi->phycal_txpower = pi->sh->now; + } } if (NORADIO_ENAB(pi->pubpi)) @@ -2731,9 +2800,8 @@ void wlc_phy_watchdog(struct brcms_phy_pub *pih) ((pi->sh->now - pi->phy_lastcal) >= pi->sh->glacial_timer)) { if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi))) - wlc_lcnphy_calib_modes( - pi, - LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); + wlc_lcnphy_calib_modes(pi, + LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); if (! (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || ASSOC_INPROG_PHY(pi) @@ -2751,12 +2819,13 @@ void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi) uint i; uint k; - for (i = 0; i < MA_WINDOW_SZ; i++) + for (i = 0; i < MA_WINDOW_SZ; i++) { pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff); + } if (ISLCNPHY(pi)) { for (i = 0; i < MA_WINDOW_SZ; i++) pi->sh->phy_noise_window[i] = - PHY_NOISE_FIXED_VAL_LCNPHY; + PHY_NOISE_FIXED_VAL_LCNPHY; } pi->sh->phy_noise_index = 0; @@ -2779,6 +2848,69 @@ wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag) *eps_real -= 0x2000; } +static const fixed AtanTbl[] = { + 2949120, + 1740967, + 919879, + 466945, + 234379, + 117304, + 58666, + 29335, + 14668, + 7334, + 3667, + 1833, + 917, + 458, + 229, + 115, + 57, + 29 +}; + +void wlc_phy_cordic(fixed theta, cs32 *val) +{ + fixed angle, valtmp; + unsigned iter; + int signx = 1; + int signtheta; + + val[0].i = CORDIC_AG; + val[0].q = 0; + angle = 0; + + signtheta = (theta < 0) ? -1 : 1; + theta = + ((theta + FIXED(180) * signtheta) % FIXED(360)) - + FIXED(180) * signtheta; + + if (FLOAT(theta) > 90) { + theta -= FIXED(180); + signx = -1; + } else if (FLOAT(theta) < -90) { + theta += FIXED(180); + signx = -1; + } + + for (iter = 0; iter < CORDIC_NI; iter++) { + if (theta > angle) { + valtmp = val[0].i - (val[0].q >> iter); + val[0].q = (val[0].i >> iter) + val[0].q; + val[0].i = valtmp; + angle += AtanTbl[iter]; + } else { + valtmp = val[0].i + (val[0].q >> iter); + val[0].q = -(val[0].i >> iter) + val[0].q; + val[0].i = valtmp; + angle -= AtanTbl[iter]; + } + } + + val[0].i = val[0].i * signx; + val[0].q = val[0].q * signx; +} + void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi) { wlapi_del_timer(pi->sh->physhim, pi->phycal_timer); @@ -2822,12 +2954,11 @@ void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason) case PHY_PERICAL_PHYINIT: if (pi->nphy_perical == PHY_PERICAL_MPHASE) { - if (PHY_PERICAL_MPHASE_PENDING(pi)) + if (PHY_PERICAL_MPHASE_PENDING(pi)) { wlc_phy_cal_perical_mphase_reset(pi); - - wlc_phy_cal_perical_mphase_schedule( - pi, - PHY_PERICAL_INIT_DELAY); + } + wlc_phy_cal_perical_mphase_schedule(pi, + PHY_PERICAL_INIT_DELAY); } break; @@ -2835,16 +2966,17 @@ void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason) case PHY_PERICAL_START_IBSS: case PHY_PERICAL_UP_BSS: if ((pi->nphy_perical == PHY_PERICAL_MPHASE) && - PHY_PERICAL_MPHASE_PENDING(pi)) + PHY_PERICAL_MPHASE_PENDING(pi)) { wlc_phy_cal_perical_mphase_reset(pi); + } pi->first_cal_after_assoc = true; pi->cal_type_override = PHY_PERICAL_FULL; - if (pi->phycal_tempdelta) + if (pi->phycal_tempdelta) { pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi); - + } wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL); break; @@ -2852,24 +2984,26 @@ void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason) if (pi->phycal_tempdelta) { nphy_currtemp = wlc_phy_tempsense_nphy(pi); delta_temp = - (nphy_currtemp > pi->nphy_lastcal_temp) ? - nphy_currtemp - pi->nphy_lastcal_temp : - pi->nphy_lastcal_temp - nphy_currtemp; + (nphy_currtemp > pi->nphy_lastcal_temp) ? + nphy_currtemp - pi->nphy_lastcal_temp : + pi->nphy_lastcal_temp - nphy_currtemp; if ((delta_temp < (s16) pi->phycal_tempdelta) && (pi->nphy_txiqlocal_chanspec == - pi->radio_chanspec)) + pi->radio_chanspec)) { do_periodic_cal = false; - else + } else { pi->nphy_lastcal_temp = nphy_currtemp; + } } if (do_periodic_cal) { + if (pi->nphy_perical == PHY_PERICAL_MPHASE) { + if (!PHY_PERICAL_MPHASE_PENDING(pi)) - wlc_phy_cal_perical_mphase_schedule( - pi, - PHY_PERICAL_WDOG_DELAY); + wlc_phy_cal_perical_mphase_schedule(pi, + PHY_PERICAL_WDOG_DELAY); } else if (pi->nphy_perical == PHY_PERICAL_SPHASE) wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO); @@ -2915,9 +3049,9 @@ void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) pi->sh->phytxchain = txchain; - if (ISNPHY(pi)) + if (ISNPHY(pi)) { wlc_phy_rxcore_setstate_nphy(pih, rxchain); - + } pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain); } @@ -2961,17 +3095,17 @@ u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih) return active_bitmap; } -s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec) +s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, chanspec_t chanspec) { struct brcms_phy *pi = (struct brcms_phy *) pih; u8 siso_mcs_id, cdd_mcs_id; siso_mcs_id = - (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO : - TXP_FIRST_MCS_20_SISO; + (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO : + TXP_FIRST_MCS_20_SISO; cdd_mcs_id = - (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD : - TXP_FIRST_MCS_20_CDD; + (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD : + TXP_FIRST_MCS_20_CDD; if (pi->tx_power_target[siso_mcs_id] > (pi->tx_power_target[cdd_mcs_id] + 12)) @@ -2999,13 +3133,12 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) } ai_corereg(pi->sh->sih, SI_CC_IDX, - offsetof(struct chipcregs, gpiocontrol), - ~0x0, 0x0); + offsetof(chipcregs_t, gpiocontrol), ~0x0, + 0x0); ai_corereg(pi->sh->sih, SI_CC_IDX, - offsetof(struct chipcregs, gpioout), 0x40, - 0x40); + offsetof(chipcregs_t, gpioout), 0x40, 0x40); ai_corereg(pi->sh->sih, SI_CC_IDX, - offsetof(struct chipcregs, gpioouten), 0x40, + offsetof(chipcregs_t, gpioouten), 0x40, 0x40); } else { mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); @@ -3013,14 +3146,12 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); ai_corereg(pi->sh->sih, SI_CC_IDX, - offsetof(struct chipcregs, gpioout), 0x40, - 0x00); + offsetof(chipcregs_t, gpioout), 0x40, 0x00); ai_corereg(pi->sh->sih, SI_CC_IDX, - offsetof(struct chipcregs, gpioouten), 0x40, - 0x0); + offsetof(chipcregs_t, gpioouten), 0x40, 0x0); ai_corereg(pi->sh->sih, SI_CC_IDX, - offsetof(struct chipcregs, gpiocontrol), - ~0x0, 0x40); + offsetof(chipcregs_t, gpiocontrol), ~0x0, + 0x40); } } } @@ -3077,7 +3208,7 @@ wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset) *ofdmoffset = 0; } -s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec) +s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, chanspec_t chanspec) { return rssi; diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h index 1dbfaa3522be..e27d9e95a2dc 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h @@ -103,9 +103,6 @@ #define BRCMS_RSSI_INVALID 0 /* invalid RSSI value */ -struct d11regs; -struct phy_shim_info; - struct txpwr_limits { u8 cck[BRCMS_NUM_RATES_CCK]; u8 ofdm[BRCMS_NUM_RATES_OFDM]; @@ -129,43 +126,40 @@ struct txpwr_limits { struct tx_power { u32 flags; - u16 chanspec; /* txpwr report for this channel */ - u16 local_chanspec; /* channel on which we are associated */ - u8 local_max; /* local max according to the AP */ - u8 local_constraint; /* local constraint according to the AP */ - s8 antgain[2]; /* Ant gain for each band - from SROM */ - u8 rf_cores; /* count of RF Cores being reported */ - u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ - u8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain - * without adjustment */ - u8 est_Pout_cck; /* Latest CCK tx power out estimate */ - u8 tx_power_max[4]; /* Maximum target power among all rates */ - /* Index of the rate with the max target power */ - u8 tx_power_max_rate_ind[4]; - /* User limit */ - u8 user_limit[WL_TX_POWER_RATES]; - /* Regulatory power limit */ - u8 reg_limit[WL_TX_POWER_RATES]; - /* Max power board can support (SROM) */ - u8 board_limit[WL_TX_POWER_RATES]; - /* Latest target power */ - u8 target[WL_TX_POWER_RATES]; + chanspec_t chanspec; /* txpwr report for this channel */ + chanspec_t local_chanspec; /* channel on which we are associated */ + u8 local_max; /* local max according to the AP */ + u8 local_constraint; /* local constraint according to the AP */ + s8 antgain[2]; /* Ant gain for each band - from SROM */ + u8 rf_cores; /* count of RF Cores being reported */ + u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ + u8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain + * without adjustment + */ + u8 est_Pout_cck; /* Latest CCK tx power out estimate */ + u8 tx_power_max[4]; /* Maximum target power among all rates */ + u8 tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ + u8 user_limit[WL_TX_POWER_RATES]; /* User limit */ + u8 reg_limit[WL_TX_POWER_RATES]; /* Regulatory power limit */ + u8 board_limit[WL_TX_POWER_RATES]; /* Max power board can support (SROM) */ + u8 target[WL_TX_POWER_RATES]; /* Latest target power */ }; struct tx_inst_power { - u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ - u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ + u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ + u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ }; -struct brcms_chanvec { +struct chanvec { u8 vec[MAXCHANNEL / NBBY]; }; struct shared_phy_params { struct si_pub *sih; - struct phy_shim_info *physhim; + void *physhim; uint unit; uint corerev; + uint bustype; uint buscorerev; char *vars; u16 vid; @@ -183,10 +177,8 @@ struct shared_phy_params { extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp); -extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, - struct d11regs *regs, - int bandtype, char *vars, - struct wiphy *wiphy); +extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, void *regs, + int bandtype, char *vars, struct wiphy *wiphy); extern void wlc_phy_detach(struct brcms_phy_pub *ppi); extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, @@ -197,7 +189,7 @@ extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih); extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate); extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate); -extern void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec); +extern void wlc_phy_init(struct brcms_phy_pub *ppi, chanspec_t chanspec); extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi); extern int wlc_phy_down(struct brcms_phy_pub *ppi); extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih); @@ -205,15 +197,14 @@ extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi); extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init); extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, - u16 chanspec); -extern u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi); + chanspec_t chanspec); +extern chanspec_t wlc_phy_chanspec_get(struct brcms_phy_pub *ppi); extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, - u16 newch); + chanspec_t newch); extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi); extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw); -extern void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, - struct brcms_d11rxhdr *wlc_rxhdr); +extern void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx); extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi); extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi); extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi); @@ -229,9 +220,9 @@ extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi); extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, bool wide_filter); extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, - struct brcms_chanvec *channels); -extern u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, - uint band); + chanvec_t *channels); +extern chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, + uint band); extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan, u8 *_min_, u8 *_max_, int rate); @@ -241,7 +232,7 @@ extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint band, s32 *, s32 *, u32 *); extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *, - u16 chanspec); + chanspec_t chanspec); extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override); extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, @@ -263,7 +254,7 @@ extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain); extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih); extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, - u16 chanspec); + chanspec_t chanspec); extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val); extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason); @@ -273,8 +264,8 @@ extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi); extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val); extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi); -extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val); -extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags); +extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, mbool id, bool val); +extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, mbool flags); extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type); @@ -298,6 +289,6 @@ extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi); extern const u8 *wlc_phy_get_ofdm_rate_lookup(void); extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi, - u8 mcs_offset); + u8 mcs_offset); extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset); -#endif /* _BRCM_PHY_HAL_H_ */ +#endif /* _BRCM_PHY_HAL_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h index 0594a088e726..a01b01ccd9ff 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h @@ -41,21 +41,25 @@ extern u32 phyhal_msg_level; #define LCNXN_BASEREV 16 -struct phy_shim_info; - struct brcms_phy_srom_fem { - /* TSSI positive slope, 1: positive, 0: negative */ - u8 tssipos; - /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ - u8 extpagain; - /* support 32 combinations of different Pdet dynamic ranges */ - u8 pdetrange; - /* TR switch isolation */ - u8 triso; - /* antswctrl lookup table configuration: 32 possible choices */ - u8 antswctrllut; + u8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */ + u8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ + u8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */ + u8 triso; /* TR switch isolation */ + u8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */ }; +typedef void (*initfn_t) (struct brcms_phy *); +typedef void (*chansetfn_t) (struct brcms_phy *, chanspec_t); +typedef int (*longtrnfn_t) (struct brcms_phy *, int); +typedef void (*txiqccgetfn_t) (struct brcms_phy *, u16 *, u16 *); +typedef void (*txiqccsetfn_t) (struct brcms_phy *, u16, u16); +typedef u16(*txloccgetfn_t) (struct brcms_phy *); +typedef void (*radioloftgetfn_t) (struct brcms_phy *, u8 *, u8 *, u8 *, + u8 *); +typedef s32(*rxsigpwrfn_t) (struct brcms_phy *, s32); +typedef void (*detachfn_t) (struct brcms_phy *); + #undef ISNPHY #undef ISLCNPHY #define ISNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N) @@ -199,9 +203,7 @@ struct brcms_phy_srom_fem { #define PHY_PERICAL_WDOG_DELAY 5 #define MPHASE_TXCAL_NUMCMDS 2 - -#define PHY_PERICAL_MPHASE_PENDING(pi) \ - (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE) +#define PHY_PERICAL_MPHASE_PENDING(pi) (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE) enum { MPHASE_CAL_STATE_IDLE = 0, @@ -246,9 +248,7 @@ enum phy_cal_mode { #define CORDIC_AG 39797 #define CORDIC_NI 18 #define FIXED(X) ((s32)((X) << 16)) - -#define FLOAT(X) \ - (((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1)) +#define FLOAT(X) (((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1)) #define PHY_CHAIN_TX_DISABLE_TEMP 115 #define PHY_HYSTERESIS_DELTATEMP 5 @@ -256,46 +256,30 @@ enum phy_cal_mode { #define PHY_BITSCNT(x) brcmu_bitcount((u8 *)&(x), sizeof(u8)) #define MOD_PHY_REG(pi, phy_type, reg_name, field, value) \ - mod_phy_reg(pi, phy_type##_##reg_name, \ - phy_type##_##reg_name##_##field##_MASK, \ - (value) << phy_type##_##reg_name##_##field##_##SHIFT) - + mod_phy_reg(pi, phy_type##_##reg_name, phy_type##_##reg_name##_##field##_MASK, \ + (value) << phy_type##_##reg_name##_##field##_##SHIFT); #define READ_PHY_REG(pi, phy_type, reg_name, field) \ - ((read_phy_reg(pi, phy_type##_##reg_name) & \ - phy_type##_##reg_name##_##field##_##MASK) \ - >> phy_type##_##reg_name##_##field##_##SHIFT) + ((read_phy_reg(pi, phy_type##_##reg_name) & phy_type##_##reg_name##_##field##_##MASK)\ + >> phy_type##_##reg_name##_##field##_##SHIFT) #define VALID_PHYTYPE(phytype) (((uint)phytype == PHY_TYPE_N) || \ ((uint)phytype == PHY_TYPE_LCN)) -#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \ - (radioid == BCM2056_ID) || \ - (radioid == BCM2057_ID)) - +#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || (radioid == BCM2056_ID) || \ + (radioid == BCM2057_ID)) #define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID) -#define VALID_RADIO(pi, radioid) ( \ - (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \ - (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false)) - -#define SCAN_INPROG_PHY(pi) \ - (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN)) - -#define RM_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_RM)) - -#define PLT_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT)) +#define VALID_RADIO(pi, radioid) (\ + (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \ + (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false)) -#define ASSOC_INPROG_PHY(pi) \ - (mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC)) - -#define SCAN_RM_IN_PROGRESS(pi) \ - (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM)) - -#define PHY_MUTED(pi) \ - (mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE)) - -#define PUB_NOT_ASSOC(pi) \ - (mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC)) +#define SCAN_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN)) +#define RM_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_RM)) +#define PLT_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT)) +#define ASSOC_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC)) +#define SCAN_RM_IN_PROGRESS(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM)) +#define PHY_MUTED(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE)) +#define PUB_NOT_ASSOC(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC)) #if defined(EXT_CBALL) #define NORADIO_ENAB(pub) ((pub).radioid == NORADIO_ID) @@ -548,7 +532,7 @@ struct shared_phy { struct brcms_phy *phy_head; uint unit; struct si_pub *sih; - struct phy_shim_info *physhim; + void *physhim; uint corerev; u32 machwcap; bool up; @@ -565,6 +549,7 @@ struct shared_phy { uint boardvendor; u32 boardflags; u32 boardflags2; + uint bustype; uint buscorerev; uint fast_timer; uint slow_timer; @@ -594,31 +579,32 @@ struct brcms_phy_pub { }; struct phy_func_ptr { - void (*init)(struct brcms_phy *); - void (*calinit)(struct brcms_phy *); - void (*chanset)(struct brcms_phy *, u16 chanspec); - void (*txpwrrecalc)(struct brcms_phy *); - int (*longtrn)(struct brcms_phy *, int); - void (*txiqccget)(struct brcms_phy *, u16 *, u16 *); - void (*txiqccset)(struct brcms_phy *, u16, u16); - u16 (*txloccget)(struct brcms_phy *); - void (*radioloftget)(struct brcms_phy *, u8 *, u8 *, u8 *, u8 *); - void (*carrsuppr)(struct brcms_phy *); - s32 (*rxsigpwr)(struct brcms_phy *, s32); - void (*detach)(struct brcms_phy *); + initfn_t init; + initfn_t calinit; + chansetfn_t chanset; + initfn_t txpwrrecalc; + longtrnfn_t longtrn; + txiqccgetfn_t txiqccget; + txiqccsetfn_t txiqccset; + txloccgetfn_t txloccget; + radioloftgetfn_t radioloftget; + initfn_t carrsuppr; + rxsigpwrfn_t rxsigpwr; + detachfn_t detach; }; struct brcms_phy { struct brcms_phy_pub pubpi_ro; struct shared_phy *sh; struct phy_func_ptr pi_fptr; + void *pi_ptr; union { struct brcms_phy_lcnphy *pi_lcnphy; } u; bool user_txpwr_at_rfport; - struct d11regs *regs; + d11regs_t *regs; struct brcms_phy *next; char *vars; struct brcms_phy_pub pubpi; @@ -627,7 +613,7 @@ struct brcms_phy { bool phytest_on; bool ofdm_rateset_war; bool bf_preempt_4306; - u16 radio_chanspec; + chanspec_t radio_chanspec; u8 antsel_type; u16 bw; u8 txpwr_percent; @@ -643,7 +629,7 @@ struct brcms_phy { int phynoise_chan_watchdog; bool phynoise_polling; bool disable_percal; - u32 measure_hold; + mbool measure_hold; s16 txpa_2g[PWRTBL_NUM_COEFF]; s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF]; @@ -737,7 +723,7 @@ struct brcms_phy { u16 mintxbias; u16 mintxmag; struct lo_complex_abgphy_info gphy_locomp_iq - [STATIC_NUM_RF][STATIC_NUM_BB]; + [STATIC_NUM_RF][STATIC_NUM_BB]; s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB]; u16 gain_table[TX_GAIN_TABLE_LENGTH]; bool loopback_gain; @@ -854,11 +840,11 @@ struct brcms_phy { u8 mphase_txcal_cmdidx; u8 mphase_txcal_numcmds; u16 mphase_txcal_bestcoeffs[11]; - u16 nphy_txiqlocal_chanspec; - u16 nphy_iqcal_chanspec_2G; - u16 nphy_iqcal_chanspec_5G; - u16 nphy_rssical_chanspec_2G; - u16 nphy_rssical_chanspec_5G; + chanspec_t nphy_txiqlocal_chanspec; + chanspec_t nphy_iqcal_chanspec_2G; + chanspec_t nphy_iqcal_chanspec_5G; + chanspec_t nphy_rssical_chanspec_2G; + chanspec_t nphy_rssical_chanspec_5G; struct wlapi_timer *phycal_timer; bool use_int_tx_iqlo_cal_nphy; bool internal_tx_iqlo_cal_tapoff_intpa_nphy; @@ -951,9 +937,9 @@ struct brcms_phy { struct wiphy *wiphy; }; -struct cs32 { - s32 q; - s32 i; +struct _cs32 { + fixed q; + fixed i; }; struct radio_regs { @@ -980,29 +966,26 @@ struct lcnphy_radio_regs { extern struct lcnphy_radio_regs lcnphy_radio_regs_2064[]; extern struct lcnphy_radio_regs lcnphy_radio_regs_2066[]; - extern struct radio_regs regs_2055[], regs_SYN_2056[], regs_TX_2056[], - regs_RX_2056[]; + regs_RX_2056[]; extern struct radio_regs regs_SYN_2056_A1[], regs_TX_2056_A1[], - regs_RX_2056_A1[]; + regs_RX_2056_A1[]; extern struct radio_regs regs_SYN_2056_rev5[], regs_TX_2056_rev5[], - regs_RX_2056_rev5[]; + regs_RX_2056_rev5[]; extern struct radio_regs regs_SYN_2056_rev6[], regs_TX_2056_rev6[], - regs_RX_2056_rev6[]; + regs_RX_2056_rev6[]; extern struct radio_regs regs_SYN_2056_rev7[], regs_TX_2056_rev7[], - regs_RX_2056_rev7[]; + regs_RX_2056_rev7[]; extern struct radio_regs regs_SYN_2056_rev8[], regs_TX_2056_rev8[], - regs_RX_2056_rev8[]; - + regs_RX_2056_rev8[]; extern struct radio_20xx_regs regs_2057_rev4[], regs_2057_rev5[], - regs_2057_rev5v1[]; + regs_2057_rev5v1[]; extern struct radio_20xx_regs regs_2057_rev7[], regs_2057_rev8[]; extern char *phy_getvar(struct brcms_phy *pi, const char *name); extern int phy_getintvar(struct brcms_phy *pi, const char *name); - -#define PHY_GETVAR(pi, name) phy_getvar(pi, name) -#define PHY_GETINTVAR(pi, name) phy_getintvar(pi, name) +#define PHY_GETVAR(pi, name) phy_getvar(pi, name) +#define PHY_GETINTVAR(pi, name) phy_getintvar(pi, name) extern u16 read_phy_reg(struct brcms_phy *pi, u16 addr); extern void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); @@ -1039,6 +1022,7 @@ extern void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val); extern void write_phy_channel_reg(struct brcms_phy *pi, uint val); extern void wlc_phy_txpower_update_shm(struct brcms_phy *pi); +extern void wlc_phy_cordic(fixed theta, cs32 *val); extern u8 wlc_phy_nbits(s32 value); extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core); @@ -1069,14 +1053,14 @@ extern void wlc_phy_cal_init_nphy(struct brcms_phy *pi); extern void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi); extern void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, - u16 chanspec); + chanspec_t chanspec); extern void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, - u16 chanspec); + chanspec_t chanspec); extern void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi, - u16 chanspec); + chanspec_t chanspec); extern int wlc_phy_channel2freq(uint channel); extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint); -extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec); +extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, chanspec_t); extern void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode); extern s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi); @@ -1158,17 +1142,13 @@ extern void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable); extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode); -#define wlc_phy_write_table_nphy(pi, pti) \ - wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73) - -#define wlc_phy_read_table_nphy(pi, pti) \ - wlc_phy_read_table(pi, pti, 0x72, 0x74, 0x73) - -#define wlc_nphy_table_addr(pi, id, off) \ - wlc_phy_table_addr((pi), (id), (off), 0x72, 0x74, 0x73) - -#define wlc_nphy_table_data_write(pi, w, v) \ - wlc_phy_table_data_write((pi), (w), (v)) +#define wlc_phy_write_table_nphy(pi, pti) wlc_phy_write_table(pi, pti, 0x72, \ + 0x74, 0x73) +#define wlc_phy_read_table_nphy(pi, pti) wlc_phy_read_table(pi, pti, 0x72, \ + 0x74, 0x73) +#define wlc_nphy_table_addr(pi, id, off) wlc_phy_table_addr((pi), (id), (off), \ + 0x72, 0x74, 0x73) +#define wlc_nphy_table_data_write(pi, w, v) wlc_phy_table_data_write((pi), (w), (v)) extern void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o, u32 w, void *d); @@ -1180,7 +1160,7 @@ extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec))) #define BRCMS_PHY_WAR_PR51571(pi) \ - if (NREV_LT((pi)->pubpi.phy_rev, 3)) \ + if (((pi)->sh->bustype == PCI_BUS) && NREV_LT((pi)->pubpi.phy_rev, 3)) \ (void)R_REG(&(pi)->regs->maccontrol) extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype); @@ -1249,7 +1229,7 @@ extern void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs); void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset); extern s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, - u16 chanspec); + chanspec_t chanspec); extern bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih); #endif /* _BRCM_PHY_INT_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c index 269346e18a13..6a3fbe67302f 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c @@ -15,7 +15,6 @@ */ #include -#include #include #include @@ -80,15 +79,15 @@ #define wlc_lcnphy_enable_tx_gain_override(pi) \ wlc_lcnphy_set_tx_gain_override(pi, true) -#define wlc_lcnphy_disable_tx_gain_override(pi) \ +#define wlc_lcnphy_disable_tx_gain_override(pi) \ wlc_lcnphy_set_tx_gain_override(pi, false) #define wlc_lcnphy_iqcal_active(pi) \ (read_phy_reg((pi), 0x451) & \ - ((0x1 << 15) | (0x1 << 14))) + ((0x1 << 15) | (0x1 << 14))) #define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13)) -#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \ +#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \ (pi->temppwrctrl_capable) #define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \ (pi->hwpwrctrl_capable) @@ -133,12 +132,12 @@ #define LCNPHY_ACI_DETECT_TIMEOUT 2 #define LCNPHY_ACI_START_DELAY 0 -#define wlc_lcnphy_tx_gain_override_enabled(pi) \ +#define wlc_lcnphy_tx_gain_override_enabled(pi) \ (0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6))) #define wlc_lcnphy_total_tx_frames(pi) \ - wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \ - offsetof(struct macstat, txallfrm)) + wlapi_bmac_read_shm((pi)->sh->physhim, \ + M_UCODE_MACSTAT + offsetof(struct macstat, txallfrm)) struct lcnphy_txgains { u16 gm_gain; @@ -199,7 +198,7 @@ static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = { static const u16 iqcal_gainparams_numgains_lcnphy[1] = { sizeof(tbl_iqcal_gainparams_lcnphy_2G) / - sizeof(*tbl_iqcal_gainparams_lcnphy_2G), + sizeof(*tbl_iqcal_gainparams_lcnphy_2G), }; static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = { @@ -921,52 +920,47 @@ u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM] #define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \ mod_phy_reg(pi, 0x4a4, \ - (0x1ff << 0), \ - (u16)(idx) << 0) + (0x1ff << 0), \ + (u16)(idx) << 0) #define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \ mod_phy_reg(pi, 0x4a5, \ - (0x7 << 8), \ - (u16)(npt) << 8) + (0x7 << 8), \ + (u16)(npt) << 8) #define wlc_lcnphy_get_tx_pwr_ctrl(pi) \ (read_phy_reg((pi), 0x4a4) & \ - ((0x1 << 15) | \ - (0x1 << 14) | \ - (0x1 << 13))) + ((0x1 << 15) | \ + (0x1 << 14) | \ + (0x1 << 13))) #define wlc_lcnphy_get_tx_pwr_npt(pi) \ ((read_phy_reg(pi, 0x4a5) & \ - (0x7 << 8)) >> \ - 8) + (0x7 << 8)) >> \ + 8) #define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \ (read_phy_reg(pi, 0x473) & 0x1ff) #define wlc_lcnphy_get_target_tx_pwr(pi) \ ((read_phy_reg(pi, 0x4a7) & \ - (0xff << 0)) >> \ - 0) + (0xff << 0)) >> \ + 0) #define wlc_lcnphy_set_target_tx_pwr(pi, target) \ mod_phy_reg(pi, 0x4a7, \ - (0xff << 0), \ - (u16)(target) << 0) + (0xff << 0), \ + (u16)(target) << 0) -#define wlc_radio_2064_rcal_done(pi) \ - (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20)) - -#define tempsense_done(pi) \ - (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000)) - -#define LCNPHY_IQLOCC_READ(val) \ - ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f))) +#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20)) +#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000)) +#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f))) #define FIXED_TXPWR 78 #define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val)) static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor, - u8 precision); + u8 precision); static void wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, u16 ext_lna, u16 trsw, u16 biq2, u16 biq1, @@ -995,10 +989,8 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi); static void wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel); -static void wlc_lcnphy_load_tx_gain_table( - struct brcms_phy *pi, - const struct lcnphy_tx_gain_tbl_entry - *g); +static void wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, + const struct lcnphy_tx_gain_tbl_entry *g); static void wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh, s16 *ptr, int mode); @@ -1016,7 +1008,7 @@ static void wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi); static void wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, - u16 chanspec); + chanspec_t chanspec); static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi); static void wlc_lcnphy_temp_adj(struct brcms_phy *pi); static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi); @@ -1042,7 +1034,7 @@ void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti) static void wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id, - const u16 *tbl_ptr, u32 tbl_len, + const void *tbl_ptr, u32 tbl_len, u32 tbl_width, u32 tbl_offset) { struct phytbl_info tab; @@ -1056,7 +1048,7 @@ wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id, static void wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id, - const u16 *tbl_ptr, u32 tbl_len, + const void *tbl_ptr, u32 tbl_len, u32 tbl_width, u32 tbl_offset) { @@ -1100,12 +1092,12 @@ static int wlc_lcnphy_calc_floor(s16 coeff_x, int type) int k; k = 0; if (type == 0) { - if (coeff_x < 0) + if (coeff_x < 0) { k = (coeff_x - 1) / 2; - else + } else { k = coeff_x / 2; + } } - if (type == 1) { if ((coeff_x + 1) < 0) k = (coeff_x) / 2; @@ -1123,8 +1115,9 @@ s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi) if (txpwrctrl_off(pi)) index = pi_lcn->lcnphy_current_index; else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) - index = (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on( - pi) / 2); + index = + (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) + / 2); else index = pi_lcn->lcnphy_current_index; return index; @@ -1207,7 +1200,7 @@ wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable) wlapi_switch_macfreq(pi->sh->physhim, enable); } -void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) +void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, chanspec_t chanspec) { u8 channel = CHSPEC_CHANNEL(chanspec); @@ -1272,7 +1265,7 @@ static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi) pa_gain = (read_phy_reg(pi, 0x4fb) & LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >> - LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT; + LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT; return pa_gain; } @@ -1282,22 +1275,18 @@ static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi, { u16 pa_gain = wlc_lcnphy_get_pa_gain(pi); - mod_phy_reg( - pi, 0x4b5, - (0xffff << 0), - ((target_gains->gm_gain) | - (target_gains->pga_gain << 8)) << - 0); + mod_phy_reg(pi, 0x4b5, + (0xffff << 0), + ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) << + 0); mod_phy_reg(pi, 0x4fb, (0x7fff << 0), ((target_gains->pad_gain) | (pa_gain << 8)) << 0); - mod_phy_reg( - pi, 0x4fc, - (0xffff << 0), - ((target_gains->gm_gain) | - (target_gains->pga_gain << 8)) << - 0); + mod_phy_reg(pi, 0x4fc, + (0xffff << 0), + ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) << + 0); mod_phy_reg(pi, 0x4fd, (0x7fff << 0), ((target_gains->pad_gain) | (pa_gain << 8)) << 0); @@ -1415,8 +1404,8 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi) u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp; struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; - auxpga_vmid = (2 << 8) | - (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf; + auxpga_vmid = + (2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf; auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4; auxpga_gain_temp = 2; @@ -1542,9 +1531,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3); - if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) + if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { mod_phy_reg(pi, 0x4d7, (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12); + } rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi); tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; @@ -1611,7 +1601,7 @@ void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi) { struct phytbl_info tab; u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM + - BRCMS_NUM_RATES_MCS_1_STREAM]; + BRCMS_NUM_RATES_MCS_1_STREAM]; uint i, j; if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) return; @@ -1707,28 +1697,31 @@ static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi) if (NORADIO_ENAB(pi->pubpi)) return index; - if (pi_lcn->lcnphy_tempsense_slope == 0) + if (pi_lcn->lcnphy_tempsense_slope == 0) { return index; - + } temp = (u16) wlc_lcnphy_tempsense(pi, 0); meas_temp = LCNPHY_TEMPSENSE(temp); - if (pi->tx_power_min != 0) + if (pi->tx_power_min != 0) { delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min); - else + } else { delta_brd = 0; + } manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense); temp_diff = manp - meas_temp; if (temp_diff < 0) { + neg = 1; + temp_diff = -temp_diff; } delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192), - (u32) (pi_lcn-> - lcnphy_tempsense_slope - * 10), 0); + (u32) (pi_lcn-> + lcnphy_tempsense_slope + * 10), 0); if (neg) delta_temp = -delta_temp; @@ -1742,15 +1735,14 @@ static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi) if (LCNREV_IS(pi->pubpi.phy_rev, 1)) tempcorrx = 4; new_index = - index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr; + index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr; new_index += tempcorrx; if (LCNREV_IS(pi->pubpi.phy_rev, 1)) index = 127; - - if (new_index < 0 || new_index > 126) + if (new_index < 0 || new_index > 126) { return index; - + } return new_index; } @@ -1800,7 +1792,7 @@ void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode) mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0); pi_lcn->lcnphy_tssi_tx_cnt = - wlc_lcnphy_total_tx_frames(pi); + wlc_lcnphy_total_tx_frames(pi); wlc_lcnphy_disable_tx_gain_override(pi); pi_lcn->lcnphy_tx_power_idx_override = -1; @@ -1813,9 +1805,7 @@ void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode) index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index); pi_lcn->lcnphy_current_index = (s8) - ((read_phy_reg(pi, - 0x4a9) & - 0xFF) / 2); + ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2); } } } @@ -1847,23 +1837,20 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, int j; u16 ncorr_override[5]; u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + }; u16 commands_fullcal[] = { - 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 - }; + 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 }; u16 commands_recal[] = { - 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 - }; + 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 }; u16 command_nums_fullcal[] = { - 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 - }; + 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 }; u16 command_nums_recal[] = { - 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 - }; + 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 }; u16 *command_nums = command_nums_fullcal; u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start; @@ -1879,8 +1866,9 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, return; values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); - if (NULL == values_to_save) + if (NULL == values_to_save) { return; + } save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); @@ -1939,7 +1927,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, } hash = (target_gains->gm_gain << 8) | - (target_gains->pga_gain << 4) | (target_gains->pad_gain); + (target_gains->pga_gain << 4) | (target_gains->pad_gain); band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0); @@ -1948,11 +1936,11 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) { if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) { cal_gains.gm_gain = - tbl_iqcal_gainparams_lcnphy[band_idx][j][1]; + tbl_iqcal_gainparams_lcnphy[band_idx][j][1]; cal_gains.pga_gain = - tbl_iqcal_gainparams_lcnphy[band_idx][j][2]; + tbl_iqcal_gainparams_lcnphy[band_idx][j][2]; cal_gains.pad_gain = - tbl_iqcal_gainparams_lcnphy[band_idx][j][3]; + tbl_iqcal_gainparams_lcnphy[band_idx][j][3]; memcpy(ncorr_override, &tbl_iqcal_gainparams_lcnphy[band_idx][j][3], sizeof(ncorr_override)); @@ -1966,14 +1954,14 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, write_phy_reg(pi, 0x93d, 0xc0); wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, + (const void *) lcnphy_iqcal_loft_gainladder, ARRAY_SIZE(lcnphy_iqcal_loft_gainladder), 16, 0); wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, - lcnphy_iqcal_ir_gainladder, - ARRAY_SIZE( - lcnphy_iqcal_ir_gainladder), 16, + (const void *)lcnphy_iqcal_ir_gainladder, + ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16, 32); if (pi->phy_tx_tone_freq) { @@ -1997,12 +1985,13 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, command_num = command_nums[i]; if (ncorr_override[cal_type]) command_num = - ncorr_override[cal_type] << 8 | (command_num & - 0xff); + ncorr_override[cal_type] << 8 | (command_num & + 0xff); write_phy_reg(pi, 0x452, command_num); if ((cal_type == 3) || (cal_type == 4)) { + wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, &diq_start, 1, 16, 69); @@ -2012,8 +2001,10 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, write_phy_reg(pi, 0x451, cal_cmds[i]); - if (!wlc_lcnphy_iqcal_wait(pi)) + if (!wlc_lcnphy_iqcal_wait(pi)) { + goto cleanup; + } wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, best_coeffs, @@ -2022,15 +2013,16 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, best_coeffs, ARRAY_SIZE(best_coeffs), 16, 64); - if ((cal_type == 3) || (cal_type == 4)) + if ((cal_type == 3) || (cal_type == 4)) { wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, &diq_start, 1, 16, 69); + } wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, pi_lcn->lcnphy_cal_results. txiqlocal_bestcoeffs, ARRAY_SIZE(pi_lcn-> - lcnphy_cal_results. - txiqlocal_bestcoeffs), + lcnphy_cal_results. + txiqlocal_bestcoeffs), 16, 96); } @@ -2038,7 +2030,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, pi_lcn->lcnphy_cal_results. txiqlocal_bestcoeffs, ARRAY_SIZE(pi_lcn->lcnphy_cal_results. - txiqlocal_bestcoeffs), 16, 96); + txiqlocal_bestcoeffs), 16, 96); pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true; wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, @@ -2049,7 +2041,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, &pi_lcn->lcnphy_cal_results. txiqlocal_bestcoeffs[5], 2, 16, 85); -cleanup: + cleanup: wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save); kfree(values_to_save); @@ -2079,14 +2071,14 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112); u16 SAVE_jtag_bb_afe_switch = - read_radio_reg(pi, RADIO_2064_REG007) & 1; + read_radio_reg(pi, RADIO_2064_REG007) & 1; u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; idleTssi = read_phy_reg(pi, 0x4ab); suspend = - (0 == - (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) & - MCTL_EN_MAC)); + (0 == + (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) & + MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); @@ -2144,7 +2136,7 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode) struct phytbl_info tab; u32 val; u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025, - save_reg112; + save_reg112; u16 values_to_save[14]; s8 index; int i; @@ -2160,7 +2152,8 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode) for (i = 0; i < 14; i++) values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]); - suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + suspend = + (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4); @@ -2243,7 +2236,7 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode) auxpga_gain = 2; } auxpga_vmid = - (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine); + (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine); mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0); mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2); @@ -2287,7 +2280,7 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) struct brcms_phy *pi = (struct brcms_phy *) ppi; suspend = - (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); @@ -2537,10 +2530,9 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, gain16_19 = biq2 & 0xf; gain0_15 = ((biq1 & 0xf) << 12) | - ((tia & 0xf) << 8) | - ((lna2 & 0x3) << 6) | - ((lna2 & - 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0); + ((tia & 0xf) << 8) | + ((lna2 & 0x3) << 6) | + ((lna2 & 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0); mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); @@ -2597,9 +2589,9 @@ void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable) and_phy_reg(pi, 0x44c, ~(u16) ((0x1 << 3) | - (0x1 << 5) | - (0x1 << 12) | - (0x1 << 0) | (0x1 << 1) | (0x1 << 2))); + (0x1 << 5) | + (0x1 << 12) | + (0x1 << 0) | (0x1 << 1) | (0x1 << 2))); and_phy_reg(pi, 0x44d, ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14))); @@ -2709,8 +2701,7 @@ void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode) mod_phy_reg((pi), 0x410, (0x1 << 6) | (0x1 << 5), - ((CHSPEC_IS2G( - pi->radio_chanspec)) ? (!mode) : 0) << + ((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) << 6 | (!mode) << 5); mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7); } @@ -2723,8 +2714,8 @@ wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val, u8 phy_bw; u16 num_samps, t, k; u32 bw; - s32 theta = 0, rot = 0; - struct cordic_iq tone_samp; + fixed theta = 0, rot = 0; + cs32 tone_samp; u32 data_buf[64]; u16 i_samp, q_samp; struct phytbl_info tab; @@ -2752,12 +2743,12 @@ wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val, } else num_samps = 2; - rot = ((f_kHz * 36) / phy_bw) / 100; + rot = FIXED((f_kHz * 36) / phy_bw) / 100; theta = 0; for (t = 0; t < num_samps; t++) { - tone_samp = cordic_calc_iq(theta); + wlc_phy_cordic(theta, &tone_samp); theta += rot; @@ -2887,6 +2878,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) lcnphy_recal ? LCNPHY_CAL_RECAL : LCNPHY_CAL_FULL), false); } else { + wlc_lcnphy_tx_iqlo_soft_cal_full(pi); } @@ -2913,8 +2905,10 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) wlc_lcnphy_tx_iqlo_cal(pi, &target_gains, LCNPHY_CAL_FULL, false); } else { + wlc_lcnphy_tx_iqlo_soft_cal_full(pi); } + } wlc_lcnphy_get_tx_iqcc(pi, &a, &b); @@ -2933,7 +2927,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) wlc_lcnphy_read_table(pi, &tab); val = (val & 0xfff00000) | - ((u32) (a & 0x3FF) << 10) | (b & 0x3ff); + ((u32) (a & 0x3FF) << 10) | (b & 0x3ff); wlc_lcnphy_write_table(pi, &tab); val = didq; @@ -2970,8 +2964,8 @@ s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode) if (mode == 1) { suspend = - (0 == - (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + (0 == + (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); @@ -3017,8 +3011,8 @@ u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode) if (mode == 1) { suspend = - (0 == - (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + (0 == + (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); @@ -3069,9 +3063,8 @@ s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode) { s32 degree = wlc_lcnphy_tempsense_new(pi, mode); degree = - ((degree << - 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1)) - / LCN_TEMPSENSE_DEN; + ((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1)) + / LCN_TEMPSENSE_DEN; return (s8) degree; } @@ -3086,8 +3079,8 @@ s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode) if (mode == 1) { suspend = - (0 == - (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + (0 == + (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE); @@ -3100,8 +3093,9 @@ s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode) else avg = (s32) vbatsenseval; - avg = (avg * LCN_VBAT_SCALE_NOM + - (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN; + avg = + (avg * LCN_VBAT_SCALE_NOM + + (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN; if (mode == 1) { if (!suspend) @@ -3157,13 +3151,13 @@ wlc_lcnphy_rx_iq_est(struct brcms_phy *pi, } iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) | - (u32) read_phy_reg(pi, 0x484); + (u32) read_phy_reg(pi, 0x484); iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) | - (u32) read_phy_reg(pi, 0x486); + (u32) read_phy_reg(pi, 0x486); iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) | - (u32) read_phy_reg(pi, 0x488); + (u32) read_phy_reg(pi, 0x488); -cleanup: + cleanup: mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3); mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5); @@ -3211,26 +3205,30 @@ static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps) if (arsh >= 0) { a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); temp = (s32) (ii >> arsh); - if (temp == 0) + if (temp == 0) { return false; + } } else { a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); temp = (s32) (ii << -arsh); - if (temp == 0) + if (temp == 0) { return false; + } } a /= temp; brsh = qq_nbits - 31 + 20; if (brsh >= 0) { b = (qq << (31 - qq_nbits)); temp = (s32) (ii >> brsh); - if (temp == 0) + if (temp == 0) { return false; + } } else { b = (qq << (31 - qq_nbits)); temp = (s32) (ii << -brsh); - if (temp == 0) + if (temp == 0) { return false; + } } b /= temp; b -= a * a; @@ -3238,7 +3236,7 @@ static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps) b -= (1 << 10); a0_new = (u16) (a & 0x3ff); b0_new = (u16) (b & 0x3ff); -cleanup: + cleanup: wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new); @@ -3274,12 +3272,14 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); - if (NULL == ptr) + if (NULL == ptr) { return false; + } if (module == 2) { while (iqcomp_sz--) { if (iqcomp[iqcomp_sz].chan == CHSPEC_CHANNEL(pi->radio_chanspec)) { + wlc_lcnphy_set_rx_iq_comp(pi, (u16) iqcomp[iqcomp_sz].a, @@ -3297,9 +3297,10 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); - for (i = 0; i < 11; i++) + for (i = 0; i < 11; i++) { values_to_save[i] = - read_radio_reg(pi, rxiq_cal_rf_reg[i]); + read_radio_reg(pi, rxiq_cal_rf_reg[i]); + } Core1TxControl_old = read_phy_reg(pi, 0x631); or_phy_reg(pi, 0x631, 0x0015); @@ -3373,7 +3374,7 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, udelay(500); received_power = - wlc_lcnphy_measure_digital_power(pi, 2000); + wlc_lcnphy_measure_digital_power(pi, 2000); if (received_power < rx_pwr_threshold) break; } @@ -3400,20 +3401,21 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); - for (i = 0; i < 11; i++) + for (i = 0; i < 11; i++) { write_radio_reg(pi, rxiq_cal_rf_reg[i], values_to_save[i]); + } - if (tx_gain_override_old) + if (tx_gain_override_old) { wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); - else + } else wlc_lcnphy_disable_tx_gain_override(pi); - wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); + wlc_lcnphy_rx_gain_override_enable(pi, false); } -cal_done: + cal_done: kfree(ptr); return result; } @@ -3431,7 +3433,7 @@ static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi) u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; suspend = - (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); wlc_lcnphy_deaf_mode(pi, true); @@ -3467,18 +3469,18 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi) pi->phy_lastcal = pi->sh->now; pi->phy_forcecal = false; full_cal = - (pi_lcn->lcnphy_full_cal_channel != - CHSPEC_CHANNEL(pi->radio_chanspec)); + (pi_lcn->lcnphy_full_cal_channel != + CHSPEC_CHANNEL(pi->radio_chanspec)); pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec); index = pi_lcn->lcnphy_current_index; suspend = - (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) { + wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); wlapi_suspend_mac_and_wait(pi->sh->physhim); } - wlc_lcnphy_deaf_mode(pi, true); wlc_lcnphy_txpwrtbl_iqlo_cal(pi); @@ -3529,6 +3531,7 @@ void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode) switch (mode) { case PHY_PERICAL_CHAN: + break; case PHY_FULLCAL: wlc_lcnphy_periodic_cal(pi); @@ -3555,7 +3558,7 @@ void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode) case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL: if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) wlc_lcnphy_tx_power_adjustment( - (struct brcms_phy_pub *) pi); + (struct brcms_phy_pub *) pi); break; } } @@ -3568,7 +3571,7 @@ void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr) if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) && (status & (0x1 << 15))) { *ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) - >> 0) >> 1); + >> 0) >> 1); if (wlc_phy_tpc_isenabled_lcnphy(pi)) cck_offset = pi->tx_power_offset[TXP_FIRST_CCK]; @@ -3589,7 +3592,7 @@ void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi) } static void -wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) +wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, chanspec_t chanspec) { u8 channel = CHSPEC_CHANNEL(chanspec); struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; @@ -3597,11 +3600,13 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) if (NORADIO_ENAB(pi->pubpi)) return; - if (channel == 14) + if (channel == 14) { mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); - else + + } else { mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); + } pi_lcn->lcnphy_bandedge_corr = 2; if (channel == 1) pi_lcn->lcnphy_bandedge_corr = 4; @@ -3646,14 +3651,13 @@ void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi) struct brcms_phy *pi = (struct brcms_phy *) ppi; struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); - if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && - SAVE_txpwrctrl) { + if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) { index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); index2 = (u16) (index * 2); mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0); - pi_lcn->lcnphy_current_index = - (s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2); + pi_lcn->lcnphy_current_index = (s8) + ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2); } } @@ -3727,9 +3731,10 @@ wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save) { u16 vmid; int i; - for (i = 0; i < 20; i++) + for (i = 0; i < 20; i++) { values_to_save[i] = - read_radio_reg(pi, iqlo_loopback_rf_regs[i]); + read_radio_reg(pi, iqlo_loopback_rf_regs[i]); + } mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12); mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14); @@ -3867,24 +3872,22 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh, val = R_REG(&pi->regs->tplatewrdata); imag = ((val >> 16) & 0x3ff); real = ((val) & 0x3ff); - if (imag > 511) + if (imag > 511) { imag -= 1024; - - if (real > 511) + } + if (real > 511) { real -= 1024; - + } if (pi_lcn->lcnphy_iqcal_swp_dis) ptr[(strptr - 0x7E00) / 4] = real; else ptr[(strptr - 0x7E00) / 4] = imag; - if (clip_detect_algo) { if (imag > thresh || imag < -thresh) { strptr = 0x8000; ptr[130] = 1; } } - strptr += 4; } @@ -4016,8 +4019,9 @@ wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, phy_c21 = 0; phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0; ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); - if (NULL == ptr) + if (NULL == ptr) { return; + } phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); if (NULL == phy_c32) { @@ -4050,16 +4054,18 @@ wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, phy_c4 = 32; if (num_levels == 0) { - if (cal_type != 0) + if (cal_type != 0) { num_levels = 4; - else + } else { num_levels = 9; + } } if (step_size_lg2 == 0) { - if (cal_type != 0) + if (cal_type != 0) { step_size_lg2 = 3; - else + } else { step_size_lg2 = 8; + } } phy_c7 = (1 << step_size_lg2); @@ -4144,11 +4150,11 @@ wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, phy_c18 = 0; phy_c19 = 0; for (j = 0; j < 128; j++) { - if (cal_type != 0) + if (cal_type != 0) { phy_c6 = j % phy_c4; - else + } else { phy_c6 = (2 * j) % phy_c4; - + } phy_c2.re = phy_c1[phy_c6].re; phy_c2.im = phy_c1[phy_c6].im; phy_c17 = ptr[j]; @@ -4158,8 +4164,8 @@ wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, phy_c18 = phy_c18 >> 10; phy_c19 = phy_c19 >> 10; - phy_c20 = ((phy_c18 * phy_c18) + - (phy_c19 * phy_c19)); + phy_c20 = + ((phy_c18 * phy_c18) + (phy_c19 * phy_c19)); if (phy_c23 || phy_c20 < phy_c21) { phy_c21 = phy_c20; @@ -4177,7 +4183,7 @@ wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, udelay(20); } goto cleanup; -cleanup: + cleanup: wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32); wlc_lcnphy_stop_tx_tone(pi); write_phy_reg(pi, 0x6da, phy_c26); @@ -4200,15 +4206,15 @@ wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save) and_phy_reg(pi, 0x43b, 0xC); - for (i = 0; i < 20; i++) + for (i = 0; i < 20; i++) { write_radio_reg(pi, iqlo_loopback_rf_regs[i], values_to_save[i]); + } } static void wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, - const struct lcnphy_tx_gain_tbl_entry *gain_table) -{ + const struct lcnphy_tx_gain_tbl_entry *gain_table) { u32 j; struct phytbl_info tab; u32 val; @@ -4300,8 +4306,9 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) phybw40 = CHSPEC_IS40(pi->radio_chanspec); - for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) + for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) { wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]); + } if (pi->sh->boardflags & BFL_FEM_BT) { tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; @@ -4332,35 +4339,39 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) if (CHSPEC_IS2G(pi->radio_chanspec)) { if (pi->sh->boardflags & BFL_FEM) - wlc_lcnphy_load_tx_gain_table( - pi, - dot11lcnphy_2GHz_extPA_gaintable_rev0); + wlc_lcnphy_load_tx_gain_table(pi, + dot11lcnphy_2GHz_extPA_gaintable_rev0); else - wlc_lcnphy_load_tx_gain_table( - pi, - dot11lcnphy_2GHz_gaintable_rev0); + wlc_lcnphy_load_tx_gain_table(pi, + dot11lcnphy_2GHz_gaintable_rev0); } if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { - const struct phytbl_info *tb; - int l; - if (CHSPEC_IS2G(pi->radio_chanspec)) { - l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz; - if (pi->sh->boardflags & BFL_EXTLNA) - tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2; - else - tb = dot11lcnphytbl_rx_gain_info_2G_rev2; + for (idx = 0; + idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz; + idx++) + if (pi->sh->boardflags & BFL_EXTLNA) + wlc_lcnphy_write_table(pi, + &dot11lcnphytbl_rx_gain_info_extlna_2G_rev2 + [idx]); + else + wlc_lcnphy_write_table(pi, + &dot11lcnphytbl_rx_gain_info_2G_rev2 + [idx]); } else { - l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz; - if (pi->sh->boardflags & BFL_EXTLNA_5GHz) - tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2; - else - tb = dot11lcnphytbl_rx_gain_info_5G_rev2; + for (idx = 0; + idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz; + idx++) + if (pi->sh->boardflags & BFL_EXTLNA_5GHz) + wlc_lcnphy_write_table(pi, + &dot11lcnphytbl_rx_gain_info_extlna_5G_rev2 + [idx]); + else + wlc_lcnphy_write_table(pi, + &dot11lcnphytbl_rx_gain_info_5G_rev2 + [idx]); } - - for (idx = 0; idx < l; idx++) - wlc_lcnphy_write_table(pi, &tb[idx]); } if ((pi->sh->boardflags & BFL_FEM) @@ -4368,13 +4379,11 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa); else if (pi->sh->boardflags & BFL_FEM_BT) { if (pi->sh->boardrev < 0x1250) - wlc_lcnphy_write_table( - pi, - &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa); + wlc_lcnphy_write_table(pi, + &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa); else - wlc_lcnphy_write_table( - pi, - &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250); + wlc_lcnphy_write_table(pi, + &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250); } else wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313); @@ -4411,8 +4420,9 @@ static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi) if (0) { afectrl1 = 0; afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) | - (pi_lcn->lcnphy_rssi_vc << 4) | - (pi_lcn->lcnphy_rssi_gs << 10)); + (pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn-> + lcnphy_rssi_gs + << 10)); write_phy_reg(pi, 0x43e, afectrl1); } @@ -4433,6 +4443,7 @@ static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi) { if (CHSPEC_IS5G(pi->radio_chanspec)) { mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0); + mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8); } } @@ -4473,15 +4484,18 @@ static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi) tableBuffer[1] -= 128; pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1]; - temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0)); + temp = (s16) (read_phy_reg(pi, 0x434) + & (0xff << 0)); if (temp > 127) temp -= 256; pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp; - pi_lcn->lcnphy_Med_Low_Gain_db = - (read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8; - pi_lcn->lcnphy_Very_Low_Gain_db = - (read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0; + pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424) + & (0xff << 8)) + >> 8; + pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425) + & (0xff << 0)) + >> 0; tab.tbl_ptr = tableBuffer; tab.tbl_len = 2; @@ -4672,8 +4686,8 @@ static void wlc_lcnphy_rc_cal(struct brcms_phy *pi) if (LCNREV_IS(pi->pubpi.phy_rev, 1)) dflt_rc_cal_val = 11; flt_val = - (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) | - (dflt_rc_cal_val); + (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) | + (dflt_rc_cal_val); write_phy_reg(pi, 0x933, flt_val); write_phy_reg(pi, 0x934, flt_val); write_phy_reg(pi, 0x935, flt_val); @@ -4694,10 +4708,10 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) u32 offset_ofdm, offset_mcs; pi_lcn->lcnphy_tr_isolation_mid = - (u8) PHY_GETINTVAR(pi, "triso2g"); + (u8) PHY_GETINTVAR(pi, "triso2g"); pi_lcn->lcnphy_rx_power_offset = - (u8) PHY_GETINTVAR(pi, "rxpo2g"); + (u8) PHY_GETINTVAR(pi, "rxpo2g"); pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0"); pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1"); @@ -4713,11 +4727,11 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs; pi_lcn->lcnphy_rssi_vf_hightemp = - pi_lcn->lcnphy_rssi_vf; + pi_lcn->lcnphy_rssi_vf; pi_lcn->lcnphy_rssi_vc_hightemp = - pi_lcn->lcnphy_rssi_vc; + pi_lcn->lcnphy_rssi_vc; pi_lcn->lcnphy_rssi_gs_hightemp = - pi_lcn->lcnphy_rssi_gs; + pi_lcn->lcnphy_rssi_gs; } txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0"); @@ -4733,16 +4747,15 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) uint max_pwr_chan = txpwr; for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) { - pi->tx_srom_max_rate_2g[i] = - max_pwr_chan - ((cckpo & 0xf) * 2); + pi->tx_srom_max_rate_2g[i] = max_pwr_chan - + ((cckpo & 0xf) * 2); cckpo >>= 4; } offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo"); for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { - pi->tx_srom_max_rate_2g[i] = - max_pwr_chan - - ((offset_ofdm & 0xf) * 2); + pi->tx_srom_max_rate_2g[i] = max_pwr_chan - + ((offset_ofdm & 0xf) * 2); offset_ofdm >>= 4; } } else { @@ -4750,55 +4763,57 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) opo = (u8) PHY_GETINTVAR(pi, "opo"); - for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) + for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) { pi->tx_srom_max_rate_2g[i] = txpwr; + } offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo"); for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { pi->tx_srom_max_rate_2g[i] = txpwr - - ((offset_ofdm & 0xf) * 2); + ((offset_ofdm & 0xf) * 2); offset_ofdm >>= 4; } offset_mcs = - ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) | - (u16) PHY_GETINTVAR(pi, "mcs2gpo0"); + ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) | + (u16) PHY_GETINTVAR(pi, "mcs2gpo0"); pi_lcn->lcnphy_mcs20_po = offset_mcs; for (i = TXP_FIRST_SISO_MCS_20; i <= TXP_LAST_SISO_MCS_20; i++) { pi->tx_srom_max_rate_2g[i] = - txpwr - ((offset_mcs & 0xf) * 2); + txpwr - ((offset_mcs & 0xf) * 2); offset_mcs >>= 4; } } pi_lcn->lcnphy_rawtempsense = - (u16) PHY_GETINTVAR(pi, "rawtempsense"); + (u16) PHY_GETINTVAR(pi, "rawtempsense"); pi_lcn->lcnphy_measPower = - (u8) PHY_GETINTVAR(pi, "measpower"); + (u8) PHY_GETINTVAR(pi, "measpower"); pi_lcn->lcnphy_tempsense_slope = - (u8) PHY_GETINTVAR(pi, "tempsense_slope"); + (u8) PHY_GETINTVAR(pi, "tempsense_slope"); pi_lcn->lcnphy_hw_iqcal_en = - (bool) PHY_GETINTVAR(pi, "hw_iqcal_en"); + (bool) PHY_GETINTVAR(pi, "hw_iqcal_en"); pi_lcn->lcnphy_iqcal_swp_dis = - (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis"); + (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis"); pi_lcn->lcnphy_tempcorrx = - (u8) PHY_GETINTVAR(pi, "tempcorrx"); + (u8) PHY_GETINTVAR(pi, "tempcorrx"); pi_lcn->lcnphy_tempsense_option = - (u8) PHY_GETINTVAR(pi, "tempsense_option"); + (u8) PHY_GETINTVAR(pi, "tempsense_option"); pi_lcn->lcnphy_freqoffset_corr = - (u8) PHY_GETINTVAR(pi, "freqoffset_corr"); + (u8) PHY_GETINTVAR(pi, "freqoffset_corr"); if ((u8) getintvar(pi->vars, "aa2g") > 1) wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, (u8) getintvar(pi->vars, - "aa2g")); + "aa2g")); } pi_lcn->lcnphy_cck_dig_filt_type = -1; if (PHY_GETVAR(pi, "cckdigfilttype")) { s16 temp; temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype"); - if (temp >= 0) + if (temp >= 0) { pi_lcn->lcnphy_cck_dig_filt_type = temp; + } } return true; @@ -4826,7 +4841,7 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) const struct chan_info_2064_lcnphy *ci; u8 rfpll_doubler = 0; u8 pll_pwrup, pll_pwrup_ovr; - s32 qFxtal, qFref, qFvco, qFcal; + fixed qFxtal, qFref, qFvco, qFcal; u8 d15, d16, f16, e44, e45; u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div; u16 loop_bw, d30, setCount; @@ -4851,8 +4866,9 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) if (chan_info_2064_lcnphy[i].chan == channel) break; - if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) + if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) { return; + } ci = &chan_info_2064_lcnphy[i]; } @@ -4956,7 +4972,7 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) * (fvco3 / 2 - PLL_2064_LOW_END_VCO)) / (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO)) - + PLL_2064_LOW_END_KVCO; + + PLL_2064_LOW_END_KVCO; h28_ten = (d28 * 10) / c28; c30 = 2640; e30 = (d30 - 680) / 490; @@ -4999,11 +5015,14 @@ void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi) if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); } else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) { + pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); wlc_lcnphy_txpower_recalc_target(pi); + wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl); - } + } else + return; } void wlc_phy_detach_lcnphy(struct brcms_phy *pi) @@ -5016,13 +5035,13 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) struct brcms_phy_lcnphy *pi_lcn; pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC); - if (pi->u.pi_lcnphy == NULL) + if (pi->u.pi_lcnphy == NULL) { return false; + } pi_lcn = pi->u.pi_lcnphy; - if ((0 == (pi->sh->boardflags & BFL_NOPA)) && - !NORADIO_ENAB(pi->pubpi)) { + if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) { pi->hwpwrctrl = true; pi->hwpwrctrl_capable = true; } @@ -5043,8 +5062,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) return false; - if ((pi->sh->boardflags & BFL_FEM) && - (LCNREV_IS(pi->pubpi.phy_rev, 1))) { + if ((pi->sh->boardflags & BFL_FEM) && (LCNREV_IS(pi->pubpi.phy_rev, 1))) { if (pi_lcn->lcnphy_tempsense_option == 3) { pi->hwpwrctrl = true; pi->hwpwrctrl_capable = true; @@ -5072,8 +5090,8 @@ static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain) biq1 = (u16) (gain >> 16) & 0xf; gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) | - ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) | - ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12)); + ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) | + ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12)); gain16_19 = biq1; mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0); @@ -5108,19 +5126,18 @@ static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index) lcnphy_23bitgaincode_table [*gain_index]); received_power = - wlc_lcnphy_measure_digital_power( - pi, - pi_lcn-> - lcnphy_noise_samples); + wlc_lcnphy_measure_digital_power(pi, + pi_lcn-> + lcnphy_noise_samples); (*gain_index)++; } (*gain_index)--; } else { wlc_lcnphy_set_rx_gain(pi, gain_code); received_power = - wlc_lcnphy_measure_digital_power(pi, - pi_lcn-> - lcnphy_noise_samples); + wlc_lcnphy_measure_digital_power(pi, + pi_lcn-> + lcnphy_noise_samples); } return received_power; @@ -5171,7 +5188,7 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index) input_power_db = input_power_offset_db - desired_gain; input_power_db = - input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index]; + input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index]; freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec)); if ((freq > 2427) && (freq <= 2467)) @@ -5179,19 +5196,18 @@ s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index) temperature = pi_lcn->lcnphy_lastsensed_temperature; - if ((temperature - 15) < -30) + if ((temperature - 15) < -30) { input_power_db = - input_power_db + - (((temperature - 10 - 25) * 286) >> 12) - - 7; - else if ((temperature - 15) < 4) + input_power_db + (((temperature - 10 - 25) * 286) >> 12) - + 7; + } else if ((temperature - 15) < 4) { input_power_db = - input_power_db + - (((temperature - 10 - 25) * 286) >> 12) - - 3; - else - input_power_db = input_power_db + - (((temperature - 10 - 25) * 286) >> 12); + input_power_db + (((temperature - 10 - 25) * 286) >> 12) - + 3; + } else { + input_power_db = + input_power_db + (((temperature - 10 - 25) * 286) >> 12); + } wlc_lcnphy_rx_gain_override_enable(pi, 0); @@ -5251,10 +5267,11 @@ wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type) } if (filt_index != -1) { - for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) + for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) { write_phy_reg(pi, addr[j], LCNPHY_txdigfiltcoeffs_cck [filt_index][j + 1]); + } } } else { for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) { @@ -5265,10 +5282,11 @@ wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type) } if (filt_index != -1) { - for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) + for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) { write_phy_reg(pi, addr_ofdm[j], LCNPHY_txdigfiltcoeffs_ofdm [filt_index][j + 1]); + } } } diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c index 2d90f098b078..f8e419239425 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c @@ -15,7 +15,6 @@ */ #include -#include #include #include @@ -29,42 +28,27 @@ #include "phyreg_n.h" #include "phytbl_n.h" -#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \ - read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ - ((core == PHY_CORE_0) ? \ - radio_type##_##jspace##0 : \ - radio_type##_##jspace##1)) - -#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \ +#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \ + read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ + ((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1)) +#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \ write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ - ((core == PHY_CORE_0) ? \ - radio_type##_##jspace##0 : \ - radio_type##_##jspace##1), value) - -#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \ - write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value) - -#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \ - read_radio_reg(pi, ((core == PHY_CORE_0) ? \ - radio_type##_##jspace##0##_##reg_name : \ - radio_type##_##jspace##1##_##reg_name)) - -#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \ - write_radio_reg(pi, ((core == PHY_CORE_0) ? \ - radio_type##_##jspace##0##_##reg_name : \ - radio_type##_##jspace##1##_##reg_name), \ - value) - -#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \ - read_radio_reg(pi, ((core == PHY_CORE_0) ? \ - radio_type##_##reg_name##_##jspace##0 : \ - radio_type##_##reg_name##_##jspace##1)) - -#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \ - write_radio_reg(pi, ((core == PHY_CORE_0) ? \ - radio_type##_##reg_name##_##jspace##0 : \ - radio_type##_##reg_name##_##jspace##1), \ - value) + ((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1), value); +#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \ + write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value); + +#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \ + read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \ + radio_type##_##jspace##1##_##reg_name)); +#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \ + write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \ + radio_type##_##jspace##1##_##reg_name), value); +#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \ + read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \ + radio_type##_##reg_name##_##jspace##1)); +#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \ + write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \ + radio_type##_##reg_name##_##jspace##1), value); #define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40 #define NPHY_ACI_CHANNEL_DELTA 5 @@ -119,11 +103,9 @@ #define NPHY_CALSANITY_RSSI_NB_MAX_POS 9 #define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9 #define NPHY_CALSANITY_RSSI_W1_MAX_POS 12 -#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - \ - NPHY_RSSICAL_MAXREAD) +#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - NPHY_RSSICAL_MAXREAD) #define NPHY_CALSANITY_RSSI_W2_MAX_POS NPHY_CALSANITY_RSSI_W1_MAX_POS -#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - \ - NPHY_RSSICAL_MAXREAD) +#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - NPHY_RSSICAL_MAXREAD) #define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f))) #define NPHY_RSSI_NB_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \ ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG)) @@ -142,11 +124,11 @@ #define NPHY_PAPD_COMP_OFF 0 #define NPHY_PAPD_COMP_ON 1 -#define NPHY_SROM_TEMPSHIFT 32 -#define NPHY_SROM_MAXTEMPOFFSET 16 -#define NPHY_SROM_MINTEMPOFFSET -16 +#define NPHY_SROM_TEMPSHIFT 32 +#define NPHY_SROM_MAXTEMPOFFSET 16 +#define NPHY_SROM_MINTEMPOFFSET -16 -#define NPHY_CAL_MAXTEMPDELTA 64 +#define NPHY_CAL_MAXTEMPDELTA 64 #define NPHY_NOISEVAR_TBLLEN40 256 #define NPHY_NOISEVAR_TBLLEN20 128 @@ -156,8 +138,8 @@ #define NPHY_ADJUSTED_MINCRSPOWER 0x1e /* 5357 Chip specific ChipControl register bits */ -#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ -#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ +#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ +#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ struct nphy_iqcal_params { u16 txlpf; @@ -202,40 +184,38 @@ struct nphy_ipa_txrxgain { #define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1) -struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = { - {0, 0, 0, 0, 0, 100}, - {0, 0, 0, 0, 0, 50}, - {0, 0, 0, 0, 0, -1}, - {0, 0, 0, 3, 0, -1}, - {0, 0, 3, 3, 0, -1}, - {0, 2, 3, 3, 0, -1} +struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = { {0, 0, 0, 0, 0, 100}, +{0, 0, 0, 0, 0, 50}, +{0, 0, 0, 0, 0, -1}, +{0, 0, 0, 3, 0, -1}, +{0, 0, 3, 3, 0, -1}, +{0, 2, 3, 3, 0, -1} }; -struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = { - {0, 0, 0, 0, 0, 128}, - {0, 0, 0, 0, 0, 70}, - {0, 0, 0, 0, 0, 20}, - {0, 0, 0, 3, 0, 20}, - {0, 0, 3, 3, 0, 20}, - {0, 2, 3, 3, 0, 20} +struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = { {0, 0, 0, 0, 0, 128}, +{0, 0, 0, 0, 0, 70}, +{0, 0, 0, 0, 0, 20}, +{0, 0, 0, 3, 0, 20}, +{0, 0, 3, 3, 0, 20}, +{0, 2, 3, 3, 0, 20} }; struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = { - {0, 0, 0, 0, 0, 100}, - {0, 0, 0, 0, 0, 50}, - {0, 0, 0, 0, 0, -1}, - {0, 0, 0, 3, 0, -1}, - {0, 0, 3, 3, 0, -1}, - {0, 0, 5, 3, 0, -1} +{0, 0, 0, 0, 0, 100}, +{0, 0, 0, 0, 0, 50}, +{0, 0, 0, 0, 0, -1}, +{0, 0, 0, 3, 0, -1}, +{0, 0, 3, 3, 0, -1}, +{0, 0, 5, 3, 0, -1} }; struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = { - {0, 0, 0, 0, 0, 10}, - {0, 0, 0, 1, 0, 10}, - {0, 0, 1, 2, 0, 10}, - {0, 0, 1, 3, 0, 10}, - {0, 0, 4, 3, 0, 10}, - {0, 0, 6, 3, 0, 10} +{0, 0, 0, 0, 0, 10}, +{0, 0, 0, 1, 0, 10}, +{0, 0, 1, 2, 0, 10}, +{0, 0, 1, 3, 0, 10}, +{0, 0, 4, 3, 0, 10}, +{0, 0, 6, 3, 0, 10} }; #define NPHY_RXCAL_TONEAMP 181 @@ -250,9 +230,9 @@ enum { #define wlc_phy_get_papd_nphy(pi) \ (read_phy_reg((pi), 0x1e7) & \ - ((0x1 << 15) | \ - (0x1 << 14) | \ - (0x1 << 13))) + ((0x1 << 15) | \ + (0x1 << 14) | \ + (0x1 << 13))) #define TXFILT_SHAPING_OFDM20 0 #define TXFILT_SHAPING_OFDM40 1 @@ -13310,27 +13290,27 @@ static s32 nphy_lnagain_est1[] = { -224, 23242 }; static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = { { - {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69}, - {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69}, - {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68}, - {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67}, - {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66}, - {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65}, - {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65}, - {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65}, - {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65} - }, - { - {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, - {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, - {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79}, - {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78}, - {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78}, - {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78}, - {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78}, - {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78}, - {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78} - } + {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69}, + {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69}, + {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68}, + {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67}, + {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66}, + {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65}, + {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65}, + {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65}, + {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65} + }, + { + {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, + {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, + {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79}, + {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78}, + {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78}, + {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78}, + {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78}, + {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78}, + {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78} + } }; static const u32 nphy_tpc_txgain[] = { @@ -14101,18 +14081,16 @@ static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = { static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 }; static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 }; static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = { - 0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a -}; + 0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a }; static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = { - 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 -}; + 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 }; static bool wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, struct chan_info_nphy_radio2057 **t0, struct chan_info_nphy_radio205x **t1, struct chan_info_nphy_radio2057_rev5 **t2, struct chan_info_nphy_2055 **t3); -static void wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chans, +static void wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chans, const struct nphy_sfo_cfg *c); static void wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, @@ -14166,14 +14144,10 @@ static void wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32, static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core); static void wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *, enum phy_cal_mode, u8); - -static void -wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi, - struct nphy_papd_restore_state *state); - +static void wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi, + struct nphy_papd_restore_state *state); static void wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, - struct nphy_papd_restore_state *state, - u8); + struct nphy_papd_restore_state *state, u8); static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals); @@ -14212,10 +14186,9 @@ static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi); static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi); static u16 wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, - u16 max_val, - u8 dac_test_mode); -static void wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, - struct cordic_iq *tone_buf, + u16 max_val, + u8 dac_test_mode); +static void wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, cs32 *tone_buf, u16 num_samps); static void wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 n, u16 lps, u16 wait, u8 iq, u8 dac_test_mode, @@ -14236,8 +14209,9 @@ bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih) phybist4 = read_phy_reg(pi, 0x156); if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) && - (phybist3 == 0) && (phybist4 == 0)) + (phybist3 == 0) && (phybist4 == 0)) { return true; + } return false; } @@ -14265,6 +14239,7 @@ static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi) or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_LNA_GAIN_RANGE, 0x1a); } else { + write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668); } } @@ -14332,8 +14307,7 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi) if (NREV_GE(pi->pubpi.phy_rev, 7)) { antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ? - pi->srom_fem2g.antswctrllut : pi->srom_fem5g. - antswctrllut; + pi->srom_fem2g.antswctrllut : pi->srom_fem5g.antswctrllut; switch (antswctrllut) { case 0: @@ -14342,20 +14316,20 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi) case 1: - if (pi->aa2g == 7) - wlc_phy_table_write_nphy( - pi, - NPHY_TBL_ID_ANTSWCTRLLUT, - 2, 0x21, 8, - &ant_sw_ctrl_tbl_rev8_2o3[0]); - else - wlc_phy_table_write_nphy( - pi, - NPHY_TBL_ID_ANTSWCTRLLUT, - 2, 0x21, 8, - &ant_sw_ctrl_tbl_rev8 - [0]); + if (pi->aa2g == 7) { + wlc_phy_table_write_nphy(pi, + NPHY_TBL_ID_ANTSWCTRLLUT, + 2, 0x21, 8, + &ant_sw_ctrl_tbl_rev8_2o3 + [0]); + } else { + wlc_phy_table_write_nphy(pi, + NPHY_TBL_ID_ANTSWCTRLLUT, + 2, 0x21, 8, + &ant_sw_ctrl_tbl_rev8 + [0]); + } wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, 2, 0x25, 8, &ant_sw_ctrl_tbl_rev8[2]); @@ -14366,31 +14340,31 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi) case 2: - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_ANTSWCTRLLUT, - 2, 0x1, 8, - &ant_sw_ctrl_tbl_rev8_2057v7_core0[0]); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_ANTSWCTRLLUT, - 2, 0x5, 8, - &ant_sw_ctrl_tbl_rev8_2057v7_core0[2]); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_ANTSWCTRLLUT, - 2, 0x9, 8, - &ant_sw_ctrl_tbl_rev8_2057v7_core0[4]); - - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_ANTSWCTRLLUT, - 2, 0x21, 8, - &ant_sw_ctrl_tbl_rev8_2057v7_core1[0]); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_ANTSWCTRLLUT, - 2, 0x25, 8, - &ant_sw_ctrl_tbl_rev8_2057v7_core1[2]); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_ANTSWCTRLLUT, - 2, 0x29, 8, - &ant_sw_ctrl_tbl_rev8_2057v7_core1[4]); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, + 2, 0x1, 8, + &ant_sw_ctrl_tbl_rev8_2057v7_core0 + [0]); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, + 2, 0x5, 8, + &ant_sw_ctrl_tbl_rev8_2057v7_core0 + [2]); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, + 2, 0x9, 8, + &ant_sw_ctrl_tbl_rev8_2057v7_core0 + [4]); + + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, + 2, 0x21, 8, + &ant_sw_ctrl_tbl_rev8_2057v7_core1 + [0]); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, + 2, 0x25, 8, + &ant_sw_ctrl_tbl_rev8_2057v7_core1 + [2]); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, + 2, 0x29, 8, + &ant_sw_ctrl_tbl_rev8_2057v7_core1 + [4]); break; default: @@ -14401,49 +14375,45 @@ static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi) for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) { if (idx == ANT_SWCTRL_TBL_REV3_IDX) { - antswctrllut = - CHSPEC_IS2G(pi->radio_chanspec) ? - pi->srom_fem2g.antswctrllut : - pi->srom_fem5g.antswctrllut; + antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ? + pi->srom_fem2g.antswctrllut : pi-> + srom_fem5g.antswctrllut; switch (antswctrllut) { case 0: - wlc_phy_write_table_nphy( - pi, - &mimophytbl_info_rev3_volatile - [idx]); + wlc_phy_write_table_nphy(pi, + &mimophytbl_info_rev3_volatile + [idx]); break; case 1: - wlc_phy_write_table_nphy( - pi, - &mimophytbl_info_rev3_volatile1 - [idx]); + wlc_phy_write_table_nphy(pi, + &mimophytbl_info_rev3_volatile1 + [idx]); break; case 2: - wlc_phy_write_table_nphy( - pi, - &mimophytbl_info_rev3_volatile2 - [idx]); + wlc_phy_write_table_nphy(pi, + &mimophytbl_info_rev3_volatile2 + [idx]); break; case 3: - wlc_phy_write_table_nphy( - pi, - &mimophytbl_info_rev3_volatile3 - [idx]); + wlc_phy_write_table_nphy(pi, + &mimophytbl_info_rev3_volatile3 + [idx]); break; default: break; } } else { - wlc_phy_write_table_nphy( - pi, - &mimophytbl_info_rev3_volatile[idx]); + wlc_phy_write_table_nphy(pi, + &mimophytbl_info_rev3_volatile + [idx]); } } } else { - for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) + for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) { wlc_phy_write_table_nphy(pi, &mimophytbl_info_rev0_volatile [idx]); + } } } @@ -14470,25 +14440,32 @@ void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs) wlc_phy_write_txmacreg_nphy(pi, holdoff, delay); - if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) + if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) { pi->sh->_rifs_phy = rifs; + } } bool wlc_phy_attach_nphy(struct brcms_phy *pi) { uint i; - if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) + if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) { pi->phyhang_avoid = true; + } if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { + pi->nphy_gband_spurwar_en = true; - if (pi->sh->boardflags2 & BFL2_SPUR_WAR) + + if (pi->sh->boardflags2 & BFL2_SPUR_WAR) { pi->nphy_aband_spurwar_en = true; + } } if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) { - if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) + + if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) { pi->nphy_gband_spurwar2_en = true; + } } pi->n_preamble_override = AUTO; @@ -14508,8 +14485,9 @@ bool wlc_phy_attach_nphy(struct brcms_phy *pi) pi->nphy_elna_gain_config = false; pi->radio_is_on = false; - for (i = 0; i < pi->pubpi.phy_corenum; i++) + for (i = 0; i < pi->pubpi.phy_corenum; i++) { pi->nphy_txpwrindex[i].index = AUTO; + } wlc_phy_txpwrctrl_config_nphy(pi); if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) @@ -14546,44 +14524,6 @@ static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi) pi->phy_5g_pwrgain = true; } -static s32 get_rf_pwr_offset(struct brcms_phy *pi, s16 pga_gn, s16 pad_gn) -{ - s32 rfpwr_offset = 0; - - if (CHSPEC_IS2G(pi->radio_chanspec)) { - if ((pi->pubpi.radiorev == 3) || - (pi->pubpi.radiorev == 4) || - (pi->pubpi.radiorev == 6)) - rfpwr_offset = (s16) - nphy_papd_padgain_dlt_2g_2057rev3n4 - [pad_gn]; - else if (pi->pubpi.radiorev == 5) - rfpwr_offset = (s16) - nphy_papd_padgain_dlt_2g_2057rev5 - [pad_gn]; - else if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == - 8)) - rfpwr_offset = (s16) - nphy_papd_padgain_dlt_2g_2057rev7 - [pad_gn]; - } else { - if ((pi->pubpi.radiorev == 3) || - (pi->pubpi.radiorev == 4) || - (pi->pubpi.radiorev == 6)) - rfpwr_offset = (s16) - nphy_papd_pgagain_dlt_5g_2057 - [pga_gn]; - else if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == - 8)) - rfpwr_offset = (s16) - nphy_papd_pgagain_dlt_5g_2057rev7 - [pga_gn]; - } - return rfpwr_offset; -} - void wlc_phy_init_nphy(struct brcms_phy *pi) { u16 val; @@ -14593,30 +14533,31 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) bool do_nphy_cal = false; uint core; uint origidx, intr_val; - struct d11regs *regs; + d11regs_t *regs; u32 d11_clk_ctl_st; core = 0; - if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) + if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) { pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; + } if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) && ((pi->sh->chippkg == BCM4717_PKG_ID) || (pi->sh->chippkg == BCM4718_PKG_ID))) { if ((pi->sh->boardflags & BFL_EXTLNA) && - (CHSPEC_IS2G(pi->radio_chanspec))) + (CHSPEC_IS2G(pi->radio_chanspec))) { ai_corereg(pi->sh->sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol), - 0x40, 0x40); + offsetof(chipcregs_t, chipcontrol), 0x40, + 0x40); + } } if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && CHSPEC_IS40(pi->radio_chanspec)) { - regs = (struct d11regs *) ai_switch_core(pi->sh->sih, - D11_CORE_ID, &origidx, - &intr_val); + regs = (d11regs_t *) ai_switch_core(pi->sh->sih, D11_CORE_ID, + &origidx, &intr_val); d11_clk_ctl_st = R_REG(®s->clk_ctl_st); AND_REG(®s->clk_ctl_st, ~(CCS_FORCEHT | CCS_HTAREQ)); @@ -14627,10 +14568,10 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) } pi->use_int_tx_iqlo_cal_nphy = - (PHY_IPA(pi) || - (NREV_GE(pi->pubpi.phy_rev, 7) || - (NREV_GE(pi->pubpi.phy_rev, 5) - && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL))); + (PHY_IPA(pi) || + (NREV_GE(pi->pubpi.phy_rev, 7) || + (NREV_GE(pi->pubpi.phy_rev, 5) + && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL))); pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false; @@ -14691,8 +14632,9 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) write_phy_reg(pi, 0x1ff, 48); - if (NREV_LT(pi->pubpi.phy_rev, 8)) + if (NREV_LT(pi->pubpi.phy_rev, 8)) { wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override); + } wlc_phy_stf_chain_upd_nphy(pi); @@ -14714,8 +14656,11 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) } wlc_phy_ipa_set_tx_digi_filts_nphy(pi); - } else if (NREV_GE(pi->pubpi.phy_rev, 5)) { - wlc_phy_extpa_set_tx_digi_filts_nphy(pi); + } else { + + if (NREV_GE(pi->pubpi.phy_rev, 5)) { + wlc_phy_extpa_set_tx_digi_filts_nphy(pi); + } } wlc_phy_workarounds_nphy(pi); @@ -14754,40 +14699,44 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) u16 idx; s16 pga_gn = 0; s16 pad_gn = 0; - s32 rfpwr_offset; + s32 rfpwr_offset = 0; if (PHY_IPA(pi)) { tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi); } else { if (CHSPEC_IS5G(pi->radio_chanspec)) { - if (NREV_IS(pi->pubpi.phy_rev, 3)) + if (NREV_IS(pi->pubpi.phy_rev, 3)) { tx_pwrctrl_tbl = - nphy_tpc_5GHz_txgain_rev3; - else if (NREV_IS(pi->pubpi.phy_rev, 4)) + nphy_tpc_5GHz_txgain_rev3; + } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { tx_pwrctrl_tbl = - (pi->srom_fem5g.extpagain == - 3) ? - nphy_tpc_5GHz_txgain_HiPwrEPA : - nphy_tpc_5GHz_txgain_rev4; - else + (pi->srom_fem5g.extpagain == 3) ? + nphy_tpc_5GHz_txgain_HiPwrEPA : + nphy_tpc_5GHz_txgain_rev4; + } else { tx_pwrctrl_tbl = - nphy_tpc_5GHz_txgain_rev5; + nphy_tpc_5GHz_txgain_rev5; + } + } else { if (NREV_GE(pi->pubpi.phy_rev, 7)) { - if (pi->pubpi.radiorev == 5) + if (pi->pubpi.radiorev == 5) { tx_pwrctrl_tbl = - nphy_tpc_txgain_epa_2057rev5; - else if (pi->pubpi.radiorev == 3) + nphy_tpc_txgain_epa_2057rev5; + } else if (pi->pubpi.radiorev == 3) { tx_pwrctrl_tbl = - nphy_tpc_txgain_epa_2057rev3; + nphy_tpc_txgain_epa_2057rev3; + } + } else { if (NREV_GE(pi->pubpi.phy_rev, 5) && - (pi->srom_fem2g.extpagain == 3)) + (pi->srom_fem2g.extpagain == 3)) { tx_pwrctrl_tbl = - nphy_tpc_txgain_HiPwrEPA; - else + nphy_tpc_txgain_HiPwrEPA; + } else { tx_pwrctrl_tbl = - nphy_tpc_txgain_rev3; + nphy_tpc_txgain_rev3; + } } } } @@ -14804,42 +14753,71 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) for (idx = 0; idx < 128; idx++) { pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf; pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f; - rfpwr_offset = get_rf_pwr_offset(pi, pga_gn, - pad_gn); - wlc_phy_table_write_nphy( - pi, - NPHY_TBL_ID_CORE1TXPWRCTL, - 1, 576 + idx, 32, - &rfpwr_offset); - wlc_phy_table_write_nphy( - pi, - NPHY_TBL_ID_CORE2TXPWRCTL, - 1, 576 + idx, 32, - &rfpwr_offset); + + if (CHSPEC_IS2G(pi->radio_chanspec)) { + if ((pi->pubpi.radiorev == 3) || + (pi->pubpi.radiorev == 4) || + (pi->pubpi.radiorev == 6)) { + rfpwr_offset = (s16) + nphy_papd_padgain_dlt_2g_2057rev3n4 + [pad_gn]; + } else if (pi->pubpi.radiorev == 5) { + rfpwr_offset = (s16) + nphy_papd_padgain_dlt_2g_2057rev5 + [pad_gn]; + } else if ((pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == + 8)) { + rfpwr_offset = (s16) + nphy_papd_padgain_dlt_2g_2057rev7 + [pad_gn]; + } + } else { + if ((pi->pubpi.radiorev == 3) || + (pi->pubpi.radiorev == 4) || + (pi->pubpi.radiorev == 6)) { + rfpwr_offset = (s16) + nphy_papd_pgagain_dlt_5g_2057 + [pga_gn]; + } else if ((pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == + 8)) { + rfpwr_offset = (s16) + nphy_papd_pgagain_dlt_5g_2057rev7 + [pga_gn]; + } + } + wlc_phy_table_write_nphy(pi, + NPHY_TBL_ID_CORE1TXPWRCTL, + 1, 576 + idx, 32, + &rfpwr_offset); + wlc_phy_table_write_nphy(pi, + NPHY_TBL_ID_CORE2TXPWRCTL, + 1, 576 + idx, 32, + &rfpwr_offset); } } else { for (idx = 0; idx < 128; idx++) { pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf; - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { rfpwr_offset = (s16) - nphy_papd_pga_gain_delta_ipa_2g - [pga_gn]; - else + nphy_papd_pga_gain_delta_ipa_2g + [pga_gn]; + } else { rfpwr_offset = (s16) - nphy_papd_pga_gain_delta_ipa_5g - [pga_gn]; - - wlc_phy_table_write_nphy( - pi, - NPHY_TBL_ID_CORE1TXPWRCTL, - 1, 576 + idx, 32, - &rfpwr_offset); - wlc_phy_table_write_nphy( - pi, - NPHY_TBL_ID_CORE2TXPWRCTL, - 1, 576 + idx, 32, - &rfpwr_offset); + nphy_papd_pga_gain_delta_ipa_5g + [pga_gn]; + } + + wlc_phy_table_write_nphy(pi, + NPHY_TBL_ID_CORE1TXPWRCTL, + 1, 576 + idx, 32, + &rfpwr_offset); + wlc_phy_table_write_nphy(pi, + NPHY_TBL_ID_CORE2TXPWRCTL, + 1, 576 + idx, 32, + &rfpwr_offset); } } @@ -14851,33 +14829,37 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) 192, 32, nphy_tpc_txgain); } - if (pi->sh->phyrxchain != 0x3) + if (pi->sh->phyrxchain != 0x3) { wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi, pi->sh->phyrxchain); + } - if (PHY_PERICAL_MPHASE_PENDING(pi)) + if (PHY_PERICAL_MPHASE_PENDING(pi)) { wlc_phy_cal_perical_mphase_restart(pi); + } if (!NORADIO_ENAB(pi->pubpi)) { bool do_rssi_cal = false; if (NREV_GE(pi->pubpi.phy_rev, 3)) { do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ? - (pi->nphy_rssical_chanspec_2G == 0) : - (pi->nphy_rssical_chanspec_5G == 0); + (pi->nphy_rssical_chanspec_2G == 0) : + (pi->nphy_rssical_chanspec_5G == 0); - if (do_rssi_cal) + if (do_rssi_cal) { wlc_phy_rssi_cal_nphy(pi); - else + } else { wlc_phy_restore_rssical_nphy(pi); + } } else { wlc_phy_rssi_cal_nphy(pi); } - if (!SCAN_RM_IN_PROGRESS(pi)) + if (!SCAN_RM_IN_PROGRESS(pi)) { do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ? - (pi->nphy_iqcal_chanspec_2G == 0) : - (pi->nphy_iqcal_chanspec_5G == 0); + (pi->nphy_iqcal_chanspec_2G == 0) : + (pi->nphy_iqcal_chanspec_5G == 0); + } if (!pi->do_initcal) do_nphy_cal = false; @@ -14895,30 +14877,29 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) if (NREV_GE(pi->pubpi.phy_rev, 3)) { pi->nphy_cal_orig_pwr_idx[0] = - pi->nphy_txpwrindex[PHY_CORE_0] - . - index_internal; + pi->nphy_txpwrindex[PHY_CORE_0]. + index_internal; pi->nphy_cal_orig_pwr_idx[1] = - pi->nphy_txpwrindex[PHY_CORE_1] - . - index_internal; + pi->nphy_txpwrindex[PHY_CORE_1]. + index_internal; wlc_phy_precal_txgain_nphy(pi); target_gain = - wlc_phy_get_tx_gain_nphy(pi); + wlc_phy_get_tx_gain_nphy(pi); } if (wlc_phy_cal_txiqlo_nphy - (pi, target_gain, true, - false) == 0) { + (pi, target_gain, true, false) == 0) { if (wlc_phy_cal_rxiq_nphy - (pi, target_gain, 2, - false) == 0) + (pi, target_gain, 2, + false) == 0) { wlc_phy_savecal_nphy(pi); + } } } else if (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) { + wlc_phy_cal_perical((struct brcms_phy_pub *) pi, PHY_PERICAL_PHYINIT); } @@ -14986,18 +14967,20 @@ void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en) pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91); pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92); - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { rfctrlintc_override_val = 0x1480; - else if (NREV_GE(pi->pubpi.phy_rev, 3)) + } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { rfctrlintc_override_val = - CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480; - else + CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480; + } else { rfctrlintc_override_val = - CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120; + CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120; + } write_phy_reg(pi, 0x91, rfctrlintc_override_val); write_phy_reg(pi, 0x92, rfctrlintc_override_val); } else { + write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save); write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save); } @@ -15008,26 +14991,29 @@ void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi) { u16 txrx_chain = - (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1); + (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1); bool CoreActv_override = false; if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) { txrx_chain = NPHY_RfseqCoreActv_TxRxChain0; CoreActv_override = true; - if (NREV_LE(pi->pubpi.phy_rev, 2)) + if (NREV_LE(pi->pubpi.phy_rev, 2)) { and_phy_reg(pi, 0xa0, ~0x20); + } } else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) { txrx_chain = NPHY_RfseqCoreActv_TxRxChain1; CoreActv_override = true; - if (NREV_LE(pi->pubpi.phy_rev, 2)) + if (NREV_LE(pi->pubpi.phy_rev, 2)) { or_phy_reg(pi, 0xa0, 0x20); + } } mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain); if (CoreActv_override) { + pi->nphy_perical = PHY_PERICAL_DISABLE; or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override); } else { @@ -15050,7 +15036,8 @@ void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask) if (!pi->sh->clk) return; - suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + suspend = + (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); if (!suspend) wlapi_suspend_mac_and_wait(pi->sh->physhim); @@ -15075,19 +15062,20 @@ void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask) for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) { if (tbl_buf[i] == NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) { + pi->rx2tx_biasentry = (u8) i; tbl_opcode = - NPHY_REV3_RFSEQ_CMD_NOP; - wlc_phy_table_write_nphy( - pi, - NPHY_TBL_ID_RFSEQ, - 1, i, - 16, - &tbl_opcode); + NPHY_REV3_RFSEQ_CMD_NOP; + wlc_phy_table_write_nphy(pi, + NPHY_TBL_ID_RFSEQ, + 1, i, + 16, + &tbl_opcode); break; } else if (tbl_buf[i] == - NPHY_REV3_RFSEQ_CMD_END) + NPHY_REV3_RFSEQ_CMD_END) { break; + } } } } @@ -15135,8 +15123,9 @@ static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi) { u8 idx, idx2, i, delta_ind; - for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) + for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) { pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx]; + } for (i = 0; i < 4; i++) { idx2 = 0; @@ -15151,7 +15140,7 @@ static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi) idx = TXP_FIRST_MCS_40_SISO; } else { idx = (CHSPEC_IS40(pi->radio_chanspec)) ? - TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM; + TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM; delta_ind = 1; } break; @@ -15159,68 +15148,68 @@ static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi) case 1: idx = (CHSPEC_IS40(pi->radio_chanspec)) ? - TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD; + TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD; break; case 2: idx = (CHSPEC_IS40(pi->radio_chanspec)) ? - TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC; + TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC; break; case 3: idx = (CHSPEC_IS40(pi->radio_chanspec)) ? - TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM; + TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM; break; } pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; idx = idx + delta_ind; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx++]; + pi->tx_power_offset[idx++]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx++]; + pi->tx_power_offset[idx++]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx++]; + pi->tx_power_offset[idx++]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx++]; + pi->tx_power_offset[idx++]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx++]; + pi->tx_power_offset[idx++]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx++]; + pi->tx_power_offset[idx++]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; idx = idx + 1 - delta_ind; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = - pi->tx_power_offset[idx]; + pi->tx_power_offset[idx]; } } @@ -15233,16 +15222,18 @@ wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core) { if (core == PHY_CORE_0) { write_phy_reg(pi, 0x38, 0x4); - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { write_phy_reg(pi, 0x37, 0x0060); - else + } else { write_phy_reg(pi, 0x37, 0x1080); + } } else if (core == PHY_CORE_1) { write_phy_reg(pi, 0x2ae, 0x4); - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { write_phy_reg(pi, 0x2ad, 0x0060); - else + } else { write_phy_reg(pi, 0x2ad, 0x1080); + } } } @@ -15252,11 +15243,13 @@ static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain) txchain0 = txchain & 0x1; txchain1 = (txchain & 0x2) >> 1; - if (!txchain0) + if (!txchain0) { wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); + } - if (!txchain1) + if (!txchain1) { wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); + } } static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) @@ -15369,10 +15362,11 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 freq; int coreNum; - if (CHSPEC_IS5G(pi->radio_chanspec)) + if (CHSPEC_IS5G(pi->radio_chanspec)) { wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0); - else + } else { wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1); + } if (pi->phyhang_avoid) wlc_phy_stay_in_carriersearch_nphy(pi, true); @@ -15407,8 +15401,9 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) write_phy_reg(pi, 0x240, 0x1b0); } - if (NREV_GE(pi->pubpi.phy_rev, 8)) + if (NREV_GE(pi->pubpi.phy_rev, 8)) { mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0)); + } wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, &dac_control); @@ -15427,7 +15422,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16, rfseq_rx2tx_dacbufpu_rev7); - if (PHY_IPA(pi)) + if (PHY_IPA(pi)) { wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events_rev3_ipa, rfseq_rx2tx_dlys_rev3_ipa, @@ -15436,6 +15431,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) sizeof (rfseq_rx2tx_events_rev3_ipa [0])); + } mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14)); mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14)); @@ -15452,13 +15448,11 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) || (pi->pubpi.radiorev == 8)) { rccal_bcap_val = - read_radio_reg( - pi, - RADIO_2057_RCCAL_BCAP_VAL); + read_radio_reg(pi, + RADIO_2057_RCCAL_BCAP_VAL); rccal_scap_val = - read_radio_reg( - pi, - RADIO_2057_RCCAL_SCAP_VAL); + read_radio_reg(pi, + RADIO_2057_RCCAL_SCAP_VAL); rccal_tx20_11b_bcap = rccal_bcap_val; rccal_tx20_11b_scap = rccal_scap_val; @@ -15503,13 +15497,11 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) tx_lpf_bw_ofdm_40mhz = 3; rccal_bcap_val = - read_radio_reg( - pi, - RADIO_2057_RCCAL_BCAP_VAL); + read_radio_reg(pi, + RADIO_2057_RCCAL_BCAP_VAL); rccal_scap_val = - read_radio_reg( - pi, - RADIO_2057_RCCAL_SCAP_VAL); + read_radio_reg(pi, + RADIO_2057_RCCAL_SCAP_VAL); rccal_tx20_11b_bcap = rccal_bcap_val; rccal_tx20_11b_scap = rccal_scap_val; @@ -15525,84 +15517,70 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) if (rccal_ovrd) { - rx2tx_lpf_rc_lut_tx20_11b = - (rccal_tx20_11b_bcap << 8) | - (rccal_tx20_11b_scap << 3) | - tx_lpf_bw_11b; - rx2tx_lpf_rc_lut_tx20_11n = - (rccal_tx20_11n_bcap << 8) | - (rccal_tx20_11n_scap << 3) | - tx_lpf_bw_ofdm_20mhz; - rx2tx_lpf_rc_lut_tx40_11n = - (rccal_tx40_11n_bcap << 8) | - (rccal_tx40_11n_scap << 3) | - tx_lpf_bw_ofdm_40mhz; + rx2tx_lpf_rc_lut_tx20_11b = (rccal_tx20_11b_bcap << 8) | + (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b; + rx2tx_lpf_rc_lut_tx20_11n = (rccal_tx20_11n_bcap << 8) | + (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz; + rx2tx_lpf_rc_lut_tx40_11n = (rccal_tx40_11n_bcap << 8) | + (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz; for (coreNum = 0; coreNum <= 1; coreNum++) { - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x152 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx20_11b); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x153 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx20_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x154 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx20_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x155 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x156 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x157 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x158 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_RFSEQ, - 1, - 0x159 + coreNum * 0x10, - 16, - &rx2tx_lpf_rc_lut_tx40_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, + 1, + 0x152 + coreNum * 0x10, + 16, + &rx2tx_lpf_rc_lut_tx20_11b); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, + 1, + 0x153 + coreNum * 0x10, + 16, + &rx2tx_lpf_rc_lut_tx20_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, + 1, + 0x154 + coreNum * 0x10, + 16, + &rx2tx_lpf_rc_lut_tx20_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, + 1, + 0x155 + coreNum * 0x10, + 16, + &rx2tx_lpf_rc_lut_tx40_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, + 1, + 0x156 + coreNum * 0x10, + 16, + &rx2tx_lpf_rc_lut_tx40_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, + 1, + 0x157 + coreNum * 0x10, + 16, + &rx2tx_lpf_rc_lut_tx40_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, + 1, + 0x158 + coreNum * 0x10, + 16, + &rx2tx_lpf_rc_lut_tx40_11n); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, + 1, + 0x159 + coreNum * 0x10, + 16, + &rx2tx_lpf_rc_lut_tx40_11n); } - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 4), - 1, 0x3, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID2); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), + 1, 0x3, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID2); } - if (!NORADIO_ENAB(pi->pubpi)) + if (!NORADIO_ENAB(pi->pubpi)) { write_phy_reg(pi, 0x32f, 0x3); + } - if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 2), - 1, 0x3, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID0); + if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) { + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), + 1, 0x3, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID0); + } if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) { @@ -15657,16 +15635,17 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) if (CHSPEC_IS2G(pi->radio_chanspec)) { if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) - || (pi->pubpi.radiorev == 6)) + || (pi->pubpi.radiorev == 6)) { + txgm_idac_bleed = 0x7f; + } for (coreNum = 0; coreNum <= 1; coreNum++) { if (txgm_idac_bleed != 0) - WRITE_RADIO_REG4( - pi, RADIO_2057, - CORE, coreNum, - TXGM_IDAC_BLEED, - txgm_idac_bleed); + WRITE_RADIO_REG4(pi, RADIO_2057, + CORE, coreNum, + TXGM_IDAC_BLEED, + txgm_idac_bleed); } if (pi->pubpi.radiorev == 5) { @@ -15681,20 +15660,18 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) CORE, coreNum, IPA2G_IMAIN, 0x1f); - WRITE_RADIO_REG4( - pi, RADIO_2057, - CORE, coreNum, - IPA2G_BIAS_FILTER, - 0xee); + WRITE_RADIO_REG4(pi, RADIO_2057, + CORE, coreNum, + IPA2G_BIAS_FILTER, + 0xee); WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, PAD2G_IDACS, 0x8a); - WRITE_RADIO_REG4( - pi, RADIO_2057, - CORE, coreNum, - PAD_BIAS_FILTER_BWS, - 0x3e); + WRITE_RADIO_REG4(pi, RADIO_2057, + CORE, coreNum, + PAD_BIAS_FILTER_BWS, + 0x3e); } } else if ((pi->pubpi.radiorev == 7) @@ -15723,8 +15700,9 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) } } else { - freq = CHAN5G_FREQ(CHSPEC_CHANNEL( - pi->radio_chanspec)); + freq = + CHAN5G_FREQ(CHSPEC_CHANNEL + (pi->radio_chanspec)); if (((freq >= 5180) && (freq <= 5230)) || ((freq >= 5745) && (freq <= 5805))) { WRITE_RADIO_REG4(pi, RADIO_2057, CORE, @@ -15831,12 +15809,12 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) wlc_phy_workarounds_nphy_gainctrl(pi); pdetrange = - (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. - pdetrange : pi->srom_fem2g.pdetrange; + (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. + pdetrange : pi->srom_fem2g.pdetrange; if (pdetrange == 0) { chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); + wlc_phy_get_chan_freq_range_nphy(pi, 0); if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { aux_adc_vmid_rev7_core0[3] = 0x70; aux_adc_vmid_rev7_core1[3] = 0x70; @@ -15864,15 +15842,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) { aux_adc_vmid_rev7_core0[3] = - 0x8c; + 0x8c; aux_adc_vmid_rev7_core1[3] = - 0x8c; + 0x8c; aux_adc_gain_rev7[3] = 0; } else { aux_adc_vmid_rev7_core0[3] = - 0x96; + 0x96; aux_adc_vmid_rev7_core1[3] = - 0x96; + 0x96; aux_adc_gain_rev7[3] = 0; } } @@ -15940,7 +15918,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) sizeof(rfseq_tx2rx_events_rev3) / sizeof(rfseq_tx2rx_events_rev3[0])); - if (PHY_IPA(pi)) + if (PHY_IPA(pi)) { wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events_rev3_ipa, rfseq_rx2tx_dlys_rev3_ipa, @@ -15949,6 +15927,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) sizeof (rfseq_rx2tx_events_rev3_ipa [0])); + } if ((pi->sh->hw_phyrxchain != 0x3) && (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) { @@ -15957,21 +15936,22 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) rfseq_rx2tx_dlys_rev3[5] = 59; rfseq_rx2tx_dlys_rev3[6] = 1; rfseq_rx2tx_events_rev3[7] = - NPHY_REV3_RFSEQ_CMD_END; + NPHY_REV3_RFSEQ_CMD_END; } - wlc_phy_set_rfseq_nphy( - pi, NPHY_RFSEQ_RX2TX, - rfseq_rx2tx_events_rev3, - rfseq_rx2tx_dlys_rev3, - sizeof(rfseq_rx2tx_events_rev3) / - sizeof(rfseq_rx2tx_events_rev3[0])); + wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, + rfseq_rx2tx_events_rev3, + rfseq_rx2tx_dlys_rev3, + sizeof(rfseq_rx2tx_events_rev3) / + sizeof(rfseq_rx2tx_events_rev3 + [0])); } - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { write_phy_reg(pi, 0x6a, 0x2); - else + } else { write_phy_reg(pi, 0x6a, 0x9c40); + } mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8)); @@ -15998,8 +15978,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) &dac_control); pdetrange = - (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. - pdetrange : pi->srom_fem2g.pdetrange; + (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. + pdetrange : pi->srom_fem2g.pdetrange; if (pdetrange == 0) { if (NREV_GE(pi->pubpi.phy_rev, 4)) { @@ -16010,7 +15990,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) aux_adc_gain = aux_adc_gain_rev3; } chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); + wlc_phy_get_chan_freq_range_nphy(pi, 0); if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { switch (chan_freq_range) { case WL_CHAN_FREQ_RANGE_5GL: @@ -16053,7 +16033,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) if (NREV_GE(pi->pubpi.phy_rev, 6)) { chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); + wlc_phy_get_chan_freq_range_nphy(pi, 0); if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { bcm_adc_vmid[3] = 0x8e; bcm_adc_gain[3] = 0x03; @@ -16076,16 +16056,14 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) 0x1c, 16, bcm_adc_gain); } else if (pdetrange == 3) { chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); + wlc_phy_get_chan_freq_range_nphy(pi, 0); if ((NREV_GE(pi->pubpi.phy_rev, 4)) && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) { u16 auxadc_vmid[] = { - 0xa2, 0xb4, 0xb4, 0x270 - }; + 0xa2, 0xb4, 0xb4, 0x270 }; u16 auxadc_gain[] = { - 0x02, 0x02, 0x02, 0x00 - }; + 0x02, 0x02, 0x02, 0x00 }; wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, @@ -16106,7 +16084,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 Vmid[2], Av[2]; chan_freq_range = - wlc_phy_get_chan_freq_range_nphy(pi, 0); + wlc_phy_get_chan_freq_range_nphy(pi, 0); if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89; Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89; @@ -16177,8 +16155,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) 0x0); triso = - (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. - triso : pi->srom_fem2g.triso; + (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. + triso : pi->srom_fem2g.triso; if (triso == 7) { wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); @@ -16234,10 +16212,11 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) if (NREV_GE(pi->pubpi.phy_rev, 6)) { - if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) + if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) { wlapi_bmac_mhf(pi->sh->physhim, MHF4, - MHF4_BPHY_TXCORE0, - MHF4_BPHY_TXCORE0, BRCM_BAND_ALL); + MHF4_BPHY_TXCORE0, + MHF4_BPHY_TXCORE0, BRCM_BAND_ALL); + } } } else { @@ -16335,10 +16314,11 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) write_phy_reg(pi, 0x194, 0x0); } - if (NREV_IS(pi->pubpi.phy_rev, 2)) + if (NREV_IS(pi->pubpi.phy_rev, 2)) { mod_phy_reg(pi, 0x221, NPHY_FORCESIG_DECODEGATEDCLKS, NPHY_FORCESIG_DECODEGATEDCLKS); + } } if (pi->phyhang_avoid) @@ -16501,10 +16481,11 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) u8 triso; triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso : - pi->srom_fem2g.triso; + pi->srom_fem2g.triso; if (NREV_GE(pi->pubpi.phy_rev, 7)) { if (pi->pubpi.radiorev == 5) { + wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi); } else if (pi->pubpi.radiorev == 7) { wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); @@ -16533,20 +16514,20 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); currband = - read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; + read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; if (currband == 0) { if (NREV_GE(pi->pubpi.phy_rev, 6)) { if (pi->pubpi.radiorev == 11) { lna1_gain_db = lna1G_gain_db_rev6_224B0; lna2_gain_db = lna2G_gain_db_rev6_224B0; rfseq_init_gain = - rfseqG_init_gain_rev6_224B0; + rfseqG_init_gain_rev6_224B0; init_gaincode = - initG_gaincode_rev6_224B0; + initG_gaincode_rev6_224B0; clip1hi_gaincode = - clip1hiG_gaincode_rev6; + clip1hiG_gaincode_rev6; clip1lo_gaincode = - clip1loG_gaincode_rev6_224B0; + clip1loG_gaincode_rev6_224B0; nbclip_th = nbclipG_th_rev6; w1clip_th = w1clipG_th_rev6; crsmin_th = crsminG_th_rev6; @@ -16559,59 +16540,51 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) if (pi->sh->boardflags & BFL_EXTLNA) { rfseq_init_gain = - rfseqG_init_gain_rev6_elna; + rfseqG_init_gain_rev6_elna; init_gaincode = - initG_gaincode_rev6_elna; + initG_gaincode_rev6_elna; } else { rfseq_init_gain = - rfseqG_init_gain_rev6; + rfseqG_init_gain_rev6; init_gaincode = - initG_gaincode_rev6; + initG_gaincode_rev6; } clip1hi_gaincode = - clip1hiG_gaincode_rev6; + clip1hiG_gaincode_rev6; switch (triso) { case 0: clip1lo_gaincode = - clip1loG_gaincode_rev6 - [0]; + clip1loG_gaincode_rev6[0]; break; case 1: clip1lo_gaincode = - clip1loG_gaincode_rev6 - [1]; + clip1loG_gaincode_rev6[1]; break; case 2: clip1lo_gaincode = - clip1loG_gaincode_rev6 - [2]; + clip1loG_gaincode_rev6[2]; break; case 3: default: clip1lo_gaincode = - clip1loG_gaincode_rev6 - [3]; + clip1loG_gaincode_rev6[3]; break; case 4: clip1lo_gaincode = - clip1loG_gaincode_rev6 - [4]; + clip1loG_gaincode_rev6[4]; break; case 5: clip1lo_gaincode = - clip1loG_gaincode_rev6 - [5]; + clip1loG_gaincode_rev6[5]; break; case 6: clip1lo_gaincode = - clip1loG_gaincode_rev6 - [6]; + clip1loG_gaincode_rev6[6]; break; case 7: clip1lo_gaincode = - clip1loG_gaincode_rev6 - [7]; + clip1loG_gaincode_rev6[7]; break; } nbclip_th = nbclipG_th_rev6; @@ -16627,9 +16600,9 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) if (pi->sh->boardflags & BFL_EXTLNA) { rfseq_init_gain = - rfseqG_init_gain_rev5_elna; + rfseqG_init_gain_rev5_elna; init_gaincode = - initG_gaincode_rev5_elna; + initG_gaincode_rev5_elna; } else { rfseq_init_gain = rfseqG_init_gain_rev5; init_gaincode = initG_gaincode_rev5; @@ -16638,40 +16611,40 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) switch (triso) { case 0: clip1lo_gaincode = - clip1loG_gaincode_rev5[0]; + clip1loG_gaincode_rev5[0]; break; case 1: clip1lo_gaincode = - clip1loG_gaincode_rev5[1]; + clip1loG_gaincode_rev5[1]; break; case 2: clip1lo_gaincode = - clip1loG_gaincode_rev5[2]; + clip1loG_gaincode_rev5[2]; break; case 3: clip1lo_gaincode = - clip1loG_gaincode_rev5[3]; + clip1loG_gaincode_rev5[3]; break; case 4: clip1lo_gaincode = - clip1loG_gaincode_rev5[4]; + clip1loG_gaincode_rev5[4]; break; case 5: clip1lo_gaincode = - clip1loG_gaincode_rev5[5]; + clip1loG_gaincode_rev5[5]; break; case 6: clip1lo_gaincode = - clip1loG_gaincode_rev5[6]; + clip1loG_gaincode_rev5[6]; break; case 7: clip1lo_gaincode = - clip1loG_gaincode_rev5[7]; + clip1loG_gaincode_rev5[7]; break; default: clip1lo_gaincode = - clip1loG_gaincode_rev5[3]; + clip1loG_gaincode_rev5[3]; break; } nbclip_th = nbclipG_th_rev5; @@ -16724,11 +16697,11 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) crsmin_th = crsminA_th_rev6; crsminl_th = crsminlA_th_rev6; if ((pi->pubpi.radiorev == 11) && - (CHSPEC_IS40(pi->radio_chanspec) == 0)) + (CHSPEC_IS40(pi->radio_chanspec) == 0)) { crsminu_th = crsminuA_th_rev6_224B0; - else + } else { crsminu_th = crsminuA_th_rev6; - + } nbclip_th = nbclipA_th_rev6; rssi_gain = rssiA_gain_rev6; } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { @@ -16754,9 +16727,9 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) if (pi->sh->boardflags & BFL_EXTLNA_5GHz) { rfseq_init_gain = - rfseqA_init_gain_rev4_elna; + rfseqA_init_gain_rev4_elna; init_gaincode = - initA_gaincode_rev4_elna; + initA_gaincode_rev4_elna; } else { rfseq_init_gain = rfseqA_init_gain_rev4; init_gaincode = initA_gaincode_rev4; @@ -16922,8 +16895,9 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7)); mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7)); - for (ctr = 0; ctr < 4; ctr++) + for (ctr = 0; ctr < 4; ctr++) { regval[ctr] = (hpf_code << 8) | 0x7c; + } wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval); wlc_phy_adjust_lnagaintbl_nphy(pi); @@ -16936,19 +16910,22 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval); wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval); - for (ctr = 0; ctr < 4; ctr++) + for (ctr = 0; ctr < 4; ctr++) { regval[ctr] = (hpf_code << 8) | 0x74; + } wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval); } if (NREV_IS(pi->pubpi.phy_rev, 2)) { - for (ctr = 0; ctr < 21; ctr++) + for (ctr = 0; ctr < 21; ctr++) { regval[ctr] = 3 * ctr; + } wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval); wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval); - for (ctr = 0; ctr < 21; ctr++) + for (ctr = 0; ctr < 21; ctr++) { regval[ctr] = (u16) ctr; + } wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval); wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval); } @@ -17098,7 +17075,7 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; s8 lna1A_gain_db_2_rev7[] = { - 11, 17, 22, 25}; + 11, 17, 22, 25 }; s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; crsminu_th = 0x3e; @@ -17109,7 +17086,7 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; s8 lna1A_gain_db_2_rev7[] = { - 12, 18, 22, 26}; + 12, 18, 22, 26 }; s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; crsminu_th = 0x45; @@ -17123,7 +17100,7 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; s8 lna1A_gain_db_2_rev7[] = { - 12, 18, 22, 26}; + 12, 18, 22, 26 }; s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; crsminu_th = 0x41; @@ -17224,7 +17201,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) } else { mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0)); } + } + } static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi) @@ -17248,15 +17227,15 @@ static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi) curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec); gain_delta[0] = - (s16) - PHY_HW_ROUND(((nphy_lnagain_est0[0] * - curr_channel) + - nphy_lnagain_est0[1]), 13); + (s16) + PHY_HW_ROUND(((nphy_lnagain_est0[0] * + curr_channel) + + nphy_lnagain_est0[1]), 13); gain_delta[1] = - (s16) - PHY_HW_ROUND(((nphy_lnagain_est1[0] * - curr_channel) + - nphy_lnagain_est1[1]), 13); + (s16) + PHY_HW_ROUND(((nphy_lnagain_est1[0] * + curr_channel) + + nphy_lnagain_est1[1]), 13); } } else { @@ -17272,15 +17251,15 @@ static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi) regval[2] = nphy_def_lnagains[3] + gain_delta[core]; regval[3] = nphy_def_lnagains[3] + gain_delta[core]; } else { - for (ctr = 0; ctr < 4; ctr++) + for (ctr = 0; ctr < 4; ctr++) { regval[ctr] = - nphy_def_lnagains[ctr] + - gain_delta[core]; + nphy_def_lnagains[ctr] + gain_delta[core]; + } } wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval); minmax_gain[core] = - (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4); + (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4); } mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0)); @@ -17418,7 +17397,7 @@ static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi) RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000); if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) & - RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE, + RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE, "HW error: radio calibration1\n")) return; @@ -17536,15 +17515,19 @@ static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi) mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0); if ((pi->sh->boardflags2 & BFL2_LEGACY) - || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) + || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) { + mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0); - else + } else { + mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0); + } mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0); - if (pi->phy_init_por) + if (pi->phy_init_por) { wlc_phy_radio205x_rcal(pi); + } } static void wlc_phy_radio_init_2057(struct brcms_phy *pi) @@ -17552,18 +17535,23 @@ static void wlc_phy_radio_init_2057(struct brcms_phy *pi) struct radio_20xx_regs *regs_2057_ptr = NULL; if (NREV_IS(pi->pubpi.phy_rev, 7)) { + regs_2057_ptr = regs_2057_rev4; } else if (NREV_IS(pi->pubpi.phy_rev, 8) || NREV_IS(pi->pubpi.phy_rev, 9)) { switch (pi->pubpi.radiorev) { case 5: - if (pi->pubpi.radiover == 0x0) + if (pi->pubpi.radiover == 0x0) { + regs_2057_ptr = regs_2057_rev5; - else if (pi->pubpi.radiover == 0x1) + + } else if (pi->pubpi.radiover == 0x1) { + regs_2057_ptr = regs_2057_rev5v1; - else + } else { break; + } case 7: @@ -17633,38 +17621,40 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, if (pi->pubpi.radiover == 0x0) { chan_info_tbl_p_2 = - chan_info_nphyrev8_2057_rev5; - tbl_len = ARRAY_SIZE( - chan_info_nphyrev8_2057_rev5); + chan_info_nphyrev8_2057_rev5; + tbl_len = + ARRAY_SIZE + (chan_info_nphyrev8_2057_rev5); } else if (pi->pubpi.radiover == 0x1) { chan_info_tbl_p_2 = - chan_info_nphyrev9_2057_rev5v1; - tbl_len = ARRAY_SIZE( - chan_info_nphyrev9_2057_rev5v1); + chan_info_nphyrev9_2057_rev5v1; + tbl_len = + ARRAY_SIZE + (chan_info_nphyrev9_2057_rev5v1); } break; case 7: chan_info_tbl_p_0 = - chan_info_nphyrev8_2057_rev7; - tbl_len = ARRAY_SIZE( - chan_info_nphyrev8_2057_rev7); + chan_info_nphyrev8_2057_rev7; + tbl_len = + ARRAY_SIZE(chan_info_nphyrev8_2057_rev7); break; case 8: chan_info_tbl_p_0 = - chan_info_nphyrev8_2057_rev8; - tbl_len = ARRAY_SIZE( - chan_info_nphyrev8_2057_rev8); + chan_info_nphyrev8_2057_rev8; + tbl_len = + ARRAY_SIZE(chan_info_nphyrev8_2057_rev8); break; default: - if (NORADIO_ENAB(pi->pubpi)) + if (NORADIO_ENAB(pi->pubpi)) { goto fail; - + } break; } } else if (NREV_IS(pi->pubpi.phy_rev, 16)) { @@ -17687,9 +17677,9 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, } } - if (i >= tbl_len) + if (i >= tbl_len) { goto fail; - + } if (pi->pubpi.radiorev == 5) { *t2 = &chan_info_tbl_p_2[i]; freq = chan_info_tbl_p_2[i].freq; @@ -17720,7 +17710,7 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, case 9: chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7; tbl_len = - ARRAY_SIZE(chan_info_nphyrev5n6_2056v7); + ARRAY_SIZE(chan_info_nphyrev5n6_2056v7); break; case 8: chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8; @@ -17728,13 +17718,12 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, break; case 11: chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11; - tbl_len = ARRAY_SIZE( - chan_info_nphyrev6_2056v11); + tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v11); break; default: - if (NORADIO_ENAB(pi->pubpi)) + if (NORADIO_ENAB(pi->pubpi)) { goto fail; - + } break; } } @@ -17744,9 +17733,9 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, break; } - if (i >= tbl_len) + if (i >= tbl_len) { goto fail; - + } *t1 = &chan_info_tbl_p_1[i]; freq = chan_info_tbl_p_1[i].freq; @@ -17755,9 +17744,9 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, if (chan_info_nphy_2055[i].chan == channel) break; - if (i >= ARRAY_SIZE(chan_info_nphy_2055)) + if (i >= ARRAY_SIZE(chan_info_nphy_2055)) { goto fail; - + } *t3 = &chan_info_nphy_2055[i]; freq = chan_info_nphy_2055[i].freq; } @@ -17765,7 +17754,7 @@ wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, *f = freq; return true; -fail: + fail: *f = WL_CHAN_FREQ_RANGE_2G; return false; } @@ -17789,12 +17778,13 @@ u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel) if (CHSPEC_IS2G(pi->radio_chanspec)) return WL_CHAN_FREQ_RANGE_2G; - if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) + if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) { return WL_CHAN_FREQ_RANGE_5GL; - else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) + } else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) { return WL_CHAN_FREQ_RANGE_5GM; - else + } else { return WL_CHAN_FREQ_RANGE_5GH; + } } static void @@ -17970,14 +17960,15 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, break; } } - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN, (u16) regs_SYN_2056_ptr[0x49 - 2].init_g); - else + } else { write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN, (u16) regs_SYN_2056_ptr[0x49 - 2].init_a); + } if (pi->sh->boardflags2 & BFL2_GPLL_WAR) { if (CHSPEC_IS2G(pi->radio_chanspec)) { @@ -18125,11 +18116,11 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, paa_boost_tune = 0x0; pada_boost_tune = 0x77; - if (freq != 5825) + if (freq != 5825) { pgaa_boost_tune = -(int)(freq - 18) / 36 + 168; - else + } else { pgaa_boost_tune = 6; - + } mixa_boost_tune = 0xf; } @@ -18155,8 +18146,9 @@ wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, if ((pi->sh->chip == BCM43224_CHIP_ID) || (pi->sh->chip == BCM43225_CHIP_ID)) { - if (pi->sh->chippkg == BCM43224_FAB_SMIC) + if (pi->sh->chippkg == BCM43224_FAB_SMIC) { cascbias = 0x35; + } } pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias; @@ -18221,9 +18213,9 @@ static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi) for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS); - if (rcal_reg & 0x1) + if (rcal_reg & 0x1) { break; - + } udelay(100); } @@ -18255,10 +18247,8 @@ static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi) u16 savereg; savereg = - read_radio_reg( - pi, - RADIO_2056_SYN_PLL_MAST2 | - RADIO_2056_SYN); + read_radio_reg(pi, + RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN); write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN, savereg | 0x7); udelay(10); @@ -18271,13 +18261,12 @@ static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi) 0x9); for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { - rcal_reg = read_radio_reg( - pi, - RADIO_2056_SYN_RCAL_CODE_OUT | - RADIO_2056_SYN); - if (rcal_reg & 0x80) + rcal_reg = read_radio_reg(pi, + RADIO_2056_SYN_RCAL_CODE_OUT | + RADIO_2056_SYN); + if (rcal_reg & 0x80) { break; - + } udelay(100); } @@ -18289,9 +18278,9 @@ static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi) 0x1); rcal_reg = - read_radio_reg(pi, - RADIO_2056_SYN_RCAL_CODE_OUT | - RADIO_2056_SYN); + read_radio_reg(pi, + RADIO_2056_SYN_RCAL_CODE_OUT | + RADIO_2056_SYN); write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, 0x0); @@ -18305,11 +18294,9 @@ static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi) } static void -wlc_phy_chanspec_radio2057_setup( - struct brcms_phy *pi, - const struct chan_info_nphy_radio2057 *ci, - const struct chan_info_nphy_radio2057_rev5 * - ci2) +wlc_phy_chanspec_radio2057_setup(struct brcms_phy *pi, + const struct chan_info_nphy_radio2057 *ci, + const struct chan_info_nphy_radio2057_rev5 *ci2) { int coreNum; u16 txmix2g_tune_boost_pu = 0; @@ -18468,8 +18455,9 @@ wlc_phy_chanspec_radio2057_setup( if (CHSPEC_IS2G(pi->radio_chanspec)) { if (PHY_IPA(pi)) { - if (pi->pubpi.radiorev == 3) + if (pi->pubpi.radiorev == 3) { txmix2g_tune_boost_pu = 0x6b; + } if (pi->pubpi.radiorev == 5) pad2g_tune_pus = 0x73; @@ -18525,9 +18513,9 @@ static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi) for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); - if (rccal_valid & 0x2) + if (rccal_valid & 0x2) { break; - + } udelay(500); } @@ -18547,9 +18535,9 @@ static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi) for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); - if (rccal_valid & 0x2) + if (rccal_valid & 0x2) { break; - + } udelay(500); } @@ -18570,9 +18558,9 @@ static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi) for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); - if (rccal_valid & 0x2) + if (rccal_valid & 0x2) { break; - + } udelay(500); } @@ -18620,19 +18608,20 @@ wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones, u32 offset; int tone_id; int tbllen = - CHSPEC_IS40(pi->radio_chanspec) ? - NPHY_NOISEVAR_TBLLEN40 : NPHY_NOISEVAR_TBLLEN20; + CHSPEC_IS40(pi-> + radio_chanspec) ? NPHY_NOISEVAR_TBLLEN40 : + NPHY_NOISEVAR_TBLLEN20; if (pi->nphy_noisevars_adjusted) { for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) { tone_id = pi->nphy_saved_noisevars.tone_id[i]; offset = (tone_id >= 0) ? - ((tone_id * - 2) + 1) : (tbllen + (tone_id * 2) + 1); - wlc_phy_table_write_nphy( - pi, NPHY_TBL_ID_NOISEVAR, 1, - offset, 32, - &pi->nphy_saved_noisevars.min_noise_vars[i]); + ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, + offset, 32, + (void *)&pi-> + nphy_saved_noisevars. + min_noise_vars[i]); } pi->nphy_saved_noisevars.bufcount = 0; @@ -18645,15 +18634,15 @@ wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones, for (i = 0; i < ntones; i++) { tone_id = tone_id_buf[i]; offset = (tone_id >= 0) ? - ((tone_id * 2) + 1) : - (tbllen + (tone_id * 2) + 1); + ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1); pi->nphy_saved_noisevars.tone_id[i] = tone_id; wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, offset, 32, &pi->nphy_saved_noisevars. min_noise_vars[i]); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, - offset, 32, &noise_var_buf[i]); + offset, 32, + (void *)&noise_var_buf[i]); pi->nphy_saved_noisevars.bufcount++; } @@ -18717,18 +18706,19 @@ static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi) u8 tx_lpf_bw = 0; if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { - if (CHSPEC_IS40(pi->radio_chanspec)) + if (CHSPEC_IS40(pi->radio_chanspec)) { tx_lpf_bw = 3; - else + } else { tx_lpf_bw = 1; + } if (PHY_IPA(pi)) { - if (CHSPEC_IS40(pi->radio_chanspec)) + if (CHSPEC_IS40(pi->radio_chanspec)) { tx_lpf_bw = 5; - else + } else { tx_lpf_bw = 4; + } } - write_phy_reg(pi, 0xe8, (tx_lpf_bw << 0) | (tx_lpf_bw << 3) | @@ -18736,10 +18726,11 @@ static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi) if (PHY_IPA(pi)) { - if (CHSPEC_IS40(pi->radio_chanspec)) + if (CHSPEC_IS40(pi->radio_chanspec)) { tx_lpf_bw = 4; - else + } else { tx_lpf_bw = 1; + } write_phy_reg(pi, 0xe9, (tx_lpf_bw << 0) | @@ -18766,25 +18757,25 @@ static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) if (pi->nphy_gband_spurwar_en) { - wlc_phy_adjust_rx_analpfbw_nphy( - pi, - NPHY_ANARXLPFBW_REDUCTIONFACT); + wlc_phy_adjust_rx_analpfbw_nphy(pi, + NPHY_ANARXLPFBW_REDUCTIONFACT); if (CHSPEC_IS2G(pi->radio_chanspec)) { if ((cur_channel == 11) - && CHSPEC_IS40(pi->radio_chanspec)) - wlc_phy_adjust_min_noisevar_nphy( - pi, 2, - nphy_adj_tone_id_buf, - nphy_adj_noise_var_buf); - else + && CHSPEC_IS40(pi->radio_chanspec)) { + + wlc_phy_adjust_min_noisevar_nphy(pi, 2, + nphy_adj_tone_id_buf, + nphy_adj_noise_var_buf); + } else { + wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL, NULL); + } } - wlc_phy_adjust_crsminpwr_nphy(pi, - NPHY_ADJUSTED_MINCRSPOWER); + NPHY_ADJUSTED_MINCRSPOWER); } if ((pi->nphy_gband_spurwar2_en) @@ -18856,17 +18847,17 @@ static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) if (isAdjustNoiseVar) { numTonesAdjust = sizeof(nphy_adj_tone_id_buf) / - sizeof(nphy_adj_tone_id_buf[0]); + sizeof(nphy_adj_tone_id_buf[0]); - wlc_phy_adjust_min_noisevar_nphy( - pi, - numTonesAdjust, - nphy_adj_tone_id_buf, - nphy_adj_noise_var_buf); + wlc_phy_adjust_min_noisevar_nphy(pi, + numTonesAdjust, + nphy_adj_tone_id_buf, + nphy_adj_noise_var_buf); tempval = 0; } else { + wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL, NULL); } @@ -18905,14 +18896,14 @@ static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) } if (nphy_adj_tone_id_buf[0] - && nphy_adj_noise_var_buf[0]) - wlc_phy_adjust_min_noisevar_nphy( - pi, 1, - nphy_adj_tone_id_buf, - nphy_adj_noise_var_buf); - else + && nphy_adj_noise_var_buf[0]) { + wlc_phy_adjust_min_noisevar_nphy(pi, 1, + nphy_adj_tone_id_buf, + nphy_adj_noise_var_buf); + } else { wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL, NULL); + } } if (pi->phyhang_avoid) @@ -18921,7 +18912,7 @@ static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) } static void -wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, +wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec, const struct nphy_sfo_cfg *ci) { u16 val; @@ -18973,11 +18964,14 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840); } - if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) + if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) { wlc_phy_txpwr_fixpower_nphy(pi); + } + + if (NREV_LT(pi->pubpi.phy_rev, 3)) { - if (NREV_LT(pi->pubpi.phy_rev, 3)) wlc_phy_adjust_lnagaintbl_nphy(pi); + } wlc_phy_txlpfbw_nphy(pi); @@ -18988,20 +18982,28 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, val = CHSPEC_CHANNEL(chanspec); if (!CHSPEC_IS40(pi->radio_chanspec)) { if (NREV_GE(pi->pubpi.phy_rev, 7)) { - if ((val == 13) || (val == 14) || (val == 153)) + if ((val == 13) || (val == 14) || (val == 153)) { spuravoid = 1; - } else if (((val >= 5) && (val <= 8)) || (val == 13) - || (val == 14)) { - spuravoid = 1; + } + } else { + + if (((val >= 5) && (val <= 8)) || (val == 13) + || (val == 14)) { + spuravoid = 1; + } } - } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { - if (val == 54) - spuravoid = 1; } else { - if (pi->nphy_aband_spurwar_en && - ((val == 38) || (val == 102) - || (val == 118))) - spuravoid = 1; + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + if (val == 54) { + spuravoid = 1; + } + } else { + + if (pi->nphy_aband_spurwar_en && + ((val == 38) || (val == 102) + || (val == 118))) + spuravoid = 1; + } } if (pi->phy_spuravoid == SPURAVOID_FORCEON) @@ -19045,7 +19047,7 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, wlc_phy_spurwar_nphy(pi); } -void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec) +void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, chanspec_t chanspec) { int freq; struct chan_info_nphy_radio2057 *t0 = NULL; @@ -19053,11 +19055,12 @@ void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec) struct chan_info_nphy_radio2057_rev5 *t2 = NULL; struct chan_info_nphy_2055 *t3 = NULL; - if (NORADIO_ENAB(pi->pubpi)) + if (NORADIO_ENAB(pi->pubpi)) { return; + } if (!wlc_phy_chan2freq_nphy - (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3)) + (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3)) return; wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec); @@ -19068,13 +19071,15 @@ void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec) if (CHSPEC_IS40(chanspec)) { if (CHSPEC_SB_UPPER(chanspec)) { or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20); - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { or_phy_reg(pi, 0x310, PRIM_SEL_UP20); + } } else { and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20); - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { and_phy_reg(pi, 0x310, (~PRIM_SEL_UP20 & 0xffff)); + } } } @@ -19119,8 +19124,8 @@ void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec) wlc_phy_chanspec_radio2055_setup(pi, t3); wlc_phy_chanspec_nphy_setup(pi, chanspec, - (const struct nphy_sfo_cfg *) - &(t3->PHY_BW1a)); + (const struct nphy_sfo_cfg *)&(t3-> + PHY_BW1a)); } } @@ -19142,51 +19147,51 @@ static void wlc_phy_savecal_nphy(struct brcms_phy *pi) if (NREV_GE(pi->pubpi.phy_rev, 7)) { txcal_radio_regs = - pi->calibration_cache.txcal_radio_regs_2G; + pi->calibration_cache.txcal_radio_regs_2G; } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { pi->calibration_cache.txcal_radio_regs_2G[0] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_FINE_I | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_FINE_I | + RADIO_2056_TX0); pi->calibration_cache.txcal_radio_regs_2G[1] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_FINE_Q | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_FINE_Q | + RADIO_2056_TX0); pi->calibration_cache.txcal_radio_regs_2G[2] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_FINE_I | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_FINE_I | + RADIO_2056_TX1); pi->calibration_cache.txcal_radio_regs_2G[3] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_FINE_Q | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_FINE_Q | + RADIO_2056_TX1); pi->calibration_cache.txcal_radio_regs_2G[4] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_COARSE_I | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_COARSE_I | + RADIO_2056_TX0); pi->calibration_cache.txcal_radio_regs_2G[5] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_COARSE_Q | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_COARSE_Q | + RADIO_2056_TX0); pi->calibration_cache.txcal_radio_regs_2G[6] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_COARSE_I | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_COARSE_I | + RADIO_2056_TX1); pi->calibration_cache.txcal_radio_regs_2G[7] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_COARSE_Q | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_COARSE_Q | + RADIO_2056_TX1); } else { pi->calibration_cache.txcal_radio_regs_2G[0] = - read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); + read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); pi->calibration_cache.txcal_radio_regs_2G[1] = - read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); + read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); pi->calibration_cache.txcal_radio_regs_2G[2] = - read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); + read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); pi->calibration_cache.txcal_radio_regs_2G[3] = - read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); + read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); } pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec; @@ -19199,51 +19204,51 @@ static void wlc_phy_savecal_nphy(struct brcms_phy *pi) if (NREV_GE(pi->pubpi.phy_rev, 7)) { txcal_radio_regs = - pi->calibration_cache.txcal_radio_regs_5G; + pi->calibration_cache.txcal_radio_regs_5G; } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { pi->calibration_cache.txcal_radio_regs_5G[0] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_FINE_I | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_FINE_I | + RADIO_2056_TX0); pi->calibration_cache.txcal_radio_regs_5G[1] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_FINE_Q | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_FINE_Q | + RADIO_2056_TX0); pi->calibration_cache.txcal_radio_regs_5G[2] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_FINE_I | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_FINE_I | + RADIO_2056_TX1); pi->calibration_cache.txcal_radio_regs_5G[3] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_FINE_Q | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_FINE_Q | + RADIO_2056_TX1); pi->calibration_cache.txcal_radio_regs_5G[4] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_COARSE_I | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_COARSE_I | + RADIO_2056_TX0); pi->calibration_cache.txcal_radio_regs_5G[5] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_COARSE_Q | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_COARSE_Q | + RADIO_2056_TX0); pi->calibration_cache.txcal_radio_regs_5G[6] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_COARSE_I | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_COARSE_I | + RADIO_2056_TX1); pi->calibration_cache.txcal_radio_regs_5G[7] = - read_radio_reg(pi, - RADIO_2056_TX_LOFT_COARSE_Q | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_LOFT_COARSE_Q | + RADIO_2056_TX1); } else { pi->calibration_cache.txcal_radio_regs_5G[0] = - read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); + read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); pi->calibration_cache.txcal_radio_regs_5G[1] = - read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); + read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); pi->calibration_cache.txcal_radio_regs_5G[2] = - read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); + read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); pi->calibration_cache.txcal_radio_regs_5G[3] = - read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); + read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); } pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec; @@ -19253,18 +19258,18 @@ static void wlc_phy_savecal_nphy(struct brcms_phy *pi) for (coreNum = 0; coreNum <= 1; coreNum++) { txcal_radio_regs[2 * coreNum] = - READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, - LOFT_FINE_I); + READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, + LOFT_FINE_I); txcal_radio_regs[2 * coreNum + 1] = - READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, - LOFT_FINE_Q); + READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, + LOFT_FINE_Q); txcal_radio_regs[2 * coreNum + 4] = - READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, - LOFT_COARSE_I); + READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, + LOFT_COARSE_I); txcal_radio_regs[2 * coreNum + 5] = - READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, - LOFT_COARSE_Q); + READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, + LOFT_COARSE_Q); } } @@ -19296,7 +19301,8 @@ static void wlc_phy_restorecal_nphy(struct brcms_phy *pi) loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5]; } - wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16, tbl_ptr); + wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16, + (void *)tbl_ptr); if (NREV_GE(pi->pubpi.phy_rev, 3)) { txcal_coeffs_bphy[0] = tbl_ptr[0]; @@ -19323,7 +19329,7 @@ static void wlc_phy_restorecal_nphy(struct brcms_phy *pi) if (CHSPEC_IS2G(pi->radio_chanspec)) { if (NREV_GE(pi->pubpi.phy_rev, 7)) { txcal_radio_regs = - pi->calibration_cache.txcal_radio_regs_2G; + pi->calibration_cache.txcal_radio_regs_2G; } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { write_radio_reg(pi, @@ -19388,7 +19394,7 @@ static void wlc_phy_restorecal_nphy(struct brcms_phy *pi) } else { if (NREV_GE(pi->pubpi.phy_rev, 7)) { txcal_radio_regs = - pi->calibration_cache.txcal_radio_regs_5G; + pi->calibration_cache.txcal_radio_regs_5G; } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { write_radio_reg(pi, @@ -19539,8 +19545,8 @@ u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val) if (D11REV_IS(pi->sh->corerev, 16)) { suspended = - (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ? - false : true; + (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ? + false : true; if (!suspended) wlapi_suspend_mac_and_wait(pi->sh->physhim); } @@ -19620,8 +19626,8 @@ wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys, u32 t1_offset, t2_offset; u8 ctr; u8 end_event = - NREV_GE(pi->pubpi.phy_rev, - 3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END; + NREV_GE(pi->pubpi.phy_rev, + 3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END; u8 end_dly = 1; if (pi->phyhang_avoid) @@ -19651,10 +19657,11 @@ static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset) u16 rx2tx_lpf_rc_lut_offset = 0; if (offset == 0) { - if (CHSPEC_IS40(pi->radio_chanspec)) + if (CHSPEC_IS40(pi->radio_chanspec)) { rx2tx_lpf_rc_lut_offset = 0x159; - else + } else { rx2tx_lpf_rc_lut_offset = 0x154; + } } else { rx2tx_lpf_rc_lut_offset = offset; } @@ -19684,77 +19691,77 @@ wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value, case (0x1 << 2): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x7a : - 0x7d; + 0x7d; val_mask = (0x1 << 1); val_shift = 1; break; case (0x1 << 3): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x7a : - 0x7d; + 0x7d; val_mask = (0x1 << 2); val_shift = 2; break; case (0x1 << 4): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x7a : - 0x7d; + 0x7d; val_mask = (0x1 << 4); val_shift = 4; break; case (0x1 << 5): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x7a : - 0x7d; + 0x7d; val_mask = (0x1 << 5); val_shift = 5; break; case (0x1 << 6): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x7a : - 0x7d; + 0x7d; val_mask = (0x1 << 6); val_shift = 6; break; case (0x1 << 7): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x7a : - 0x7d; + 0x7d; val_mask = (0x1 << 7); val_shift = 7; break; case (0x1 << 10): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0xf8 : - 0xfa; + 0xfa; val_mask = (0x7 << 4); val_shift = 4; break; case (0x1 << 11): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x7b : - 0x7e; + 0x7e; val_mask = (0xffff << 0); val_shift = 0; break; case (0x1 << 12): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x7c : - 0x7f; + 0x7f; val_mask = (0xffff << 0); val_shift = 0; break; case (0x3 << 13): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x348 : - 0x349; + 0x349; val_mask = (0xff << 0); val_shift = 0; break; case (0x1 << 13): en_addr = (core_num == 0) ? 0xe7 : 0xec; val_addr = (core_num == 0) ? 0x348 : - 0x349; + 0x349; val_mask = (0xf << 0); val_shift = 0; break; @@ -19762,105 +19769,104 @@ wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value, addr = 0xffff; break; } - } else if (override_id == - NPHY_REV7_RFCTRLOVERRIDE_ID1) { + } else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID1) { switch (field) { case (0x1 << 1): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 1); val_shift = 1; break; case (0x1 << 3): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 3); val_shift = 3; break; case (0x1 << 5): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 5); val_shift = 5; break; case (0x1 << 4): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 4); val_shift = 4; break; case (0x1 << 2): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 2); val_shift = 2; break; case (0x1 << 7): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x7 << 8); val_shift = 8; break; case (0x1 << 11): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 14); val_shift = 14; break; case (0x1 << 10): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 13); val_shift = 13; break; case (0x1 << 9): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 12); val_shift = 12; break; case (0x1 << 8): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 11); val_shift = 11; break; case (0x1 << 6): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 6); val_shift = 6; break; case (0x1 << 0): en_addr = (core_num == 0) ? 0x342 : - 0x343; + 0x343; val_addr = (core_num == 0) ? 0x340 : - 0x341; + 0x341; val_mask = (0x1 << 0); val_shift = 0; break; @@ -19868,47 +19874,46 @@ wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value, addr = 0xffff; break; } - } else if (override_id == - NPHY_REV7_RFCTRLOVERRIDE_ID2) { + } else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID2) { switch (field) { case (0x1 << 3): en_addr = (core_num == 0) ? 0x346 : - 0x347; + 0x347; val_addr = (core_num == 0) ? 0x344 : - 0x345; + 0x345; val_mask = (0x1 << 3); val_shift = 3; break; case (0x1 << 1): en_addr = (core_num == 0) ? 0x346 : - 0x347; + 0x347; val_addr = (core_num == 0) ? 0x344 : - 0x345; + 0x345; val_mask = (0x1 << 1); val_shift = 1; break; case (0x1 << 0): en_addr = (core_num == 0) ? 0x346 : - 0x347; + 0x347; val_addr = (core_num == 0) ? 0x344 : - 0x345; + 0x345; val_mask = (0x1 << 0); val_shift = 0; break; case (0x1 << 2): en_addr = (core_num == 0) ? 0x346 : - 0x347; + 0x347; val_addr = (core_num == 0) ? 0x344 : - 0x345; + 0x345; val_mask = (0x1 << 2); val_shift = 2; break; case (0x1 << 4): en_addr = (core_num == 0) ? 0x346 : - 0x347; + 0x347; val_addr = (core_num == 0) ? 0x344 : - 0x345; + 0x345; val_mask = (0x1 << 4); val_shift = 4; break; @@ -19927,11 +19932,12 @@ wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value, || (core_mask & (1 << core_num))) { or_phy_reg(pi, en_addr, en_mask); - if (addr != 0xffff) + if (addr != 0xffff) { mod_phy_reg(pi, val_addr, val_mask, (value << val_shift)); + } } } } @@ -19944,7 +19950,7 @@ wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value, { u8 core_num; u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask = - 0, val_mask = 0; + 0, val_mask = 0; u8 shift = 0, val_shift = 0; if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { @@ -20060,11 +20066,12 @@ wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value, || (core_mask & (1 << core_num))) { or_phy_reg(pi, en_addr, en_mask); - if (addr != 0xffff) + if (addr != 0xffff) { mod_phy_reg(pi, val_addr, val_mask, (value << val_shift)); + } } } } @@ -20171,8 +20178,9 @@ wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value, break; } - if ((addr != 0xffff) && (core_mask & (1 << core_num))) + if ((addr != 0xffff) && (core_mask & (1 << core_num))) { mod_phy_reg(pi, addr, mask, (value << shift)); + } } or_phy_reg(pi, 0xec, (0x1 << 0)); @@ -20193,93 +20201,76 @@ wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value, switch (cmd) { case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu: - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 5), - value, core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID1); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 4), value, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID1); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 3), value, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), + value, core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), value, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), value, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID1); break; case NPHY_REV7_RfctrlOverride_cmd_rx_pu: - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 2), - value, core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID1); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 1), value, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID1); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 0), value, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID1); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 1), value, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID2); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 11), 0, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), + value, core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID2); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID1); break; case NPHY_REV7_RfctrlOverride_cmd_tx_pu: - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 2), - value, core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID0); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 1), value, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID1); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 0), value, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID2); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 2), value, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID2); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 11), 1, - core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), + value, core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID2); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), value, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID2); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, + core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID1); break; case NPHY_REV7_RfctrlOverride_cmd_rxgain: rfmxgain = value & 0x000ff; lpfgain = value & 0x0ff00; lpfgain = lpfgain >> 8; - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 11), - rfmxgain, core_mask, - off, - NPHY_REV7_RFCTRLOVERRIDE_ID0); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x3 << 13), - lpfgain, core_mask, - off, - NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), + rfmxgain, core_mask, + off, + NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x3 << 13), + lpfgain, core_mask, + off, + NPHY_REV7_RFCTRLOVERRIDE_ID0); break; case NPHY_REV7_RfctrlOverride_cmd_txgain: tgain = value & 0x7fff; lpfgain = value & 0x8000; lpfgain = lpfgain >> 14; - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 12), - tgain, core_mask, off, - NPHY_REV7_RFCTRLOVERRIDE_ID0); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 13), - lpfgain, core_mask, - off, - NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), + tgain, core_mask, off, + NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 13), + lpfgain, core_mask, + off, + NPHY_REV7_RFCTRLOVERRIDE_ID0); break; } } @@ -20292,164 +20283,137 @@ wlc_phy_scale_offset_rssi_nphy(struct brcms_phy *pi, u16 scale, s8 offset, u16 valuetostuff; offset = (offset > NPHY_RSSICAL_MAXREAD) ? - NPHY_RSSICAL_MAXREAD : offset; + NPHY_RSSICAL_MAXREAD : offset; offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ? - -NPHY_RSSICAL_MAXREAD - 1 : offset; + -NPHY_RSSICAL_MAXREAD - 1 : offset; valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f); if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) { write_phy_reg(pi, 0x1a6, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) { write_phy_reg(pi, 0x1ac, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) { write_phy_reg(pi, 0x1b2, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) { write_phy_reg(pi, 0x1b8, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) { write_phy_reg(pi, 0x1a4, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) { write_phy_reg(pi, 0x1aa, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) { write_phy_reg(pi, 0x1b0, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) { write_phy_reg(pi, 0x1b6, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) { write_phy_reg(pi, 0x1a5, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) { write_phy_reg(pi, 0x1ab, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) { write_phy_reg(pi, 0x1b1, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) { write_phy_reg(pi, 0x1b7, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) { write_phy_reg(pi, 0x1a7, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) { write_phy_reg(pi, 0x1ad, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) { write_phy_reg(pi, 0x1b3, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) { write_phy_reg(pi, 0x1b9, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) { write_phy_reg(pi, 0x1a8, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) { write_phy_reg(pi, 0x1ae, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) + (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) { write_phy_reg(pi, 0x1b4, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) + (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) { write_phy_reg(pi, 0x1ba, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) + (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) { write_phy_reg(pi, 0x1a9, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) + (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) { write_phy_reg(pi, 0x1b5, valuetostuff); + } if (((coresel == RADIO_MIMO_CORESEL_CORE1) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) + (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) { write_phy_reg(pi, 0x1af, valuetostuff); - + } if (((coresel == RADIO_MIMO_CORESEL_CORE2) || (coresel == RADIO_MIMO_CORESEL_ALLRX)) && - (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) + (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) { write_phy_reg(pi, 0x1bb, valuetostuff); -} - -static void brcms_phy_wr_tx_mux(struct brcms_phy *pi, u8 core) -{ - if (PHY_IPA(pi)) { - if (NREV_GE(pi->pubpi.phy_rev, 7)) - write_radio_reg(pi, - ((core == PHY_CORE_0) ? - RADIO_2057_TX0_TX_SSI_MUX : - RADIO_2057_TX1_TX_SSI_MUX), - (CHSPEC_IS5G(pi->radio_chanspec) ? - 0xc : 0xe)); - else - write_radio_reg(pi, - RADIO_2056_TX_TX_SSI_MUX | - ((core == PHY_CORE_0) ? - RADIO_2056_TX0 : RADIO_2056_TX1), - (CHSPEC_IS5G(pi->radio_chanspec) ? - 0xc : 0xe)); - } else { - if (NREV_GE(pi->pubpi.phy_rev, 7)) { - write_radio_reg(pi, - ((core == PHY_CORE_0) ? - RADIO_2057_TX0_TX_SSI_MUX : - RADIO_2057_TX1_TX_SSI_MUX), - 0x11); - - if (pi->pubpi.radioid == BCM2057_ID) - write_radio_reg(pi, - RADIO_2057_IQTEST_SEL_PU, 0x1); - - } else { - write_radio_reg(pi, - RADIO_2056_TX_TX_SSI_MUX | - ((core == PHY_CORE_0) ? - RADIO_2056_TX0 : RADIO_2056_TX1), - 0x11); - } } } @@ -20476,7 +20440,7 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) mod_phy_reg(pi, 0xe6, (0x1 << 5), 0); mask = (0x1 << 2) | - (0x1 << 3) | (0x1 << 4) | (0x1 << 5); + (0x1 << 3) | (0x1 << 4) | (0x1 << 5); mod_phy_reg(pi, 0xf9, mask, 0); mod_phy_reg(pi, 0xfb, mask, 0); @@ -20495,22 +20459,23 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) if (rssi_type == NPHY_RSSI_SEL_W1 || rssi_type == NPHY_RSSI_SEL_W2 || rssi_type == NPHY_RSSI_SEL_NB) { + mod_phy_reg(pi, (core == PHY_CORE_0) ? 0xa6 : 0xa7, (0x3 << 8), 0); mask = (0x1 << 2) | - (0x1 << 3) | - (0x1 << 4) | (0x1 << 5); + (0x1 << 3) | + (0x1 << 4) | (0x1 << 5); mod_phy_reg(pi, (core == PHY_CORE_0) ? 0xf9 : 0xfb, mask, 0); if (rssi_type == NPHY_RSSI_SEL_W1) { - if (CHSPEC_IS5G( - pi->radio_chanspec)) { + if (CHSPEC_IS5G + (pi->radio_chanspec)) { mask = (0x1 << 2); val = 1 << 2; } else { @@ -20536,6 +20501,7 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) 0xe5 : 0xe6, mask, val); } else { if (rssi_type == NPHY_RSSI_SEL_TBD) { + mask = (0x3 << 8); val = 1 << 8; mod_phy_reg(pi, @@ -20550,6 +20516,7 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) : 0xa7, mask, val); } else if (rssi_type == NPHY_RSSI_SEL_IQ) { + mask = (0x3 << 8); val = 2 << 8; mod_phy_reg(pi, @@ -20563,6 +20530,7 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) PHY_CORE_0) ? 0xa6 : 0xa7, mask, val); } else { + mask = (0x3 << 8); val = 3 << 8; mod_phy_reg(pi, @@ -20575,13 +20543,86 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) (core == PHY_CORE_0) ? 0xa6 : 0xa7, mask, val); - brcms_phy_wr_tx_mux(pi, core); + + if (PHY_IPA(pi)) { + if (NREV_GE + (pi->pubpi.phy_rev, + 7)) { + + write_radio_reg + (pi, + ((core == + PHY_CORE_0) + ? + RADIO_2057_TX0_TX_SSI_MUX + : + RADIO_2057_TX1_TX_SSI_MUX), + (CHSPEC_IS5G + (pi-> + radio_chanspec) + ? 0xc : + 0xe)); + } else { + write_radio_reg + (pi, + RADIO_2056_TX_TX_SSI_MUX + | + ((core == + PHY_CORE_0) + ? + RADIO_2056_TX0 + : + RADIO_2056_TX1), + (CHSPEC_IS5G + (pi-> + radio_chanspec) + ? 0xc : + 0xe)); + } + } else { + + if (NREV_GE + (pi->pubpi.phy_rev, + 7)) { + write_radio_reg + (pi, + ((core == + PHY_CORE_0) + ? + RADIO_2057_TX0_TX_SSI_MUX + : + RADIO_2057_TX1_TX_SSI_MUX), + 0x11); + + if (pi->pubpi. + radioid == + BCM2057_ID) + write_radio_reg + (pi, + RADIO_2057_IQTEST_SEL_PU, + 0x1); + + } else { + write_radio_reg + (pi, + RADIO_2056_TX_TX_SSI_MUX + | + ((core == + PHY_CORE_0) + ? + RADIO_2056_TX0 + : + RADIO_2056_TX1), + 0x11); + } + } + afectrlovr_rssi_val = 1 << 9; mod_phy_reg(pi, - (core == - PHY_CORE_0) ? 0x8f - : 0xa5, (0x1 << 9), - afectrlovr_rssi_val); + (core == + PHY_CORE_0) ? 0x8f + : 0xa5, (0x1 << 9), + afectrlovr_rssi_val); } } } @@ -20590,15 +20631,19 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) if ((rssi_type == NPHY_RSSI_SEL_W1) || (rssi_type == NPHY_RSSI_SEL_W2) || - (rssi_type == NPHY_RSSI_SEL_NB)) + (rssi_type == NPHY_RSSI_SEL_NB)) { + val = 0x0; - else if (rssi_type == NPHY_RSSI_SEL_TBD) + } else if (rssi_type == NPHY_RSSI_SEL_TBD) { + val = 0x1; - else if (rssi_type == NPHY_RSSI_SEL_IQ) + } else if (rssi_type == NPHY_RSSI_SEL_IQ) { + val = 0x2; - else - val = 0x3; + } else { + val = 0x3; + } mask = ((0x3 << 12) | (0x3 << 14)); val = (val << 12) | (val << 14); mod_phy_reg(pi, 0xa6, mask, val); @@ -20607,13 +20652,15 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) if ((rssi_type == NPHY_RSSI_SEL_W1) || (rssi_type == NPHY_RSSI_SEL_W2) || (rssi_type == NPHY_RSSI_SEL_NB)) { - if (rssi_type == NPHY_RSSI_SEL_W1) + if (rssi_type == NPHY_RSSI_SEL_W1) { val = 0x1; - if (rssi_type == NPHY_RSSI_SEL_W2) + } + if (rssi_type == NPHY_RSSI_SEL_W2) { val = 0x2; - if (rssi_type == NPHY_RSSI_SEL_NB) + } + if (rssi_type == NPHY_RSSI_SEL_NB) { val = 0x3; - + } mask = (0x3 << 4); val = (val << 4); mod_phy_reg(pi, 0x7a, mask, val); @@ -20651,16 +20698,16 @@ void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) (rssi_type == NPHY_RSSI_SEL_NB)) { rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3)); rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) | - (rfctrlcmd_coresel_val << 3); + (rfctrlcmd_coresel_val << 3); rfctrlovr_mask = ((0x1 << 5) | (0x1 << 12) | (0x1 << 1) | (0x1 << 0)); rfctrlovr_val = (rfctrlovr_rssi_val << 5) | - (rfctrlovr_rxen_val << 12) | - (rfctrlovr_coresel_val << 1) | - (rfctrlovr_trigger_val << 0); + (rfctrlovr_rxen_val << 12) | + (rfctrlovr_coresel_val << 1) | + (rfctrlovr_trigger_val << 0); mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val); mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val); @@ -20715,11 +20762,13 @@ wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf, wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type); gpiosel_orig = read_phy_reg(pi, 0xca); - if (NREV_LT(pi->pubpi.phy_rev, 2)) + if (NREV_LT(pi->pubpi.phy_rev, 2)) { write_phy_reg(pi, 0xca, 5); + } - for (ctr = 0; ctr < 4; ctr++) + for (ctr = 0; ctr < 4; ctr++) { rssi_buf[ctr] = 0; + } for (samp = 0; samp < nsamps; samp++) { if (NREV_LT(pi->pubpi.phy_rev, 2)) { @@ -20736,8 +20785,9 @@ wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf, tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2; tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2; - for (ctr = 0; ctr < 4; ctr++) + for (ctr = 0; ctr < 4; ctr++) { rssi_buf[ctr] += tmp_buf[ctr]; + } } @@ -20746,8 +20796,9 @@ wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf, rssi_out_val |= (rssi_buf[1] & 0xff) << 16; rssi_out_val |= (rssi_buf[0] & 0xff) << 24; - if (NREV_LT(pi->pubpi.phy_rev, 2)) + if (NREV_LT(pi->pubpi.phy_rev, 2)) { write_phy_reg(pi, 0xca, gpiosel_orig); + } write_phy_reg(pi, 0xa6, afectrlCore1_save); write_phy_reg(pi, 0xa7, afectrlCore2_save); @@ -20797,7 +20848,7 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) u16 tempsense_Rcal; syn_tempprocsense_save = - read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG); + read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG); afectrlCore1_save = read_phy_reg(pi, 0xa6); afectrlCore2_save = read_phy_reg(pi, 0xa7); @@ -20931,7 +20982,7 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { syn_tempprocsense_save = - read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE); + read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE); afectrlCore1_save = read_phy_reg(pi, 0xa6); afectrlCore2_save = read_phy_reg(pi, 0xa7); @@ -20946,13 +20997,14 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05); wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01); - else + } else { write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01); + } radio_temp[0] = - (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64; + (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64; write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, syn_tempprocsense_save); @@ -20967,17 +21019,17 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) } else { pwrdet_rxtx_core1_save = - read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); + read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); pwrdet_rxtx_core2_save = - read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); + read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); core1_txrf_iqcal1_save = - read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); + read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); core1_txrf_iqcal2_save = - read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); + read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); core2_txrf_iqcal1_save = - read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); + read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); core2_txrf_iqcal2_save = - read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); + read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS); afectrlCore1_save = read_phy_reg(pi, 0xa6); @@ -21008,12 +21060,11 @@ s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) radio_temp[3] = (radio_temp[3] + radio_temp2[3]); radio_temp[0] = - (radio_temp[0] + radio_temp[1] + radio_temp[2] + - radio_temp[3]); + (radio_temp[0] + radio_temp[1] + radio_temp[2] + + radio_temp[3]); radio_temp[0] = - (radio_temp[0] + - (8 * 32)) * (950 - 350) / 63 + (350 * 8); + (radio_temp[0] + (8 * 32)) * (950 - 350) / 63 + (350 * 8); radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38; @@ -21075,20 +21126,22 @@ wlc_phy_set_rssi_2055_vcm(struct brcms_phy *pi, u8 rssi_type, u8 *vcm_buf) RADIO_2055_NBRSSI_VCM_Q_SHIFT); } } else { - if (core == PHY_CORE_0) + + if (core == PHY_CORE_0) { mod_radio_reg(pi, RADIO_2055_CORE1_RXBB_RSSI_CTRL5, RADIO_2055_WBRSSI_VCM_IQ_MASK, vcm_buf[2 * core] << RADIO_2055_WBRSSI_VCM_IQ_SHIFT); - else + } else { mod_radio_reg(pi, RADIO_2055_CORE2_RXBB_RSSI_CTRL5, RADIO_2055_WBRSSI_VCM_IQ_MASK, vcm_buf[2 * core] << RADIO_2055_WBRSSI_VCM_IQ_SHIFT); + } } } } @@ -21096,6 +21149,7 @@ wlc_phy_set_rssi_2055_vcm(struct brcms_phy *pi, u8 rssi_type, u8 *vcm_buf) void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi) { if (NREV_GE(pi->pubpi.phy_rev, 3)) { + wlc_phy_rssi_cal_nphy_rev3(pi); } else { wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB); @@ -21156,7 +21210,7 @@ static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type) rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4; rfctrlintc_override_val = - CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110; + CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110; rfctrlintc_state[0] = read_phy_reg(pi, 0x91); rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX); @@ -21169,19 +21223,19 @@ static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type) write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val); pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD | - RADIO_2055_WBRSSI_G2_PD; + RADIO_2055_WBRSSI_G2_PD; pd_state[0] = - read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask; + read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask; pd_state[1] = - read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask; + read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask; mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0); mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0); rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL | - RADIO_2055_WBRSSI_G2_SEL; + RADIO_2055_WBRSSI_G2_SEL; rssi_ctrl_state[0] = - read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask; + read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask; rssi_ctrl_state[1] = - read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask; + read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask; wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type); wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX, @@ -21192,18 +21246,20 @@ static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type) for (vcm = 0; vcm < 4; vcm++) { vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm; - if (rssi_type != NPHY_RSSI_SEL_W2) + if (rssi_type != NPHY_RSSI_SEL_W2) { wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp); + } wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0], NPHY_RSSICAL_NPOLL); if ((rssi_type == NPHY_RSSI_SEL_W1) || (rssi_type == NPHY_RSSI_SEL_W2)) { - for (ctr = 0; ctr < 2; ctr++) + for (ctr = 0; ctr < 2; ctr++) { poll_miniq[vcm][ctr] = - min(poll_results[vcm][ctr * 2 + 0], - poll_results[vcm][ctr * 2 + 1]); + min(poll_results[vcm][ctr * 2 + 0], + poll_results[vcm][ctr * 2 + 1]); + } } } @@ -21220,38 +21276,41 @@ static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type) min_d = curr_d; min_vcm = vcm; } - if (poll_results[vcm][result_idx] < min_poll) + if (poll_results[vcm][result_idx] < min_poll) { min_poll = poll_results[vcm][result_idx]; + } } vcm_final[result_idx] = min_vcm; poll_results_min[result_idx] = min_poll; } - if (rssi_type != NPHY_RSSI_SEL_W2) + if (rssi_type != NPHY_RSSI_SEL_W2) { wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final); + } for (result_idx = 0; result_idx < 4; result_idx++) { fine_digital_offset[result_idx] = - (target_code * NPHY_RSSICAL_NPOLL) - - poll_results[vcm_final[result_idx]][result_idx]; + (target_code * NPHY_RSSICAL_NPOLL) - + poll_results[vcm_final[result_idx]][result_idx]; if (fine_digital_offset[result_idx] < 0) { fine_digital_offset[result_idx] = - ABS(fine_digital_offset[result_idx]); + ABS(fine_digital_offset[result_idx]); fine_digital_offset[result_idx] += - (NPHY_RSSICAL_NPOLL / 2); + (NPHY_RSSICAL_NPOLL / 2); fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL; fine_digital_offset[result_idx] = - -fine_digital_offset[result_idx]; + -fine_digital_offset[result_idx]; } else { fine_digital_offset[result_idx] += - (NPHY_RSSICAL_NPOLL / 2); + (NPHY_RSSICAL_NPOLL / 2); fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL; } if (poll_results_min[result_idx] == - NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) + NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) { fine_digital_offset[result_idx] = - (target_code - NPHY_RSSICAL_MAXREAD - 1); + (target_code - NPHY_RSSICAL_MAXREAD - 1); + } wlc_phy_scale_offset_rssi_nphy(pi, 0x0, (s8) @@ -21266,30 +21325,32 @@ static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type) mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]); mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]); - if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) + if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) { wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, NPHY_RSSI_SEL_NB); - else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) + } else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) { wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, NPHY_RSSI_SEL_W1); - else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) + } else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) { wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, NPHY_RSSI_SEL_W2); - else + } else { wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, NPHY_RSSI_SEL_W2); - if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) + } + if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) { wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, NPHY_RSSI_SEL_NB); - else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) + } else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) { wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, NPHY_RSSI_SEL_W1); - else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) + } else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) { wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, NPHY_RSSI_SEL_W2); - else + } else { wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, NPHY_RSSI_SEL_W2); + } wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type); @@ -21400,8 +21461,8 @@ wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value, } else { mask = (0x1 << 6) | - (0x1 << 7) | - (0x1 << 8) | (0x1 << 9); + (0x1 << 7) | + (0x1 << 8) | (0x1 << 9); val = value << 6; mod_phy_reg(pi, (core == @@ -21415,8 +21476,8 @@ wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value, PHY_CORE_0) ? 0xe7 : 0xec, mask, val); - mask = (core == PHY_CORE_0) ? - (0x1 << 0) : (0x1 << 1); + mask = (core == PHY_CORE_0) ? (0x1 << 0) + : (0x1 << 1); val = 1 << ((core == PHY_CORE_0) ? 0 : 1); mod_phy_reg(pi, 0x78, mask, val); @@ -21424,7 +21485,7 @@ wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value, SPINWAIT(((read_phy_reg(pi, 0x78) & val) != 0), 10000); if (WARN(read_phy_reg(pi, 0x78) & val, - "HW error: override failed")) + "HW error: override failed")) return; mask = (0x1 << 0); @@ -21439,10 +21500,11 @@ wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value, mask = (0x1 << 4) | (0x1 << 5); - if (CHSPEC_IS5G(pi->radio_chanspec)) + if (CHSPEC_IS5G(pi->radio_chanspec)) { val = value << 5; - else + } else { val = value << 4; + } mod_phy_reg(pi, (core == @@ -21467,8 +21529,7 @@ wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value, PHY_CORE_0) ? 0x91 : 0x92, mask, val); } - } else if (field == - NPHY_RfctrlIntc_override_EXT_LNA_PU) { + } else if (field == NPHY_RfctrlIntc_override_EXT_LNA_PU) { if (NREV_GE(pi->pubpi.phy_rev, 7)) { if (CHSPEC_IS5G(pi->radio_chanspec)) { @@ -21575,6 +21636,8 @@ wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value, } } } + } else { + return; } } @@ -21620,14 +21683,10 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save; u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save; - NPHY_REV7_RfctrlOverride3_save = - NPHY_REV7_RfctrlOverride4_save = - NPHY_REV7_RfctrlOverride5_save = - NPHY_REV7_RfctrlOverride6_save = - NPHY_REV7_RfctrlMiscReg3_save = - NPHY_REV7_RfctrlMiscReg4_save = - NPHY_REV7_RfctrlMiscReg5_save = - NPHY_REV7_RfctrlMiscReg6_save = 0; + NPHY_REV7_RfctrlOverride3_save = NPHY_REV7_RfctrlOverride4_save = + NPHY_REV7_RfctrlOverride5_save = NPHY_REV7_RfctrlOverride6_save = + NPHY_REV7_RfctrlMiscReg3_save = NPHY_REV7_RfctrlMiscReg4_save = + NPHY_REV7_RfctrlMiscReg5_save = NPHY_REV7_RfctrlMiscReg6_save = 0; classif_state = wlc_phy_classifier_nphy(pi, 0, 0); wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); @@ -21667,21 +21726,21 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1, RADIO_MIMO_CORESEL_ALLRXTX); - if (NREV_GE(pi->pubpi.phy_rev, 7)) - wlc_phy_rfctrl_override_1tomany_nphy( - pi, - NPHY_REV7_RfctrlOverride_cmd_rxrf_pu, - 0, 0, 0); - else + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + wlc_phy_rfctrl_override_1tomany_nphy(pi, + NPHY_REV7_RfctrlOverride_cmd_rxrf_pu, + 0, 0, 0); + } else { wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0); + } - if (NREV_GE(pi->pubpi.phy_rev, 7)) - wlc_phy_rfctrl_override_1tomany_nphy( - pi, - NPHY_REV7_RfctrlOverride_cmd_rx_pu, - 1, 0, 0); - else + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + wlc_phy_rfctrl_override_1tomany_nphy(pi, + NPHY_REV7_RfctrlOverride_cmd_rx_pu, + 1, 0, 0); + } else { wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0); + } if (NREV_GE(pi->pubpi.phy_rev, 7)) { wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), @@ -21696,14 +21755,12 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) if (CHSPEC_IS5G(pi->radio_chanspec)) { if (NREV_GE(pi->pubpi.phy_rev, 7)) { - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 5), - 0, 0, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID0); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 4), 1, 0, - 0, - NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), + 0, 0, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0, + 0, + NPHY_REV7_RFCTRLOVERRIDE_ID0); } else { wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0); wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0); @@ -21711,14 +21768,12 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) } else { if (NREV_GE(pi->pubpi.phy_rev, 7)) { - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 4), - 0, 0, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID0); - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 5), 1, 0, - 0, - NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), + 0, 0, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 1, 0, + 0, + NPHY_REV7_RFCTRLOVERRIDE_ID0); } else { wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0); wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0); @@ -21726,7 +21781,7 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) } rxcore_state = wlc_phy_rxcore_getstate_nphy( - (struct brcms_phy_pub *) pi); + (struct brcms_phy_pub *) pi); vcm_level_max = 8; @@ -21749,18 +21804,21 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) NPHY_RAIL_Q, NPHY_RSSI_SEL_NB); for (vcm = 0; vcm < vcm_level_max; vcm++) { - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + mod_radio_reg(pi, (core == PHY_CORE_0) ? RADIO_2057_NB_MASTER_CORE0 : RADIO_2057_NB_MASTER_CORE1, RADIO_2057_VCM_MASK, vcm); - else + } else { + mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC | ((core == PHY_CORE_0) ? RADIO_2056_RX0 : RADIO_2056_RX1), RADIO_2056_VCM_MASK, vcm << RADIO_2056_RSSI_VCM_SHIFT); + } wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB, &poll_results[vcm][0], @@ -21768,90 +21826,92 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) } for (result_idx = 0; result_idx < 4; result_idx++) { - if ((core == result_idx / 2) && - (result_idx % 2 == 0)) { + if ((core == result_idx / 2) && (result_idx % 2 == 0)) { min_d = NPHY_RSSICAL_MAXD; min_vcm = 0; min_poll = - NPHY_RSSICAL_MAXREAD * - NPHY_RSSICAL_NPOLL + 1; + NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + + 1; for (vcm = 0; vcm < vcm_level_max; vcm++) { - curr_d = - poll_results[vcm][result_idx] * - poll_results[vcm][result_idx] + - poll_results[vcm][result_idx + - 1] * - poll_results[vcm][result_idx + - 1]; + curr_d = poll_results[vcm][result_idx] * + poll_results[vcm][result_idx] + + poll_results[vcm][result_idx + 1] * + poll_results[vcm][result_idx + 1]; if (curr_d < min_d) { min_d = curr_d; min_vcm = vcm; } if (poll_results[vcm][result_idx] < - min_poll) + min_poll) { min_poll = - poll_results[vcm] - [result_idx]; + poll_results[vcm] + [result_idx]; + } } vcm_final = min_vcm; poll_results_min[result_idx] = min_poll; } } - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { mod_radio_reg(pi, (core == PHY_CORE_0) ? RADIO_2057_NB_MASTER_CORE0 : RADIO_2057_NB_MASTER_CORE1, RADIO_2057_VCM_MASK, vcm_final); - else + } else { mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC | ((core == PHY_CORE_0) ? RADIO_2056_RX0 : RADIO_2056_RX1), RADIO_2056_VCM_MASK, vcm_final << RADIO_2056_RSSI_VCM_SHIFT); + } for (result_idx = 0; result_idx < 4; result_idx++) { if (core == result_idx / 2) { fine_digital_offset[result_idx] = - (NPHY_RSSICAL_NB_TARGET * - NPHY_RSSICAL_NPOLL) - - poll_results[vcm_final][result_idx]; + (NPHY_RSSICAL_NB_TARGET * + NPHY_RSSICAL_NPOLL) - + poll_results[vcm_final][result_idx]; if (fine_digital_offset[result_idx] < 0) { fine_digital_offset[result_idx] = - ABS(fine_digital_offset - [result_idx]); + ABS(fine_digital_offset + [result_idx]); fine_digital_offset[result_idx] += - (NPHY_RSSICAL_NPOLL / 2); + (NPHY_RSSICAL_NPOLL / 2); fine_digital_offset[result_idx] /= - NPHY_RSSICAL_NPOLL; + NPHY_RSSICAL_NPOLL; fine_digital_offset[result_idx] = - -fine_digital_offset[ - result_idx]; + -fine_digital_offset[result_idx]; } else { fine_digital_offset[result_idx] += - (NPHY_RSSICAL_NPOLL / 2); + (NPHY_RSSICAL_NPOLL / 2); fine_digital_offset[result_idx] /= - NPHY_RSSICAL_NPOLL; + NPHY_RSSICAL_NPOLL; } if (poll_results_min[result_idx] == - NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) + NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) { fine_digital_offset[result_idx] = - (NPHY_RSSICAL_NB_TARGET - - NPHY_RSSICAL_MAXREAD - 1); - - wlc_phy_scale_offset_rssi_nphy( - pi, 0x0, - (s8) - fine_digital_offset - [result_idx], - (result_idx / 2 == 0) ? - RADIO_MIMO_CORESEL_CORE1 : - RADIO_MIMO_CORESEL_CORE2, - (result_idx % 2 == 0) ? - NPHY_RAIL_I : NPHY_RAIL_Q, - NPHY_RSSI_SEL_NB); + (NPHY_RSSICAL_NB_TARGET - + NPHY_RSSICAL_MAXREAD - 1); + } + + wlc_phy_scale_offset_rssi_nphy(pi, 0x0, + (s8) + fine_digital_offset + [result_idx], + (result_idx / + 2 == + 0) ? + RADIO_MIMO_CORESEL_CORE1 + : + RADIO_MIMO_CORESEL_CORE2, + (result_idx % + 2 == + 0) ? NPHY_RAIL_I + : NPHY_RAIL_Q, + NPHY_RSSI_SEL_NB); } } @@ -21892,44 +21952,46 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) for (result_idx = 0; result_idx < 4; result_idx++) { if (core == result_idx / 2) { fine_digital_offset[result_idx] = - (target_code * - NPHY_RSSICAL_NPOLL) - - poll_result_core[result_idx]; - if (fine_digital_offset[result_idx] < - 0) { + (target_code * NPHY_RSSICAL_NPOLL) - + poll_result_core[result_idx]; + if (fine_digital_offset[result_idx] < 0) { fine_digital_offset[result_idx] - = ABS( - fine_digital_offset - [result_idx]); + = + ABS(fine_digital_offset + [result_idx]); fine_digital_offset[result_idx] - += (NPHY_RSSICAL_NPOLL - / 2); + += (NPHY_RSSICAL_NPOLL / 2); fine_digital_offset[result_idx] - /= NPHY_RSSICAL_NPOLL; + /= NPHY_RSSICAL_NPOLL; fine_digital_offset[result_idx] - = -fine_digital_offset - [result_idx]; + = + -fine_digital_offset + [result_idx]; } else { fine_digital_offset[result_idx] - += (NPHY_RSSICAL_NPOLL - / 2); + += (NPHY_RSSICAL_NPOLL / 2); fine_digital_offset[result_idx] - /= NPHY_RSSICAL_NPOLL; + /= NPHY_RSSICAL_NPOLL; } - wlc_phy_scale_offset_rssi_nphy( - pi, 0x0, - (s8) - fine_digital_offset - [core * - 2], - (core == PHY_CORE_0) ? - RADIO_MIMO_CORESEL_CORE1 : - RADIO_MIMO_CORESEL_CORE2, - (result_idx % 2 == 0) ? - NPHY_RAIL_I : - NPHY_RAIL_Q, - rssi_type); + wlc_phy_scale_offset_rssi_nphy(pi, 0x0, + (s8) + fine_digital_offset + [core * + 2], + (core == + PHY_CORE_0) + ? + RADIO_MIMO_CORESEL_CORE1 + : + RADIO_MIMO_CORESEL_CORE2, + (result_idx + % 2 == + 0) ? + NPHY_RAIL_I + : + NPHY_RAIL_Q, + rssi_type); } } @@ -21978,87 +22040,87 @@ static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) if (CHSPEC_IS2G(pi->radio_chanspec)) { if (NREV_GE(pi->pubpi.phy_rev, 7)) { pi->rssical_cache.rssical_radio_regs_2G[0] = - read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); + read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); pi->rssical_cache.rssical_radio_regs_2G[1] = - read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); + read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); } else { pi->rssical_cache.rssical_radio_regs_2G[0] = - read_radio_reg(pi, - RADIO_2056_RX_RSSI_MISC | - RADIO_2056_RX0); + read_radio_reg(pi, + RADIO_2056_RX_RSSI_MISC | + RADIO_2056_RX0); pi->rssical_cache.rssical_radio_regs_2G[1] = - read_radio_reg(pi, - RADIO_2056_RX_RSSI_MISC | - RADIO_2056_RX1); + read_radio_reg(pi, + RADIO_2056_RX_RSSI_MISC | + RADIO_2056_RX1); } pi->rssical_cache.rssical_phyregs_2G[0] = - read_phy_reg(pi, 0x1a6); + read_phy_reg(pi, 0x1a6); pi->rssical_cache.rssical_phyregs_2G[1] = - read_phy_reg(pi, 0x1ac); + read_phy_reg(pi, 0x1ac); pi->rssical_cache.rssical_phyregs_2G[2] = - read_phy_reg(pi, 0x1b2); + read_phy_reg(pi, 0x1b2); pi->rssical_cache.rssical_phyregs_2G[3] = - read_phy_reg(pi, 0x1b8); + read_phy_reg(pi, 0x1b8); pi->rssical_cache.rssical_phyregs_2G[4] = - read_phy_reg(pi, 0x1a4); + read_phy_reg(pi, 0x1a4); pi->rssical_cache.rssical_phyregs_2G[5] = - read_phy_reg(pi, 0x1aa); + read_phy_reg(pi, 0x1aa); pi->rssical_cache.rssical_phyregs_2G[6] = - read_phy_reg(pi, 0x1b0); + read_phy_reg(pi, 0x1b0); pi->rssical_cache.rssical_phyregs_2G[7] = - read_phy_reg(pi, 0x1b6); + read_phy_reg(pi, 0x1b6); pi->rssical_cache.rssical_phyregs_2G[8] = - read_phy_reg(pi, 0x1a5); + read_phy_reg(pi, 0x1a5); pi->rssical_cache.rssical_phyregs_2G[9] = - read_phy_reg(pi, 0x1ab); + read_phy_reg(pi, 0x1ab); pi->rssical_cache.rssical_phyregs_2G[10] = - read_phy_reg(pi, 0x1b1); + read_phy_reg(pi, 0x1b1); pi->rssical_cache.rssical_phyregs_2G[11] = - read_phy_reg(pi, 0x1b7); + read_phy_reg(pi, 0x1b7); pi->nphy_rssical_chanspec_2G = pi->radio_chanspec; } else { if (NREV_GE(pi->pubpi.phy_rev, 7)) { pi->rssical_cache.rssical_radio_regs_5G[0] = - read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); + read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); pi->rssical_cache.rssical_radio_regs_5G[1] = - read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); + read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); } else { pi->rssical_cache.rssical_radio_regs_5G[0] = - read_radio_reg(pi, - RADIO_2056_RX_RSSI_MISC | - RADIO_2056_RX0); + read_radio_reg(pi, + RADIO_2056_RX_RSSI_MISC | + RADIO_2056_RX0); pi->rssical_cache.rssical_radio_regs_5G[1] = - read_radio_reg(pi, - RADIO_2056_RX_RSSI_MISC | - RADIO_2056_RX1); + read_radio_reg(pi, + RADIO_2056_RX_RSSI_MISC | + RADIO_2056_RX1); } pi->rssical_cache.rssical_phyregs_5G[0] = - read_phy_reg(pi, 0x1a6); + read_phy_reg(pi, 0x1a6); pi->rssical_cache.rssical_phyregs_5G[1] = - read_phy_reg(pi, 0x1ac); + read_phy_reg(pi, 0x1ac); pi->rssical_cache.rssical_phyregs_5G[2] = - read_phy_reg(pi, 0x1b2); + read_phy_reg(pi, 0x1b2); pi->rssical_cache.rssical_phyregs_5G[3] = - read_phy_reg(pi, 0x1b8); + read_phy_reg(pi, 0x1b8); pi->rssical_cache.rssical_phyregs_5G[4] = - read_phy_reg(pi, 0x1a4); + read_phy_reg(pi, 0x1a4); pi->rssical_cache.rssical_phyregs_5G[5] = - read_phy_reg(pi, 0x1aa); + read_phy_reg(pi, 0x1aa); pi->rssical_cache.rssical_phyregs_5G[6] = - read_phy_reg(pi, 0x1b0); + read_phy_reg(pi, 0x1b0); pi->rssical_cache.rssical_phyregs_5G[7] = - read_phy_reg(pi, 0x1b6); + read_phy_reg(pi, 0x1b6); pi->rssical_cache.rssical_phyregs_5G[8] = - read_phy_reg(pi, 0x1a5); + read_phy_reg(pi, 0x1a5); pi->rssical_cache.rssical_phyregs_5G[9] = - read_phy_reg(pi, 0x1ab); + read_phy_reg(pi, 0x1ab); pi->rssical_cache.rssical_phyregs_5G[10] = - read_phy_reg(pi, 0x1b1); + read_phy_reg(pi, 0x1b1); pi->rssical_cache.rssical_phyregs_5G[11] = - read_phy_reg(pi, 0x1b7); + read_phy_reg(pi, 0x1b7); pi->nphy_rssical_chanspec_5G = pi->radio_chanspec; } @@ -22179,9 +22241,9 @@ wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, { u8 phy_bw, is_phybw40; u16 num_samps, t, spur; - s32 theta = 0, rot = 0; + fixed theta = 0, rot = 0; u32 tbl_len; - struct cordic_iq *tone_buf = NULL; + cs32 *tone_buf = NULL; is_phybw40 = CHSPEC_IS40(pi->radio_chanspec); phy_bw = (is_phybw40 == 1) ? 40 : 20; @@ -22196,17 +22258,18 @@ wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, tbl_len = (phy_bw << 1); } - tone_buf = kmalloc(sizeof(struct cordic_iq) * tbl_len, GFP_ATOMIC); - if (tone_buf == NULL) + tone_buf = kmalloc(sizeof(cs32) * tbl_len, GFP_ATOMIC); + if (tone_buf == NULL) { return 0; + } num_samps = (u16) tbl_len; - rot = ((f_kHz * 36) / phy_bw) / 100; + rot = FIXED((f_kHz * 36) / phy_bw) / 100; theta = 0; for (t = 0; t < num_samps; t++) { - tone_buf[t] = cordic_calc_iq(theta); + wlc_phy_cordic(theta, &tone_buf[t]); theta += rot; @@ -22229,10 +22292,11 @@ wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, u16 loops = 0xffff; u16 wait = 0; - num_samps = wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, - dac_test_mode); - if (num_samps == 0) + num_samps = + wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, dac_test_mode); + if (num_samps == 0) { return -EBADE; + } wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode, dac_test_mode, modify_bbmult); @@ -22241,22 +22305,24 @@ wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, } static void -wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, struct cordic_iq *tone_buf, +wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, cs32 *tone_buf, u16 num_samps) { u16 t; u32 *data_buf = NULL; data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC); - if (data_buf == NULL) + if (data_buf == NULL) { return; + } if (pi->phyhang_avoid) wlc_phy_stay_in_carriersearch_nphy(pi, true); - for (t = 0; t < num_samps; t++) + for (t = 0; t < num_samps; t++) { data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) | - (((unsigned int)tone_buf[t].q) & 0x3ff); + (((unsigned int)tone_buf[t].q) & 0x3ff); + } wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32, data_buf); @@ -22290,24 +22356,22 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops, lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7); if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) { lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) & - (0x7 << 8); + (0x7 << 8); lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) & - (0x7 << 8); + (0x7 << 8); } else { - wlc_phy_rfctrl_override_nphy_rev7( - pi, - (0x1 << 7), - wlc_phy_read_lpf_bw_ctl_nphy - (pi, - 0), 0, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, + (0x1 << 7), + wlc_phy_read_lpf_bw_ctl_nphy + (pi, 0), 0, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID1); pi->nphy_sample_play_lpf_bw_ctl_ovr = true; lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) & - (0x7 << 8); + (0x7 << 8); lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) & - (0x7 << 8); + (0x7 << 8); } } @@ -22316,7 +22380,7 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops, wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, &bb_mult); pi->nphy_bb_mult_save = - BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK); + BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK); } if (modify_bbmult) { @@ -22331,11 +22395,11 @@ wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops, write_phy_reg(pi, 0xc6, num_samps - 1); - if (loops != 0xffff) + if (loops != 0xffff) { write_phy_reg(pi, 0xc4, loops - 1); - else + } else { write_phy_reg(pi, 0xc4, loops); - + } write_phy_reg(pi, 0xc5, wait); orig_RfseqCoreActv = read_phy_reg(pi, 0xa1); @@ -22365,11 +22429,13 @@ void wlc_phy_stopplayback_nphy(struct brcms_phy *pi) wlc_phy_stay_in_carriersearch_nphy(pi, true); playback_status = read_phy_reg(pi, 0xc7); - if (playback_status & 0x1) + if (playback_status & 0x1) { or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP); - else if (playback_status & 0x2) + } else if (playback_status & 0x2) { + and_phy_reg(pi, 0xc2, (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN); + } and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2)); @@ -22384,11 +22450,10 @@ void wlc_phy_stopplayback_nphy(struct brcms_phy *pi) if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) { if (pi->nphy_sample_play_lpf_bw_ctl_ovr) { - wlc_phy_rfctrl_override_nphy_rev7( - pi, - (0x1 << 7), - 0, 0, 1, - NPHY_REV7_RFCTRLOVERRIDE_ID1); + wlc_phy_rfctrl_override_nphy_rev7(pi, + (0x1 << 7), + 0, 0, 1, + NPHY_REV7_RFCTRLOVERRIDE_ID1); pi->nphy_sample_play_lpf_bw_ctl_ovr = false; } } @@ -22397,47 +22462,6 @@ void wlc_phy_stopplayback_nphy(struct brcms_phy *pi) wlc_phy_stay_in_carriersearch_nphy(pi, false); } -static u32 *brcms_phy_get_tx_pwrctrl_tbl(struct brcms_phy *pi) -{ - u32 *tx_pwrctrl_tbl = NULL; - uint phyrev = pi->pubpi.phy_rev; - - if (PHY_IPA(pi)) { - tx_pwrctrl_tbl = - wlc_phy_get_ipa_gaintbl_nphy(pi); - } else { - if (CHSPEC_IS5G(pi->radio_chanspec)) { - if (NREV_IS(phyrev, 3)) - tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev3; - else if (NREV_IS(phyrev, 4)) - tx_pwrctrl_tbl = - (pi->srom_fem5g.extpagain == 3) ? - nphy_tpc_5GHz_txgain_HiPwrEPA : - nphy_tpc_5GHz_txgain_rev4; - else - tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev5; - } else { - if (NREV_GE(phyrev, 7)) { - if (pi->pubpi.radiorev == 3) - tx_pwrctrl_tbl = - nphy_tpc_txgain_epa_2057rev3; - else if (pi->pubpi.radiorev == 5) - tx_pwrctrl_tbl = - nphy_tpc_txgain_epa_2057rev5; - } else { - if (NREV_GE(phyrev, 5) && - (pi->srom_fem2g.extpagain == 3)) - tx_pwrctrl_tbl = - nphy_tpc_txgain_HiPwrEPA; - else - tx_pwrctrl_tbl = - nphy_tpc_txgain_rev3; - } - } - } - return tx_pwrctrl_tbl; -} - struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi) { u16 base_idx[2], curr_gain[2]; @@ -22458,33 +22482,33 @@ struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi) for (core_no = 0; core_no < 2; core_no++) { if (NREV_GE(pi->pubpi.phy_rev, 7)) { target_gain.ipa[core_no] = - curr_gain[core_no] & 0x0007; + curr_gain[core_no] & 0x0007; target_gain.pad[core_no] = - ((curr_gain[core_no] & 0x00F8) >> 3); + ((curr_gain[core_no] & 0x00F8) >> 3); target_gain.pga[core_no] = - ((curr_gain[core_no] & 0x0F00) >> 8); + ((curr_gain[core_no] & 0x0F00) >> 8); target_gain.txgm[core_no] = - ((curr_gain[core_no] & 0x7000) >> 12); + ((curr_gain[core_no] & 0x7000) >> 12); target_gain.txlpf[core_no] = - ((curr_gain[core_no] & 0x8000) >> 15); + ((curr_gain[core_no] & 0x8000) >> 15); } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { target_gain.ipa[core_no] = - curr_gain[core_no] & 0x000F; + curr_gain[core_no] & 0x000F; target_gain.pad[core_no] = - ((curr_gain[core_no] & 0x00F0) >> 4); + ((curr_gain[core_no] & 0x00F0) >> 4); target_gain.pga[core_no] = - ((curr_gain[core_no] & 0x0F00) >> 8); + ((curr_gain[core_no] & 0x0F00) >> 8); target_gain.txgm[core_no] = - ((curr_gain[core_no] & 0x7000) >> 12); + ((curr_gain[core_no] & 0x7000) >> 12); } else { target_gain.ipa[core_no] = - curr_gain[core_no] & 0x0003; + curr_gain[core_no] & 0x0003; target_gain.pad[core_no] = - ((curr_gain[core_no] & 0x000C) >> 2); + ((curr_gain[core_no] & 0x000C) >> 2); target_gain.pga[core_no] = - ((curr_gain[core_no] & 0x0070) >> 4); + ((curr_gain[core_no] & 0x0070) >> 4); target_gain.txgm[core_no] = - ((curr_gain[core_no] & 0x0380) >> 7); + ((curr_gain[core_no] & 0x0380) >> 7); } } } else { @@ -22494,60 +22518,96 @@ struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi) base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f; for (core_no = 0; core_no < 2; core_no++) { if (NREV_GE(phyrev, 3)) { - tx_pwrctrl_tbl = - brcms_phy_get_tx_pwrctrl_tbl(pi); + if (PHY_IPA(pi)) { + tx_pwrctrl_tbl = + wlc_phy_get_ipa_gaintbl_nphy(pi); + } else { + if (CHSPEC_IS5G(pi->radio_chanspec)) { + if (NREV_IS(phyrev, 3)) { + tx_pwrctrl_tbl = + nphy_tpc_5GHz_txgain_rev3; + } else if (NREV_IS(phyrev, 4)) { + tx_pwrctrl_tbl = + (pi->srom_fem5g. + extpagain == + 3) ? + nphy_tpc_5GHz_txgain_HiPwrEPA + : + nphy_tpc_5GHz_txgain_rev4; + } else { + tx_pwrctrl_tbl = + nphy_tpc_5GHz_txgain_rev5; + } + } else { + if (NREV_GE(phyrev, 7)) { + if (pi->pubpi. + radiorev == 3) { + tx_pwrctrl_tbl = + nphy_tpc_txgain_epa_2057rev3; + } else if (pi->pubpi. + radiorev == + 5) { + tx_pwrctrl_tbl = + nphy_tpc_txgain_epa_2057rev5; + } + + } else { + if (NREV_GE(phyrev, 5) + && (pi->srom_fem2g. + extpagain == + 3)) { + tx_pwrctrl_tbl = + nphy_tpc_txgain_HiPwrEPA; + } else { + tx_pwrctrl_tbl = + nphy_tpc_txgain_rev3; + } + } + } + } if (NREV_GE(phyrev, 7)) { target_gain.ipa[core_no] = - (tx_pwrctrl_tbl - [base_idx[core_no]] - >> 16) & 0x7; + (tx_pwrctrl_tbl[base_idx[core_no]] + >> 16) & 0x7; target_gain.pad[core_no] = - (tx_pwrctrl_tbl - [base_idx[core_no]] - >> 19) & 0x1f; + (tx_pwrctrl_tbl[base_idx[core_no]] + >> 19) & 0x1f; target_gain.pga[core_no] = - (tx_pwrctrl_tbl - [base_idx[core_no]] - >> 24) & 0xf; + (tx_pwrctrl_tbl[base_idx[core_no]] + >> 24) & 0xf; target_gain.txgm[core_no] = - (tx_pwrctrl_tbl - [base_idx[core_no]] - >> 28) & 0x7; + (tx_pwrctrl_tbl[base_idx[core_no]] + >> 28) & 0x7; target_gain.txlpf[core_no] = - (tx_pwrctrl_tbl - [base_idx[core_no]] - >> 31) & 0x1; + (tx_pwrctrl_tbl[base_idx[core_no]] + >> 31) & 0x1; } else { target_gain.ipa[core_no] = - (tx_pwrctrl_tbl - [base_idx[core_no]] - >> 16) & 0xf; + (tx_pwrctrl_tbl[base_idx[core_no]] + >> 16) & 0xf; target_gain.pad[core_no] = - (tx_pwrctrl_tbl - [base_idx[core_no]] - >> 20) & 0xf; + (tx_pwrctrl_tbl[base_idx[core_no]] + >> 20) & 0xf; target_gain.pga[core_no] = - (tx_pwrctrl_tbl - [base_idx[core_no]] - >> 24) & 0xf; + (tx_pwrctrl_tbl[base_idx[core_no]] + >> 24) & 0xf; target_gain.txgm[core_no] = - (tx_pwrctrl_tbl - [base_idx[core_no]] - >> 28) & 0x7; + (tx_pwrctrl_tbl[base_idx[core_no]] + >> 28) & 0x7; } } else { target_gain.ipa[core_no] = - (nphy_tpc_txgain[base_idx[core_no]] >> - 16) & 0x3; + (nphy_tpc_txgain[base_idx[core_no]] >> 16) & + 0x3; target_gain.pad[core_no] = - (nphy_tpc_txgain[base_idx[core_no]] >> - 18) & 0x3; + (nphy_tpc_txgain[base_idx[core_no]] >> 18) & + 0x3; target_gain.pga[core_no] = - (nphy_tpc_txgain[base_idx[core_no]] >> - 20) & 0x7; + (nphy_tpc_txgain[base_idx[core_no]] >> 20) & + 0x7; target_gain.txgm[core_no] = - (nphy_tpc_txgain[base_idx[core_no]] >> - 23) & 0x7; + (nphy_tpc_txgain[base_idx[core_no]] >> 23) & + 0x7; } } } @@ -22566,23 +22626,26 @@ wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no, u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0); if (NREV_GE(pi->pubpi.phy_rev, 3)) { - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { params->txlpf = target_gain.txlpf[core_no]; - + } params->txgm = target_gain.txgm[core_no]; params->pga = target_gain.pga[core_no]; params->pad = target_gain.pad[core_no]; params->ipa = target_gain.ipa[core_no]; - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { params->cal_gain = - ((params->txlpf << 15) | (params->txgm << 12) | - (params->pga << 8) | - (params->pad << 3) | (params->ipa)); - else + ((params->txlpf << 15) | (params-> + txgm << 12) | (params-> + pga << 8) | + (params->pad << 3) | (params->ipa)); + } else { params->cal_gain = - ((params->txgm << 12) | (params->pga << 8) | - (params->pad << 4) | (params->ipa)); - + ((params->txgm << 12) | (params-> + pga << 8) | (params-> + pad << 4) | + (params->ipa)); + } params->ncorr[0] = 0x79; params->ncorr[1] = 0x79; params->ncorr[2] = 0x79; @@ -22591,8 +22654,9 @@ wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no, } else { gain_index = ((target_gain.pad[core_no] << 0) | - (target_gain.pga[core_no] << 4) | - (target_gain.txgm[core_no] << 8)); + (target_gain.pga[core_no] << 4) | (target_gain. + txgm[core_no] + << 8)); idx = -1; for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) { @@ -22624,39 +22688,37 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) for (core = 0; core <= 1; core++) { pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - TX_SSI_MASTER); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + TX_SSI_MASTER); pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - IQCAL_VCM_HG); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + IQCAL_VCM_HG); pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - IQCAL_IDAC); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + IQCAL_IDAC); pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - TSSI_VCM); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM); pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0; pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - TX_SSI_MUX); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + TX_SSI_MUX); if (pi->pubpi.radiorev != 5) pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] = - READ_RADIO_REG3(pi, RADIO_2057, TX, - core, - TSSIA); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + TSSIA); pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG); pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - TSSI_MISC1); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + TSSI_MISC1); if (CHSPEC_IS5G(pi->radio_chanspec)) { WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, @@ -22672,15 +22734,19 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) if (pi->use_int_tx_iqlo_cal_nphy) { WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX, 0x4); - if (!(pi-> - internal_tx_iqlo_cal_tapoff_intpa_nphy)) + if (! + (pi-> + internal_tx_iqlo_cal_tapoff_intpa_nphy)) { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIA, 0x31); - else + } else { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIA, 0x21); + } } WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1, 0x00); @@ -22701,15 +22767,19 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX, 0x06); - if (!(pi-> - internal_tx_iqlo_cal_tapoff_intpa_nphy)) + if (! + (pi-> + internal_tx_iqlo_cal_tapoff_intpa_nphy)) { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG, 0x31); - else + } else { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG, 0x21); + } } WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1, 0x00); @@ -22719,62 +22789,58 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) for (core = 0; core <= 1; core++) { jtag_core = - (core == - PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1; + (core == + PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1; pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] = - read_radio_reg(pi, - RADIO_2056_TX_TX_SSI_MASTER | - jtag_core); + read_radio_reg(pi, + RADIO_2056_TX_TX_SSI_MASTER | + jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] = - read_radio_reg(pi, - RADIO_2056_TX_IQCAL_VCM_HG | - jtag_core); + read_radio_reg(pi, + RADIO_2056_TX_IQCAL_VCM_HG | + jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] = - read_radio_reg(pi, - RADIO_2056_TX_IQCAL_IDAC | - jtag_core); + read_radio_reg(pi, + RADIO_2056_TX_IQCAL_IDAC | + jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] = - read_radio_reg( - pi, - RADIO_2056_TX_TSSI_VCM | - jtag_core); + read_radio_reg(pi, + RADIO_2056_TX_TSSI_VCM | jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = - read_radio_reg(pi, - RADIO_2056_TX_TX_AMP_DET | - jtag_core); + read_radio_reg(pi, + RADIO_2056_TX_TX_AMP_DET | + jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] = - read_radio_reg(pi, - RADIO_2056_TX_TX_SSI_MUX | - jtag_core); + read_radio_reg(pi, + RADIO_2056_TX_TX_SSI_MUX | + jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] = - read_radio_reg(pi, - RADIO_2056_TX_TSSIA | jtag_core); + read_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] = - read_radio_reg(pi, - RADIO_2056_TX_TSSIG | jtag_core); + read_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] = - read_radio_reg(pi, - RADIO_2056_TX_TSSI_MISC1 | - jtag_core); + read_radio_reg(pi, + RADIO_2056_TX_TSSI_MISC1 | + jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] = - read_radio_reg(pi, - RADIO_2056_TX_TSSI_MISC2 | - jtag_core); + read_radio_reg(pi, + RADIO_2056_TX_TSSI_MISC2 | + jtag_core); pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] = - read_radio_reg(pi, - RADIO_2056_TX_TSSI_MISC3 | - jtag_core); + read_radio_reg(pi, + RADIO_2056_TX_TSSI_MISC3 | + jtag_core); if (CHSPEC_IS5G(pi->radio_chanspec)) { write_radio_reg(pi, @@ -22794,18 +22860,16 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) jtag_core, 0x00); if (PHY_IPA(pi)) { - write_radio_reg( - pi, - RADIO_2056_TX_TX_SSI_MUX - | jtag_core, 0x4); + write_radio_reg(pi, + RADIO_2056_TX_TX_SSI_MUX + | jtag_core, 0x4); write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core, 0x1); } else { - write_radio_reg( - pi, - RADIO_2056_TX_TX_SSI_MUX - | jtag_core, 0x00); + write_radio_reg(pi, + RADIO_2056_TX_TX_SSI_MUX + | jtag_core, 0x00); write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core, 0x2f); @@ -22845,27 +22909,26 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) if (PHY_IPA(pi)) { - write_radio_reg( - pi, - RADIO_2056_TX_TX_SSI_MUX - | jtag_core, 0x06); - if (NREV_LT(pi->pubpi.phy_rev, 5)) - write_radio_reg( - pi, - RADIO_2056_TX_TSSIG - | jtag_core, - 0x11); - else - write_radio_reg( - pi, - RADIO_2056_TX_TSSIG - | jtag_core, - 0x1); + write_radio_reg(pi, + RADIO_2056_TX_TX_SSI_MUX + | jtag_core, 0x06); + if (NREV_LT(pi->pubpi.phy_rev, 5)) { + + write_radio_reg(pi, + RADIO_2056_TX_TSSIG + | jtag_core, + 0x11); + } else { + + write_radio_reg(pi, + RADIO_2056_TX_TSSIG + | jtag_core, + 0x1); + } } else { - write_radio_reg( - pi, - RADIO_2056_TX_TX_SSI_MUX - | jtag_core, 0x00); + write_radio_reg(pi, + RADIO_2056_TX_TX_SSI_MUX + | jtag_core, 0x00); write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core, 0x20); @@ -22885,23 +22948,23 @@ static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) } else { pi->tx_rx_cal_radio_saveregs[0] = - read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); + read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29); pi->tx_rx_cal_radio_saveregs[1] = - read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); + read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54); pi->tx_rx_cal_radio_saveregs[2] = - read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); + read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29); pi->tx_rx_cal_radio_saveregs[3] = - read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); + read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54); pi->tx_rx_cal_radio_saveregs[4] = - read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); + read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); pi->tx_rx_cal_radio_saveregs[5] = - read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); + read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) == 0) { @@ -22962,8 +23025,11 @@ static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi) if (pi->pubpi.radiorev != 5) WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIA, - pi->tx_rx_cal_radio_saveregs - [(core * 11) + 6]); + pi-> + tx_rx_cal_radio_saveregs[(core + * + 11) + + 6]); WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG, pi-> @@ -22977,8 +23043,9 @@ static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi) } } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { for (core = 0; core <= 1; core++) { - jtag_core = (core == PHY_CORE_0) ? - RADIO_2056_TX0 : RADIO_2056_TX1; + jtag_core = + (core == + PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1; write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MASTER | jtag_core, @@ -23104,22 +23171,23 @@ static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi) pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91); pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92); - if (!(pi->use_int_tx_iqlo_cal_nphy)) - wlc_phy_rfctrlintc_override_nphy( - pi, - NPHY_RfctrlIntc_override_PA, - 1, - RADIO_MIMO_CORESEL_CORE1 - | - RADIO_MIMO_CORESEL_CORE2); - else - wlc_phy_rfctrlintc_override_nphy( - pi, - NPHY_RfctrlIntc_override_PA, - 0, - RADIO_MIMO_CORESEL_CORE1 - | - RADIO_MIMO_CORESEL_CORE2); + if (!(pi->use_int_tx_iqlo_cal_nphy)) { + + wlc_phy_rfctrlintc_override_nphy(pi, + NPHY_RfctrlIntc_override_PA, + 1, + RADIO_MIMO_CORESEL_CORE1 + | + RADIO_MIMO_CORESEL_CORE2); + } else { + + wlc_phy_rfctrlintc_override_nphy(pi, + NPHY_RfctrlIntc_override_PA, + 0, + RADIO_MIMO_CORESEL_CORE1 + | + RADIO_MIMO_CORESEL_CORE2); + } wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, @@ -23137,13 +23205,12 @@ static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi) 0x29b, (0x1 << 0), (0) << 0); if (NREV_IS(pi->pubpi.phy_rev, 7) - || NREV_GE(pi->pubpi.phy_rev, 8)) - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 7), - wlc_phy_read_lpf_bw_ctl_nphy - (pi, - 0), 0, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID1); + || NREV_GE(pi->pubpi.phy_rev, 8)) { + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), + wlc_phy_read_lpf_bw_ctl_nphy + (pi, 0), 0, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + } if (pi->use_int_tx_iqlo_cal_nphy && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) { @@ -23154,30 +23221,25 @@ static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi) 1 << 4); if (CHSPEC_IS2G(pi->radio_chanspec)) { - mod_radio_reg( - pi, - RADIO_2057_PAD2G_TUNE_PUS_CORE0, - 1, 0); - mod_radio_reg( - pi, - RADIO_2057_PAD2G_TUNE_PUS_CORE1, - 1, 0); + mod_radio_reg(pi, + RADIO_2057_PAD2G_TUNE_PUS_CORE0, + 1, 0); + mod_radio_reg(pi, + RADIO_2057_PAD2G_TUNE_PUS_CORE1, + 1, 0); } else { - mod_radio_reg( - pi, - RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, - 1, 0); - mod_radio_reg( - pi, - RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, - 1, 0); + mod_radio_reg(pi, + RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, + 1, 0); + mod_radio_reg(pi, + RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, + 1, 0); } } else if (NREV_GE(pi->pubpi.phy_rev, 8)) { - wlc_phy_rfctrl_override_nphy_rev7( - pi, - (0x1 << 3), 0, - 0x3, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, + (0x1 << 3), 0, + 0x3, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID0); } } } else { @@ -23240,11 +23302,11 @@ static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi) write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]); if (NREV_IS(pi->pubpi.phy_rev, 7) - || NREV_GE(pi->pubpi.phy_rev, 8)) - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 7), 0, 0, - 1, - NPHY_REV7_RFCTRLOVERRIDE_ID1); + || NREV_GE(pi->pubpi.phy_rev, 8)) { + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0, + 1, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + } wlc_phy_resetcca_nphy(pi); @@ -23253,33 +23315,28 @@ static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi) if (NREV_IS(pi->pubpi.phy_rev, 7)) { if (CHSPEC_IS2G(pi->radio_chanspec)) { - mod_radio_reg( - pi, - RADIO_2057_PAD2G_TUNE_PUS_CORE0, - 1, 1); - mod_radio_reg( - pi, - RADIO_2057_PAD2G_TUNE_PUS_CORE1, - 1, 1); + mod_radio_reg(pi, + RADIO_2057_PAD2G_TUNE_PUS_CORE0, + 1, 1); + mod_radio_reg(pi, + RADIO_2057_PAD2G_TUNE_PUS_CORE1, + 1, 1); } else { - mod_radio_reg( - pi, - RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, - 1, 1); - mod_radio_reg( - pi, - RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, - 1, 1); + mod_radio_reg(pi, + RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, + 1, 1); + mod_radio_reg(pi, + RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, + 1, 1); } mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4, 0); } else if (NREV_GE(pi->pubpi.phy_rev, 8)) { - wlc_phy_rfctrl_override_nphy_rev7( - pi, - (0x1 << 3), 0, - 0x3, 1, - NPHY_REV7_RFCTRLOVERRIDE_ID0); + wlc_phy_rfctrl_override_nphy_rev7(pi, + (0x1 << 3), 0, + 0x3, 1, + NPHY_REV7_RFCTRLOVERRIDE_ID0); } } } else { @@ -23299,7 +23356,7 @@ static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi) } } -#define NPHY_CAL_TSSISAMPS 64 +#define NPHY_CAL_TSSISAMPS 64 #define NPHY_TEST_TONE_FREQ_40MHz 4000 #define NPHY_TEST_TONE_FREQ_20MHz 2500 @@ -23322,8 +23379,8 @@ wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps) idle_tssi[1] = (temp <= 31) ? temp : (temp - 64); tssi_type = - CHSPEC_IS5G(pi->radio_chanspec) ? - (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G; + CHSPEC_IS5G(pi->radio_chanspec) ? + (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G; wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps); @@ -23333,15 +23390,17 @@ wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps) pwrindex[0] = idle_tssi[0] - tssival[0] + 64; pwrindex[1] = idle_tssi[1] - tssival[1] + 64; - if (pwrindex[0] < 0) + if (pwrindex[0] < 0) { pwrindex[0] = 0; - else if (pwrindex[0] > 63) + } else if (pwrindex[0] > 63) { pwrindex[0] = 63; + } - if (pwrindex[1] < 0) + if (pwrindex[1] < 0) { pwrindex[1] = 0; - else if (pwrindex[1] > 63) + } else if (pwrindex[1] > 63) { pwrindex[1] = 63; + } wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1, (u32) pwrindex[0], 32, &qdBm_pwrbuf[0]); @@ -23386,23 +23445,21 @@ static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi) (pi->pubpi.radiorev == 6)) { pi->nphy_txcal_pwr_idx[0] = - txcal_index_2057_rev3n4n6; + txcal_index_2057_rev3n4n6; pi->nphy_txcal_pwr_idx[1] = - txcal_index_2057_rev3n4n6; - wlc_phy_txpwr_index_nphy( - pi, 3, - txcal_index_2057_rev3n4n6, - false); + txcal_index_2057_rev3n4n6; + wlc_phy_txpwr_index_nphy(pi, 3, + txcal_index_2057_rev3n4n6, + false); } else { pi->nphy_txcal_pwr_idx[0] = - txcal_index_2057_rev5n7; + txcal_index_2057_rev5n7; pi->nphy_txcal_pwr_idx[1] = - txcal_index_2057_rev5n7; - wlc_phy_txpwr_index_nphy( - pi, 3, - txcal_index_2057_rev5n7, - false); + txcal_index_2057_rev5n7; + wlc_phy_txpwr_index_nphy(pi, 3, + txcal_index_2057_rev5n7, + false); } save_bbmult = true; @@ -23410,7 +23467,7 @@ static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi) wlc_phy_cal_txgainctrl_nphy(pi, 11, false); if (pi->sh->hw_phytxchain != 3) { pi->nphy_txcal_pwr_idx[1] = - pi->nphy_txcal_pwr_idx[0]; + pi->nphy_txcal_pwr_idx[0]; wlc_phy_txpwr_index_nphy(pi, 3, pi-> nphy_txcal_pwr_idx[0], @@ -23431,19 +23488,22 @@ static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi) save_bbmult = true; } } else { + wlc_phy_internal_cal_txgain_nphy(pi); save_bbmult = true; } } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { if (PHY_IPA(pi)) { - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { wlc_phy_cal_txgainctrl_nphy(pi, 12, false); - else + } else { wlc_phy_cal_txgainctrl_nphy(pi, 14, false); + } } else { + wlc_phy_internal_cal_txgain_nphy(pi); save_bbmult = true; } @@ -23453,9 +23513,10 @@ static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi) wlc_phy_cal_txgainctrl_nphy(pi, 10, false); } - if (save_bbmult) + if (save_bbmult) { wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult); + } } void @@ -23475,15 +23536,19 @@ wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower, uint stepsize; bool phyhang_avoid_state = false; - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + stepsize = 2; - else + } else { + stepsize = 1; + } - if (CHSPEC_IS40(pi->radio_chanspec)) + if (CHSPEC_IS40(pi->radio_chanspec)) { freq_test = 5000; - else + } else { freq_test = 2500; + } wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true); wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true); @@ -23531,10 +23596,11 @@ wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower, wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0, false); - if (core == PHY_CORE_0) + if (core == PHY_CORE_0) { curr_m0m1 = m0m1 & 0xff00; - else + } else { curr_m0m1 = m0m1 & 0x00ff; + } wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1); wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1); @@ -23550,22 +23616,25 @@ wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower, delta_power = (dBm_targetpower * 4) - qdBm_power[core]; txpwrindex -= stepsize * delta_power; - if (txpwrindex < 0) + if (txpwrindex < 0) { txpwrindex = 0; - else if (txpwrindex > 127) + } else if (txpwrindex > 127) { txpwrindex = 127; + } if (CHSPEC_IS5G(pi->radio_chanspec)) { if (NREV_IS(pi->pubpi.phy_rev, 4) && (pi->srom_fem5g.extpagain == 3)) { - if (txpwrindex < 30) + if (txpwrindex < 30) { txpwrindex = 30; + } } } else { if (NREV_GE(pi->pubpi.phy_rev, 5) && (pi->srom_fem2g.extpagain == 3)) { - if (txpwrindex < 50) + if (txpwrindex < 50) { txpwrindex = 50; + } } } @@ -23639,15 +23708,15 @@ static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) }; bbmult = (core == PHY_CORE_0) ? - ((pi->nphy_txcal_bbmult >> 8) & 0xff) : - (pi->nphy_txcal_bbmult & 0xff); + ((pi->nphy_txcal_bbmult >> 8) & 0xff) : (pi-> + nphy_txcal_bbmult & 0xff); for (index = 0; index < 18; index++) { bbmult_scale = ladder_lo[index].percent * bbmult; bbmult_scale /= 100; tblentry = - ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env; + ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env; wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16, &tblentry); @@ -23655,7 +23724,7 @@ static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) bbmult_scale /= 100; tblentry = - ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env; + ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env; wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32, 16, &tblentry); } @@ -23682,18 +23751,19 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) else if (caltype == PHY_PERICAL_PARTIAL) fullcal = false; - if (pi->cal_type_override != PHY_PERICAL_AUTO) + if (pi->cal_type_override != PHY_PERICAL_AUTO) { fullcal = - (pi->cal_type_override == - PHY_PERICAL_FULL) ? true : false; + (pi->cal_type_override == PHY_PERICAL_FULL) ? true : false; + } if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) { if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec) wlc_phy_cal_perical_mphase_restart(pi); } - if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) + if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) { wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); + } wlapi_suspend_mac_and_wait(pi->sh->physhim); @@ -23702,9 +23772,9 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) || (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) { pi->nphy_cal_orig_pwr_idx[0] = - (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f); + (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f); pi->nphy_cal_orig_pwr_idx[1] = - (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f); + (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f); if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) { wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, @@ -23733,8 +23803,7 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) target_gain = pi->nphy_cal_target_gain; } if (0 == - wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, - mphase)) { + wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, mphase)) { if (PHY_IPA(pi)) wlc_phy_a4(pi, true); @@ -23746,9 +23815,13 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) wlc_phyreg_enter((struct brcms_phy_pub *) pi); if (0 == wlc_phy_cal_rxiq_nphy(pi, target_gain, - (pi->first_cal_after_assoc || - (pi->cal_type_override == - PHY_PERICAL_FULL)) ? 2 : 0, false)) { + (pi-> + first_cal_after_assoc + || (pi-> + cal_type_override + == + PHY_PERICAL_FULL)) + ? 2 : 0, false)) { wlc_phy_savecal_nphy(pi); wlc_phy_txpwrctrl_coeff_setup_nphy(pi); @@ -23756,8 +23829,9 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) pi->nphy_perical_last = pi->sh->now; } } - if (caltype != PHY_PERICAL_AUTO) + if (caltype != PHY_PERICAL_AUTO) { wlc_phy_rssi_cal_nphy(pi); + } if (pi->first_cal_after_assoc || (pi->cal_type_override == PHY_PERICAL_FULL)) { @@ -23766,17 +23840,18 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) wlc_phy_txpwrctrl_pwr_setup_nphy(pi); } - if (NREV_GE(pi->pubpi.phy_rev, 3)) + if (NREV_GE(pi->pubpi.phy_rev, 3)) { wlc_phy_radio205x_vcocal_nphy(pi); + } } else { switch (pi->mphase_cal_phase_id) { case MPHASE_CAL_STATE_INIT: pi->nphy_perical_last = pi->sh->now; pi->nphy_txiqlocal_chanspec = pi->radio_chanspec; - if (NREV_GE(pi->pubpi.phy_rev, 3)) + if (NREV_GE(pi->pubpi.phy_rev, 3)) { wlc_phy_precal_txgain_nphy(pi); - + } pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi); pi->mphase_cal_phase_id++; break; @@ -23791,8 +23866,8 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) pi->nphy_rxcal_active = true; if (wlc_phy_cal_txiqlo_nphy - (pi, pi->nphy_cal_target_gain, fullcal, - true) != 0) { + (pi, pi->nphy_cal_target_gain, fullcal, + true) != 0) { wlc_phy_cal_perical_mphase_reset(pi); break; @@ -23800,19 +23875,20 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) if (NREV_LE(pi->pubpi.phy_rev, 2) && (pi->mphase_cal_phase_id == - MPHASE_CAL_STATE_TXPHASE4)) + MPHASE_CAL_STATE_TXPHASE4)) { pi->mphase_cal_phase_id += 2; - else + } else { pi->mphase_cal_phase_id++; + } break; case MPHASE_CAL_STATE_PAPDCAL: if ((pi->radar_percal_mask & 0x2) != 0) pi->nphy_rxcal_active = true; - if (PHY_IPA(pi)) + if (PHY_IPA(pi)) { wlc_phy_a4(pi, true); - + } pi->mphase_cal_phase_id++; break; @@ -23823,8 +23899,9 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) (pi->first_cal_after_assoc || (pi->cal_type_override == PHY_PERICAL_FULL)) ? 2 : 0, - false) == 0) + false) == 0) { wlc_phy_savecal_nphy(pi); + } pi->mphase_cal_phase_id++; break; @@ -23835,15 +23912,16 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) wlc_phy_txpwrctrl_coeff_setup_nphy(pi); wlc_phy_rssi_cal_nphy(pi); - if (NREV_GE(pi->pubpi.phy_rev, 3)) + if (NREV_GE(pi->pubpi.phy_rev, 3)) { wlc_phy_radio205x_vcocal_nphy(pi); - + } restore_tx_gain = true; - if (pi->first_cal_after_assoc) + if (pi->first_cal_after_assoc) { pi->mphase_cal_phase_id++; - else + } else { wlc_phy_cal_perical_mphase_reset(pi); + } break; @@ -23884,15 +23962,15 @@ void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) } else { wlc_phy_txpwr_index_nphy(pi, (1 << 0), (s8) (pi-> - nphy_txpwrindex - [0]. - index_internal), + nphy_txpwrindex + [0]. + index_internal), false); wlc_phy_txpwr_index_nphy(pi, (1 << 1), (s8) (pi-> - nphy_txpwrindex - [1]. - index_internal), + nphy_txpwrindex + [1]. + index_internal), false); } } @@ -23929,35 +24007,35 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { 0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901, - 0x1902, + 0x1902, 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607, - 0x6407 + 0x6407 }; u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { 0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400, - 0x3200, + 0x3200, 0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406, - 0x6407 + 0x6407 }; u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { 0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201, - 0x1202, + 0x1202, 0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207, - 0x4707 + 0x4707 }; u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { 0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900, - 0x2300, + 0x2300, 0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, - 0x4707 + 0x4707 }; u16 tbl_tx_iqlo_cal_startcoefs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000 + 0x0000 }; u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { @@ -23993,10 +24071,11 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, pi->phyhang_avoid = false; } - if (CHSPEC_IS40(pi->radio_chanspec)) + if (CHSPEC_IS40(pi->radio_chanspec)) { phy_bw = 40; - else + } else { phy_bw = 20; + } wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); @@ -24038,10 +24117,11 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, 16, tbl_ptr); } - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { write_phy_reg(pi, 0xc2, 0x8ad9); - else + } else { write_phy_reg(pi, 0xc2, 0x8aa9); + } max_val = 250; tone_freq = (phy_bw == 20) ? 2500 : 5000; @@ -24051,8 +24131,7 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, bcmerror = 0; } else { bcmerror = - wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, - false); + wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, false); } if (bcmerror == 0) { @@ -24060,15 +24139,19 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) { tbl_ptr = pi->mphase_txcal_bestcoeffs; tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs); - if (NREV_LT(pi->pubpi.phy_rev, 3)) + if (NREV_LT(pi->pubpi.phy_rev, 3)) { + tbl_len -= 2; + } } else { if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) { tbl_ptr = pi->nphy_txiqlocal_bestc; tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc); - if (NREV_LT(pi->pubpi.phy_rev, 3)) + if (NREV_LT(pi->pubpi.phy_rev, 3)) { + tbl_len -= 2; + } } else { fullcal = true; @@ -24076,12 +24159,14 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, if (NREV_GE(pi->pubpi.phy_rev, 3)) { tbl_ptr = tbl_tx_iqlo_cal_startcoefs_nphyrev3; - tbl_len = ARRAY_SIZE( - tbl_tx_iqlo_cal_startcoefs_nphyrev3); + tbl_len = + ARRAY_SIZE + (tbl_tx_iqlo_cal_startcoefs_nphyrev3); } else { tbl_ptr = tbl_tx_iqlo_cal_startcoefs; - tbl_len = ARRAY_SIZE( - tbl_tx_iqlo_cal_startcoefs); + tbl_len = + ARRAY_SIZE + (tbl_tx_iqlo_cal_startcoefs); } } } @@ -24090,22 +24175,21 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, if (fullcal) { max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ? - ARRAY_SIZE( - tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) : - ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal); + ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) : + ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal); } else { max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ? - ARRAY_SIZE( - tbl_tx_iqlo_cal_cmds_recal_nphyrev3) : - ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal); + ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal_nphyrev3) : + ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal); } if (mphase) { cal_cnt = pi->mphase_txcal_cmdidx; - if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) + if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) { num_cals = cal_cnt + pi->mphase_txcal_numcmds; - else + } else { num_cals = max_cal_cmds; + } } else { cal_cnt = 0; num_cals = max_cal_cmds; @@ -24115,14 +24199,13 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, if (fullcal) { cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ? - tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3 - [cal_cnt] : - tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt]; + tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3 + [cal_cnt] : + tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt]; } else { cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ? - tbl_tx_iqlo_cal_cmds_recal_nphyrev3[ - cal_cnt] - : tbl_tx_iqlo_cal_cmds_recal[cal_cnt]; + tbl_tx_iqlo_cal_cmds_recal_nphyrev3[cal_cnt] + : tbl_tx_iqlo_cal_cmds_recal[cal_cnt]; } core_no = ((cal_cmd & 0x3000) >> 12); @@ -24133,16 +24216,15 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, PHY_IPA(pi) && (CHSPEC_IS2G(pi->radio_chanspec)))) { if (!ladder_updated[core_no]) { - wlc_phy_update_txcal_ladder_nphy( - pi, - core_no); + wlc_phy_update_txcal_ladder_nphy(pi, + core_no); ladder_updated[core_no] = true; } } val = - (cal_params[core_no]. - ncorr[cal_type] << 8) | NPHY_N_GCTL; + (cal_params[core_no]. + ncorr[cal_type] << 8) | NPHY_N_GCTL; write_phy_reg(pi, 0xc1, val); if ((cal_type == 1) || (cal_type == 3) @@ -24190,8 +24272,8 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, } mphase_cal_lastphase = - (NREV_LE(pi->pubpi.phy_rev, 2)) ? - MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5; + (NREV_LE(pi->pubpi.phy_rev, 2)) ? + MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5; if (!mphase || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) { @@ -24221,9 +24303,10 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, 16, tbl_buf); tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc); - if (NREV_LT(pi->pubpi.phy_rev, 3)) - tbl_len -= 2; + if (NREV_LT(pi->pubpi.phy_rev, 3)) { + tbl_len -= 2; + } wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 96, 16, pi->nphy_txiqlocal_bestc); @@ -24232,9 +24315,10 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, pi->nphy_txiqlocal_chanspec = pi->radio_chanspec; } else { tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs); - if (NREV_LT(pi->pubpi.phy_rev, 3)) - tbl_len -= 2; + if (NREV_LT(pi->pubpi.phy_rev, 3)) { + tbl_len -= 2; + } wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 96, 16, pi->mphase_txcal_bestcoeffs); @@ -24259,8 +24343,9 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, wlc_phy_tx_iq_war_nphy(pi); } - if (NREV_GE(pi->pubpi.phy_rev, 4)) + if (NREV_GE(pi->pubpi.phy_rev, 4)) { pi->phyhang_avoid = phyhang_avoid_state; + } wlc_phy_stay_in_carriersearch_nphy(pi, false); @@ -24306,7 +24391,7 @@ static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi) { struct nphy_iq_comp tx_comp; - wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, &tx_comp); + wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, (void *)&tx_comp); wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0); wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0); @@ -24353,17 +24438,14 @@ wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est, if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) { for (core = 0; core < pi->pubpi.phy_corenum; core++) { est[core].i_pwr = - (read_phy_reg(pi, - NPHY_IqestipwrAccHi(core)) << 16) - | read_phy_reg(pi, NPHY_IqestipwrAccLo(core)); + (read_phy_reg(pi, NPHY_IqestipwrAccHi(core)) << 16) + | read_phy_reg(pi, NPHY_IqestipwrAccLo(core)); est[core].q_pwr = - (read_phy_reg(pi, - NPHY_IqestqpwrAccHi(core)) << 16) - | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core)); + (read_phy_reg(pi, NPHY_IqestqpwrAccHi(core)) << 16) + | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core)); est[core].iq_prod = - (read_phy_reg(pi, - NPHY_IqestIqAccHi(core)) << 16) | - read_phy_reg(pi, NPHY_IqestIqAccLo(core)); + (read_phy_reg(pi, NPHY_IqestIqAccHi(core)) << 16) | + read_phy_reg(pi, NPHY_IqestIqAccLo(core)); } } } @@ -24388,7 +24470,7 @@ static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask) new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0; wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp); -cal_try: + cal_try: wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0); new_comp = old_comp; @@ -24479,7 +24561,7 @@ static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask) if (bcmerror != 0) { printk(KERN_DEBUG "%s: Failed, cnt = %d\n", __func__, - cal_retry); + cal_retry); if (cal_retry < CAL_RETRY_CNT) { cal_retry++; @@ -24502,125 +24584,121 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core) if (rx_core == PHY_CORE_0) { if (CHSPEC_IS5G(pi->radio_chanspec)) { pi->tx_rx_cal_radio_saveregs[0] = - read_radio_reg(pi, - RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP); + read_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP); pi->tx_rx_cal_radio_saveregs[1] = - read_radio_reg(pi, - RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN); + read_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN); write_radio_reg(pi, - RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, - 0x3); + RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, + 0x3); write_radio_reg(pi, - RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, - 0xaf); + RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, + 0xaf); } else { pi->tx_rx_cal_radio_saveregs[0] = - read_radio_reg(pi, - RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP); + read_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP); pi->tx_rx_cal_radio_saveregs[1] = - read_radio_reg(pi, - RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN); - - write_radio_reg( - pi, - RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, - 0x3); - write_radio_reg( - pi, - RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, - 0x7f); + read_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN); + + write_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, + 0x3); + write_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, + 0x7f); } } else { if (CHSPEC_IS5G(pi->radio_chanspec)) { pi->tx_rx_cal_radio_saveregs[0] = - read_radio_reg(pi, - RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP); + read_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP); pi->tx_rx_cal_radio_saveregs[1] = - read_radio_reg(pi, - RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN); - - write_radio_reg( - pi, - RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, - 0x3); - write_radio_reg( - pi, - RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, - 0xaf); + read_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN); + + write_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, + 0x3); + write_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, + 0xaf); } else { pi->tx_rx_cal_radio_saveregs[0] = - read_radio_reg(pi, - RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP); + read_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP); pi->tx_rx_cal_radio_saveregs[1] = - read_radio_reg(pi, - RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN); + read_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN); write_radio_reg(pi, - RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, - 0x3); + RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, + 0x3); write_radio_reg(pi, - RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, - 0x7f); + RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, + 0x7f); } } } else { if (rx_core == PHY_CORE_0) { pi->tx_rx_cal_radio_saveregs[0] = - read_radio_reg(pi, - RADIO_2056_TX_RXIQCAL_TXMUX | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_RXIQCAL_TXMUX | + RADIO_2056_TX1); pi->tx_rx_cal_radio_saveregs[1] = - read_radio_reg(pi, - RADIO_2056_RX_RXIQCAL_RXMUX | - RADIO_2056_RX0); + read_radio_reg(pi, + RADIO_2056_RX_RXIQCAL_RXMUX | + RADIO_2056_RX0); if (pi->pubpi.radiorev >= 5) { pi->tx_rx_cal_radio_saveregs[2] = - read_radio_reg(pi, - RADIO_2056_RX_RXSPARE2 | - RADIO_2056_RX0); + read_radio_reg(pi, + RADIO_2056_RX_RXSPARE2 | + RADIO_2056_RX0); pi->tx_rx_cal_radio_saveregs[3] = - read_radio_reg(pi, - RADIO_2056_TX_TXSPARE2 | - RADIO_2056_TX1); + read_radio_reg(pi, + RADIO_2056_TX_TXSPARE2 | + RADIO_2056_TX1); } if (CHSPEC_IS5G(pi->radio_chanspec)) { if (pi->pubpi.radiorev >= 5) { pi->tx_rx_cal_radio_saveregs[4] = - read_radio_reg(pi, - RADIO_2056_RX_LNAA_MASTER - | RADIO_2056_RX0); + read_radio_reg(pi, + RADIO_2056_RX_LNAA_MASTER + | RADIO_2056_RX0); - write_radio_reg( - pi, - RADIO_2056_RX_LNAA_MASTER - | RADIO_2056_RX0, 0x40); + write_radio_reg(pi, + RADIO_2056_RX_LNAA_MASTER + | RADIO_2056_RX0, 0x40); write_radio_reg(pi, - RADIO_2056_TX_TXSPARE2 | - RADIO_2056_TX1, bias_a); + RADIO_2056_TX_TXSPARE2 | + RADIO_2056_TX1, bias_a); write_radio_reg(pi, - RADIO_2056_RX_RXSPARE2 | - RADIO_2056_RX0, bias_a); + RADIO_2056_RX_RXSPARE2 | + RADIO_2056_RX0, bias_a); } else { pi->tx_rx_cal_radio_saveregs[4] = - read_radio_reg(pi, - RADIO_2056_RX_LNAA_TUNE - | RADIO_2056_RX0); + read_radio_reg(pi, + RADIO_2056_RX_LNAA_TUNE + | RADIO_2056_RX0); offtune_val = - (pi->tx_rx_cal_radio_saveregs - [2] & 0xF0) >> 8; + (pi-> + tx_rx_cal_radio_saveregs[2] & 0xF0) + >> 8; offtune_val = - (offtune_val <= 0x7) ? 0xF : 0; + (offtune_val <= 0x7) ? 0xF : 0; mod_radio_reg(pi, RADIO_2056_RX_LNAA_TUNE | @@ -24637,41 +24715,34 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core) } else { if (pi->pubpi.radiorev >= 5) { pi->tx_rx_cal_radio_saveregs[4] = - read_radio_reg( - pi, - RADIO_2056_RX_LNAG_MASTER - | RADIO_2056_RX0); - - write_radio_reg( - pi, - RADIO_2056_RX_LNAG_MASTER - | RADIO_2056_RX0, 0x40); - - write_radio_reg( - pi, - RADIO_2056_TX_TXSPARE2 - | - RADIO_2056_TX1, bias_g); - - write_radio_reg( - pi, - RADIO_2056_RX_RXSPARE2 - | - RADIO_2056_RX0, bias_g); + read_radio_reg(pi, + RADIO_2056_RX_LNAG_MASTER + | RADIO_2056_RX0); + + write_radio_reg(pi, + RADIO_2056_RX_LNAG_MASTER + | RADIO_2056_RX0, 0x40); + + write_radio_reg(pi, + RADIO_2056_TX_TXSPARE2 | + RADIO_2056_TX1, bias_g); + + write_radio_reg(pi, + RADIO_2056_RX_RXSPARE2 | + RADIO_2056_RX0, bias_g); } else { pi->tx_rx_cal_radio_saveregs[4] = - read_radio_reg( - pi, - RADIO_2056_RX_LNAG_TUNE - | RADIO_2056_RX0); + read_radio_reg(pi, + RADIO_2056_RX_LNAG_TUNE + | RADIO_2056_RX0); offtune_val = - (pi-> - tx_rx_cal_radio_saveregs[2] & - 0xF0) >> 8; + (pi-> + tx_rx_cal_radio_saveregs[2] & 0xF0) + >> 8; offtune_val = - (offtune_val <= 0x7) ? 0xF : 0; + (offtune_val <= 0x7) ? 0xF : 0; mod_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | @@ -24689,63 +24760,56 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core) } else { pi->tx_rx_cal_radio_saveregs[0] = - read_radio_reg(pi, - RADIO_2056_TX_RXIQCAL_TXMUX | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_RXIQCAL_TXMUX | + RADIO_2056_TX0); pi->tx_rx_cal_radio_saveregs[1] = - read_radio_reg(pi, - RADIO_2056_RX_RXIQCAL_RXMUX | - RADIO_2056_RX1); + read_radio_reg(pi, + RADIO_2056_RX_RXIQCAL_RXMUX | + RADIO_2056_RX1); if (pi->pubpi.radiorev >= 5) { pi->tx_rx_cal_radio_saveregs[2] = - read_radio_reg(pi, - RADIO_2056_RX_RXSPARE2 | - RADIO_2056_RX1); + read_radio_reg(pi, + RADIO_2056_RX_RXSPARE2 | + RADIO_2056_RX1); pi->tx_rx_cal_radio_saveregs[3] = - read_radio_reg(pi, - RADIO_2056_TX_TXSPARE2 | - RADIO_2056_TX0); + read_radio_reg(pi, + RADIO_2056_TX_TXSPARE2 | + RADIO_2056_TX0); } if (CHSPEC_IS5G(pi->radio_chanspec)) { if (pi->pubpi.radiorev >= 5) { pi->tx_rx_cal_radio_saveregs[4] = - read_radio_reg( - pi, - RADIO_2056_RX_LNAA_MASTER - | RADIO_2056_RX1); - - write_radio_reg( - pi, - RADIO_2056_RX_LNAA_MASTER | - RADIO_2056_RX1, 0x40); - - write_radio_reg( - pi, - RADIO_2056_TX_TXSPARE2 - | - RADIO_2056_TX0, bias_a); - - write_radio_reg( - pi, - RADIO_2056_RX_RXSPARE2 - | - RADIO_2056_RX1, bias_a); + read_radio_reg(pi, + RADIO_2056_RX_LNAA_MASTER + | RADIO_2056_RX1); + + write_radio_reg(pi, + RADIO_2056_RX_LNAA_MASTER + | RADIO_2056_RX1, 0x40); + + write_radio_reg(pi, + RADIO_2056_TX_TXSPARE2 | + RADIO_2056_TX0, bias_a); + + write_radio_reg(pi, + RADIO_2056_RX_RXSPARE2 | + RADIO_2056_RX1, bias_a); } else { pi->tx_rx_cal_radio_saveregs[4] = - read_radio_reg( - pi, - RADIO_2056_RX_LNAA_TUNE - | RADIO_2056_RX1); + read_radio_reg(pi, + RADIO_2056_RX_LNAA_TUNE + | RADIO_2056_RX1); offtune_val = - (pi-> - tx_rx_cal_radio_saveregs[2] & - 0xF0) >> 8; + (pi-> + tx_rx_cal_radio_saveregs[2] & 0xF0) + >> 8; offtune_val = - (offtune_val <= 0x7) ? 0xF : 0; + (offtune_val <= 0x7) ? 0xF : 0; mod_radio_reg(pi, RADIO_2056_RX_LNAA_TUNE | @@ -24762,40 +24826,33 @@ static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core) } else { if (pi->pubpi.radiorev >= 5) { pi->tx_rx_cal_radio_saveregs[4] = - read_radio_reg( - pi, - RADIO_2056_RX_LNAG_MASTER - | RADIO_2056_RX1); - - write_radio_reg( - pi, - RADIO_2056_RX_LNAG_MASTER - | RADIO_2056_RX1, 0x40); - - write_radio_reg( - pi, - RADIO_2056_TX_TXSPARE2 - | - RADIO_2056_TX0, bias_g); - - write_radio_reg( - pi, - RADIO_2056_RX_RXSPARE2 - | - RADIO_2056_RX1, bias_g); + read_radio_reg(pi, + RADIO_2056_RX_LNAG_MASTER + | RADIO_2056_RX1); + + write_radio_reg(pi, + RADIO_2056_RX_LNAG_MASTER + | RADIO_2056_RX1, 0x40); + + write_radio_reg(pi, + RADIO_2056_TX_TXSPARE2 | + RADIO_2056_TX0, bias_g); + + write_radio_reg(pi, + RADIO_2056_RX_RXSPARE2 | + RADIO_2056_RX1, bias_g); } else { pi->tx_rx_cal_radio_saveregs[4] = - read_radio_reg( - pi, - RADIO_2056_RX_LNAG_TUNE - | RADIO_2056_RX1); + read_radio_reg(pi, + RADIO_2056_RX_LNAG_TUNE + | RADIO_2056_RX1); offtune_val = - (pi-> - tx_rx_cal_radio_saveregs[2] & - 0xF0) >> 8; + (pi-> + tx_rx_cal_radio_saveregs[2] & 0xF0) + >> 8; offtune_val = - (offtune_val <= 0x7) ? 0xF : 0; + (offtune_val <= 0x7) ? 0xF : 0; mod_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | @@ -24819,54 +24876,46 @@ static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core) if (NREV_GE(pi->pubpi.phy_rev, 7)) { if (rx_core == PHY_CORE_0) { if (CHSPEC_IS5G(pi->radio_chanspec)) { - write_radio_reg( - pi, - RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, - pi-> - tx_rx_cal_radio_saveregs[0]); - write_radio_reg( - pi, - RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, - pi-> - tx_rx_cal_radio_saveregs[1]); + write_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, + pi-> + tx_rx_cal_radio_saveregs[0]); + write_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, + pi-> + tx_rx_cal_radio_saveregs[1]); } else { - write_radio_reg( - pi, - RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, - pi-> - tx_rx_cal_radio_saveregs[0]); - write_radio_reg( - pi, - RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, - pi-> - tx_rx_cal_radio_saveregs[1]); + write_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, + pi-> + tx_rx_cal_radio_saveregs[0]); + write_radio_reg(pi, + RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, + pi-> + tx_rx_cal_radio_saveregs[1]); } } else { if (CHSPEC_IS5G(pi->radio_chanspec)) { - write_radio_reg( - pi, - RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, - pi-> - tx_rx_cal_radio_saveregs[0]); - write_radio_reg( - pi, - RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, - pi-> - tx_rx_cal_radio_saveregs[1]); + write_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, + pi-> + tx_rx_cal_radio_saveregs[0]); + write_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, + pi-> + tx_rx_cal_radio_saveregs[1]); } else { - write_radio_reg( - pi, - RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, - pi-> - tx_rx_cal_radio_saveregs[0]); - write_radio_reg( - pi, - RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, - pi-> - tx_rx_cal_radio_saveregs[1]); + write_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, + pi-> + tx_rx_cal_radio_saveregs[0]); + write_radio_reg(pi, + RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, + pi-> + tx_rx_cal_radio_saveregs[1]); } } @@ -24897,39 +24946,37 @@ static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core) } if (CHSPEC_IS5G(pi->radio_chanspec)) { - if (pi->pubpi.radiorev >= 5) - write_radio_reg( - pi, - RADIO_2056_RX_LNAA_MASTER - | RADIO_2056_RX0, - pi-> - tx_rx_cal_radio_saveregs - [4]); - else - write_radio_reg( - pi, - RADIO_2056_RX_LNAA_TUNE - | RADIO_2056_RX0, - pi-> - tx_rx_cal_radio_saveregs - [4]); + if (pi->pubpi.radiorev >= 5) { + write_radio_reg(pi, + RADIO_2056_RX_LNAA_MASTER + | RADIO_2056_RX0, + pi-> + tx_rx_cal_radio_saveregs + [4]); + } else { + write_radio_reg(pi, + RADIO_2056_RX_LNAA_TUNE + | RADIO_2056_RX0, + pi-> + tx_rx_cal_radio_saveregs + [4]); + } } else { - if (pi->pubpi.radiorev >= 5) - write_radio_reg( - pi, - RADIO_2056_RX_LNAG_MASTER - | RADIO_2056_RX0, - pi-> - tx_rx_cal_radio_saveregs - [4]); - else - write_radio_reg( - pi, - RADIO_2056_RX_LNAG_TUNE - | RADIO_2056_RX0, - pi-> - tx_rx_cal_radio_saveregs - [4]); + if (pi->pubpi.radiorev >= 5) { + write_radio_reg(pi, + RADIO_2056_RX_LNAG_MASTER + | RADIO_2056_RX0, + pi-> + tx_rx_cal_radio_saveregs + [4]); + } else { + write_radio_reg(pi, + RADIO_2056_RX_LNAG_TUNE + | RADIO_2056_RX0, + pi-> + tx_rx_cal_radio_saveregs + [4]); + } } } else { @@ -24958,39 +25005,37 @@ static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core) } if (CHSPEC_IS5G(pi->radio_chanspec)) { - if (pi->pubpi.radiorev >= 5) - write_radio_reg( - pi, - RADIO_2056_RX_LNAA_MASTER - | RADIO_2056_RX1, - pi-> - tx_rx_cal_radio_saveregs - [4]); - else - write_radio_reg( - pi, - RADIO_2056_RX_LNAA_TUNE - | RADIO_2056_RX1, - pi-> - tx_rx_cal_radio_saveregs - [4]); + if (pi->pubpi.radiorev >= 5) { + write_radio_reg(pi, + RADIO_2056_RX_LNAA_MASTER + | RADIO_2056_RX1, + pi-> + tx_rx_cal_radio_saveregs + [4]); + } else { + write_radio_reg(pi, + RADIO_2056_RX_LNAA_TUNE + | RADIO_2056_RX1, + pi-> + tx_rx_cal_radio_saveregs + [4]); + } } else { - if (pi->pubpi.radiorev >= 5) - write_radio_reg( - pi, - RADIO_2056_RX_LNAG_MASTER - | RADIO_2056_RX1, - pi-> - tx_rx_cal_radio_saveregs - [4]); - else - write_radio_reg( - pi, - RADIO_2056_RX_LNAG_TUNE - | RADIO_2056_RX1, - pi-> - tx_rx_cal_radio_saveregs - [4]); + if (pi->pubpi.radiorev >= 5) { + write_radio_reg(pi, + RADIO_2056_RX_LNAG_MASTER + | RADIO_2056_RX1, + pi-> + tx_rx_cal_radio_saveregs + [4]); + } else { + write_radio_reg(pi, + RADIO_2056_RX_LNAG_TUNE + | RADIO_2056_RX1, + pi-> + tx_rx_cal_radio_saveregs + [4]); + } } } } @@ -25001,16 +25046,18 @@ static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core) u8 tx_core; u16 rx_antval, tx_antval; - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + tx_core = rx_core; - else + } else { tx_core = (rx_core == PHY_CORE_0) ? 1 : 0; + } pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2); pi->tx_rx_cal_phy_saveregs[1] = - read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7); + read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7); pi->tx_rx_cal_phy_saveregs[2] = - read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5); + read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5); pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91); pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92); pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a); @@ -25075,19 +25122,17 @@ static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core) NPHY_REV7_RFCTRLOVERRIDE_ID2); wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0, NPHY_REV7_RFCTRLOVERRIDE_ID1); - if (CHSPEC_IS40(pi->radio_chanspec)) - wlc_phy_rfctrl_override_nphy_rev7( - pi, - (0x1 << 7), - 2, 0, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID1); - else - wlc_phy_rfctrl_override_nphy_rev7( - pi, - (0x1 << 7), - 0, 0, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID1); - + if (CHSPEC_IS40(pi->radio_chanspec)) { + wlc_phy_rfctrl_override_nphy_rev7(pi, + (0x1 << 7), + 2, 0, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + } else { + wlc_phy_rfctrl_override_nphy_rev7(pi, + (0x1 << 7), + 0, 0, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + } wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0, 0, NPHY_REV7_RFCTRLOVERRIDE_ID1); @@ -25158,8 +25203,8 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core, struct phy_iq_est est[PHY_CORE_MAX]; u8 tx_core; struct nphy_iq_comp save_comp, zero_comp; - u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, - thresh_pwr = 10000; + u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, thresh_pwr = + 10000; s16 desired_log2_pwr, actual_log2_pwr, delta_pwr; bool gainctrl_done = false; u8 mix_tia_gain = 3; @@ -25172,10 +25217,12 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core, s8 txpwrindex; u16 nphy_rxcal_txgain[2]; - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + tx_core = rx_core; - else + } else { tx_core = 1 - rx_core; + } num_samps = 1024; desired_log2_pwr = (cal_type == 0) ? 13 : 13; @@ -25185,42 +25232,45 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core, wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp); if (CHSPEC_IS5G(pi->radio_chanspec)) { - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { mix_tia_gain = 3; - else if (NREV_GE(pi->pubpi.phy_rev, 4)) + } else if (NREV_GE(pi->pubpi.phy_rev, 4)) { mix_tia_gain = 4; - else + } else { mix_tia_gain = 6; - if (NREV_GE(pi->pubpi.phy_rev, 7)) + } + if (NREV_GE(pi->pubpi.phy_rev, 7)) { nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7; - else + } else { nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz; + } } else { - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7; - else + } else { nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz; + } } do { hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ? - 0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga; + 0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga; lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1; lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0; lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2; lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1; txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex; - if (NREV_GE(pi->pubpi.phy_rev, 7)) - wlc_phy_rfctrl_override_1tomany_nphy( - pi, - NPHY_REV7_RfctrlOverride_cmd_rxgain, - ((lpf_biq1 << 12) | - (lpf_biq0 << 8) | - (mix_tia_gain << 4) | (lna2 << 2) - | lna1), 0x3, 0); - else + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + wlc_phy_rfctrl_override_1tomany_nphy(pi, + NPHY_REV7_RfctrlOverride_cmd_rxgain, + ((lpf_biq1 << 12) | + (lpf_biq0 << 8) | + (mix_tia_gain << + 4) | (lna2 << 2) + | lna1), 0x3, 0); + } else { wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), ((hpvga << 12) | (lpf_biq1 << 10) | @@ -25228,6 +25278,7 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core, (mix_tia_gain << 4) | (lna2 << 2) | lna1), 0x3, 0); + } pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex; @@ -25316,28 +25367,27 @@ wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core, if (NREV_GE(pi->pubpi.phy_rev, 7)) { fine_gain_idx = (int)lpf_biq1 + delta_pwr; - if (fine_gain_idx + (int)lpf_biq0 > 10) + if (fine_gain_idx + (int)lpf_biq0 > 10) { lpf_biq1 = 10 - lpf_biq0; - else + } else { lpf_biq1 = (u16) max(fine_gain_idx, 0); - - wlc_phy_rfctrl_override_1tomany_nphy( - pi, - NPHY_REV7_RfctrlOverride_cmd_rxgain, - ((lpf_biq1 << 12) | - (lpf_biq0 << 8) | - (mix_tia_gain << 4) | - (lna2 << 2) | lna1), 0x3, - 0); + } + wlc_phy_rfctrl_override_1tomany_nphy(pi, + NPHY_REV7_RfctrlOverride_cmd_rxgain, + ((lpf_biq1 << 12) | + (lpf_biq0 << 8) | + (mix_tia_gain << 4) | + (lna2 << 2) | lna1), 0x3, + 0); } else { hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0); wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), - ((hpvga << 12) | - (lpf_biq1 << 10) | - (lpf_biq0 << 8) | - (mix_tia_gain << 4) | - (lna2 << 2) | + ((hpvga << 12) | (lpf_biq1 << 10) | + (lpf_biq0 << 8) | (mix_tia_gain << + 4) | (lna2 << + 2) | lna1), 0x3, 0); + } if (rxgain != NULL) { @@ -25394,8 +25444,9 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type) u16 num_samps, log_num_samps = 10; struct phy_iq_est est[PHY_CORE_MAX]; - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { return 0; + } num_samps = (1 << log_num_samps); @@ -25414,21 +25465,20 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type) if (core_idx == 0) { radio_addr_offset_rx = RADIO_2056_RX0; radio_addr_offset_tx = - (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1; + (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1; } else { radio_addr_offset_rx = RADIO_2056_RX1; radio_addr_offset_tx = - (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0; + (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0; } orig_txlpf_rccal_lpc_ovr_val = - read_radio_reg(pi, - (RADIO_2056_TX_TXLPF_RCCAL | - radio_addr_offset_tx)); + read_radio_reg(pi, + (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx)); orig_rxlpf_rccal_hpc_ovr_val = - read_radio_reg(pi, - (RADIO_2056_RX_RXLPF_RCCAL_HPC | - radio_addr_offset_rx)); + read_radio_reg(pi, + (RADIO_2056_RX_RXLPF_RCCAL_HPC | + radio_addr_offset_rx)); orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1); @@ -25499,18 +25549,17 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type) wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); - if (core_idx == 0) + if (core_idx == 0) { ref_iq_vals = - max_t(u32, (est[0].i_pwr + - est[0].q_pwr) >> - (log_num_samps + 1), - 1); - else + max_t(u32, (est[0].i_pwr + + est[0].q_pwr) >> (log_num_samps + 1), + 1); + } else { ref_iq_vals = - max_t(u32, (est[1].i_pwr + - est[1].q_pwr) >> - (log_num_samps + 1), - 1); + max_t(u32, (est[1].i_pwr + + est[1].q_pwr) >> (log_num_samps + 1), + 1); + } wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP, 0, 1, false); @@ -25519,19 +25568,20 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type) wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); - if (core_idx == 0) - target_iq_vals = (est[0].i_pwr + est[0].q_pwr) >> - (log_num_samps + 1); - else + if (core_idx == 0) { target_iq_vals = - (est[1].i_pwr + - est[1].q_pwr) >> (log_num_samps + 1); - + (est[0].i_pwr + est[0].q_pwr) >> (log_num_samps + + 1); + } else { + target_iq_vals = + (est[1].i_pwr + est[1].q_pwr) >> (log_num_samps + + 1); + } pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals); - if (rccal_stepsize == 0) + if (rccal_stepsize == 0) { rccal_stepsize--; - else if (rccal_stepsize == 1) { + } else if (rccal_stepsize == 1) { last_rccal_val = rccal_val; rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1; last_pwr_ratio = pwr_ratio; @@ -25544,20 +25594,21 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type) if (rccal_stepsize == -1) { best_rccal_val = - (ABS((int)last_pwr_ratio - - (int)target_pwr_ratio) < - ABS((int)pwr_ratio - - (int)target_pwr_ratio)) ? last_rccal_val : - rccal_val; + (ABS((int)last_pwr_ratio - (int)target_pwr_ratio) < + ABS((int)pwr_ratio - + (int)target_pwr_ratio)) ? last_rccal_val : + rccal_val; if (CHSPEC_IS40(pi->radio_chanspec)) { if ((best_rccal_val > 140) - || (best_rccal_val < 135)) + || (best_rccal_val < 135)) { best_rccal_val = 138; + } } else { if ((best_rccal_val > 142) - || (best_rccal_val < 137)) + || (best_rccal_val < 137)) { best_rccal_val = 140; + } } write_radio_reg(pi, @@ -25598,7 +25649,7 @@ wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type) return best_rccal_val - 0x80; } -#define WAIT_FOR_SCOPE 4000 +#define WAIT_FOR_SCOPE 4000 static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, struct nphy_txgains target_gain, u8 cal_type, bool debug) @@ -25636,12 +25687,12 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); rxcore_state = wlc_phy_rxcore_getstate_nphy( - (struct brcms_phy_pub *) pi); + (struct brcms_phy_pub *) pi); for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) { skip_rxiqcal = - ((rxcore_state & (1 << rx_core)) == 0) ? true : false; + ((rxcore_state & (1 << rx_core)) == 0) ? true : false; wlc_phy_rxcal_physetup_nphy(pi, rx_core); @@ -25652,8 +25703,7 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0); wlc_phy_tx_tone_nphy(pi, - (CHSPEC_IS40( - pi->radio_chanspec)) ? + (CHSPEC_IS40(pi->radio_chanspec)) ? NPHY_RXCAL_TONEFREQ_40MHz : NPHY_RXCAL_TONEFREQ_20MHz, NPHY_RXCAL_TONEAMP, 0, cal_type, @@ -25671,21 +25721,23 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, if (rx_core == PHY_CORE_1) { - if (rxcore_state == 1) + if (rxcore_state == 1) { wlc_phy_rxcore_setstate_nphy( (struct brcms_phy_pub *) pi, 3); + } wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 1); best_rccal[rx_core] = - wlc_phy_rc_sweep_nphy(pi, rx_core, 1); + wlc_phy_rc_sweep_nphy(pi, rx_core, 1); pi->nphy_rccal_value = best_rccal[rx_core]; - if (rxcore_state == 1) + if (rxcore_state == 1) { wlc_phy_rxcore_setstate_nphy( (struct brcms_phy_pub *) pi, rxcore_state); + } } } @@ -25704,7 +25756,7 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) { rxlpf_rccal_hpc = - (((int)best_rccal[rx_core] - 12) >> 1) + 10; + (((int)best_rccal[rx_core] - 12) >> 1) + 10; txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10; if (PHY_IPA(pi)) { @@ -25714,10 +25766,8 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, TXLPF_IDAC_4, txlpf_idac); } - rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), - 0); - txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), - 0); + rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), 0); + txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), 0); write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC | ((rx_core == @@ -25737,21 +25787,21 @@ static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, wlc_phy_resetcca_nphy(pi); - if (NREV_GE(pi->pubpi.phy_rev, 7)) - wlc_phy_rfctrl_override_1tomany_nphy( - pi, - NPHY_REV7_RfctrlOverride_cmd_rxgain, - 0, 0x3, 1); - else + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + wlc_phy_rfctrl_override_1tomany_nphy(pi, + NPHY_REV7_RfctrlOverride_cmd_rxgain, + 0, 0x3, 1); + } else { wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1); - + } wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); - if (NREV_GE(pi->pubpi.phy_rev, 4)) + if (NREV_GE(pi->pubpi.phy_rev, 4)) { pi->phyhang_avoid = phyhang_avoid_state; + } wlc_phy_stay_in_carriersearch_nphy(pi, false); @@ -25785,8 +25835,10 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, wlc_phy_stay_in_carriersearch_nphy(pi, true); - if (NREV_LT(pi->pubpi.phy_rev, 2)) + if (NREV_LT(pi->pubpi.phy_rev, 2)) { + wlc_phy_reapply_txcal_coeffs_nphy(pi); + } wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); @@ -25822,16 +25874,19 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, ((0x1 << 1) | (0x1 << 2))); or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2))); - if (((pi->nphy_rxcalparams) & 0xff000000)) + if (((pi->nphy_rxcalparams) & 0xff000000)) { + write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 : 0x92, - (CHSPEC_IS5G(pi->radio_chanspec) ? - 0x140 : 0x110)); - else + (CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : + 0x110)); + } else { + write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 : 0x92, - (CHSPEC_IS5G(pi->radio_chanspec) ? - 0x180 : 0x120)); + (CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : + 0x120)); + } write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92, (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 : @@ -25871,7 +25926,7 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, use_hpf_num = 1; curr_hpf = curr_hpf1; actual_log2_pwr = - wlc_phy_nbits(tot_pwr[2]); + wlc_phy_nbits(tot_pwr[2]); } else { if (tot_pwr[0] > 10000) { curr_lna = lna_vals[1]; @@ -25880,8 +25935,7 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, use_hpf_num = 1; curr_hpf = curr_hpf1; actual_log2_pwr = - wlc_phy_nbits( - tot_pwr[1]); + wlc_phy_nbits(tot_pwr[1]); } else { curr_lna = lna_vals[0]; curr_hpf1 = hpf1_vals[0]; @@ -25889,18 +25943,18 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, use_hpf_num = 2; curr_hpf = curr_hpf2; actual_log2_pwr = - wlc_phy_nbits( - tot_pwr[0]); + wlc_phy_nbits(tot_pwr[0]); } } hpf_change = desired_log2_pwr - actual_log2_pwr; curr_hpf += hpf_change; curr_hpf = max(min_t(u16, curr_hpf, 10), 0); - if (use_hpf_num == 1) + if (use_hpf_num == 1) { curr_hpf1 = curr_hpf; - else + } else { curr_hpf2 = curr_hpf; + } } wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), @@ -25913,12 +25967,15 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, if (first_playtone) { bcmerror = wlc_phy_tx_tone_nphy(pi, 4000, - (u16) (pi->nphy_rxcalparams & - 0xffff), 0, 0, true); + (u16) (pi-> + nphy_rxcalparams + & + 0xffff), + 0, 0, true); first_playtone = false; } else { - phy_bw = (CHSPEC_IS40(pi->radio_chanspec)) ? - 40 : 20; + phy_bw = + (CHSPEC_IS40(pi->radio_chanspec)) ? 40 : 20; wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 0, 0, true); } @@ -25929,10 +25986,12 @@ wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); - i_pwr = (est[rx_core].i_pwr + - num_samps / 2) / num_samps; - q_pwr = (est[rx_core].q_pwr + - num_samps / 2) / num_samps; + i_pwr = + (est[rx_core].i_pwr + + num_samps / 2) / num_samps; + q_pwr = + (est[rx_core].q_pwr + + num_samps / 2) / num_samps; tot_pwr[gain_pass] = i_pwr + q_pwr; } else { @@ -25979,14 +26038,16 @@ int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, u8 cal_type, bool debug) { - if (NREV_GE(pi->pubpi.phy_rev, 7)) - cal_type = 0; + if (NREV_GE(pi->pubpi.phy_rev, 7)) { - if (NREV_GE(pi->pubpi.phy_rev, 3)) + cal_type = 0; + } + if (NREV_GE(pi->pubpi.phy_rev, 3)) { return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type, debug); - else + } else { return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug); + } } static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi) @@ -25994,37 +26055,46 @@ static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi) int j, type = 2; u16 addr_offset = 0x2c5; - for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) + for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) { write_phy_reg(pi, addr_offset + j, NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]); + } } static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi) { int j, type; - u16 addr_offset[] = { 0x186, 0x195, 0x2c5}; + u16 addr_offset[] = { 0x186, 0x195, + 0x2c5 + }; for (type = 0; type < 3; type++) { - for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) + for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) { write_phy_reg(pi, addr_offset[type] + j, NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]); + } } if (IS40MHZ(pi)) { - for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) + for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) { write_phy_reg(pi, 0x186 + j, NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]); + } } else { if (CHSPEC_IS5G(pi->radio_chanspec)) { - for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) + for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) { write_phy_reg(pi, 0x186 + j, - NPHY_IPA_REV4_txdigi_filtcoeffs[5][j]); + NPHY_IPA_REV4_txdigi_filtcoeffs[5] + [j]); + } } if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { - for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) + for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) { write_phy_reg(pi, 0x2c5 + j, - NPHY_IPA_REV4_txdigi_filtcoeffs[6][j]); + NPHY_IPA_REV4_txdigi_filtcoeffs[6] + [j]); + } } } } @@ -26034,13 +26104,15 @@ static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi) int j; if (IS40MHZ(pi)) { - for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) + for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) { write_phy_reg(pi, 0x195 + j, NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]); + } } else { - for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) + for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) { write_phy_reg(pi, 0x186 + j, NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]); + } } } @@ -26066,39 +26138,55 @@ static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi) u32 *tx_pwrctrl_tbl = NULL; if (CHSPEC_IS2G(pi->radio_chanspec)) { + if (NREV_GE(pi->pubpi.phy_rev, 7)) { + if ((pi->pubpi.radiorev == 4) - || (pi->pubpi.radiorev == 6)) + || (pi->pubpi.radiorev == 6)) { + tx_pwrctrl_tbl = - nphy_tpc_txgain_ipa_2g_2057rev4n6; - else if (pi->pubpi.radiorev == 3) + nphy_tpc_txgain_ipa_2g_2057rev4n6; + } else if (pi->pubpi.radiorev == 3) { + tx_pwrctrl_tbl = - nphy_tpc_txgain_ipa_2g_2057rev3; - else if (pi->pubpi.radiorev == 5) + nphy_tpc_txgain_ipa_2g_2057rev3; + } else if (pi->pubpi.radiorev == 5) { + tx_pwrctrl_tbl = - nphy_tpc_txgain_ipa_2g_2057rev5; - else if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) + nphy_tpc_txgain_ipa_2g_2057rev5; + } else if ((pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == 8)) { + tx_pwrctrl_tbl = - nphy_tpc_txgain_ipa_2g_2057rev7; + nphy_tpc_txgain_ipa_2g_2057rev7; + } + } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { + tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6; } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { + tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5; } else { + tx_pwrctrl_tbl = nphy_tpc_txgain_ipa; } + } else { if (NREV_GE(pi->pubpi.phy_rev, 7)) { if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || - (pi->pubpi.radiorev == 6)) + (pi->pubpi.radiorev == 6)) { + tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057; - else if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) + } else if ((pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == 8)) { + tx_pwrctrl_tbl = - nphy_tpc_txgain_ipa_5g_2057rev7; + nphy_tpc_txgain_ipa_5g_2057rev7; + } + } else { tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g; } @@ -26119,45 +26207,51 @@ wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, if (NREV_GE(pi->pubpi.phy_rev, 7)) { if (NREV_IS(pi->pubpi.phy_rev, 7) - || NREV_GE(pi->pubpi.phy_rev, 8)) - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 7), - wlc_phy_read_lpf_bw_ctl_nphy - (pi, - 0), 0, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID1); + || NREV_GE(pi->pubpi.phy_rev, 8)) { + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), + wlc_phy_read_lpf_bw_ctl_nphy + (pi, 0), 0, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + } if (CHSPEC_IS2G(pi->radio_chanspec)) { - if (pi->pubpi.radiorev == 5) + if (pi->pubpi.radiorev == 5) { mixgain = (core == 0) ? 0x20 : 0x00; - else if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) + + } else if ((pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == 8)) { + mixgain = 0x00; - else if ((pi->pubpi.radiorev <= 4) - || (pi->pubpi.radiorev == 6)) + + } else if ((pi->pubpi.radiorev <= 4) + || (pi->pubpi.radiorev == 6)) { + mixgain = 0x00; + } + } else { if ((pi->pubpi.radiorev == 4) || - (pi->pubpi.radiorev == 6)) + (pi->pubpi.radiorev == 6)) { + mixgain = 0x50; - else if ((pi->pubpi.radiorev == 3) - || (pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) + } else if ((pi->pubpi.radiorev == 3) + || (pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == 8)) { + mixgain = 0x0; + } } wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), mixgain, (1 << core), 0, NPHY_REV7_RFCTRLOVERRIDE_ID0); - wlc_phy_rfctrl_override_1tomany_nphy( - pi, - NPHY_REV7_RfctrlOverride_cmd_tx_pu, - 1, (1 << core), 0); - wlc_phy_rfctrl_override_1tomany_nphy( - pi, - NPHY_REV7_RfctrlOverride_cmd_tx_pu, - 0, (1 << off_core), 0); + wlc_phy_rfctrl_override_1tomany_nphy(pi, + NPHY_REV7_RfctrlOverride_cmd_tx_pu, + 1, (1 << core), 0); + wlc_phy_rfctrl_override_1tomany_nphy(pi, + NPHY_REV7_RfctrlOverride_cmd_tx_pu, + 0, (1 << off_core), 0); wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 0, @@ -26194,11 +26288,11 @@ wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa6 : 0xa7); state->afeoverride[core] = - read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); + read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); state->afectrl[off_core] = - read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6); + read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6); state->afeoverride[off_core] = - read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f); + read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f); mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0); @@ -26212,64 +26306,74 @@ wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, if (CHSPEC_IS2G(pi->radio_chanspec)) { state->pwrup[core] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - TXRXCOUPLE_2G_PWRUP); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + TXRXCOUPLE_2G_PWRUP); state->atten[core] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - TXRXCOUPLE_2G_ATTEN); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + TXRXCOUPLE_2G_ATTEN); state->pwrup[off_core] = - READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, - TXRXCOUPLE_2G_PWRUP); + READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, + TXRXCOUPLE_2G_PWRUP); state->atten[off_core] = - READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, - TXRXCOUPLE_2G_ATTEN); + READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, + TXRXCOUPLE_2G_ATTEN); WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TXRXCOUPLE_2G_PWRUP, 0xc); if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || - (pi->pubpi.radiorev == 6)) + (pi->pubpi.radiorev == 6)) { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TXRXCOUPLE_2G_ATTEN, 0xf0); - else if (pi->pubpi.radiorev == 5) + + } else if (pi->pubpi.radiorev == 5) { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TXRXCOUPLE_2G_ATTEN, (core == 0) ? 0xf7 : 0xf2); - else if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) + + } else if ((pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == 8)) { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TXRXCOUPLE_2G_ATTEN, 0xf0); + } + WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, TXRXCOUPLE_2G_PWRUP, 0x0); WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, TXRXCOUPLE_2G_ATTEN, 0xff); + } else { state->pwrup[core] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - TXRXCOUPLE_5G_PWRUP); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + TXRXCOUPLE_5G_PWRUP); state->atten[core] = - READ_RADIO_REG3(pi, RADIO_2057, TX, core, - TXRXCOUPLE_5G_ATTEN); + READ_RADIO_REG3(pi, RADIO_2057, TX, core, + TXRXCOUPLE_5G_ATTEN); state->pwrup[off_core] = - READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, - TXRXCOUPLE_5G_PWRUP); + READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, + TXRXCOUPLE_5G_PWRUP); state->atten[off_core] = - READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, - TXRXCOUPLE_5G_ATTEN); + READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, + TXRXCOUPLE_5G_ATTEN); WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TXRXCOUPLE_5G_PWRUP, 0xc); if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) + || (pi->pubpi.radiorev == 8)) { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TXRXCOUPLE_5G_ATTEN, 0xf4); - else + } else { WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TXRXCOUPLE_5G_ATTEN, 0xf0); + } WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, TXRXCOUPLE_5G_PWRUP, 0x0); @@ -26307,7 +26411,7 @@ wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa6 : 0xa7); state->afeoverride[core] = - read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); + read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0); @@ -26318,15 +26422,15 @@ wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); state->vga_master[core] = - READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER); + READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER); WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b); if (CHSPEC_IS2G(pi->radio_chanspec)) { state->fbmix[core] = - READ_RADIO_REG2(pi, RADIO_2056, RX, core, - TXFBMIX_G); + READ_RADIO_REG2(pi, RADIO_2056, RX, core, + TXFBMIX_G); state->intpa_master[core] = - READ_RADIO_REG2(pi, RADIO_2056, TX, core, - INTPAG_MASTER); + READ_RADIO_REG2(pi, RADIO_2056, TX, core, + INTPAG_MASTER); WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G, 0x03); @@ -26334,11 +26438,11 @@ wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, INTPAG_MASTER, 0x04); } else { state->fbmix[core] = - READ_RADIO_REG2(pi, RADIO_2056, RX, core, - TXFBMIX_A); + READ_RADIO_REG2(pi, RADIO_2056, RX, core, + TXFBMIX_A); state->intpa_master[core] = - READ_RADIO_REG2(pi, RADIO_2056, TX, core, - INTPAA_MASTER); + READ_RADIO_REG2(pi, RADIO_2056, TX, core, + INTPAA_MASTER); WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A, 0x03); @@ -26388,17 +26492,15 @@ wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi, } } - if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 2), - 1, 0x3, 0, - NPHY_REV7_RFCTRLOVERRIDE_ID0); - else - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 2), - 0, 0x3, 1, - NPHY_REV7_RFCTRLOVERRIDE_ID0); - + if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) { + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), + 1, 0x3, 0, + NPHY_REV7_RFCTRLOVERRIDE_ID0); + } else { + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), + 0, 0x3, 1, + NPHY_REV7_RFCTRLOVERRIDE_ID0); + } wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 0, 0x3, 1, NPHY_REV7_RFCTRLOVERRIDE_ID1); @@ -26445,12 +26547,13 @@ wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi, (state->mm & 0xff)); if (NREV_IS(pi->pubpi.phy_rev, 7) - || NREV_GE(pi->pubpi.phy_rev, 8)) - wlc_phy_rfctrl_override_nphy_rev7( - pi, (0x1 << 7), 0, 0, - 1, - NPHY_REV7_RFCTRLOVERRIDE_ID1); + || NREV_GE(pi->pubpi.phy_rev, 8)) { + wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0, + 1, + NPHY_REV7_RFCTRLOVERRIDE_ID1); + } } else { + wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1); wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1); wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1); @@ -26498,8 +26601,9 @@ wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start, sz = end - start + 1; buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC); - if (NULL == buf) + if (NULL == buf) { return; + } src = buf; dst = buf + NPHY_PAPD_EPS_TBL_SIZE; @@ -26515,8 +26619,7 @@ wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start, s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7; phy_a1 = end - min(end, (winsz >> 1)); - phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, - end + (winsz >> 1)); + phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, end + (winsz >> 1)); phy_a3 = phy_a2 - phy_a1 + 1; phy_a6 = 0; phy_a7 = 0; @@ -26564,29 +26667,33 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, phy_a9 = wlc_phy_get_tx_gain_nphy(pi); - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { phy_a5 = ((phy_a9.txlpf[core] << 15) | (phy_a9.txgm[core] << 12) | (phy_a9.pga[core] << 8) | (txgains->gains.pad[core] << 3) | (phy_a9.ipa[core])); - else + } else { phy_a5 = ((phy_a9.txlpf[core] << 15) | (phy_a9.txgm[core] << 12) | (txgains->gains.pga[core] << 8) | (phy_a9.pad[core] << 3) | (phy_a9.ipa[core])); + } - wlc_phy_rfctrl_override_1tomany_nphy( - pi, - NPHY_REV7_RfctrlOverride_cmd_txgain, - phy_a5, (1 << core), 0); + wlc_phy_rfctrl_override_1tomany_nphy(pi, + NPHY_REV7_RfctrlOverride_cmd_txgain, + phy_a5, (1 << core), 0); if (CHSPEC_IS2G(pi->radio_chanspec)) { if ((pi->pubpi.radiorev <= 4) - || (pi->pubpi.radiorev == 6)) + || (pi->pubpi.radiorev == 6)) { + m[core] = IS40MHZ(pi) ? 60 : 79; - else + } else { + m[core] = IS40MHZ(pi) ? 45 : 64; + } + } else { m[core] = IS40MHZ(pi) ? 75 : 107; } @@ -26619,15 +26726,16 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, if (cal_mode == CAL_GCTRL) { if ((pi->pubpi.radiorev == 5) - && (CHSPEC_IS2G(pi->radio_chanspec))) + && (CHSPEC_IS2G(pi->radio_chanspec))) { phy_a1 = 55; - else if (((pi->pubpi.radiorev == 7) && - (CHSPEC_IS2G(pi->radio_chanspec))) || - ((pi->pubpi.radiorev == 8) && - (CHSPEC_IS2G(pi->radio_chanspec)))) + } else if (((pi->pubpi.radiorev == 7) && + (CHSPEC_IS2G(pi->radio_chanspec))) || + ((pi->pubpi.radiorev == 8) && + (CHSPEC_IS2G(pi->radio_chanspec)))) { phy_a1 = 60; - else + } else { phy_a1 = 63; + } } else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) { @@ -26688,14 +26796,14 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, 32, &phy_a8); if (cal_mode != CAL_GCTRL) { - if (CHSPEC_IS5G(pi->radio_chanspec)) + if (CHSPEC_IS5G(pi->radio_chanspec)) { wlc_phy_a1_nphy(pi, core, 5, 0, 35); + } } - wlc_phy_rfctrl_override_1tomany_nphy( - pi, - NPHY_REV7_RfctrlOverride_cmd_txgain, - phy_a5, (1 << core), 1); + wlc_phy_rfctrl_override_1tomany_nphy(pi, + NPHY_REV7_RfctrlOverride_cmd_txgain, + phy_a5, (1 << core), 1); } else { @@ -26707,7 +26815,7 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, phy_a5 = 0x00f7 | (phy_a4 << 8); else - if (NREV_IS(pi->pubpi.phy_rev, 5)) + if (NREV_IS(pi->pubpi.phy_rev, 5)) phy_a5 = 0x10f7 | (phy_a4 << 8); else phy_a5 = 0x50f7 | (phy_a4 << 8); @@ -26726,10 +26834,11 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, } } - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { m[core] = IS40MHZ(pi) ? 45 : 64; - else + } else { m[core] = IS40MHZ(pi) ? 75 : 107; + } m[phy_a7] = 0; wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]); @@ -26819,8 +26928,9 @@ wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3, 32, &phy_a8); - if (cal_mode != CAL_GCTRL) + if (cal_mode != CAL_GCTRL) { wlc_phy_a1_nphy(pi, core, 5, 0, 40); + } } } @@ -26853,44 +26963,40 @@ static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) if (pi->pubpi.radiorev == 5) { phy_a15 = pad_gain_codes_used_2057rev5; - phy_a13 = - sizeof(pad_gain_codes_used_2057rev5) / - sizeof(pad_gain_codes_used_2057rev5 - [0]) - 1; + phy_a13 = sizeof(pad_gain_codes_used_2057rev5) / + sizeof(pad_gain_codes_used_2057rev5[0]) - 1; } else if ((pi->pubpi.radiorev == 7) || (pi->pubpi.radiorev == 8)) { phy_a15 = pad_gain_codes_used_2057rev7; - phy_a13 = - sizeof(pad_gain_codes_used_2057rev7) / - sizeof(pad_gain_codes_used_2057rev7 - [0]) - 1; + phy_a13 = sizeof(pad_gain_codes_used_2057rev7) / + sizeof(pad_gain_codes_used_2057rev7[0]) - 1; } else { phy_a15 = pad_all_gain_codes_2057; phy_a13 = sizeof(pad_all_gain_codes_2057) / - sizeof(pad_all_gain_codes_2057[0]) - - 1; + sizeof(pad_all_gain_codes_2057[0]) - 1; } } else { phy_a15 = pga_all_gain_codes_2057; phy_a13 = sizeof(pga_all_gain_codes_2057) / - sizeof(pga_all_gain_codes_2057[0]) - 1; + sizeof(pga_all_gain_codes_2057[0]) - 1; } phy_a14 = 0; for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) { - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { phy_a4.gains.pad[core] = - (u16) phy_a15[phy_a12]; - else + (u16) phy_a15[phy_a12]; + } else { phy_a4.gains.pga[core] = - (u16) phy_a15[phy_a12]; + (u16) phy_a15[phy_a12]; + } wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core); @@ -26907,9 +27013,9 @@ static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) (phy_a8 == 4095) || (phy_a8 == -4096)); if (!phy_a6 && (phy_a3 != phy_a5)) { - if (!phy_a3) + if (!phy_a3) { phy_a12 -= (u8) phy_a1; - + } phy_a11 = true; break; } @@ -26920,11 +27026,11 @@ static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) phy_a12 -= (u8) phy_a1; if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) { - if (phy_a12 < phy_a14) + if (phy_a12 < phy_a14) { phy_a12 = phy_a14; - else + } else { phy_a12 = phy_a13; - + } phy_a11 = true; break; } @@ -26953,9 +27059,9 @@ static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) (phy_a8 == 4095) || (phy_a8 == -4096)); if (!phy_a6 && (phy_a3 != phy_a5)) { - if (!phy_a3) + if (!phy_a3) { phy_a12 -= (u8) phy_a1; - + } phy_a11 = true; break; } @@ -26966,11 +27072,11 @@ static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) phy_a12 -= (u8) phy_a1; if ((phy_a12 < 0) || (phy_a12 > 127)) { - if (phy_a12 < 0) + if (phy_a12 < 0) { phy_a12 = 0; - else + } else { phy_a12 = 127; - + } phy_a11 = true; break; } @@ -26981,10 +27087,11 @@ static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) } - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { return (u8) phy_a15[phy_a12]; - else + } else { return (u8) phy_a12; + } } @@ -27008,9 +27115,11 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) if (pi->nphy_papd_skip == 1) return; - phy_b3 = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); - if (!phy_b3) + phy_b3 = + (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); + if (!phy_b3) { wlapi_suspend_mac_and_wait(pi->sh->physhim); + } wlc_phy_stay_in_carriersearch_nphy(pi, true); @@ -27018,7 +27127,7 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) pi->nphy_papd_tx_gain_at_last_cal[phy_b5] = - wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5); + wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5); pi->nphy_papd_last_cal = pi->sh->now; pi->nphy_papd_recal_counter++; @@ -27039,13 +27148,14 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { s32 i, val = 0; - for (i = 0; i < 64; i++) + for (i = 0; i < 64; i++) { wlc_phy_table_write_nphy(pi, ((phy_b5 == PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 : NPHY_TBL_ID_EPSILONTBL1), 1, i, 32, &val); + } } wlc_phy_ipa_restore_tx_digi_filts_nphy(pi); @@ -27056,60 +27166,58 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) if (NREV_GE(pi->pubpi.phy_rev, 7)) { if (CHSPEC_IS2G(pi->radio_chanspec)) { + if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) { + pi->nphy_papd_cal_gain_index[phy_b5] = - 23; + 23; + } else if (pi->pubpi.radiorev == 5) { + pi->nphy_papd_cal_gain_index[phy_b5] = - 0; + 0; pi->nphy_papd_cal_gain_index[phy_b5] = - wlc_phy_a3_nphy( - pi, - pi-> - nphy_papd_cal_gain_index - [phy_b5], - phy_b5); + wlc_phy_a3_nphy(pi, + pi-> + nphy_papd_cal_gain_index + [phy_b5], phy_b5); } else if ((pi->pubpi.radiorev == 7) || (pi->pubpi.radiorev == 8)) { pi->nphy_papd_cal_gain_index[phy_b5] = - 0; + 0; pi->nphy_papd_cal_gain_index[phy_b5] = - wlc_phy_a3_nphy( - pi, - pi-> - nphy_papd_cal_gain_index - [phy_b5], - phy_b5); + wlc_phy_a3_nphy(pi, + pi-> + nphy_papd_cal_gain_index + [phy_b5], phy_b5); } phy_b1[phy_b5].gains.pad[phy_b5] = - pi->nphy_papd_cal_gain_index[phy_b5]; + pi->nphy_papd_cal_gain_index[phy_b5]; } else { pi->nphy_papd_cal_gain_index[phy_b5] = 0; pi->nphy_papd_cal_gain_index[phy_b5] = - wlc_phy_a3_nphy( - pi, - pi-> - nphy_papd_cal_gain_index - [phy_b5], phy_b5); + wlc_phy_a3_nphy(pi, + pi-> + nphy_papd_cal_gain_index + [phy_b5], phy_b5); phy_b1[phy_b5].gains.pga[phy_b5] = - pi->nphy_papd_cal_gain_index[phy_b5]; + pi->nphy_papd_cal_gain_index[phy_b5]; } } else { phy_b1[phy_b5].useindex = true; phy_b1[phy_b5].index = 16; phy_b1[phy_b5].index = - wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, - phy_b5); + wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, phy_b5); pi->nphy_papd_cal_gain_index[phy_b5] = - 15 - ((phy_b1[phy_b5].index) >> 3); + 15 - ((phy_b1[phy_b5].index) >> 3); } switch (pi->nphy_papd_cal_type) { @@ -27121,24 +27229,27 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) break; } - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2); + } } - if (NREV_LT(pi->pubpi.phy_rev, 7)) + if (NREV_LT(pi->pubpi.phy_rev, 7)) { wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2); + } for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { int eps_offset = 0; if (NREV_GE(pi->pubpi.phy_rev, 7)) { if (CHSPEC_IS2G(pi->radio_chanspec)) { - if (pi->pubpi.radiorev == 3) + if (pi->pubpi.radiorev == 3) { eps_offset = -2; - else if (pi->pubpi.radiorev == 5) + } else if (pi->pubpi.radiorev == 5) { eps_offset = 3; - else + } else { eps_offset = -1; + } } else { eps_offset = 2; } @@ -27149,70 +27260,74 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) { - phy_b12 = -( - nphy_papd_padgain_dlt_2g_2057rev3n4 - [phy_b8] + 1) / 2; + phy_b12 = + - + (nphy_papd_padgain_dlt_2g_2057rev3n4 + [phy_b8] + + 1) / 2; phy_b10 = -1; } else if (pi->pubpi.radiorev == 5) { - phy_b12 = -( - nphy_papd_padgain_dlt_2g_2057rev5 - [phy_b8] + 1) / 2; + phy_b12 = + -(nphy_papd_padgain_dlt_2g_2057rev5 + [phy_b8] + + 1) / 2; } else if ((pi->pubpi.radiorev == 7) || (pi->pubpi.radiorev == 8)) { - phy_b12 = -( - nphy_papd_padgain_dlt_2g_2057rev7 - [phy_b8] + 1) / 2; + phy_b12 = + -(nphy_papd_padgain_dlt_2g_2057rev7 + [phy_b8] + + 1) / 2; } } else { phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5]; if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || - (pi->pubpi.radiorev == 6)) + (pi->pubpi.radiorev == 6)) { + phy_b11 = + -(nphy_papd_pgagain_dlt_5g_2057 + [phy_b7] + + 1) / 2; + } else if ((pi->pubpi.radiorev == 7) + || (pi->pubpi.radiorev == 8)) { phy_b11 = - -(nphy_papd_pgagain_dlt_5g_2057 - [phy_b7] - + 1) / 2; - else if ((pi->pubpi.radiorev == 7) - || (pi->pubpi.radiorev == 8)) - phy_b11 = -( - nphy_papd_pgagain_dlt_5g_2057rev7 - [phy_b7] + 1) / 2; + -(nphy_papd_pgagain_dlt_5g_2057rev7 + [phy_b7] + + 1) / 2; + } phy_b10 = -9; } - if (CHSPEC_IS2G(pi->radio_chanspec)) + if (CHSPEC_IS2G(pi->radio_chanspec)) { phy_b6 = - -60 + 27 + eps_offset + phy_b12 + - phy_b10; - else + -60 + 27 + eps_offset + phy_b12 + phy_b10; + } else { phy_b6 = - -60 + 27 + eps_offset + phy_b11 + - phy_b10; + -60 + 27 + eps_offset + phy_b11 + phy_b10; + } mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 : 0x29c, (0x1ff << 7), (phy_b6) << 7); pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6; } else { - if (NREV_LT(pi->pubpi.phy_rev, 5)) + if (NREV_LT(pi->pubpi.phy_rev, 5)) { eps_offset = 4; - else + } else { eps_offset = 2; + } phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3); if (CHSPEC_IS2G(pi->radio_chanspec)) { phy_b11 = - -(nphy_papd_pga_gain_delta_ipa_2g[ - phy_b7] + - 1) / 2; + -(nphy_papd_pga_gain_delta_ipa_2g[phy_b7] + + 1) / 2; phy_b10 = 0; } else { phy_b11 = - -(nphy_papd_pga_gain_delta_ipa_5g[ - phy_b7] + - 1) / 2; + -(nphy_papd_pga_gain_delta_ipa_5g[phy_b7] + + 1) / 2; phy_b10 = -9; } @@ -27256,16 +27371,17 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) if (phy_b4 == PHY_TPC_HW_OFF) { wlc_phy_txpwr_index_nphy(pi, (1 << 0), (s8) (pi->nphy_txpwrindex[0]. - index_internal), false); + index_internal), false); wlc_phy_txpwr_index_nphy(pi, (1 << 1), (s8) (pi->nphy_txpwrindex[1]. - index_internal), false); + index_internal), false); } wlc_phy_stay_in_carriersearch_nphy(pi, false); - if (!phy_b3) + if (!phy_b3) { wlapi_enable_mac(pi->sh->physhim); + } } void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi) @@ -27307,10 +27423,11 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi) } } - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { txpi[0] = txpi[1] = 30; - else if (NREV_GE(pi->pubpi.phy_rev, 3)) + } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { txpi[0] = txpi[1] = 40; + } if (NREV_LT(pi->pubpi.phy_rev, 7)) { @@ -27330,36 +27447,37 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi) if (NREV_GE(phyrev, 3)) { if (PHY_IPA(pi)) { u32 *tx_gaintbl = - wlc_phy_get_ipa_gaintbl_nphy(pi); + wlc_phy_get_ipa_gaintbl_nphy(pi); txgain = tx_gaintbl[txpi[core]]; } else { if (CHSPEC_IS5G(pi->radio_chanspec)) { if (NREV_IS(phyrev, 3)) { txgain = - nphy_tpc_5GHz_txgain_rev3 - [txpi[core]]; + nphy_tpc_5GHz_txgain_rev3 + [txpi[core]]; } else if (NREV_IS(phyrev, 4)) { - txgain = ( - pi->srom_fem5g.extpagain == - 3) ? - nphy_tpc_5GHz_txgain_HiPwrEPA - [txpi[core]] : - nphy_tpc_5GHz_txgain_rev4 - [txpi[core]]; + txgain = + (pi->srom_fem5g.extpagain == + 3) ? + nphy_tpc_5GHz_txgain_HiPwrEPA + [txpi[core]] : + nphy_tpc_5GHz_txgain_rev4 + [txpi[core]]; } else { txgain = - nphy_tpc_5GHz_txgain_rev5 - [txpi[core]]; + nphy_tpc_5GHz_txgain_rev5 + [txpi[core]]; } } else { if (NREV_GE(phyrev, 5) && (pi->srom_fem2g.extpagain == 3)) { txgain = - nphy_tpc_txgain_HiPwrEPA - [txpi[core]]; + nphy_tpc_txgain_HiPwrEPA + [txpi[core]]; } else { - txgain = nphy_tpc_txgain_rev3 - [txpi[core]]; + txgain = + nphy_tpc_txgain_rev3[txpi + [core]]; } } } @@ -27379,12 +27497,12 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi) bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1); - if (NREV_GE(phyrev, 3)) + if (NREV_GE(phyrev, 3)) { mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : 0xa5), (0x1 << 8), (0x1 << 8)); - else + } else { mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14)); - + } write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain); wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, @@ -27444,8 +27562,9 @@ wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset, { u8 rate; - for (rate = rate_start; rate <= rate_end; rate++) + for (rate = rate_start; rate <= rate_end; rate++) { srom_max[rate] -= 2 * pwr_offset; + } } void @@ -27484,8 +27603,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) u16 pwr_offsets1[2], *pwr_offsets2 = NULL; u8 *tx_srom_max_rate = NULL; - for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); - band_num++) { + for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) { switch (band_num) { case 0: @@ -27501,7 +27619,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff); pwr_offsets1[1] = - (u16) (pi->ofdm2gpo >> 16) & 0xffff; + (u16) (pi->ofdm2gpo >> 16) & 0xffff; pwr_offsets2 = pi->mcs2gpo; @@ -27518,7 +27636,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff); pwr_offsets1[1] = - (u16) (pi->ofdm5gpo >> 16) & 0xffff; + (u16) (pi->ofdm5gpo >> 16) & 0xffff; pwr_offsets2 = pi->mcs5gpo; @@ -27535,7 +27653,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff); pwr_offsets1[1] = - (u16) (pi->ofdm5glpo >> 16) & 0xffff; + (u16) (pi->ofdm5glpo >> 16) & 0xffff; pwr_offsets2 = pi->mcs5glpo; @@ -27552,7 +27670,7 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff); pwr_offsets1[1] = - (u16) (pi->ofdm5ghpo >> 16) & 0xffff; + (u16) (pi->ofdm5ghpo >> 16) & 0xffff; pwr_offsets2 = pi->mcs5ghpo; @@ -27578,10 +27696,12 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) TXP_FIRST_MCS_20_CDD, TXP_LAST_MCS_20_CDD); - if (NREV_GE(pi->pubpi.phy_rev, 3)) + if (NREV_GE(pi->pubpi.phy_rev, 3)) { + wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo, TXP_FIRST_MCS_20_CDD, TXP_LAST_MCS_20_CDD); + } wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, TXP_FIRST_OFDM_20_CDD, @@ -27593,11 +27713,13 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) TXP_FIRST_MCS_20_STBC, TXP_LAST_MCS_20_STBC); - if (NREV_GE(pi->pubpi.phy_rev, 3)) + if (NREV_GE(pi->pubpi.phy_rev, 3)) { + wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_stbcpo, TXP_FIRST_MCS_20_STBC, TXP_LAST_MCS_20_STBC); + } wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, &pwr_offsets2[2], tmp_max_pwr, @@ -27651,21 +27773,21 @@ void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) } else { for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 = - TXP_FIRST_OFDM; - rate1 <= TXP_LAST_MCS_40_SDM; + TXP_FIRST_OFDM; rate1 <= TXP_LAST_MCS_40_SDM; rate1++, rate2++) tx_srom_max_rate[rate1] = - tx_srom_max_rate[rate2]; + tx_srom_max_rate[rate2]; } - if (NREV_GE(pi->pubpi.phy_rev, 3)) + if (NREV_GE(pi->pubpi.phy_rev, 3)) { wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_bw40po, TXP_FIRST_OFDM_40_SISO, TXP_LAST_MCS_40_SDM); + } tx_srom_max_rate[TXP_MCS_32] = - tx_srom_max_rate[TXP_FIRST_MCS_40_CDD]; + tx_srom_max_rate[TXP_FIRST_MCS_40_CDD]; } return; @@ -27676,8 +27798,10 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) u16 bw40po, cddpo, stbcpo, bwduppo; uint band_num; - if (pi->sh->sromrev >= 9) + if (pi->sh->sromrev >= 9) { + return; + } bw40po = (u16) PHY_GETINTVAR(pi, "bw40po"); pi->bw402gpo = bw40po & 0xf; @@ -27703,35 +27827,34 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) pi->bwdup5glpo = (bwduppo & 0xf00) >> 8; pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12; - for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); - band_num++) { + for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) { switch (band_num) { case 0: pi->nphy_txpid2g[PHY_CORE_0] = - (u8) PHY_GETINTVAR(pi, "txpid2ga0"); + (u8) PHY_GETINTVAR(pi, "txpid2ga0"); pi->nphy_txpid2g[PHY_CORE_1] = - (u8) PHY_GETINTVAR(pi, "txpid2ga1"); + (u8) PHY_GETINTVAR(pi, "txpid2ga1"); pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g = - (s8) PHY_GETINTVAR(pi, "maxp2ga0"); + (s8) PHY_GETINTVAR(pi, "maxp2ga0"); pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g = - (s8) PHY_GETINTVAR(pi, "maxp2ga1"); + (s8) PHY_GETINTVAR(pi, "maxp2ga1"); pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 = - (s16) PHY_GETINTVAR(pi, "pa2gw0a0"); + (s16) PHY_GETINTVAR(pi, "pa2gw0a0"); pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 = - (s16) PHY_GETINTVAR(pi, "pa2gw0a1"); + (s16) PHY_GETINTVAR(pi, "pa2gw0a1"); pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 = - (s16) PHY_GETINTVAR(pi, "pa2gw1a0"); + (s16) PHY_GETINTVAR(pi, "pa2gw1a0"); pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 = - (s16) PHY_GETINTVAR(pi, "pa2gw1a1"); + (s16) PHY_GETINTVAR(pi, "pa2gw1a1"); pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 = - (s16) PHY_GETINTVAR(pi, "pa2gw2a0"); + (s16) PHY_GETINTVAR(pi, "pa2gw2a0"); pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 = - (s16) PHY_GETINTVAR(pi, "pa2gw2a1"); + (s16) PHY_GETINTVAR(pi, "pa2gw2a1"); pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g = - (s8) PHY_GETINTVAR(pi, "itt2ga0"); + (s8) PHY_GETINTVAR(pi, "itt2ga0"); pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g = - (s8) PHY_GETINTVAR(pi, "itt2ga1"); + (s8) PHY_GETINTVAR(pi, "itt2ga1"); pi->cck2gpo = (u16) PHY_GETINTVAR(pi, "cck2gpo"); @@ -27749,29 +27872,29 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) case 1: pi->nphy_txpid5g[PHY_CORE_0] = - (u8) PHY_GETINTVAR(pi, "txpid5ga0"); + (u8) PHY_GETINTVAR(pi, "txpid5ga0"); pi->nphy_txpid5g[PHY_CORE_1] = - (u8) PHY_GETINTVAR(pi, "txpid5ga1"); + (u8) PHY_GETINTVAR(pi, "txpid5ga1"); pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm = - (s8) PHY_GETINTVAR(pi, "maxp5ga0"); + (s8) PHY_GETINTVAR(pi, "maxp5ga0"); pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm = - (s8) PHY_GETINTVAR(pi, "maxp5ga1"); + (s8) PHY_GETINTVAR(pi, "maxp5ga1"); pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 = - (s16) PHY_GETINTVAR(pi, "pa5gw0a0"); + (s16) PHY_GETINTVAR(pi, "pa5gw0a0"); pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 = - (s16) PHY_GETINTVAR(pi, "pa5gw0a1"); + (s16) PHY_GETINTVAR(pi, "pa5gw0a1"); pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 = - (s16) PHY_GETINTVAR(pi, "pa5gw1a0"); + (s16) PHY_GETINTVAR(pi, "pa5gw1a0"); pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 = - (s16) PHY_GETINTVAR(pi, "pa5gw1a1"); + (s16) PHY_GETINTVAR(pi, "pa5gw1a1"); pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 = - (s16) PHY_GETINTVAR(pi, "pa5gw2a0"); + (s16) PHY_GETINTVAR(pi, "pa5gw2a0"); pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 = - (s16) PHY_GETINTVAR(pi, "pa5gw2a1"); + (s16) PHY_GETINTVAR(pi, "pa5gw2a1"); pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm = - (s8) PHY_GETINTVAR(pi, "itt5ga0"); + (s8) PHY_GETINTVAR(pi, "itt5ga0"); pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm = - (s8) PHY_GETINTVAR(pi, "itt5ga1"); + (s8) PHY_GETINTVAR(pi, "itt5ga1"); pi->ofdm5gpo = (u32) PHY_GETINTVAR(pi, "ofdm5gpo"); @@ -27787,90 +27910,90 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) case 2: pi->nphy_txpid5gl[0] = - (u8) PHY_GETINTVAR(pi, "txpid5gla0"); + (u8) PHY_GETINTVAR(pi, "txpid5gla0"); pi->nphy_txpid5gl[1] = - (u8) PHY_GETINTVAR(pi, "txpid5gla1"); + (u8) PHY_GETINTVAR(pi, "txpid5gla1"); pi->nphy_pwrctrl_info[0].max_pwr_5gl = - (s8) PHY_GETINTVAR(pi, "maxp5gla0"); + (s8) PHY_GETINTVAR(pi, "maxp5gla0"); pi->nphy_pwrctrl_info[1].max_pwr_5gl = - (s8) PHY_GETINTVAR(pi, "maxp5gla1"); + (s8) PHY_GETINTVAR(pi, "maxp5gla1"); pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 = - (s16) PHY_GETINTVAR(pi, "pa5glw0a0"); + (s16) PHY_GETINTVAR(pi, "pa5glw0a0"); pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 = - (s16) PHY_GETINTVAR(pi, "pa5glw0a1"); + (s16) PHY_GETINTVAR(pi, "pa5glw0a1"); pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 = - (s16) PHY_GETINTVAR(pi, "pa5glw1a0"); + (s16) PHY_GETINTVAR(pi, "pa5glw1a0"); pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 = - (s16) PHY_GETINTVAR(pi, "pa5glw1a1"); + (s16) PHY_GETINTVAR(pi, "pa5glw1a1"); pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 = - (s16) PHY_GETINTVAR(pi, "pa5glw2a0"); + (s16) PHY_GETINTVAR(pi, "pa5glw2a0"); pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 = - (s16) PHY_GETINTVAR(pi, "pa5glw2a1"); + (s16) PHY_GETINTVAR(pi, "pa5glw2a1"); pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0; pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0; pi->ofdm5glpo = (u32) PHY_GETINTVAR(pi, "ofdm5glpo"); pi->mcs5glpo[0] = - (u16) PHY_GETINTVAR(pi, "mcs5glpo0"); + (u16) PHY_GETINTVAR(pi, "mcs5glpo0"); pi->mcs5glpo[1] = - (u16) PHY_GETINTVAR(pi, "mcs5glpo1"); + (u16) PHY_GETINTVAR(pi, "mcs5glpo1"); pi->mcs5glpo[2] = - (u16) PHY_GETINTVAR(pi, "mcs5glpo2"); + (u16) PHY_GETINTVAR(pi, "mcs5glpo2"); pi->mcs5glpo[3] = - (u16) PHY_GETINTVAR(pi, "mcs5glpo3"); + (u16) PHY_GETINTVAR(pi, "mcs5glpo3"); pi->mcs5glpo[4] = - (u16) PHY_GETINTVAR(pi, "mcs5glpo4"); + (u16) PHY_GETINTVAR(pi, "mcs5glpo4"); pi->mcs5glpo[5] = - (u16) PHY_GETINTVAR(pi, "mcs5glpo5"); + (u16) PHY_GETINTVAR(pi, "mcs5glpo5"); pi->mcs5glpo[6] = - (u16) PHY_GETINTVAR(pi, "mcs5glpo6"); + (u16) PHY_GETINTVAR(pi, "mcs5glpo6"); pi->mcs5glpo[7] = - (u16) PHY_GETINTVAR(pi, "mcs5glpo7"); + (u16) PHY_GETINTVAR(pi, "mcs5glpo7"); break; case 3: pi->nphy_txpid5gh[0] = - (u8) PHY_GETINTVAR(pi, "txpid5gha0"); + (u8) PHY_GETINTVAR(pi, "txpid5gha0"); pi->nphy_txpid5gh[1] = - (u8) PHY_GETINTVAR(pi, "txpid5gha1"); + (u8) PHY_GETINTVAR(pi, "txpid5gha1"); pi->nphy_pwrctrl_info[0].max_pwr_5gh = - (s8) PHY_GETINTVAR(pi, "maxp5gha0"); + (s8) PHY_GETINTVAR(pi, "maxp5gha0"); pi->nphy_pwrctrl_info[1].max_pwr_5gh = - (s8) PHY_GETINTVAR(pi, "maxp5gha1"); + (s8) PHY_GETINTVAR(pi, "maxp5gha1"); pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 = - (s16) PHY_GETINTVAR(pi, "pa5ghw0a0"); + (s16) PHY_GETINTVAR(pi, "pa5ghw0a0"); pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 = - (s16) PHY_GETINTVAR(pi, "pa5ghw0a1"); + (s16) PHY_GETINTVAR(pi, "pa5ghw0a1"); pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 = - (s16) PHY_GETINTVAR(pi, "pa5ghw1a0"); + (s16) PHY_GETINTVAR(pi, "pa5ghw1a0"); pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 = - (s16) PHY_GETINTVAR(pi, "pa5ghw1a1"); + (s16) PHY_GETINTVAR(pi, "pa5ghw1a1"); pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 = - (s16) PHY_GETINTVAR(pi, "pa5ghw2a0"); + (s16) PHY_GETINTVAR(pi, "pa5ghw2a0"); pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 = - (s16) PHY_GETINTVAR(pi, "pa5ghw2a1"); + (s16) PHY_GETINTVAR(pi, "pa5ghw2a1"); pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0; pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0; pi->ofdm5ghpo = (u32) PHY_GETINTVAR(pi, "ofdm5ghpo"); pi->mcs5ghpo[0] = - (u16) PHY_GETINTVAR(pi, "mcs5ghpo0"); + (u16) PHY_GETINTVAR(pi, "mcs5ghpo0"); pi->mcs5ghpo[1] = - (u16) PHY_GETINTVAR(pi, "mcs5ghpo1"); + (u16) PHY_GETINTVAR(pi, "mcs5ghpo1"); pi->mcs5ghpo[2] = - (u16) PHY_GETINTVAR(pi, "mcs5ghpo2"); + (u16) PHY_GETINTVAR(pi, "mcs5ghpo2"); pi->mcs5ghpo[3] = - (u16) PHY_GETINTVAR(pi, "mcs5ghpo3"); + (u16) PHY_GETINTVAR(pi, "mcs5ghpo3"); pi->mcs5ghpo[4] = - (u16) PHY_GETINTVAR(pi, "mcs5ghpo4"); + (u16) PHY_GETINTVAR(pi, "mcs5ghpo4"); pi->mcs5ghpo[5] = - (u16) PHY_GETINTVAR(pi, "mcs5ghpo5"); + (u16) PHY_GETINTVAR(pi, "mcs5ghpo5"); pi->mcs5ghpo[6] = - (u16) PHY_GETINTVAR(pi, "mcs5ghpo6"); + (u16) PHY_GETINTVAR(pi, "mcs5ghpo6"); pi->mcs5ghpo[7] = - (u16) PHY_GETINTVAR(pi, "mcs5ghpo7"); + (u16) PHY_GETINTVAR(pi, "mcs5ghpo7"); break; } } @@ -27895,37 +28018,43 @@ static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) pi->srom_fem5g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain5g"); pi->srom_fem5g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange5g"); pi->srom_fem5g.triso = (u8) PHY_GETINTVAR(pi, "triso5g"); - if (PHY_GETVAR(pi, "antswctl5g")) + if (PHY_GETVAR(pi, "antswctl5g")) { + pi->srom_fem5g.antswctrllut = - (u8) PHY_GETINTVAR(pi, "antswctl5g"); - else + (u8) PHY_GETINTVAR(pi, "antswctl5g"); + } else { + pi->srom_fem5g.antswctrllut = - (u8) PHY_GETINTVAR(pi, "antswctl2g"); + (u8) PHY_GETINTVAR(pi, "antswctl2g"); + } wlc_phy_txpower_ipa_upd(pi); pi->phy_txcore_disable_temp = (s16) PHY_GETINTVAR(pi, "tempthresh"); - if (pi->phy_txcore_disable_temp == 0) + if (pi->phy_txcore_disable_temp == 0) { pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; + } pi->phy_tempsense_offset = (s8) PHY_GETINTVAR(pi, "tempoffset"); if (pi->phy_tempsense_offset != 0) { if (pi->phy_tempsense_offset > - (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) + (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) { pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET; - else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT + - NPHY_SROM_MINTEMPOFFSET)) + } else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT + + NPHY_SROM_MINTEMPOFFSET)) { pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET; - else + } else { pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT; + } } pi->phy_txcore_enable_temp = - pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP; + pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP; pi->phycal_tempdelta = (u8) PHY_GETINTVAR(pi, "phycal_tempdelta"); - if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) + if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) { pi->phycal_tempdelta = 0; + } wlc_phy_txpwr_srom_read_ppr_nphy(pi); @@ -27972,14 +28101,15 @@ static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi) for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { iqcomp = - (tbl_id == - 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) | - (iqloCalbuf[1] & 0x3ff) - : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) | - (iqloCalbuf[3] & 0x3ff); + (tbl_id == + 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) | + (iqloCalbuf[1] & 0x3ff) + : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) | + (iqloCalbuf[3] & 0x3ff); - for (idx = 0; idx < tbl_len; idx++) + for (idx = 0; idx < tbl_len; idx++) { regval[idx] = iqcomp; + } wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, regval); } @@ -27989,7 +28119,7 @@ static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi) tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { locomp = - (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]); + (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]); locomp_i = (s8) ((locomp >> 8) & 0xff); locomp_q = (s8) ((locomp) & 0xff); for (idx = 0; idx < tbl_len; idx++) { @@ -27998,12 +28128,11 @@ static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi) curr_locomp_q = locomp_q; } else { curr_locomp_i = (s8) ((locomp_i * - nphy_tpc_loscale[idx] + - 128) >> 8); + nphy_tpc_loscale[idx] + + 128) >> 8); curr_locomp_q = - (s8) ((locomp_q * - nphy_tpc_loscale[idx] + - 128) >> 8); + (s8) ((locomp_q * nphy_tpc_loscale[idx] + + 128) >> 8); } curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8); curr_locomp |= (u32) (curr_locomp_q & 0xff); @@ -28039,12 +28168,15 @@ static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi) WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIA, 0); - if (!NREV_IS(pi->pubpi.phy_rev, 7)) + if (!NREV_IS(pi->pubpi.phy_rev, 7)) { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG, 0x1); - else + } else { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG, 0x31); + } } else { WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MASTER, 0x9); @@ -28054,14 +28186,17 @@ static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi) TSSIG, 0); if (pi->pubpi.radiorev != 5) { - if (!NREV_IS(pi->pubpi.phy_rev, 7)) + if (!NREV_IS(pi->pubpi.phy_rev, 7)) { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIA, 0x1); - else + } else { + WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIA, 0x31); + } } } WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG, @@ -28103,12 +28238,14 @@ static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi) if (pi->pubpi.radiorev != 5) WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSIA, 0x0); - if (NREV_GE(pi->pubpi.phy_rev, 5)) + if (NREV_GE(pi->pubpi.phy_rev, 5)) { + WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSIG, 0x31); - else + } else { WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSIG, 0x11); + } WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_SSI_MUX, 0xe); } else { @@ -28134,15 +28271,17 @@ static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi) return; - if (PHY_IPA(pi)) + if (PHY_IPA(pi)) { wlc_phy_ipa_internal_tssi_setup_nphy(pi); + } - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 0, NPHY_REV7_RFCTRLOVERRIDE_ID0); - else if (NREV_GE(pi->pubpi.phy_rev, 3)) + } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0); + } wlc_phy_stopplayback_nphy(pi); @@ -28150,40 +28289,41 @@ static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi) udelay(20); int_val = - wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf, - 1); + wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf, + 1); wlc_phy_stopplayback_nphy(pi); wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0); - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1, NPHY_REV7_RFCTRLOVERRIDE_ID0); - else if (NREV_GE(pi->pubpi.phy_rev, 3)) + } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1); + } if (NREV_GE(pi->pubpi.phy_rev, 3)) { pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g = - (u8) ((int_val >> 24) & 0xff); + (u8) ((int_val >> 24) & 0xff); pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g = - (u8) ((int_val >> 24) & 0xff); + (u8) ((int_val >> 24) & 0xff); pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g = - (u8) ((int_val >> 8) & 0xff); + (u8) ((int_val >> 8) & 0xff); pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g = - (u8) ((int_val >> 8) & 0xff); + (u8) ((int_val >> 8) & 0xff); } else { pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g = - (u8) ((int_val >> 24) & 0xff); + (u8) ((int_val >> 24) & 0xff); pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g = - (u8) ((int_val >> 8) & 0xff); + (u8) ((int_val >> 8) & 0xff); pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g = - (u8) ((int_val >> 16) & 0xff); + (u8) ((int_val >> 16) & 0xff); pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g = - (u8) ((int_val) & 0xff); + (u8) ((int_val) & 0xff); } } @@ -28211,10 +28351,12 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) or_phy_reg(pi, 0x122, (0x1 << 0)); - if (NREV_GE(pi->pubpi.phy_rev, 3)) + if (NREV_GE(pi->pubpi.phy_rev, 3)) { and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15))); - else + } else { + or_phy_reg(pi, 0x1e7, (0x1 << 15)); + } if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); @@ -28238,9 +28380,9 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; target_pwr_qtrdbm[0] = - pi->nphy_pwrctrl_info[0].max_pwr_2g; + pi->nphy_pwrctrl_info[0].max_pwr_2g; target_pwr_qtrdbm[1] = - pi->nphy_pwrctrl_info[1].max_pwr_2g; + pi->nphy_pwrctrl_info[1].max_pwr_2g; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0; @@ -28252,9 +28394,9 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; target_pwr_qtrdbm[0] = - pi->nphy_pwrctrl_info[0].max_pwr_5gl; + pi->nphy_pwrctrl_info[0].max_pwr_5gl; target_pwr_qtrdbm[1] = - pi->nphy_pwrctrl_info[1].max_pwr_5gl; + pi->nphy_pwrctrl_info[1].max_pwr_5gl; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0; @@ -28266,9 +28408,9 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; target_pwr_qtrdbm[0] = - pi->nphy_pwrctrl_info[0].max_pwr_5gm; + pi->nphy_pwrctrl_info[0].max_pwr_5gm; target_pwr_qtrdbm[1] = - pi->nphy_pwrctrl_info[1].max_pwr_5gm; + pi->nphy_pwrctrl_info[1].max_pwr_5gm; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0; @@ -28280,9 +28422,9 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; target_pwr_qtrdbm[0] = - pi->nphy_pwrctrl_info[0].max_pwr_5gh; + pi->nphy_pwrctrl_info[0].max_pwr_5gh; target_pwr_qtrdbm[1] = - pi->nphy_pwrctrl_info[1].max_pwr_5gh; + pi->nphy_pwrctrl_info[1].max_pwr_5gh; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0; @@ -28309,22 +28451,26 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) target_pwr_qtrdbm[1] = (s8) pi->tx_power_max; if (NREV_GE(pi->pubpi.phy_rev, 3)) { - if (pi->srom_fem2g.tssipos) + if (pi->srom_fem2g.tssipos) { or_phy_reg(pi, 0x1e9, (0x1 << 14)); + } if (NREV_GE(pi->pubpi.phy_rev, 7)) { for (core = 0; core <= 1; core++) { if (PHY_IPA(pi)) { - if (CHSPEC_IS2G(pi->radio_chanspec)) + + if (CHSPEC_IS2G(pi->radio_chanspec)) { WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX, 0xe); - else + } else { WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX, 0xc); + } + } else { } } } else { @@ -28333,14 +28479,14 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | RADIO_2056_TX0, (CHSPEC_IS5G - (pi->radio_chanspec)) ? - 0xc : 0xe); + (pi-> + radio_chanspec)) ? 0xc : 0xe); write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | RADIO_2056_TX1, (CHSPEC_IS5G - (pi->radio_chanspec)) ? - 0xc : 0xe); + (pi-> + radio_chanspec)) ? 0xc : 0xe); } else { write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | @@ -28357,19 +28503,21 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) udelay(1); } - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { mod_phy_reg(pi, 0x1e7, (0x7f << 0), (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0)); - else + } else { mod_phy_reg(pi, 0x1e7, (0x7f << 0), (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0)); + } - if (NREV_GE(pi->pubpi.phy_rev, 7)) + if (NREV_GE(pi->pubpi.phy_rev, 7)) { mod_phy_reg(pi, 0x222, (0xff << 0), (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0)); - else if (NREV_GT(pi->pubpi.phy_rev, 1)) + } else if (NREV_GT(pi->pubpi.phy_rev, 1)) { mod_phy_reg(pi, 0x222, (0xff << 0), (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0)); + } if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); @@ -28389,17 +28537,17 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { for (idx = 0; idx < tbl_len; idx++) { - num = 8 * - (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx); + num = + 8 * (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx); den = 32768 + a1[tbl_id - 26] * idx; pwr_est = max(((4 * num + den / 2) / den), -8); if (NREV_LT(pi->pubpi.phy_rev, 3)) { if (idx <= (uint) (31 - idle_tssi[tbl_id - 26] + 1)) pwr_est = - max(pwr_est, - target_pwr_qtrdbm - [tbl_id - 26] + 1); + max(pwr_est, + target_pwr_qtrdbm[tbl_id - 26] + + 1); } regval[idx] = (u32) pwr_est; } @@ -28420,7 +28568,7 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi) { return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) | - (0x1 << 14) | (0x1 << 13)); + (0x1 << 14) | (0x1 << 13)); } static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core) @@ -28452,9 +28600,12 @@ u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi) tmp = (pwr_idx[0] << 8) | pwr_idx[1]; } else { - tmp = ((pi->nphy_txpwrindex[PHY_CORE_0].index_internal & 0xff) - << 8) | - (pi->nphy_txpwrindex[PHY_CORE_1].index_internal & 0xff); + tmp = + ((pi->nphy_txpwrindex[PHY_CORE_0]. + index_internal & 0xff) << 8) | (pi-> + nphy_txpwrindex + [PHY_CORE_1]. + index_internal & 0xff); } return tmp; @@ -28471,8 +28622,9 @@ void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi) pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4) || ((u32) ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) - - pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) + pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) { wlc_phy_a4(pi, true); + } } void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type) @@ -28503,29 +28655,32 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type) for (core = 0; core < pi->pubpi.phy_corenum; core++) pi->nphy_txpwr_idx[core] = - wlc_phy_txpwr_idx_cur_get_nphy( - pi, - (u8) core); + wlc_phy_txpwr_idx_cur_get_nphy(pi, + (u8) + core); } } tbl_len = 84; tbl_offset = 64; - for (ctr = 0; ctr < tbl_len; ctr++) + for (ctr = 0; ctr < tbl_len; ctr++) { regval[ctr] = 0; + } wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16, regval); wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16, regval); - if (NREV_GE(pi->pubpi.phy_rev, 3)) + if (NREV_GE(pi->pubpi.phy_rev, 3)) { + and_phy_reg(pi, 0x1e7, (u16) (~((0x1 << 15) | - (0x1 << 14) | (0x1 << 13)))); - else + (0x1 << 14) | (0x1 << 13)))); + } else { and_phy_reg(pi, 0x1e7, (u16) (~((0x1 << 14) | (0x1 << 13)))); + } if (NREV_GE(pi->pubpi.phy_rev, 3)) { or_phy_reg(pi, 0x8f, (0x1 << 8)); @@ -28575,7 +28730,7 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type) if (NREV_GE(pi->pubpi.phy_rev, 3)) { if ((pi->nphy_txpwr_idx[0] != 128) - && (pi->nphy_txpwr_idx[1] != 128)) + && (pi->nphy_txpwr_idx[1] != 128)) { wlc_phy_txpwr_idx_cur_set_nphy(pi, pi-> nphy_txpwr_idx @@ -28583,6 +28738,7 @@ void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type) pi-> nphy_txpwr_idx [1]); + } } if (NREV_GE(pi->pubpi.phy_rev, 3)) { @@ -28643,14 +28799,17 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, for (core = 0; core < pi->pubpi.phy_corenum; core++) { - if ((core_mask & (1 << core)) == 0) + if ((core_mask & (1 << core)) == 0) { continue; + } txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27; if (txpwrindex < 0) { - if (pi->nphy_txpwrindex[core].index < 0) + if (pi->nphy_txpwrindex[core].index < 0) { + continue; + } if (NREV_GE(pi->pubpi.phy_rev, 3)) { mod_phy_reg(pi, 0x8f, @@ -28683,21 +28842,29 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); if (restore_cals) { - wlc_phy_table_write_nphy( - pi, 15, 2, (80 + 2 * core), 16, - &pi->nphy_txpwrindex[core].iqcomp_a); - wlc_phy_table_write_nphy( - pi, 15, 1, (85 + core), 16, - &pi->nphy_txpwrindex[core].locomp); - wlc_phy_table_write_nphy( - pi, 15, 1, (93 + core), 16, - &pi->nphy_txpwrindex[core].locomp); + + wlc_phy_table_write_nphy(pi, 15, 2, + (80 + 2 * core), 16, + (void *)&pi-> + nphy_txpwrindex[core]. + iqcomp_a); + + wlc_phy_table_write_nphy(pi, 15, 1, (85 + core), + 16, + &pi-> + nphy_txpwrindex[core]. + locomp); + wlc_phy_table_write_nphy(pi, 15, 1, (93 + core), + 16, + (void *)&pi-> + nphy_txpwrindex[core]. + locomp); } wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); pi->nphy_txpwrindex[core].index_internal = - pi->nphy_txpwrindex[core].index_internal_save; + pi->nphy_txpwrindex[core].index_internal_save; } else { if (pi->nphy_txpwrindex[core].index < 0) { @@ -28712,13 +28879,14 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, AfectrlOverride); } else { pi->nphy_txpwrindex[core]. - AfectrlOverride = - read_phy_reg(pi, 0xa5); + AfectrlOverride = + read_phy_reg(pi, 0xa5); } pi->nphy_txpwrindex[core].AfeCtrlDacGain = - read_phy_reg(pi, (core == PHY_CORE_0) ? - 0xaa : 0xab); + read_phy_reg(pi, + (core == + PHY_CORE_0) ? 0xaa : 0xab); wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16, @@ -28730,23 +28898,23 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, &tmpval); tmpval >>= ((core == PHY_CORE_0) ? 8 : 0); tmpval &= 0xff; - pi->nphy_txpwrindex[core].bbmult = (u8) tmpval; + pi->nphy_txpwrindex[core].bbmult = + (u8) tmpval; wlc_phy_table_read_nphy(pi, 15, 2, (80 + 2 * core), 16, - &pi-> + (void *)&pi-> nphy_txpwrindex[core]. iqcomp_a); wlc_phy_table_read_nphy(pi, 15, 1, (85 + core), 16, - &pi-> + (void *)&pi-> nphy_txpwrindex[core]. locomp); pi->nphy_txpwrindex[core].index_internal_save = - pi->nphy_txpwrindex[core]. - index_internal; + pi->nphy_txpwrindex[core].index_internal; } tx_pwr_ctrl_state = pi->nphy_txpwrctrl; @@ -28759,22 +28927,22 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, (tx_ind0 + txpwrindex), 32, &txgain); - if (NREV_GE(pi->pubpi.phy_rev, 3)) - rad_gain = (txgain >> 16) & - ((1 << (32 - 16 + 1)) - 1); - else - rad_gain = (txgain >> 16) & - ((1 << (28 - 16 + 1)) - 1); - + if (NREV_GE(pi->pubpi.phy_rev, 3)) { + rad_gain = + (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1); + } else { + rad_gain = + (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1); + } dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1); bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1); - if (NREV_GE(pi->pubpi.phy_rev, 3)) + if (NREV_GE(pi->pubpi.phy_rev, 3)) { mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : 0xa5), (0x1 << 8), (0x1 << 8)); - else + } else { mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14)); - + } write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain); @@ -28783,8 +28951,9 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); - m1m2 |= ((core == PHY_CORE_0) ? - (bbmult << 8) : (bbmult << 0)); + m1m2 |= + ((core == + PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0)); wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); @@ -28805,20 +28974,23 @@ wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, (lo_ind0 + txpwrindex), 32, &locomp); - if (restore_cals) + if (restore_cals) { wlc_phy_table_write_nphy(pi, 15, 1, (85 + core), 16, &locomp); + } if (NREV_IS(pi->pubpi.phy_rev, 1)) wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); if (PHY_IPA(pi)) { wlc_phy_table_read_nphy(pi, - (core == PHY_CORE_0 ? - NPHY_TBL_ID_CORE1TXPWRCTL : - NPHY_TBL_ID_CORE2TXPWRCTL), - 1, 576 + txpwrindex, 32, - &rfpwr_offset); + (core == + PHY_CORE_0 ? + NPHY_TBL_ID_CORE1TXPWRCTL + : + NPHY_TBL_ID_CORE2TXPWRCTL), + 1, 576 + txpwrindex, 32, + &rfpwr_offset); mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : 0x29b, (0x1ff << 4), @@ -28874,7 +29046,7 @@ void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable) if (enable) { if (pi->nphy_deaf_count == 0) { pi->classifier_state = - wlc_phy_classifier_nphy(pi, 0, 0); + wlc_phy_classifier_nphy(pi, 0, 0); wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); wlc_phy_clip_det_nphy(pi, 0, pi->clip_state); wlc_phy_clip_det_nphy(pi, 1, clip_off); @@ -28902,9 +29074,9 @@ void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode) if (mode) { if (pi->nphy_deaf_count == 0) wlc_phy_stay_in_carriersearch_nphy(pi, true); - } else if (pi->nphy_deaf_count > 0) { - wlc_phy_stay_in_carriersearch_nphy(pi, false); + } else { + if (pi->nphy_deaf_count > 0) + wlc_phy_stay_in_carriersearch_nphy(pi, false); } - wlapi_enable_mac(pi->sh->physhim); } diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c index faf1ebe76068..01ff0c8eb4b9 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c @@ -17,95 +17,89 @@ #include "phy_qmath.h" /* - * Description: This function make 16 bit unsigned multiplication. - * To fit the output into 16 bits the 32 bit multiplication result is right - * shifted by 16 bits. - */ +Description: This function make 16 bit unsigned multiplication. To fit the output into +16 bits the 32 bit multiplication result is right shifted by 16 bits. +*/ u16 qm_mulu16(u16 op1, u16 op2) { return (u16) (((u32) op1 * (u32) op2) >> 16); } /* - * Description: This function make 16 bit multiplication and return the result - * in 16 bits. To fit the multiplication result into 16 bits the multiplication - * result is right shifted by 15 bits. Right shifting 15 bits instead of 16 bits - * is done to remove the extra sign bit formed due to the multiplication. - * When both the 16bit inputs are 0x8000 then the output is saturated to - * 0x7fffffff. - */ +Description: This function make 16 bit multiplication and return the result in 16 bits. +To fit the multiplication result into 16 bits the multiplication result is right shifted by +15 bits. Right shifting 15 bits instead of 16 bits is done to remove the extra sign bit formed +due to the multiplication. +When both the 16bit inputs are 0x8000 then the output is saturated to 0x7fffffff. +*/ s16 qm_muls16(s16 op1, s16 op2) { s32 result; - if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) + if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) { result = 0x7fffffff; - else + } else { result = ((s32) (op1) * (s32) (op2)); - + } return (s16) (result >> 15); } /* - * Description: This function add two 32 bit numbers and return the 32bit - * result. If the result overflow 32 bits, the output will be saturated to - * 32bits. - */ +Description: This function add two 32 bit numbers and return the 32bit result. +If the result overflow 32 bits, the output will be saturated to 32bits. +*/ s32 qm_add32(s32 op1, s32 op2) { s32 result; result = op1 + op2; - if (op1 < 0 && op2 < 0 && result > 0) + if (op1 < 0 && op2 < 0 && result > 0) { result = 0x80000000; - else if (op1 > 0 && op2 > 0 && result < 0) + } else if (op1 > 0 && op2 > 0 && result < 0) { result = 0x7fffffff; - + } return result; } /* - * Description: This function add two 16 bit numbers and return the 16bit - * result. If the result overflow 16 bits, the output will be saturated to - * 16bits. - */ +Description: This function add two 16 bit numbers and return the 16bit result. +If the result overflow 16 bits, the output will be saturated to 16bits. +*/ s16 qm_add16(s16 op1, s16 op2) { s16 result; s32 temp = (s32) op1 + (s32) op2; - if (temp > (s32) 0x7fff) + if (temp > (s32) 0x7fff) { result = (s16) 0x7fff; - else if (temp < (s32) 0xffff8000) + } else if (temp < (s32) 0xffff8000) { result = (s16) 0xffff8000; - else + } else { result = (s16) temp; - + } return result; } /* - * Description: This function make 16 bit subtraction and return the 16bit - * result. If the result overflow 16 bits, the output will be saturated to - * 16bits. - */ +Description: This function make 16 bit subtraction and return the 16bit result. +If the result overflow 16 bits, the output will be saturated to 16bits. +*/ s16 qm_sub16(s16 op1, s16 op2) { s16 result; s32 temp = (s32) op1 - (s32) op2; - if (temp > (s32) 0x7fff) + if (temp > (s32) 0x7fff) { result = (s16) 0x7fff; - else if (temp < (s32) 0xffff8000) + } else if (temp < (s32) 0xffff8000) { result = (s16) 0xffff8000; - else + } else { result = (s16) temp; - + } return result; } /* - * Description: This function make a 32 bit saturated left shift when the - * specified shift is +ve. This function will make a 32 bit right shift when - * the specified shift is -ve. This function return the result after shifting - * operation. - */ +Description: This function make a 32 bit saturated left shift when the specified shift +is +ve. This function will make a 32 bit right shift when the specified shift is -ve. +This function return the result after shifting operation. +*/ s32 qm_shl32(s32 op, int shift) { int i; @@ -116,21 +110,20 @@ s32 qm_shl32(s32 op, int shift) else if (shift < -31) shift = -31; if (shift >= 0) { - for (i = 0; i < shift; i++) + for (i = 0; i < shift; i++) { result = qm_add32(result, result); + } } else { result = result >> (-shift); } - return result; } /* - * Description: This function make a 16 bit saturated left shift when the - * specified shift is +ve. This function will make a 16 bit right shift when - * the specified shift is -ve. This function return the result after shifting - * operation. - */ +Description: This function make a 16 bit saturated left shift when the specified shift +is +ve. This function will make a 16 bit right shift when the specified shift is -ve. +This function return the result after shifting operation. +*/ s16 qm_shl16(s16 op, int shift) { int i; @@ -141,29 +134,29 @@ s16 qm_shl16(s16 op, int shift) else if (shift < -15) shift = -15; if (shift > 0) { - for (i = 0; i < shift; i++) + for (i = 0; i < shift; i++) { result = qm_add16(result, result); + } } else { result = result >> (-shift); } - return result; } /* - * Description: This function make a 16 bit right shift when shift is +ve. - * This function make a 16 bit saturated left shift when shift is -ve. This - * function return the result of the shift operation. - */ +Description: This function make a 16 bit right shift when shift is +ve. +This function make a 16 bit saturated left shift when shift is -ve. This function +return the result of the shift operation. +*/ s16 qm_shr16(s16 op, int shift) { return qm_shl16(op, -shift); } /* - * Description: This function return the number of redundant sign bits in a - * 32 bit number. Example: qm_norm32(0x00000080) = 23 - */ +Description: This function return the number of redundant sign bits in a 32 bit number. +Example: qm_norm32(0x00000080) = 23 +*/ s16 qm_norm32(s32 op) { u16 u16extraSignBits; @@ -215,30 +208,28 @@ static const s16 log_table[] = { 32024 }; -#define LOG_TABLE_SIZE 32 /* log_table size */ -#define LOG2_LOG_TABLE_SIZE 5 /* log2(log_table size) */ -#define Q_LOG_TABLE 15 /* qformat of log_table */ -#define LOG10_2 19728 /* log10(2) in q.16 */ +#define LOG_TABLE_SIZE 32 /* log_table size */ +#define LOG2_LOG_TABLE_SIZE 5 /* log2(log_table size) */ +#define Q_LOG_TABLE 15 /* qformat of log_table */ +#define LOG10_2 19728 /* log10(2) in q.16 */ /* - * Description: - * This routine takes the input number N and its q format qN and compute - * the log10(N). This routine first normalizes the input no N. Then N is in - * mag*(2^x) format. mag is any number in the range 2^30-(2^31 - 1). - * Then log2(mag * 2^x) = log2(mag) + x is computed. From that - * log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed. - * This routine looks the log2 value in the table considering - * LOG2_LOG_TABLE_SIZE+1 MSBs. As the MSB is always 1, only next - * LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup. Next 16 MSBs are used - * for interpolation. - * Inputs: - * N - number to which log10 has to be found. - * qN - q format of N - * log10N - address where log10(N) will be written. - * qLog10N - address where log10N qformat will be written. - * Note/Problem: - * For accurate results input should be in normalized or near normalized form. - */ +Description: +This routine takes the input number N and its q format qN and compute +the log10(N). This routine first normalizes the input no N. Then N is in mag*(2^x) format. +mag is any number in the range 2^30-(2^31 - 1). Then log2(mag * 2^x) = log2(mag) + x is computed. +From that log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed. +This routine looks the log2 value in the table considering LOG2_LOG_TABLE_SIZE+1 MSBs. +As the MSB is always 1, only next LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup. +Next 16 MSBs are used for interpolation. +Inputs: +N - number to which log10 has to be found. +qN - q format of N +log10N - address where log10(N) will be written. +qLog10N - address where log10N qformat will be written. +Note/Problem: +For accurate results input should be in normalized or near normalized form. +*/ void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N) { s16 s16norm, s16tableIndex, s16errorApproximation; @@ -257,13 +248,12 @@ void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N) */ qN = qN + s16norm - 30; - /* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the - * MSB */ + /* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the MSB */ s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE))); /* remove the MSB. the MSB is always 1 after normalization. */ s16tableIndex = - s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1); + s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1); /* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */ N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1); @@ -273,27 +263,23 @@ void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N) u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16))); /* look the log value in the table. */ - s32log = log_table[s16tableIndex]; /* q.15 format */ + s32log = log_table[s16tableIndex]; /* q.15 format */ - /* interpolate using the offset. q.15 format. */ - s16errorApproximation = (s16) qm_mulu16(u16offset, - (u16) (log_table[s16tableIndex + 1] - - log_table[s16tableIndex])); + /* interpolate using the offset. */ + s16errorApproximation = (s16) qm_mulu16(u16offset, (u16) (log_table[s16tableIndex + 1] - log_table[s16tableIndex])); /* q.15 */ - /* q.15 format */ - s32log = qm_add16((s16) s32log, s16errorApproximation); + s32log = qm_add16((s16) s32log, s16errorApproximation); /* q.15 format */ /* adjust for the qformat of the N as * log2(mag * 2^x) = log2(mag) + x */ - s32log = qm_add32(s32log, ((s32) -qN) << 15); /* q.15 format */ + s32log = qm_add32(s32log, ((s32) -qN) << 15); /* q.15 format */ /* normalize the result. */ s16norm = qm_norm32(s32log); /* bring all the important bits into lower 16 bits */ - /* q.15+s16norm-16 format */ - s32log = qm_shl32(s32log, s16norm - 16); + s32log = qm_shl32(s32log, s16norm - 16); /* q.15+s16norm-16 format */ /* compute the log10(N) by multiplying log2(N) with log10(2). * as log10(mag * 2^x) = log2(mag * 2^x) * log10(2) diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c index c354496d3e72..023d05aa97ad 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c @@ -2834,26 +2834,26 @@ const struct phytbl_info dot11lcnphytbl_info_rev0[] = { const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = { &dot11lcn_sw_ctrl_tbl_4313_rev0, - sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) / - sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16 + sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) / + sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16 }; const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa = { &dot11lcn_sw_ctrl_tbl_4313_epa_rev0, - sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) / - sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16 + sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) / + sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16 }; const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = { &dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo, - sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) / - sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16 + sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) / + sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16 }; const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = { &dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0, - sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) / - sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16 + sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) / + sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16 }; const u32 dot11lcnphytbl_info_sz_rev0 = @@ -2861,394 +2861,778 @@ const u32 dot11lcnphytbl_info_sz_rev0 = const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = { - {3, 0, 31, 0, 72}, - {3, 0, 31, 0, 70}, - {3, 0, 31, 0, 68}, - {3, 0, 30, 0, 67}, - {3, 0, 29, 0, 68}, - {3, 0, 28, 0, 68}, - {3, 0, 27, 0, 69}, - {3, 0, 26, 0, 70}, - {3, 0, 25, 0, 70}, - {3, 0, 24, 0, 71}, - {3, 0, 23, 0, 72}, - {3, 0, 23, 0, 70}, - {3, 0, 22, 0, 71}, - {3, 0, 21, 0, 72}, - {3, 0, 21, 0, 70}, - {3, 0, 21, 0, 68}, - {3, 0, 21, 0, 66}, - {3, 0, 21, 0, 64}, - {3, 0, 21, 0, 63}, - {3, 0, 20, 0, 64}, - {3, 0, 19, 0, 65}, - {3, 0, 19, 0, 64}, - {3, 0, 18, 0, 65}, - {3, 0, 18, 0, 64}, - {3, 0, 17, 0, 65}, - {3, 0, 17, 0, 64}, - {3, 0, 16, 0, 65}, - {3, 0, 16, 0, 64}, - {3, 0, 16, 0, 62}, - {3, 0, 16, 0, 60}, - {3, 0, 16, 0, 58}, - {3, 0, 15, 0, 61}, - {3, 0, 15, 0, 59}, - {3, 0, 14, 0, 61}, - {3, 0, 14, 0, 60}, - {3, 0, 14, 0, 58}, - {3, 0, 13, 0, 60}, - {3, 0, 13, 0, 59}, - {3, 0, 12, 0, 62}, - {3, 0, 12, 0, 60}, - {3, 0, 12, 0, 58}, - {3, 0, 11, 0, 62}, - {3, 0, 11, 0, 60}, - {3, 0, 11, 0, 59}, - {3, 0, 11, 0, 57}, - {3, 0, 10, 0, 61}, - {3, 0, 10, 0, 59}, - {3, 0, 10, 0, 57}, - {3, 0, 9, 0, 62}, - {3, 0, 9, 0, 60}, - {3, 0, 9, 0, 58}, - {3, 0, 9, 0, 57}, - {3, 0, 8, 0, 62}, - {3, 0, 8, 0, 60}, - {3, 0, 8, 0, 58}, - {3, 0, 8, 0, 57}, - {3, 0, 8, 0, 55}, - {3, 0, 7, 0, 61}, - {3, 0, 7, 0, 60}, - {3, 0, 7, 0, 58}, - {3, 0, 7, 0, 56}, - {3, 0, 7, 0, 55}, - {3, 0, 6, 0, 62}, - {3, 0, 6, 0, 60}, - {3, 0, 6, 0, 58}, - {3, 0, 6, 0, 57}, - {3, 0, 6, 0, 55}, - {3, 0, 6, 0, 54}, - {3, 0, 6, 0, 52}, - {3, 0, 5, 0, 61}, - {3, 0, 5, 0, 59}, - {3, 0, 5, 0, 57}, - {3, 0, 5, 0, 56}, - {3, 0, 5, 0, 54}, - {3, 0, 5, 0, 53}, - {3, 0, 5, 0, 51}, - {3, 0, 4, 0, 62}, - {3, 0, 4, 0, 60}, - {3, 0, 4, 0, 58}, - {3, 0, 4, 0, 57}, - {3, 0, 4, 0, 55}, - {3, 0, 4, 0, 54}, - {3, 0, 4, 0, 52}, - {3, 0, 4, 0, 51}, - {3, 0, 4, 0, 49}, - {3, 0, 4, 0, 48}, - {3, 0, 4, 0, 46}, - {3, 0, 3, 0, 60}, - {3, 0, 3, 0, 58}, - {3, 0, 3, 0, 57}, - {3, 0, 3, 0, 55}, - {3, 0, 3, 0, 54}, - {3, 0, 3, 0, 52}, - {3, 0, 3, 0, 51}, - {3, 0, 3, 0, 49}, - {3, 0, 3, 0, 48}, - {3, 0, 3, 0, 46}, - {3, 0, 3, 0, 45}, - {3, 0, 3, 0, 44}, - {3, 0, 3, 0, 43}, - {3, 0, 3, 0, 41}, - {3, 0, 2, 0, 61}, - {3, 0, 2, 0, 59}, - {3, 0, 2, 0, 57}, - {3, 0, 2, 0, 56}, - {3, 0, 2, 0, 54}, - {3, 0, 2, 0, 53}, - {3, 0, 2, 0, 51}, - {3, 0, 2, 0, 50}, - {3, 0, 2, 0, 48}, - {3, 0, 2, 0, 47}, - {3, 0, 2, 0, 46}, - {3, 0, 2, 0, 44}, - {3, 0, 2, 0, 43}, - {3, 0, 2, 0, 42}, - {3, 0, 2, 0, 41}, - {3, 0, 2, 0, 39}, - {3, 0, 2, 0, 38}, - {3, 0, 2, 0, 37}, - {3, 0, 2, 0, 36}, - {3, 0, 2, 0, 35}, - {3, 0, 2, 0, 34}, - {3, 0, 2, 0, 33}, - {3, 0, 2, 0, 32}, - {3, 0, 1, 0, 63}, - {3, 0, 1, 0, 61}, - {3, 0, 1, 0, 59}, - {3, 0, 1, 0, 57}, + {3, 0, 31, 0, 72,} + , + {3, 0, 31, 0, 70,} + , + {3, 0, 31, 0, 68,} + , + {3, 0, 30, 0, 67,} + , + {3, 0, 29, 0, 68,} + , + {3, 0, 28, 0, 68,} + , + {3, 0, 27, 0, 69,} + , + {3, 0, 26, 0, 70,} + , + {3, 0, 25, 0, 70,} + , + {3, 0, 24, 0, 71,} + , + {3, 0, 23, 0, 72,} + , + {3, 0, 23, 0, 70,} + , + {3, 0, 22, 0, 71,} + , + {3, 0, 21, 0, 72,} + , + {3, 0, 21, 0, 70,} + , + {3, 0, 21, 0, 68,} + , + {3, 0, 21, 0, 66,} + , + {3, 0, 21, 0, 64,} + , + {3, 0, 21, 0, 63,} + , + {3, 0, 20, 0, 64,} + , + {3, 0, 19, 0, 65,} + , + {3, 0, 19, 0, 64,} + , + {3, 0, 18, 0, 65,} + , + {3, 0, 18, 0, 64,} + , + {3, 0, 17, 0, 65,} + , + {3, 0, 17, 0, 64,} + , + {3, 0, 16, 0, 65,} + , + {3, 0, 16, 0, 64,} + , + {3, 0, 16, 0, 62,} + , + {3, 0, 16, 0, 60,} + , + {3, 0, 16, 0, 58,} + , + {3, 0, 15, 0, 61,} + , + {3, 0, 15, 0, 59,} + , + {3, 0, 14, 0, 61,} + , + {3, 0, 14, 0, 60,} + , + {3, 0, 14, 0, 58,} + , + {3, 0, 13, 0, 60,} + , + {3, 0, 13, 0, 59,} + , + {3, 0, 12, 0, 62,} + , + {3, 0, 12, 0, 60,} + , + {3, 0, 12, 0, 58,} + , + {3, 0, 11, 0, 62,} + , + {3, 0, 11, 0, 60,} + , + {3, 0, 11, 0, 59,} + , + {3, 0, 11, 0, 57,} + , + {3, 0, 10, 0, 61,} + , + {3, 0, 10, 0, 59,} + , + {3, 0, 10, 0, 57,} + , + {3, 0, 9, 0, 62,} + , + {3, 0, 9, 0, 60,} + , + {3, 0, 9, 0, 58,} + , + {3, 0, 9, 0, 57,} + , + {3, 0, 8, 0, 62,} + , + {3, 0, 8, 0, 60,} + , + {3, 0, 8, 0, 58,} + , + {3, 0, 8, 0, 57,} + , + {3, 0, 8, 0, 55,} + , + {3, 0, 7, 0, 61,} + , + {3, 0, 7, 0, 60,} + , + {3, 0, 7, 0, 58,} + , + {3, 0, 7, 0, 56,} + , + {3, 0, 7, 0, 55,} + , + {3, 0, 6, 0, 62,} + , + {3, 0, 6, 0, 60,} + , + {3, 0, 6, 0, 58,} + , + {3, 0, 6, 0, 57,} + , + {3, 0, 6, 0, 55,} + , + {3, 0, 6, 0, 54,} + , + {3, 0, 6, 0, 52,} + , + {3, 0, 5, 0, 61,} + , + {3, 0, 5, 0, 59,} + , + {3, 0, 5, 0, 57,} + , + {3, 0, 5, 0, 56,} + , + {3, 0, 5, 0, 54,} + , + {3, 0, 5, 0, 53,} + , + {3, 0, 5, 0, 51,} + , + {3, 0, 4, 0, 62,} + , + {3, 0, 4, 0, 60,} + , + {3, 0, 4, 0, 58,} + , + {3, 0, 4, 0, 57,} + , + {3, 0, 4, 0, 55,} + , + {3, 0, 4, 0, 54,} + , + {3, 0, 4, 0, 52,} + , + {3, 0, 4, 0, 51,} + , + {3, 0, 4, 0, 49,} + , + {3, 0, 4, 0, 48,} + , + {3, 0, 4, 0, 46,} + , + {3, 0, 3, 0, 60,} + , + {3, 0, 3, 0, 58,} + , + {3, 0, 3, 0, 57,} + , + {3, 0, 3, 0, 55,} + , + {3, 0, 3, 0, 54,} + , + {3, 0, 3, 0, 52,} + , + {3, 0, 3, 0, 51,} + , + {3, 0, 3, 0, 49,} + , + {3, 0, 3, 0, 48,} + , + {3, 0, 3, 0, 46,} + , + {3, 0, 3, 0, 45,} + , + {3, 0, 3, 0, 44,} + , + {3, 0, 3, 0, 43,} + , + {3, 0, 3, 0, 41,} + , + {3, 0, 2, 0, 61,} + , + {3, 0, 2, 0, 59,} + , + {3, 0, 2, 0, 57,} + , + {3, 0, 2, 0, 56,} + , + {3, 0, 2, 0, 54,} + , + {3, 0, 2, 0, 53,} + , + {3, 0, 2, 0, 51,} + , + {3, 0, 2, 0, 50,} + , + {3, 0, 2, 0, 48,} + , + {3, 0, 2, 0, 47,} + , + {3, 0, 2, 0, 46,} + , + {3, 0, 2, 0, 44,} + , + {3, 0, 2, 0, 43,} + , + {3, 0, 2, 0, 42,} + , + {3, 0, 2, 0, 41,} + , + {3, 0, 2, 0, 39,} + , + {3, 0, 2, 0, 38,} + , + {3, 0, 2, 0, 37,} + , + {3, 0, 2, 0, 36,} + , + {3, 0, 2, 0, 35,} + , + {3, 0, 2, 0, 34,} + , + {3, 0, 2, 0, 33,} + , + {3, 0, 2, 0, 32,} + , + {3, 0, 1, 0, 63,} + , + {3, 0, 1, 0, 61,} + , + {3, 0, 1, 0, 59,} + , + {3, 0, 1, 0, 57,} + , }; const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = { - {7, 0, 31, 0, 72}, - {7, 0, 31, 0, 70}, - {7, 0, 31, 0, 68}, - {7, 0, 30, 0, 67}, - {7, 0, 29, 0, 68}, - {7, 0, 28, 0, 68}, - {7, 0, 27, 0, 69}, - {7, 0, 26, 0, 70}, - {7, 0, 25, 0, 70}, - {7, 0, 24, 0, 71}, - {7, 0, 23, 0, 72}, - {7, 0, 23, 0, 70}, - {7, 0, 22, 0, 71}, - {7, 0, 21, 0, 72}, - {7, 0, 21, 0, 70}, - {7, 0, 21, 0, 68}, - {7, 0, 21, 0, 66}, - {7, 0, 21, 0, 64}, - {7, 0, 21, 0, 63}, - {7, 0, 20, 0, 64}, - {7, 0, 19, 0, 65}, - {7, 0, 19, 0, 64}, - {7, 0, 18, 0, 65}, - {7, 0, 18, 0, 64}, - {7, 0, 17, 0, 65}, - {7, 0, 17, 0, 64}, - {7, 0, 16, 0, 65}, - {7, 0, 16, 0, 64}, - {7, 0, 16, 0, 62}, - {7, 0, 16, 0, 60}, - {7, 0, 16, 0, 58}, - {7, 0, 15, 0, 61}, - {7, 0, 15, 0, 59}, - {7, 0, 14, 0, 61}, - {7, 0, 14, 0, 60}, - {7, 0, 14, 0, 58}, - {7, 0, 13, 0, 60}, - {7, 0, 13, 0, 59}, - {7, 0, 12, 0, 62}, - {7, 0, 12, 0, 60}, - {7, 0, 12, 0, 58}, - {7, 0, 11, 0, 62}, - {7, 0, 11, 0, 60}, - {7, 0, 11, 0, 59}, - {7, 0, 11, 0, 57}, - {7, 0, 10, 0, 61}, - {7, 0, 10, 0, 59}, - {7, 0, 10, 0, 57}, - {7, 0, 9, 0, 62}, - {7, 0, 9, 0, 60}, - {7, 0, 9, 0, 58}, - {7, 0, 9, 0, 57}, - {7, 0, 8, 0, 62}, - {7, 0, 8, 0, 60}, - {7, 0, 8, 0, 58}, - {7, 0, 8, 0, 57}, - {7, 0, 8, 0, 55}, - {7, 0, 7, 0, 61}, - {7, 0, 7, 0, 60}, - {7, 0, 7, 0, 58}, - {7, 0, 7, 0, 56}, - {7, 0, 7, 0, 55}, - {7, 0, 6, 0, 62}, - {7, 0, 6, 0, 60}, - {7, 0, 6, 0, 58}, - {7, 0, 6, 0, 57}, - {7, 0, 6, 0, 55}, - {7, 0, 6, 0, 54}, - {7, 0, 6, 0, 52}, - {7, 0, 5, 0, 61}, - {7, 0, 5, 0, 59}, - {7, 0, 5, 0, 57}, - {7, 0, 5, 0, 56}, - {7, 0, 5, 0, 54}, - {7, 0, 5, 0, 53}, - {7, 0, 5, 0, 51}, - {7, 0, 4, 0, 62}, - {7, 0, 4, 0, 60}, - {7, 0, 4, 0, 58}, - {7, 0, 4, 0, 57}, - {7, 0, 4, 0, 55}, - {7, 0, 4, 0, 54}, - {7, 0, 4, 0, 52}, - {7, 0, 4, 0, 51}, - {7, 0, 4, 0, 49}, - {7, 0, 4, 0, 48}, - {7, 0, 4, 0, 46}, - {7, 0, 3, 0, 60}, - {7, 0, 3, 0, 58}, - {7, 0, 3, 0, 57}, - {7, 0, 3, 0, 55}, - {7, 0, 3, 0, 54}, - {7, 0, 3, 0, 52}, - {7, 0, 3, 0, 51}, - {7, 0, 3, 0, 49}, - {7, 0, 3, 0, 48}, - {7, 0, 3, 0, 46}, - {7, 0, 3, 0, 45}, - {7, 0, 3, 0, 44}, - {7, 0, 3, 0, 43}, - {7, 0, 3, 0, 41}, - {7, 0, 2, 0, 61}, - {7, 0, 2, 0, 59}, - {7, 0, 2, 0, 57}, - {7, 0, 2, 0, 56}, - {7, 0, 2, 0, 54}, - {7, 0, 2, 0, 53}, - {7, 0, 2, 0, 51}, - {7, 0, 2, 0, 50}, - {7, 0, 2, 0, 48}, - {7, 0, 2, 0, 47}, - {7, 0, 2, 0, 46}, - {7, 0, 2, 0, 44}, - {7, 0, 2, 0, 43}, - {7, 0, 2, 0, 42}, - {7, 0, 2, 0, 41}, - {7, 0, 2, 0, 39}, - {7, 0, 2, 0, 38}, - {7, 0, 2, 0, 37}, - {7, 0, 2, 0, 36}, - {7, 0, 2, 0, 35}, - {7, 0, 2, 0, 34}, - {7, 0, 2, 0, 33}, - {7, 0, 2, 0, 32}, - {7, 0, 1, 0, 63}, - {7, 0, 1, 0, 61}, - {7, 0, 1, 0, 59}, - {7, 0, 1, 0, 57}, + {7, 0, 31, 0, 72,} + , + {7, 0, 31, 0, 70,} + , + {7, 0, 31, 0, 68,} + , + {7, 0, 30, 0, 67,} + , + {7, 0, 29, 0, 68,} + , + {7, 0, 28, 0, 68,} + , + {7, 0, 27, 0, 69,} + , + {7, 0, 26, 0, 70,} + , + {7, 0, 25, 0, 70,} + , + {7, 0, 24, 0, 71,} + , + {7, 0, 23, 0, 72,} + , + {7, 0, 23, 0, 70,} + , + {7, 0, 22, 0, 71,} + , + {7, 0, 21, 0, 72,} + , + {7, 0, 21, 0, 70,} + , + {7, 0, 21, 0, 68,} + , + {7, 0, 21, 0, 66,} + , + {7, 0, 21, 0, 64,} + , + {7, 0, 21, 0, 63,} + , + {7, 0, 20, 0, 64,} + , + {7, 0, 19, 0, 65,} + , + {7, 0, 19, 0, 64,} + , + {7, 0, 18, 0, 65,} + , + {7, 0, 18, 0, 64,} + , + {7, 0, 17, 0, 65,} + , + {7, 0, 17, 0, 64,} + , + {7, 0, 16, 0, 65,} + , + {7, 0, 16, 0, 64,} + , + {7, 0, 16, 0, 62,} + , + {7, 0, 16, 0, 60,} + , + {7, 0, 16, 0, 58,} + , + {7, 0, 15, 0, 61,} + , + {7, 0, 15, 0, 59,} + , + {7, 0, 14, 0, 61,} + , + {7, 0, 14, 0, 60,} + , + {7, 0, 14, 0, 58,} + , + {7, 0, 13, 0, 60,} + , + {7, 0, 13, 0, 59,} + , + {7, 0, 12, 0, 62,} + , + {7, 0, 12, 0, 60,} + , + {7, 0, 12, 0, 58,} + , + {7, 0, 11, 0, 62,} + , + {7, 0, 11, 0, 60,} + , + {7, 0, 11, 0, 59,} + , + {7, 0, 11, 0, 57,} + , + {7, 0, 10, 0, 61,} + , + {7, 0, 10, 0, 59,} + , + {7, 0, 10, 0, 57,} + , + {7, 0, 9, 0, 62,} + , + {7, 0, 9, 0, 60,} + , + {7, 0, 9, 0, 58,} + , + {7, 0, 9, 0, 57,} + , + {7, 0, 8, 0, 62,} + , + {7, 0, 8, 0, 60,} + , + {7, 0, 8, 0, 58,} + , + {7, 0, 8, 0, 57,} + , + {7, 0, 8, 0, 55,} + , + {7, 0, 7, 0, 61,} + , + {7, 0, 7, 0, 60,} + , + {7, 0, 7, 0, 58,} + , + {7, 0, 7, 0, 56,} + , + {7, 0, 7, 0, 55,} + , + {7, 0, 6, 0, 62,} + , + {7, 0, 6, 0, 60,} + , + {7, 0, 6, 0, 58,} + , + {7, 0, 6, 0, 57,} + , + {7, 0, 6, 0, 55,} + , + {7, 0, 6, 0, 54,} + , + {7, 0, 6, 0, 52,} + , + {7, 0, 5, 0, 61,} + , + {7, 0, 5, 0, 59,} + , + {7, 0, 5, 0, 57,} + , + {7, 0, 5, 0, 56,} + , + {7, 0, 5, 0, 54,} + , + {7, 0, 5, 0, 53,} + , + {7, 0, 5, 0, 51,} + , + {7, 0, 4, 0, 62,} + , + {7, 0, 4, 0, 60,} + , + {7, 0, 4, 0, 58,} + , + {7, 0, 4, 0, 57,} + , + {7, 0, 4, 0, 55,} + , + {7, 0, 4, 0, 54,} + , + {7, 0, 4, 0, 52,} + , + {7, 0, 4, 0, 51,} + , + {7, 0, 4, 0, 49,} + , + {7, 0, 4, 0, 48,} + , + {7, 0, 4, 0, 46,} + , + {7, 0, 3, 0, 60,} + , + {7, 0, 3, 0, 58,} + , + {7, 0, 3, 0, 57,} + , + {7, 0, 3, 0, 55,} + , + {7, 0, 3, 0, 54,} + , + {7, 0, 3, 0, 52,} + , + {7, 0, 3, 0, 51,} + , + {7, 0, 3, 0, 49,} + , + {7, 0, 3, 0, 48,} + , + {7, 0, 3, 0, 46,} + , + {7, 0, 3, 0, 45,} + , + {7, 0, 3, 0, 44,} + , + {7, 0, 3, 0, 43,} + , + {7, 0, 3, 0, 41,} + , + {7, 0, 2, 0, 61,} + , + {7, 0, 2, 0, 59,} + , + {7, 0, 2, 0, 57,} + , + {7, 0, 2, 0, 56,} + , + {7, 0, 2, 0, 54,} + , + {7, 0, 2, 0, 53,} + , + {7, 0, 2, 0, 51,} + , + {7, 0, 2, 0, 50,} + , + {7, 0, 2, 0, 48,} + , + {7, 0, 2, 0, 47,} + , + {7, 0, 2, 0, 46,} + , + {7, 0, 2, 0, 44,} + , + {7, 0, 2, 0, 43,} + , + {7, 0, 2, 0, 42,} + , + {7, 0, 2, 0, 41,} + , + {7, 0, 2, 0, 39,} + , + {7, 0, 2, 0, 38,} + , + {7, 0, 2, 0, 37,} + , + {7, 0, 2, 0, 36,} + , + {7, 0, 2, 0, 35,} + , + {7, 0, 2, 0, 34,} + , + {7, 0, 2, 0, 33,} + , + {7, 0, 2, 0, 32,} + , + {7, 0, 1, 0, 63,} + , + {7, 0, 1, 0, 61,} + , + {7, 0, 1, 0, 59,} + , + {7, 0, 1, 0, 57,} + , }; const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = { - {255, 255, 0xf0, 0, 152}, - {255, 255, 0xf0, 0, 147}, - {255, 255, 0xf0, 0, 143}, - {255, 255, 0xf0, 0, 139}, - {255, 255, 0xf0, 0, 135}, - {255, 255, 0xf0, 0, 131}, - {255, 255, 0xf0, 0, 128}, - {255, 255, 0xf0, 0, 124}, - {255, 255, 0xf0, 0, 121}, - {255, 255, 0xf0, 0, 117}, - {255, 255, 0xf0, 0, 114}, - {255, 255, 0xf0, 0, 111}, - {255, 255, 0xf0, 0, 107}, - {255, 255, 0xf0, 0, 104}, - {255, 255, 0xf0, 0, 101}, - {255, 255, 0xf0, 0, 99}, - {255, 255, 0xf0, 0, 96}, - {255, 255, 0xf0, 0, 93}, - {255, 255, 0xf0, 0, 90}, - {255, 255, 0xf0, 0, 88}, - {255, 255, 0xf0, 0, 85}, - {255, 255, 0xf0, 0, 83}, - {255, 255, 0xf0, 0, 81}, - {255, 255, 0xf0, 0, 78}, - {255, 255, 0xf0, 0, 76}, - {255, 255, 0xf0, 0, 74}, - {255, 255, 0xf0, 0, 72}, - {255, 255, 0xf0, 0, 70}, - {255, 255, 0xf0, 0, 68}, - {255, 255, 0xf0, 0, 66}, - {255, 255, 0xf0, 0, 64}, - {255, 248, 0xf0, 0, 64}, - {255, 241, 0xf0, 0, 64}, - {255, 251, 0xe0, 0, 64}, - {255, 244, 0xe0, 0, 64}, - {255, 254, 0xd0, 0, 64}, - {255, 246, 0xd0, 0, 64}, - {255, 239, 0xd0, 0, 64}, - {255, 249, 0xc0, 0, 64}, - {255, 242, 0xc0, 0, 64}, - {255, 255, 0xb0, 0, 64}, - {255, 248, 0xb0, 0, 64}, - {255, 241, 0xb0, 0, 64}, - {255, 254, 0xa0, 0, 64}, - {255, 246, 0xa0, 0, 64}, - {255, 239, 0xa0, 0, 64}, - {255, 255, 0x90, 0, 64}, - {255, 248, 0x90, 0, 64}, - {255, 241, 0x90, 0, 64}, - {255, 234, 0x90, 0, 64}, - {255, 255, 0x80, 0, 64}, - {255, 248, 0x80, 0, 64}, - {255, 241, 0x80, 0, 64}, - {255, 234, 0x80, 0, 64}, - {255, 255, 0x70, 0, 64}, - {255, 248, 0x70, 0, 64}, - {255, 241, 0x70, 0, 64}, - {255, 234, 0x70, 0, 64}, - {255, 227, 0x70, 0, 64}, - {255, 221, 0x70, 0, 64}, - {255, 215, 0x70, 0, 64}, - {255, 208, 0x70, 0, 64}, - {255, 203, 0x70, 0, 64}, - {255, 197, 0x70, 0, 64}, - {255, 255, 0x60, 0, 64}, - {255, 248, 0x60, 0, 64}, - {255, 241, 0x60, 0, 64}, - {255, 234, 0x60, 0, 64}, - {255, 227, 0x60, 0, 64}, - {255, 221, 0x60, 0, 64}, - {255, 255, 0x50, 0, 64}, - {255, 248, 0x50, 0, 64}, - {255, 241, 0x50, 0, 64}, - {255, 234, 0x50, 0, 64}, - {255, 227, 0x50, 0, 64}, - {255, 221, 0x50, 0, 64}, - {255, 215, 0x50, 0, 64}, - {255, 208, 0x50, 0, 64}, - {255, 255, 0x40, 0, 64}, - {255, 248, 0x40, 0, 64}, - {255, 241, 0x40, 0, 64}, - {255, 234, 0x40, 0, 64}, - {255, 227, 0x40, 0, 64}, - {255, 221, 0x40, 0, 64}, - {255, 215, 0x40, 0, 64}, - {255, 208, 0x40, 0, 64}, - {255, 203, 0x40, 0, 64}, - {255, 197, 0x40, 0, 64}, - {255, 255, 0x30, 0, 64}, - {255, 248, 0x30, 0, 64}, - {255, 241, 0x30, 0, 64}, - {255, 234, 0x30, 0, 64}, - {255, 227, 0x30, 0, 64}, - {255, 221, 0x30, 0, 64}, - {255, 215, 0x30, 0, 64}, - {255, 208, 0x30, 0, 64}, - {255, 203, 0x30, 0, 64}, - {255, 197, 0x30, 0, 64}, - {255, 191, 0x30, 0, 64}, - {255, 186, 0x30, 0, 64}, - {255, 181, 0x30, 0, 64}, - {255, 175, 0x30, 0, 64}, - {255, 255, 0x20, 0, 64}, - {255, 248, 0x20, 0, 64}, - {255, 241, 0x20, 0, 64}, - {255, 234, 0x20, 0, 64}, - {255, 227, 0x20, 0, 64}, - {255, 221, 0x20, 0, 64}, - {255, 215, 0x20, 0, 64}, - {255, 208, 0x20, 0, 64}, - {255, 203, 0x20, 0, 64}, - {255, 197, 0x20, 0, 64}, - {255, 191, 0x20, 0, 64}, - {255, 186, 0x20, 0, 64}, - {255, 181, 0x20, 0, 64}, - {255, 175, 0x20, 0, 64}, - {255, 170, 0x20, 0, 64}, - {255, 166, 0x20, 0, 64}, - {255, 161, 0x20, 0, 64}, - {255, 156, 0x20, 0, 64}, - {255, 152, 0x20, 0, 64}, - {255, 148, 0x20, 0, 64}, - {255, 143, 0x20, 0, 64}, - {255, 139, 0x20, 0, 64}, - {255, 135, 0x20, 0, 64}, - {255, 132, 0x20, 0, 64}, - {255, 255, 0x10, 0, 64}, - {255, 248, 0x10, 0, 64}, + {255, 255, 0xf0, 0, 152,} + , + {255, 255, 0xf0, 0, 147,} + , + {255, 255, 0xf0, 0, 143,} + , + {255, 255, 0xf0, 0, 139,} + , + {255, 255, 0xf0, 0, 135,} + , + {255, 255, 0xf0, 0, 131,} + , + {255, 255, 0xf0, 0, 128,} + , + {255, 255, 0xf0, 0, 124,} + , + {255, 255, 0xf0, 0, 121,} + , + {255, 255, 0xf0, 0, 117,} + , + {255, 255, 0xf0, 0, 114,} + , + {255, 255, 0xf0, 0, 111,} + , + {255, 255, 0xf0, 0, 107,} + , + {255, 255, 0xf0, 0, 104,} + , + {255, 255, 0xf0, 0, 101,} + , + {255, 255, 0xf0, 0, 99,} + , + {255, 255, 0xf0, 0, 96,} + , + {255, 255, 0xf0, 0, 93,} + , + {255, 255, 0xf0, 0, 90,} + , + {255, 255, 0xf0, 0, 88,} + , + {255, 255, 0xf0, 0, 85,} + , + {255, 255, 0xf0, 0, 83,} + , + {255, 255, 0xf0, 0, 81,} + , + {255, 255, 0xf0, 0, 78,} + , + {255, 255, 0xf0, 0, 76,} + , + {255, 255, 0xf0, 0, 74,} + , + {255, 255, 0xf0, 0, 72,} + , + {255, 255, 0xf0, 0, 70,} + , + {255, 255, 0xf0, 0, 68,} + , + {255, 255, 0xf0, 0, 66,} + , + {255, 255, 0xf0, 0, 64,} + , + {255, 248, 0xf0, 0, 64,} + , + {255, 241, 0xf0, 0, 64,} + , + {255, 251, 0xe0, 0, 64,} + , + {255, 244, 0xe0, 0, 64,} + , + {255, 254, 0xd0, 0, 64,} + , + {255, 246, 0xd0, 0, 64,} + , + {255, 239, 0xd0, 0, 64,} + , + {255, 249, 0xc0, 0, 64,} + , + {255, 242, 0xc0, 0, 64,} + , + {255, 255, 0xb0, 0, 64,} + , + {255, 248, 0xb0, 0, 64,} + , + {255, 241, 0xb0, 0, 64,} + , + {255, 254, 0xa0, 0, 64,} + , + {255, 246, 0xa0, 0, 64,} + , + {255, 239, 0xa0, 0, 64,} + , + {255, 255, 0x90, 0, 64,} + , + {255, 248, 0x90, 0, 64,} + , + {255, 241, 0x90, 0, 64,} + , + {255, 234, 0x90, 0, 64,} + , + {255, 255, 0x80, 0, 64,} + , + {255, 248, 0x80, 0, 64,} + , + {255, 241, 0x80, 0, 64,} + , + {255, 234, 0x80, 0, 64,} + , + {255, 255, 0x70, 0, 64,} + , + {255, 248, 0x70, 0, 64,} + , + {255, 241, 0x70, 0, 64,} + , + {255, 234, 0x70, 0, 64,} + , + {255, 227, 0x70, 0, 64,} + , + {255, 221, 0x70, 0, 64,} + , + {255, 215, 0x70, 0, 64,} + , + {255, 208, 0x70, 0, 64,} + , + {255, 203, 0x70, 0, 64,} + , + {255, 197, 0x70, 0, 64,} + , + {255, 255, 0x60, 0, 64,} + , + {255, 248, 0x60, 0, 64,} + , + {255, 241, 0x60, 0, 64,} + , + {255, 234, 0x60, 0, 64,} + , + {255, 227, 0x60, 0, 64,} + , + {255, 221, 0x60, 0, 64,} + , + {255, 255, 0x50, 0, 64,} + , + {255, 248, 0x50, 0, 64,} + , + {255, 241, 0x50, 0, 64,} + , + {255, 234, 0x50, 0, 64,} + , + {255, 227, 0x50, 0, 64,} + , + {255, 221, 0x50, 0, 64,} + , + {255, 215, 0x50, 0, 64,} + , + {255, 208, 0x50, 0, 64,} + , + {255, 255, 0x40, 0, 64,} + , + {255, 248, 0x40, 0, 64,} + , + {255, 241, 0x40, 0, 64,} + , + {255, 234, 0x40, 0, 64,} + , + {255, 227, 0x40, 0, 64,} + , + {255, 221, 0x40, 0, 64,} + , + {255, 215, 0x40, 0, 64,} + , + {255, 208, 0x40, 0, 64,} + , + {255, 203, 0x40, 0, 64,} + , + {255, 197, 0x40, 0, 64,} + , + {255, 255, 0x30, 0, 64,} + , + {255, 248, 0x30, 0, 64,} + , + {255, 241, 0x30, 0, 64,} + , + {255, 234, 0x30, 0, 64,} + , + {255, 227, 0x30, 0, 64,} + , + {255, 221, 0x30, 0, 64,} + , + {255, 215, 0x30, 0, 64,} + , + {255, 208, 0x30, 0, 64,} + , + {255, 203, 0x30, 0, 64,} + , + {255, 197, 0x30, 0, 64,} + , + {255, 191, 0x30, 0, 64,} + , + {255, 186, 0x30, 0, 64,} + , + {255, 181, 0x30, 0, 64,} + , + {255, 175, 0x30, 0, 64,} + , + {255, 255, 0x20, 0, 64,} + , + {255, 248, 0x20, 0, 64,} + , + {255, 241, 0x20, 0, 64,} + , + {255, 234, 0x20, 0, 64,} + , + {255, 227, 0x20, 0, 64,} + , + {255, 221, 0x20, 0, 64,} + , + {255, 215, 0x20, 0, 64,} + , + {255, 208, 0x20, 0, 64,} + , + {255, 203, 0x20, 0, 64,} + , + {255, 197, 0x20, 0, 64,} + , + {255, 191, 0x20, 0, 64,} + , + {255, 186, 0x20, 0, 64,} + , + {255, 181, 0x20, 0, 64,} + , + {255, 175, 0x20, 0, 64,} + , + {255, 170, 0x20, 0, 64,} + , + {255, 166, 0x20, 0, 64,} + , + {255, 161, 0x20, 0, 64,} + , + {255, 156, 0x20, 0, 64,} + , + {255, 152, 0x20, 0, 64,} + , + {255, 148, 0x20, 0, 64,} + , + {255, 143, 0x20, 0, 64,} + , + {255, 139, 0x20, 0, 64,} + , + {255, 135, 0x20, 0, 64,} + , + {255, 132, 0x20, 0, 64,} + , + {255, 255, 0x10, 0, 64,} + , + {255, 248, 0x10, 0, 64,} + , }; diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c index d1455aeebf4a..7f741f4868a6 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c @@ -4522,8 +4522,7 @@ const struct phytbl_info mimophytbl_info_rev0[] = { {&chanest_tbl_rev0, sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32} , - {&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, - 8} + {&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, 8} , {&noise_var_tbl0_rev0, sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0, diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h index dc8a84e85117..c5266cf23725 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h @@ -20,31 +20,21 @@ #include "phy_int.h" extern const struct phytbl_info mimophytbl_info_rev0[], - mimophytbl_info_rev0_volatile[]; - -extern const u32 mimophytbl_info_sz_rev0, - mimophytbl_info_sz_rev0_volatile; + mimophytbl_info_rev0_volatile[]; +extern const u32 mimophytbl_info_sz_rev0, mimophytbl_info_sz_rev0_volatile; extern const struct phytbl_info mimophytbl_info_rev3[], - mimophytbl_info_rev3_volatile[], - mimophytbl_info_rev3_volatile1[], - mimophytbl_info_rev3_volatile2[], - mimophytbl_info_rev3_volatile3[]; - -extern const u32 mimophytbl_info_sz_rev3, - mimophytbl_info_sz_rev3_volatile, - mimophytbl_info_sz_rev3_volatile1, - mimophytbl_info_sz_rev3_volatile2, - mimophytbl_info_sz_rev3_volatile3; + mimophytbl_info_rev3_volatile[], mimophytbl_info_rev3_volatile1[], + mimophytbl_info_rev3_volatile2[], mimophytbl_info_rev3_volatile3[]; +extern const u32 mimophytbl_info_sz_rev3, mimophytbl_info_sz_rev3_volatile, + mimophytbl_info_sz_rev3_volatile1, mimophytbl_info_sz_rev3_volatile2, + mimophytbl_info_sz_rev3_volatile3; extern const u32 noise_var_tbl_rev3[]; extern const struct phytbl_info mimophytbl_info_rev7[]; - extern const u32 mimophytbl_info_sz_rev7; - extern const u32 noise_var_tbl_rev7[]; extern const struct phytbl_info mimophytbl_info_rev16[]; - extern const u32 mimophytbl_info_sz_rev16; diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy_shim.c b/trunk/drivers/staging/brcm80211/brcmsmac/phy_shim.c index 31c93742f0ff..82ecdcda271f 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy_shim.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy_shim.c @@ -15,15 +15,15 @@ */ /* - * This is "two-way" interface, acting as the SHIM layer between driver - * and PHY layer. The driver can optionally call this translation layer - * to do some preprocessing, then reach PHY. On the PHY->driver direction, - * all calls go through this layer since PHY doesn't have access to the - * driver's brcms_hardware pointer. + * This is "two-way" interface, acting as the SHIM layer between WL and PHY layer. + * WL driver can optinally call this translation layer to do some preprocessing, then reach PHY. + * On the PHY->WL driver direction, all calls go through this layer since PHY doesn't have the + * access to wlc_hw pointer. */ #include #include +#include "bmac.h" #include "main.h" #include "mac80211_if.h" #include "phy_shim.h" @@ -31,13 +31,12 @@ /* PHY SHIM module specific state */ struct phy_shim_info { struct brcms_hardware *wlc_hw; /* pointer to main wlc_hw structure */ - struct brcms_c_info *wlc; /* pointer to main wlc structure */ - struct brcms_info *wl; /* pointer to os-specific private state */ + void *wlc; /* pointer to main wlc structure */ + void *wl; /* pointer to os-specific private state */ }; struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, - struct brcms_info *wl, - struct brcms_c_info *wlc) { + void *wl, void *wlc) { struct phy_shim_info *physhim = NULL; physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC); @@ -60,12 +59,11 @@ void wlc_phy_shim_detach(struct phy_shim_info *physhim) } struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, - void (*fn)(struct brcms_phy *pi), - void *arg, const char *name) + void (*fn) (void *arg), void *arg, + const char *name) { return (struct wlapi_timer *) - brcms_init_timer(physhim->wl, (void (*)(void *))fn, - arg, name); + brcms_init_timer(physhim->wl, fn, arg, name); } void wlapi_free_timer(struct phy_shim_info *physhim, struct wlapi_timer *t) diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/phy_shim.h b/trunk/drivers/staging/brcm80211/brcmsmac/phy_shim.h index d88c8202c97b..2d12bb4400f1 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/phy_shim.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/phy_shim.h @@ -45,17 +45,17 @@ #define FRA_ERR_20MHZ 60 #define FRA_ERR_40MHZ 120 -#define ANTSEL_NA 0 /* No boardlevel selection available */ -#define ANTSEL_2x4 1 /* 2x4 boardlevel selection available */ -#define ANTSEL_2x3 2 /* 2x3 CB2 boardlevel selection available */ +#define ANTSEL_NA 0 /* No boardlevel selection available */ +#define ANTSEL_2x4 1 /* 2x4 boardlevel selection available */ +#define ANTSEL_2x3 2 /* 2x3 CB2 boardlevel selection available */ /* Rx Antenna diversity control values */ -#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ -#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ -#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ -#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ -#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ -#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */ +#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ +#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ +#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ +#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ +#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ +#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */ #define WL_ANT_RX_MAX 2 /* max 2 receive antennas */ #define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */ @@ -77,40 +77,26 @@ #define WL_TX_POWER_RATES 101 #define WL_TX_POWER_CCK_FIRST 0 #define WL_TX_POWER_CCK_NUM 4 -/* Index for first 20MHz OFDM SISO rate */ -#define WL_TX_POWER_OFDM_FIRST 4 -/* Index for first 20MHz OFDM CDD rate */ -#define WL_TX_POWER_OFDM20_CDD_FIRST 12 -/* Index for first 40MHz OFDM SISO rate */ -#define WL_TX_POWER_OFDM40_SISO_FIRST 52 -/* Index for first 40MHz OFDM CDD rate */ -#define WL_TX_POWER_OFDM40_CDD_FIRST 60 +#define WL_TX_POWER_OFDM_FIRST 4 /* Index for first 20MHz OFDM SISO rate */ +#define WL_TX_POWER_OFDM20_CDD_FIRST 12 /* Index for first 20MHz OFDM CDD rate */ +#define WL_TX_POWER_OFDM40_SISO_FIRST 52 /* Index for first 40MHz OFDM SISO rate */ +#define WL_TX_POWER_OFDM40_CDD_FIRST 60 /* Index for first 40MHz OFDM CDD rate */ #define WL_TX_POWER_OFDM_NUM 8 -/* Index for first 20MHz MCS SISO rate */ -#define WL_TX_POWER_MCS20_SISO_FIRST 20 -/* Index for first 20MHz MCS CDD rate */ -#define WL_TX_POWER_MCS20_CDD_FIRST 28 -/* Index for first 20MHz MCS STBC rate */ -#define WL_TX_POWER_MCS20_STBC_FIRST 36 -/* Index for first 20MHz MCS SDM rate */ -#define WL_TX_POWER_MCS20_SDM_FIRST 44 -/* Index for first 40MHz MCS SISO rate */ -#define WL_TX_POWER_MCS40_SISO_FIRST 68 -/* Index for first 40MHz MCS CDD rate */ -#define WL_TX_POWER_MCS40_CDD_FIRST 76 -/* Index for first 40MHz MCS STBC rate */ -#define WL_TX_POWER_MCS40_STBC_FIRST 84 -/* Index for first 40MHz MCS SDM rate */ -#define WL_TX_POWER_MCS40_SDM_FIRST 92 +#define WL_TX_POWER_MCS20_SISO_FIRST 20 /* Index for first 20MHz MCS SISO rate */ +#define WL_TX_POWER_MCS20_CDD_FIRST 28 /* Index for first 20MHz MCS CDD rate */ +#define WL_TX_POWER_MCS20_STBC_FIRST 36 /* Index for first 20MHz MCS STBC rate */ +#define WL_TX_POWER_MCS20_SDM_FIRST 44 /* Index for first 20MHz MCS SDM rate */ +#define WL_TX_POWER_MCS40_SISO_FIRST 68 /* Index for first 40MHz MCS SISO rate */ +#define WL_TX_POWER_MCS40_CDD_FIRST 76 /* Index for first 40MHz MCS CDD rate */ +#define WL_TX_POWER_MCS40_STBC_FIRST 84 /* Index for first 40MHz MCS STBC rate */ +#define WL_TX_POWER_MCS40_SDM_FIRST 92 /* Index for first 40MHz MCS SDM rate */ #define WL_TX_POWER_MCS_1_STREAM_NUM 8 #define WL_TX_POWER_MCS_2_STREAM_NUM 8 -/* Index for 40MHz rate MCS 32 */ -#define WL_TX_POWER_MCS_32 100 +#define WL_TX_POWER_MCS_32 100 /* Index for 40MHz rate MCS 32 */ #define WL_TX_POWER_MCS_32_NUM 1 /* sslpnphy specifics */ -/* Index for first 20MHz MCS SISO rate */ -#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12 +#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12 /* Index for first 20MHz MCS SISO rate */ /* struct tx_power::flags bits */ #define WL_TX_POWER_F_ENABLED 1 @@ -122,17 +108,14 @@ #define BRCMS_N_TXRX_CHAIN0 0 #define BRCMS_N_TXRX_CHAIN1 1 -struct brcms_phy; - extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, - struct brcms_info *wl, - struct brcms_c_info *wlc); + void *wl, void *wlc); extern void wlc_phy_shim_detach(struct phy_shim_info *physhim); /* PHY to WL utility functions */ extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, - void (*fn) (struct brcms_phy *pi), - void *arg, const char *name); + void (*fn) (void *arg), void *arg, + const char *name); extern void wlapi_free_timer(struct phy_shim_info *physhim, struct wlapi_timer *t); extern void wlapi_add_timer(struct phy_shim_info *physhim, diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/pmu.c b/trunk/drivers/staging/brcm80211/brcmsmac/pmu.c index cdeaa4e534c7..e8b2b81d2d04 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/pmu.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/pmu.c @@ -70,13 +70,11 @@ #define PMURES_BIT(bit) (1 << (bit)) /* PMU corerev and chip specific PLL controls. - * PMU_PLL_XX where is PMU corerev and is an arbitrary - * number to differentiate different PLLs controlled by the same PMU rev. - */ -/* pllcontrol registers: - * ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, - * p1div, p2div, _bypass_sdmod + * PMU_PLL_XX where is PMU corerev and is an arbitrary number + * to differentiate different PLLs controlled by the same PMU rev. */ +/* pllcontrol registers */ +/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ #define PMU1_PLL0_PLLCTL0 0 #define PMU1_PLL0_PLLCTL1 1 #define PMU1_PLL0_PLLCTL2 2 @@ -139,8 +137,7 @@ static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax) } static void -si_pmu_spuravoid_pllupdate(struct si_pub *sih, struct chipcregs *cc, - u8 spuravoid) +si_pmu_spuravoid_pllupdate(struct si_pub *sih, chipcregs_t *cc, u8 spuravoid) { u32 tmp = 0; @@ -212,7 +209,7 @@ u32 si_pmu_ilp_clock(struct si_pub *sih) if (ilpcycles_per_sec == 0) { u32 start, end, delta; u32 origidx = ai_coreidx(sih); - struct chipcregs *cc = ai_setcoreidx(sih, SI_CC_IDX); + chipcregs_t *cc = ai_setcoreidx(sih, SI_CC_IDX); start = R_REG(&cc->pmutimer); mdelay(ILP_CALC_DUR); end = R_REG(&cc->pmutimer); @@ -243,7 +240,7 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) void si_pmu_sprom_enable(struct si_pub *sih, bool enable) { - struct chipcregs *cc; + chipcregs_t *cc; uint origidx; /* Remember original core before switch to chipc */ @@ -257,37 +254,34 @@ void si_pmu_sprom_enable(struct si_pub *sih, bool enable) /* Read/write a chipcontrol reg */ u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) { - ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol_addr), - ~0, reg); + ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol_addr), ~0, + reg); return ai_corereg(sih, SI_CC_IDX, - offsetof(struct chipcregs, chipcontrol_data), mask, - val); + offsetof(chipcregs_t, chipcontrol_data), mask, val); } /* Read/write a regcontrol reg */ u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) { - ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, regcontrol_addr), - ~0, reg); + ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, regcontrol_addr), ~0, + reg); return ai_corereg(sih, SI_CC_IDX, - offsetof(struct chipcregs, regcontrol_data), mask, - val); + offsetof(chipcregs_t, regcontrol_data), mask, val); } /* Read/write a pllcontrol reg */ u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) { - ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pllcontrol_addr), - ~0, reg); + ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pllcontrol_addr), ~0, + reg); return ai_corereg(sih, SI_CC_IDX, - offsetof(struct chipcregs, pllcontrol_data), mask, - val); + offsetof(chipcregs_t, pllcontrol_data), mask, val); } /* PMU PLL update */ void si_pmu_pllupd(struct si_pub *sih) { - ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pmucontrol), + ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmucontrol), PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD); } @@ -316,12 +310,12 @@ u32 si_pmu_alp_clock(struct si_pub *sih) void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid) { - struct chipcregs *cc; + chipcregs_t *cc; uint origidx, intr_val; /* Remember original core before switch to chipc */ - cc = (struct chipcregs *) - ai_switch_core(sih, CC_CORE_ID, &origidx, &intr_val); + cc = (chipcregs_t *) ai_switch_core(sih, CC_CORE_ID, &origidx, + &intr_val); /* update the pll changes */ si_pmu_spuravoid_pllupdate(sih, cc, spuravoid); @@ -333,7 +327,7 @@ void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid) /* initialize PMU */ void si_pmu_init(struct si_pub *sih) { - struct chipcregs *cc; + chipcregs_t *cc; uint origidx; /* Remember original core before switch to chipc */ @@ -372,7 +366,7 @@ void si_pmu_swreg_init(struct si_pub *sih) /* initialize PLL */ void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq) { - struct chipcregs *cc; + chipcregs_t *cc; uint origidx; /* Remember original core before switch to chipc */ @@ -396,7 +390,7 @@ void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq) /* initialize PMU resources */ void si_pmu_res_init(struct si_pub *sih) { - struct chipcregs *cc; + chipcregs_t *cc; uint origidx; u32 min_mask = 0, max_mask = 0; @@ -428,7 +422,7 @@ void si_pmu_res_init(struct si_pub *sih) u32 si_pmu_measure_alpclk(struct si_pub *sih) { - struct chipcregs *cc; + chipcregs_t *cc; uint origidx; u32 alp_khz; diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/pub.h b/trunk/drivers/staging/brcm80211/brcmsmac/pub.h index c2ab1a3e288c..01d74609560f 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/pub.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/pub.h @@ -69,53 +69,36 @@ #define BRCMS_RATE_MASK 0x7f /* Rate value mask w/o basic rate flag */ /* legacy rx Antenna diversity for SISO rates */ -#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ -#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ -#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ -#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ -#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ -/* default antdiv setting */ -#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 +#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ +#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ +#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ +#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ +#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ +#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */ /* legacy rx Antenna diversity for SISO rates */ -/* Tx on antenna 0, "legacy term Main" */ -#define ANT_TX_FORCE_0 0 -/* Tx on antenna 1, "legacy term Aux" */ -#define ANT_TX_FORCE_1 1 -/* Tx on phy's last good Rx antenna */ -#define ANT_TX_LAST_RX 3 -/* driver's default tx antenna setting */ -#define ANT_TX_DEF 3 - -/* use all available core for transmit */ -#define TXCORE_POLICY_ALL 0x1 +#define ANT_TX_FORCE_0 0 /* Tx on antenna 0, "legacy term Main" */ +#define ANT_TX_FORCE_1 1 /* Tx on antenna 1, "legacy term Aux" */ +#define ANT_TX_LAST_RX 3 /* Tx on phy's last good Rx antenna */ +#define ANT_TX_DEF 3 /* driver's default tx antenna setting */ + +#define TXCORE_POLICY_ALL 0x1 /* use all available core for transmit */ /* Tx Chain values */ -/* def bitmap of txchain */ -#define TXCHAIN_DEF 0x1 -/* default bitmap of tx chains for nphy */ -#define TXCHAIN_DEF_NPHY 0x3 -/* default bitmap of tx chains for nphy */ -#define TXCHAIN_DEF_HTPHY 0x7 -/* def bitmap of rxchain */ -#define RXCHAIN_DEF 0x1 -/* default bitmap of rx chains for nphy */ -#define RXCHAIN_DEF_NPHY 0x3 -/* default bitmap of rx chains for nphy */ -#define RXCHAIN_DEF_HTPHY 0x7 -/* no antenna switch */ -#define ANTSWITCH_NONE 0 -/* antenna switch on 4321CB2, 2of3 */ -#define ANTSWITCH_TYPE_1 1 -/* antenna switch on 4321MPCI, 2of3 */ -#define ANTSWITCH_TYPE_2 2 -/* antenna switch on 4322, 2of3 */ -#define ANTSWITCH_TYPE_3 3 +#define TXCHAIN_DEF 0x1 /* def bitmap of txchain */ +#define TXCHAIN_DEF_NPHY 0x3 /* default bitmap of tx chains for nphy */ +#define TXCHAIN_DEF_HTPHY 0x7 /* default bitmap of tx chains for nphy */ +#define RXCHAIN_DEF 0x1 /* def bitmap of rxchain */ +#define RXCHAIN_DEF_NPHY 0x3 /* default bitmap of rx chains for nphy */ +#define RXCHAIN_DEF_HTPHY 0x7 /* default bitmap of rx chains for nphy */ +#define ANTSWITCH_NONE 0 /* no antenna switch */ +#define ANTSWITCH_TYPE_1 1 /* antenna switch on 4321CB2, 2of3 */ +#define ANTSWITCH_TYPE_2 2 /* antenna switch on 4321MPCI, 2of3 */ +#define ANTSWITCH_TYPE_3 3 /* antenna switch on 4322, 2of3 */ #define RXBUFSZ PKTBUFSZ #ifndef AIDMAPSZ -/* aid bitmap size in bytes */ -#define AIDMAPSZ (roundup(MAXSCB, NBBY)/NBBY) +#define AIDMAPSZ (roundup(MAXSCB, NBBY)/NBBY) /* aid bitmap size in bytes */ #endif /* AIDMAPSZ */ #define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */ @@ -125,24 +108,24 @@ #define WL_SPURAVOID_ON2 2 struct brcms_tunables { - int ntxd; /* size of tx descriptor table */ - int nrxd; /* size of rx descriptor table */ - int rxbufsz; /* size of rx buffers to post */ - int nrxbufpost; /* # of rx buffers to post */ - int maxscb; /* # of SCBs supported */ + int ntxd; /* size of tx descriptor table */ + int nrxd; /* size of rx descriptor table */ + int rxbufsz; /* size of rx buffers to post */ + int nrxbufpost; /* # of rx buffers to post */ + int maxscb; /* # of SCBs supported */ int ampdunummpdu; /* max number of mpdu in an ampdu */ - int maxpktcb; /* max # of packet callbacks */ - int maxucodebss;/* max # of BSS handled in ucode bcn/prb */ + int maxpktcb; /* max # of packet callbacks */ + int maxucodebss; /* max # of BSS handled in ucode bcn/prb */ int maxucodebss4; /* max # of BSS handled in sw bcn/prb */ - int maxbss; /* max # of bss info elements in scan list */ - int datahiwat; /* data msg txq hiwat mark */ + int maxbss; /* max # of bss info elements in scan list */ + int datahiwat; /* data msg txq hiwat mark */ int ampdudatahiwat; /* AMPDU msg txq hiwat mark */ - int rxbnd; /* max # rx bufs to process before deferring to dpc */ - int txsbnd; /* max # tx status to process in wlc_txstatus() */ - int memreserved;/* memory reserved for BMAC's USB dma rx */ + int rxbnd; /* max # of rx bufs to process before deferring to dpc */ + int txsbnd; /* max # tx status to process in wlc_txstatus() */ + int memreserved; /* memory reserved for BMAC's USB dma rx */ }; -struct brcms_c_rateset { +struct brcms_rateset { uint count; /* number of rates in rates[] */ /* rates in 500kbps units w/hi bit set if basic */ u8 rates[BRCMS_NUMRATES]; @@ -188,9 +171,9 @@ struct brcms_bss_info { s16 SNR; /* receive signal SNR in dB */ u16 beacon_period; /* units are Kusec */ u16 atim_window; /* units are Kusec */ - u16 chanspec; /* Channel num, bw, ctrl_sb and band */ + chanspec_t chanspec; /* Channel num, bw, ctrl_sb and band */ s8 infra; /* 0=IBSS, 1=infrastructure, 2=unknown */ - struct brcms_c_rateset rateset; /* supported rates */ + wlc_rateset_t rateset; /* supported rates */ u8 dtim_period; /* DTIM period */ s8 phy_noise; /* noise right after tx (in dBm) */ u16 capability; /* Capability information */ @@ -198,7 +181,7 @@ struct brcms_bss_info { struct rsn_parms wpa; struct rsn_parms wpa2; u16 qbss_load_aac; /* qbss load available admission capacity */ - /* qbss_load_chan_free <- (0xff - chan utilization of qbss_load_ie_t) */ + /* qbss_load_chan_free <- (0xff - channel_utilization of qbss_load_ie_t) */ u8 qbss_load_chan_free; /* indicates how free the channel is */ u8 mcipher; /* multicast cipher */ u8 wpacfg; /* wpa config index */ @@ -220,15 +203,39 @@ struct brcms_bss_info { #define IOVF_GET_BAND (1<<13) /* get requires fixed band */ #define IOVF_OPEN_ALLOW (1<<14) /* set allowed iovar for opensrc */ +/* watchdog down and dump callback function proto's */ +typedef int (*watchdog_fn_t) (void *handle); +typedef int (*down_fn_t) (void *handle); +typedef int (*dump_fn_t) (void *handle, struct brcmu_strbuf *b); + +/* IOVar handler + * + * handle - a pointer value registered with the function + * vi - iovar_info that was looked up + * actionid - action ID, calculated by IOV_GVAL() and IOV_SVAL() based on varid. + * name - the actual iovar name + * params/plen - parameters and length for a get, input only. + * arg/len - buffer and length for value to be set or retrieved, input or output. + * vsize - value size, valid for integer type only. + * wlcif - interface context (brcms_c_if pointer) + * + * All pointers may point into the same buffer. + */ +typedef int (*iovar_fn_t) (void *handle, const struct brcmu_iovar *vi, + u32 actionid, const char *name, void *params, + uint plen, void *arg, int alen, int vsize, + struct brcms_c_if *wlcif); + #define MAC80211_PROMISC_BCNS (1 << 0) #define MAC80211_SCAN (1 << 1) /* - * Public portion of common driver state structure. + * Public portion of "common" os-independent state structure. * The wlc handle points at this. */ struct brcms_pub { - struct brcms_c_info *wlc; + void *wlc; + struct ieee80211_hw *ieee_hw; struct scb *global_scb; struct scb_ampdu *global_ampdu; @@ -241,8 +248,8 @@ struct brcms_pub { bool hw_off; /* HW is off */ /* tunables: ntxd, nrxd, maxscb, etc. */ struct brcms_tunables *tunables; - bool hw_up; /* one time hw up/down */ - bool _piomode; /* true if pio mode */ + bool hw_up; /* one time hw up/down(from boot or hibernation) */ + bool _piomode; /* true if pio mode *//* BMAC_NOTE: NEED In both */ uint _nbands; /* # bands supported */ uint now; /* # elapsed seconds */ @@ -263,7 +270,7 @@ struct brcms_pub { u8 _n_enab; /* bitmap of 11N + HT support */ bool _n_reqd; /* N support required for clients */ - s8 _coex; /* 20/40 MHz BSS Management AUTO, ENAB, DISABLE */ + s8 _coex; /* 20/40 MHz BSS Management AUTO, ENAB, DISABLE */ bool _priofc; /* Priority-based flowcontrol */ u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */ @@ -281,7 +288,7 @@ struct brcms_pub { int bcmerror; /* last bcm error */ - u32 radio_disabled; /* bit vector for radio disabled reasons */ + mbool radio_disabled; /* bit vector for radio disabled reasons */ bool radio_active; /* radio on/off state */ u16 roam_time_thresh; /* Max. # secs. of not hearing beacons * before roaming. @@ -324,6 +331,39 @@ struct wl_rxsts { struct brcms_if *wlif; /* wl interface */ }; +/* status per error RX pkt */ +#define WL_RXS_CRC_ERROR 0x00000001 /* CRC Error in packet */ +#define WL_RXS_RUNT_ERROR 0x00000002 /* Runt packet */ +#define WL_RXS_ALIGN_ERROR 0x00000004 /* Misaligned packet */ +#define WL_RXS_OVERSIZE_ERROR 0x00000008 /* packet bigger than RX_LENGTH (usually 1518) */ +#define WL_RXS_WEP_ICV_ERROR 0x00000010 /* Integrity Check Value error */ +#define WL_RXS_WEP_ENCRYPTED 0x00000020 /* Encrypted with WEP */ +#define WL_RXS_PLCP_SHORT 0x00000040 /* Short PLCP error */ +#define WL_RXS_DECRYPT_ERR 0x00000080 /* Decryption error */ +#define WL_RXS_OTHER_ERR 0x80000000 /* Other errors */ + +/* phy type */ +#define WL_RXS_PHY_A 0x00000000 /* A phy type */ +#define WL_RXS_PHY_B 0x00000001 /* B phy type */ +#define WL_RXS_PHY_G 0x00000002 /* G phy type */ +#define WL_RXS_PHY_N 0x00000004 /* N phy type */ + +/* encoding */ +#define WL_RXS_ENCODING_CCK 0x00000000 /* CCK encoding */ +#define WL_RXS_ENCODING_OFDM 0x00000001 /* OFDM encoding */ + +/* preamble */ +#define WL_RXS_UNUSED_STUB 0x0 /* stub to match with wlc_ethereal.h */ +#define WL_RXS_PREAMBLE_SHORT 0x00000001 /* Short preamble */ +#define WL_RXS_PREAMBLE_LONG 0x00000002 /* Long preamble */ +#define WL_RXS_PREAMBLE_MIMO_MM 0x00000003 /* MIMO mixed mode preamble */ +#define WL_RXS_PREAMBLE_MIMO_GF 0x00000004 /* MIMO green field preamble */ + +#define WL_RXS_NFRM_AMPDU_FIRST 0x00000001 /* first MPDU in A-MPDU */ +#define WL_RXS_NFRM_AMPDU_SUB 0x00000002 /* subsequent MPDU(s) in A-MPDU */ +#define WL_RXS_NFRM_AMSDU_FIRST 0x00000004 /* first MSDU in A-MSDU */ +#define WL_RXS_NFRM_AMSDU_SUB 0x00000008 /* subsequent MSDU(s) in A-MSDU */ + enum wlc_par_id { IOV_MPC = 1, IOV_RTSTHRESH, @@ -353,10 +393,8 @@ enum wlc_par_id { #define SUPPORT_11N (ENAB_1x1|ENAB_2x2) #define SUPPORT_HT (ENAB_1x1|ENAB_2x2|ENAB_3x3) /* WL11N Support */ -#if ((defined(NCONF) && (NCONF != 0)) || \ - (defined(LCNCONF) && (LCNCONF != 0)) || \ - (defined(HTCONF) && (HTCONF != 0)) || \ - (defined(SSLPNCONF) && (SSLPNCONF != 0))) +#if ((defined(NCONF) && (NCONF != 0)) || (defined(LCNCONF) && (LCNCONF != 0)) || \ + (defined(HTCONF) && (HTCONF != 0)) || (defined(SSLPNCONF) && (SSLPNCONF != 0))) #define N_ENAB(pub) ((pub)->_n_enab & SUPPORT_11N) #define N_REQD(pub) ((pub)->_n_reqd) #else @@ -388,10 +426,8 @@ enum wlc_par_id { extern const u8 wlc_prio2prec_map[]; #define BRCMS_PRIO_TO_PREC(pri) wlc_prio2prec_map[(pri) & 7] -/* - * This maps priority to one precedence higher - Used by PS-Poll response - * packets to simulate enqueue-at-head operation, but still maintain the - * order on the queue +/* This maps priority to one precedence higher - Used by PS-Poll response packets to + * simulate enqueue-at-head operation, but still maintain the order on the queue */ #define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\ BRCMS_PREC_COUNT - 1) @@ -444,34 +480,28 @@ extern const u8 wme_fifo2ac[]; /* * 54g modes (basic bits may still be overridden) * - * GMODE_LEGACY_B - * Rateset: 1b, 2b, 5.5, 11 - * Preamble: Long - * Shortslot: Off - * GMODE_AUTO - * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 - * Extended Rateset: 6, 9, 12, 48 - * Preamble: Long - * Shortslot: Auto - * GMODE_ONLY - * Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 - * Extended Rateset: 6b, 9, 12b, 48 - * Preamble: Short required - * Shortslot: Auto - * GMODE_B_DEFERRED - * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 - * Extended Rateset: 6, 9, 12, 48 - * Preamble: Long - * Shortslot: On - * GMODE_PERFORMANCE - * Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 - * Preamble: Short required - * Shortslot: On and required - * GMODE_LRS - * Rateset: 1b, 2b, 5.5b, 11b - * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 - * Preamble: Long - * Shortslot: Auto + * GMODE_LEGACY_B Rateset: 1b, 2b, 5.5, 11 + * Preamble: Long + * Shortslot: Off + * GMODE_AUTO Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 + * Extended Rateset: 6, 9, 12, 48 + * Preamble: Long + * Shortslot: Auto + * GMODE_ONLY Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 + * Extended Rateset: 6b, 9, 12b, 48 + * Preamble: Short required + * Shortslot: Auto + * GMODE_B_DEFERRED Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 + * Extended Rateset: 6, 9, 12, 48 + * Preamble: Long + * Shortslot: On + * GMODE_PERFORMANCE Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 + * Preamble: Short required + * Shortslot: On and required + * GMODE_LRS Rateset: 1b, 2b, 5.5b, 11b + * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 + * Preamble: Long + * Shortslot: Auto */ #define GMODE_LEGACY_B 0 #define GMODE_AUTO 1 @@ -514,18 +544,12 @@ extern const u8 wme_fifo2ac[]; #define BRCMS_N_SGI_40 0x02 /* defines used by the nrate iovar */ -/* MSC in use,indicates b0-6 holds an mcs */ -#define NRATE_MCS_INUSE 0x00000080 -/* rate/mcs value */ -#define NRATE_RATE_MASK 0x0000007f -/* stf mode mask: siso, cdd, stbc, sdm */ -#define NRATE_STF_MASK 0x0000ff00 -/* stf mode shift */ -#define NRATE_STF_SHIFT 8 -/* bit indicates override both rate & mode */ -#define NRATE_OVERRIDE 0x80000000 -/* bit indicate to override mcs only */ -#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 +#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ +#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ +#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ +#define NRATE_STF_SHIFT 8 /* stf mode shift */ +#define NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ +#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ #define NRATE_SGI_MASK 0x00800000 /* sgi mode */ #define NRATE_SGI_SHIFT 23 /* sgi mode */ #define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ @@ -536,11 +560,9 @@ extern const u8 wme_fifo2ac[]; #define NRATE_STF_STBC 2 /* stf mode STBC */ #define NRATE_STF_SDM 3 /* stf mode SDM */ -/* max number of antenna configurations */ -#define ANT_SELCFG_MAX 4 +#define ANT_SELCFG_MAX 4 /* max number of antenna configurations */ -/* MCS values greater than this enable multiple streams */ -#define HIGHEST_SINGLE_STREAM_MCS 7 +#define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */ struct brcms_antselcfg { u8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */ @@ -548,9 +570,9 @@ struct brcms_antselcfg { }; /* common functions for every port */ -struct brcms_c_info * -brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, - bool piomode, void *regsva, struct pci_dev *btparam, uint *perr); +extern void *brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, + uint unit, bool piomode, void *regsva, uint bustype, + void *btparam, uint *perr); extern uint brcms_c_detach(struct brcms_c_info *wlc); extern int brcms_c_up(struct brcms_c_info *wlc); extern uint brcms_c_down(struct brcms_c_info *wlc); @@ -587,15 +609,14 @@ extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc, extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, const struct ieee80211_tx_queue_params *arg, bool suspend); -extern struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc); +extern struct brcms_pub *brcms_c_pub(void *wlc); /* common functions for every port */ extern void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val, int bands); extern void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, - struct brcms_c_rateset *rateset); -extern void brcms_default_rateset(struct brcms_c_info *wlc, - struct brcms_c_rateset *rs); + wlc_rateset_t *rateset); +extern void brcms_default_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs); extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc, struct ieee80211_sta *sta, u16 tid); @@ -613,10 +634,10 @@ extern void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc); extern void brcms_c_mctrl(struct brcms_c_info *wlc, u32 mask, u32 val); extern int brcms_c_module_register(struct brcms_pub *pub, - const char *name, struct brcms_info *hdl, - int (*down_fn)(void *handle)); + const char *name, void *hdl, + watchdog_fn_t watchdog_fn, down_fn_t down_fn); extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, - struct brcms_info *hdl); + void *hdl); extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc); extern void brcms_c_enable_mac(struct brcms_c_info *wlc); extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state); @@ -638,4 +659,7 @@ extern bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc); #define BAND_2G_NAME "2.4G" #define BAND_5G_NAME "5G" +/* BMAC RPC: 7 u32 params: pkttotlen, fifo, commit, fid, txpktpend, pktflag, rpc_id */ +#define BRCMS_RPCTX_PARAMS 32 + #endif /* _BRCM_PUB_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/rate.c b/trunk/drivers/staging/brcm80211/brcmsmac/rate.c index 5fb0d9e8c5e2..f0e4b99c2566 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/rate.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/rate.c @@ -21,10 +21,7 @@ #include "pub.h" #include "rate.h" -/* - * Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate - * value - */ +/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */ const u8 rate_info[BRCM_MAXRATE + 1] = { /* 0 1 2 3 4 5 6 7 8 9 */ /* 0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -142,25 +139,20 @@ const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = { {0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M}, }; -/* - * phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams - * Number of spatial streams: always 1 other fields: refer to table 78 of - * section 17.3.2.2 of the original .11a standard +/* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams + * Number of spatial streams: always 1 + * other fields: refer to table 78 of section 17.3.2.2 of the original .11a standard */ struct legacy_phycfg { u32 rate_ofdm; /* ofdm mac rate */ - /* phy ctl byte 3, code rate, modulation type, # of streams */ - u8 tx_phy_ctl3; + u8 tx_phy_ctl3; /* phy ctl byte 3, code rate, modulation type, # of streams */ }; -/* Number of legacy_rate_cfg entries in the table */ -#define LEGACY_PHYCFG_TABLE_SIZE 12 +#define LEGACY_PHYCFG_TABLE_SIZE 12 /* Number of legacy_rate_cfg entries in the table */ -/* - * In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate - * Eventually MIMOPHY would also be converted to this format - * 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps - */ +/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */ +/* Eventually MIMOPHY would also be converted to this format */ +/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */ static const struct legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = { {BRCM_RATE_1M, 0x00}, /* CCK 1Mbps, data rate 0 */ @@ -187,89 +179,86 @@ legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = { /* Hardware rates (also encodes default basic rates) */ -const struct brcms_c_rateset cck_ofdm_mimo_rates = { +const wlc_rateset_t cck_ofdm_mimo_rates = { 12, - /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, */ - { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, - /* 54 Mbps */ - 0x6c}, + { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */ + 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x6c}, 0x00, - { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00} + {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} }; -const struct brcms_c_rateset ofdm_mimo_rates = { +const wlc_rateset_t ofdm_mimo_rates = { 8, - /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ - { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, + { /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ + 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, 0x00, - { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00} + {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} }; /* Default ratesets that include MCS32 for 40BW channels */ -const struct brcms_c_rateset cck_ofdm_40bw_mimo_rates = { +const wlc_rateset_t cck_ofdm_40bw_mimo_rates = { 12, - /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48 */ - { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, - /* 54 Mbps */ - 0x6c}, + { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */ + 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x6c}, 0x00, - { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00} + {0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} }; -const struct brcms_c_rateset ofdm_40bw_mimo_rates = { +const wlc_rateset_t ofdm_40bw_mimo_rates = { 8, - /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ - { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, + { /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ + 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, 0x00, - { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00} + {0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00} }; -const struct brcms_c_rateset cck_ofdm_rates = { +const wlc_rateset_t cck_ofdm_rates = { 12, - /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48,*/ - { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, - /*54 Mbps */ - 0x6c}, + { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */ + 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x6c}, 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} }; -const struct brcms_c_rateset gphy_legacy_rates = { +const wlc_rateset_t gphy_legacy_rates = { 4, - /* 1b, 2b, 5.5b, 11b Mbps */ - { 0x82, 0x84, 0x8b, 0x96}, + { /* 1b, 2b, 5.5b, 11b Mbps */ + 0x82, 0x84, 0x8b, 0x96}, 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} }; -const struct brcms_c_rateset ofdm_rates = { +const wlc_rateset_t ofdm_rates = { 8, - /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ - { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, + { /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ + 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, 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} }; -const struct brcms_c_rateset cck_rates = { +const wlc_rateset_t cck_rates = { 4, - /* 1b, 2b, 5.5, 11 Mbps */ - { 0x82, 0x84, 0x0b, 0x16}, + { /* 1b, 2b, 5.5, 11 Mbps */ + 0x82, 0x84, 0x0b, 0x16}, 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} }; /* check if rateset is valid. * if check_brate is true, rateset without a basic rate is considered NOT valid. */ -static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate) +static bool brcms_c_rateset_valid(wlc_rateset_t *rs, bool check_brate) { uint idx; @@ -287,20 +276,19 @@ static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate) return false; } -void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams) +void brcms_c_rateset_mcs_upd(wlc_rateset_t *rs, u8 txstreams) { int i; for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++) rs->mcs[i] = 0; } -/* - * filter based on hardware rateset, and sort filtered rateset with basic - * bit(s) preserved, and check if resulting rateset is valid. +/* filter based on hardware rateset, and sort filtered rateset with basic bit(s) preserved, + * and check if resulting rateset is valid. */ bool -brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, - const struct brcms_c_rateset *hw_rs, +brcms_c_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs, + const wlc_rateset_t *hw_rs, bool check_brate, u8 txstreams) { u8 rateset[BRCM_MAXRATE + 1]; @@ -340,10 +328,10 @@ brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, } /* calculate the rate of a rx'd frame and return it as a ratespec */ -u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp) +ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp) { int phy_type; - u32 rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT; + ratespec_t rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT; phy_type = ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT); @@ -389,10 +377,9 @@ u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp) } /* copy rateset src to dst as-is (no masking or sorting) */ -void brcms_c_rateset_copy(const struct brcms_c_rateset *src, - struct brcms_c_rateset *dst) +void brcms_c_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst) { - memcpy(dst, src, sizeof(struct brcms_c_rateset)); + memcpy(dst, src, sizeof(wlc_rateset_t)); } /* @@ -405,8 +392,8 @@ void brcms_c_rateset_copy(const struct brcms_c_rateset *src, * 'xmask' is the copy mask (typically 0x7f or 0xff). */ void -brcms_c_rateset_filter(struct brcms_c_rateset *src, struct brcms_c_rateset *dst, - bool basic_only, u8 rates, uint xmask, bool mcsallow) +brcms_c_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only, + u8 rates, uint xmask, bool mcsallow) { uint i; uint r; @@ -436,24 +423,24 @@ brcms_c_rateset_filter(struct brcms_c_rateset *src, struct brcms_c_rateset *dst, * and fill rs_tgt with result */ void -brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, - const struct brcms_c_rateset *rs_hw, - uint phy_type, int bandtype, bool cck_only, - uint rate_mask, bool mcsallow, u8 bw, u8 txstreams) +brcms_c_rateset_default(wlc_rateset_t *rs_tgt, const wlc_rateset_t *rs_hw, + uint phy_type, int bandtype, bool cck_only, uint rate_mask, + bool mcsallow, u8 bw, u8 txstreams) { - const struct brcms_c_rateset *rs_dflt; - struct brcms_c_rateset rs_sel; + const wlc_rateset_t *rs_dflt; + wlc_rateset_t rs_sel; if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) || (PHYTYPE_IS(phy_type, PHY_TYPE_N)) || (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) || (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) { - if (BAND_5G(bandtype)) + if (BAND_5G(bandtype)) { rs_dflt = (bw == BRCMS_20_MHZ ? &ofdm_mimo_rates : &ofdm_40bw_mimo_rates); - else + } else { rs_dflt = (bw == BRCMS_20_MHZ ? &cck_ofdm_mimo_rates : &cck_ofdm_40bw_mimo_rates); + } } else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) { rs_dflt = (BAND_5G(bandtype)) ? &ofdm_rates : &cck_ofdm_rates; } else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) { @@ -488,21 +475,21 @@ s16 brcms_c_rate_legacy_phyctl(uint rate) return -1; } -void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset) +void brcms_c_rateset_mcs_clear(wlc_rateset_t *rateset) { uint i; for (i = 0; i < MCSSET_LEN; i++) rateset->mcs[i] = 0; } -void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams) +void brcms_c_rateset_mcs_build(wlc_rateset_t *rateset, u8 txstreams) { memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN); brcms_c_rateset_mcs_upd(rateset, txstreams); } /* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */ -void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw) +void brcms_c_rateset_bw_mcs_filter(wlc_rateset_t *rateset, u8 bw) { if (bw == BRCMS_40_MHZ) setbit(rateset->mcs, 32); diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/rate.h b/trunk/drivers/staging/brcm80211/brcmsmac/rate.h index 39e1796e924a..dbfd3e5816d4 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/rate.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/rate.h @@ -20,28 +20,22 @@ #include "types.h" extern const u8 rate_info[]; -extern const struct brcms_c_rateset cck_ofdm_mimo_rates; -extern const struct brcms_c_rateset ofdm_mimo_rates; -extern const struct brcms_c_rateset cck_ofdm_rates; -extern const struct brcms_c_rateset ofdm_rates; -extern const struct brcms_c_rateset cck_rates; -extern const struct brcms_c_rateset gphy_legacy_rates; -extern const struct brcms_c_rateset wlc_lrs_rates; -extern const struct brcms_c_rateset rate_limit_1_2; +extern const struct brcms_rateset cck_ofdm_mimo_rates; +extern const struct brcms_rateset ofdm_mimo_rates; +extern const struct brcms_rateset cck_ofdm_rates; +extern const struct brcms_rateset ofdm_rates; +extern const struct brcms_rateset cck_rates; +extern const struct brcms_rateset gphy_legacy_rates; +extern const struct brcms_rateset wlc_lrs_rates; +extern const struct brcms_rateset rate_limit_1_2; struct brcms_mcs_info { - /* phy rate in kbps [20Mhz] */ - u32 phy_rate_20; - /* phy rate in kbps [40Mhz] */ - u32 phy_rate_40; - /* phy rate in kbps [20Mhz] with SGI */ - u32 phy_rate_20_sgi; - /* phy rate in kbps [40Mhz] with SGI */ - u32 phy_rate_40_sgi; - /* phy ctl byte 3, code rate, modulation type, # of streams */ - u8 tx_phy_ctl3; - /* matching legacy ofdm rate in 500bkps */ - u8 leg_ofdm; + u32 phy_rate_20; /* phy rate in kbps [20Mhz] */ + u32 phy_rate_40; /* phy rate in kbps [40Mhz] */ + u32 phy_rate_20_sgi; /* phy rate in kbps [20Mhz] with SGI */ + u32 phy_rate_40_sgi; /* phy rate in kbps [40Mhz] with SGI */ + u8 tx_phy_ctl3; /* phy ctl byte 3, code rate, modulation type, # of streams */ + u8 leg_ofdm; /* matching legacy ofdm rate in 500bkps */ }; #define BRCMS_MAXMCS 32 /* max valid mcs index */ @@ -55,18 +49,11 @@ extern const struct brcms_mcs_info mcs_table[]; #define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */ #define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */ #define MCS_CR(_mcs) (mcs_table[_mcs].tx_phy_ctl3 & MCS_CR_MASK) - -#define MCS_MOD(_mcs) \ - ((mcs_table[_mcs].tx_phy_ctl3 & MCS_MOD_MASK) >> MCS_MOD_SHIFT) - -#define MCS_TXS(_mcs) \ - ((mcs_table[_mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT) - +#define MCS_MOD(_mcs) ((mcs_table[_mcs].tx_phy_ctl3 & MCS_MOD_MASK) >> MCS_MOD_SHIFT) +#define MCS_TXS(_mcs) ((mcs_table[_mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT) #define MCS_RATE(_mcs, _is40, _sgi) (_sgi ? \ - (_is40 ? mcs_table[_mcs].phy_rate_40_sgi : \ - mcs_table[_mcs].phy_rate_20_sgi) : \ + (_is40 ? mcs_table[_mcs].phy_rate_40_sgi : mcs_table[_mcs].phy_rate_20_sgi) : \ (_is40 ? mcs_table[_mcs].phy_rate_40 : mcs_table[_mcs].phy_rate_20)) - #define VALID_MCS(_mcs) ((_mcs < MCS_TABLE_SIZE)) /* Macro to use the rate_info table */ @@ -75,78 +62,46 @@ extern const struct brcms_mcs_info mcs_table[]; /* convert 500kbps to bps */ #define BRCMS_RATE_500K_TO_BPS(rate) ((rate) * 500000) -/* - * rate spec : holds rate and mode specific information required to generate a - * tx frame. Legacy CCK and OFDM information is held in the same manner as was - * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO - * specific information - */ +/* rate spec : holds rate and mode specific information required to generate a tx frame. */ +/* Legacy CCK and OFDM information is held in the same manner as was done in the past */ +/* (in the lower byte) the upper 3 bytes primarily hold MIMO specific information */ /* rate spec bit fields */ - -/* Either 500Kbps units or MIMO MCS idx */ -#define RSPEC_RATE_MASK 0x0000007F -/* mimo MCS is stored in RSPEC_RATE_MASK */ -#define RSPEC_MIMORATE 0x08000000 -/* mimo bw mask */ -#define RSPEC_BW_MASK 0x00000700 -/* mimo bw shift */ -#define RSPEC_BW_SHIFT 8 -/* mimo Space/Time/Frequency mode mask */ -#define RSPEC_STF_MASK 0x00003800 -/* mimo Space/Time/Frequency mode shift */ -#define RSPEC_STF_SHIFT 11 -/* mimo coding type mask */ -#define RSPEC_CT_MASK 0x0000C000 -/* mimo coding type shift */ -#define RSPEC_CT_SHIFT 14 -/* mimo num STC streams per PLCP defn. */ -#define RSPEC_STC_MASK 0x00300000 -/* mimo num STC streams per PLCP defn. */ -#define RSPEC_STC_SHIFT 20 -/* mimo bit indicates adv coding in use */ -#define RSPEC_LDPC_CODING 0x00400000 -/* mimo bit indicates short GI in use */ -#define RSPEC_SHORT_GI 0x00800000 -/* bit indicates override both rate & mode */ -#define RSPEC_OVERRIDE 0x80000000 -/* bit indicates override rate only */ -#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 +#define RSPEC_RATE_MASK 0x0000007F /* Either 500Kbps units or MIMO MCS idx */ +#define RSPEC_MIMORATE 0x08000000 /* mimo MCS is stored in RSPEC_RATE_MASK */ +#define RSPEC_BW_MASK 0x00000700 /* mimo bw mask */ +#define RSPEC_BW_SHIFT 8 /* mimo bw shift */ +#define RSPEC_STF_MASK 0x00003800 /* mimo Space/Time/Frequency mode mask */ +#define RSPEC_STF_SHIFT 11 /* mimo Space/Time/Frequency mode shift */ +#define RSPEC_CT_MASK 0x0000C000 /* mimo coding type mask */ +#define RSPEC_CT_SHIFT 14 /* mimo coding type shift */ +#define RSPEC_STC_MASK 0x00300000 /* mimo num STC streams per PLCP defn. */ +#define RSPEC_STC_SHIFT 20 /* mimo num STC streams per PLCP defn. */ +#define RSPEC_LDPC_CODING 0x00400000 /* mimo bit indicates adv coding in use */ +#define RSPEC_SHORT_GI 0x00800000 /* mimo bit indicates short GI in use */ +#define RSPEC_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ +#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicates override rate only */ #define BRCMS_HTPHY 127 /* HT PHY Membership */ #define RSPEC_ACTIVE(rspec) (rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE)) - -#define RSPEC2RATE(rspec) \ - ((rspec & RSPEC_MIMORATE) ? \ - MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), \ - RSPEC_ISSGI(rspec)) : \ +#define RSPEC2RATE(rspec) ((rspec & RSPEC_MIMORATE) ? \ + MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec)) : \ (rspec & RSPEC_RATE_MASK)) - /* return rate in unit of 500Kbps -- for internal use in wlc_rate_sel.c */ -#define RSPEC2RATE500K(rspec) \ - ((rspec & RSPEC_MIMORATE) ? \ - MCS_RATE((rspec & RSPEC_RATE_MASK), state->is40bw, \ - RSPEC_ISSGI(rspec))/500 : \ - (rspec & RSPEC_RATE_MASK)) - -#define CRSPEC2RATE500K(rspec) \ - ((rspec & RSPEC_MIMORATE) ? \ - MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), \ - RSPEC_ISSGI(rspec))/500 :\ - (rspec & RSPEC_RATE_MASK)) - -#define RSPEC2KBPS(rspec) \ - (IS_MCS(rspec) ? RSPEC2RATE(rspec) : RSPEC2RATE(rspec)*500) - +#define RSPEC2RATE500K(rspec) ((rspec & RSPEC_MIMORATE) ? \ + MCS_RATE((rspec & RSPEC_RATE_MASK), state->is40bw, RSPEC_ISSGI(rspec))/500 : \ + (rspec & RSPEC_RATE_MASK)) +#define CRSPEC2RATE500K(rspec) ((rspec & RSPEC_MIMORATE) ? \ + MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec))/500 :\ + (rspec & RSPEC_RATE_MASK)) + +#define RSPEC2KBPS(rspec) (IS_MCS(rspec) ? RSPEC2RATE(rspec) : RSPEC2RATE(rspec)*500) #define RSPEC_PHYTXBYTE2(rspec) ((rspec & 0xff00) >> 8) - #define RSPEC_GET_BW(rspec) ((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) - -#define RSPEC_IS40MHZ(rspec) \ - ((((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) == PHY_TXC1_BW_40MHZ) || \ - (((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) == PHY_TXC1_BW_40MHZ_DUP)) - +#define RSPEC_IS40MHZ(rspec) ((((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) == \ + PHY_TXC1_BW_40MHZ) || (((rspec & RSPEC_BW_MASK) >> \ + RSPEC_BW_SHIFT) == PHY_TXC1_BW_40MHZ_DUP)) #define RSPEC_ISSGI(rspec) ((rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI) #define RSPEC_MIMOPLCP3(rspec) ((rspec & 0xf00000) >> 16) #define PLCP3_ISSGI(plcp) (plcp & (RSPEC_SHORT_GI >> 16)) @@ -156,35 +111,26 @@ extern const struct brcms_mcs_info mcs_table[]; #define PLCP3_STC_MASK 0x30 #define PLCP3_STC_SHIFT 4 -/* Rate info table; takes a legacy rate or u32 */ +/* Rate info table; takes a legacy rate or ratespec_t */ #define IS_MCS(r) (r & RSPEC_MIMORATE) - #define IS_OFDM(r) (!IS_MCS(r) && (rate_info[(r) & RSPEC_RATE_MASK] & \ BRCMS_RATE_FLAG)) - #define IS_CCK(r) (!IS_MCS(r) && ( \ ((r) & BRCMS_RATE_MASK) == BRCM_RATE_1M || \ ((r) & BRCMS_RATE_MASK) == BRCM_RATE_2M || \ ((r) & BRCMS_RATE_MASK) == BRCM_RATE_5M5 || \ ((r) & BRCMS_RATE_MASK) == BRCM_RATE_11M)) - -#define IS_SINGLE_STREAM(mcs) \ - (((mcs) <= HIGHEST_SINGLE_STREAM_MCS) || ((mcs) == 32)) - +#define IS_SINGLE_STREAM(mcs) (((mcs) <= HIGHEST_SINGLE_STREAM_MCS) || ((mcs) == 32)) #define CCK_RSPEC(cck) ((cck) & RSPEC_RATE_MASK) - #define OFDM_RSPEC(ofdm) (((ofdm) & RSPEC_RATE_MASK) |\ (PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT)) - -#define LEGACY_RSPEC(rate) \ - (IS_CCK(rate) ? CCK_RSPEC(rate) : OFDM_RSPEC(rate)) +#define LEGACY_RSPEC(rate) (IS_CCK(rate) ? CCK_RSPEC(rate) : OFDM_RSPEC(rate)) #define MCS_RSPEC(mcs) (((mcs) & RSPEC_RATE_MASK) | RSPEC_MIMORATE | \ (IS_SINGLE_STREAM(mcs) ? (PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT) : \ (PHY_TXC1_MODE_SDM << RSPEC_STF_SHIFT))) -/* Convert encoded rate value in plcp header to numerical rates in 500 KHz - * increments */ +/* Convert encoded rate value in plcp header to numerical rates in 500 KHz increments */ extern const u8 ofdm_rate_lookup[]; #define OFDM_PHY2MAC_RATE(rlpt) (ofdm_rate_lookup[rlpt & 0x7]) #define CCK_PHY2MAC_RATE(signal) (signal/5) @@ -194,36 +140,34 @@ extern const u8 ofdm_rate_lookup[]; #define BRCMS_RATES_CCK 1 #define BRCMS_RATES_OFDM 2 -/* sanitize, and sort a rateset with the basic bit(s) preserved, validate - * rateset */ +/* sanitize, and sort a rateset with the basic bit(s) preserved, validate rateset */ extern bool -brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, - const struct brcms_c_rateset *hw_rs, +brcms_c_rate_hwrs_filter_sort_validate(struct brcms_rateset *rs, + const struct brcms_rateset *hw_rs, bool check_brate, u8 txstreams); /* copy rateset src to dst as-is (no masking or sorting) */ -extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src, - struct brcms_c_rateset *dst); +extern void brcms_c_rateset_copy(const struct brcms_rateset *src, + struct brcms_rateset *dst); /* would be nice to have these documented ... */ -extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); +extern ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); -extern void brcms_c_rateset_filter(struct brcms_c_rateset *src, - struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask, +extern void brcms_c_rateset_filter(struct brcms_rateset *src, + struct brcms_rateset *dst, bool basic_only, u8 rates, uint xmask, bool mcsallow); extern void -brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, - const struct brcms_c_rateset *rs_hw, uint phy_type, +brcms_c_rateset_default(struct brcms_rateset *rs_tgt, + const struct brcms_rateset *rs_hw, uint phy_type, int bandtype, bool cck_only, uint rate_mask, bool mcsallow, u8 bw, u8 txstreams); extern s16 brcms_c_rate_legacy_phyctl(uint rate); -extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); -extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); -extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, +extern void brcms_c_rateset_mcs_upd(struct brcms_rateset *rs, u8 txstreams); +extern void brcms_c_rateset_mcs_clear(struct brcms_rateset *rateset); +extern void brcms_c_rateset_mcs_build(struct brcms_rateset *rateset, u8 txstreams); -extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, - u8 bw); +extern void brcms_c_rateset_bw_mcs_filter(struct brcms_rateset *rateset, u8 bw); #endif /* _BRCM_RATE_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/scb.h b/trunk/drivers/staging/brcm80211/brcmsmac/scb.h index efa504716612..d6c8328554d0 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/scb.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/scb.h @@ -23,15 +23,13 @@ #include "types.h" #define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */ - /* structure to store per-tid state for the ampdu initiator */ struct scb_ampdu_tid_ini { - u8 tx_in_transit; /* number of pending mpdus in transit in driver */ - u8 tid; /* initiator tid for easy lookup */ - /* tx retry count; indexed by seq modulo */ - u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; - struct scb *scb; /* backptr for easy lookup */ - u8 ba_wsize; /* negotiated ba window size (in pdu) */ + u8 tx_in_transit; /* number of pending mpdus in transit in driver */ + u8 tid; /* initiator tid for easy lookup */ + u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; /* tx retry count; indexed by seq modulo */ + struct scb *scb; /* backptr for easy lookup */ + u8 ba_wsize; /* negotiated ba window size (in pdu) */ }; #define AMPDU_MAX_SCB_TID NUMPRIO @@ -45,10 +43,9 @@ struct scb_ampdu { u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */ struct pktq txq; /* sdu transmit queue pending aggregation */ - /* - * This could easily be a ini[] pointer and we keep this info in wl - * itself instead of having mac80211 hold it for us. Also could be made - * dynamic per tid instead of static. + /* This could easily be a ini[] pointer and we keep this info in wl itself instead + * of having mac80211 hold it for us. Also could be made dynamic per tid instead of + * static. */ /* initiator info - per tid (NUMPRIO): */ struct scb_ampdu_tid_ini ini[AMPDU_MAX_SCB_TID]; @@ -59,17 +56,18 @@ struct scb_ampdu { /* station control block - one per remote MAC address */ struct scb { u32 magic; - u32 flags; /* various bit flags as defined below */ - u32 flags2; /* various bit flags2 as defined below */ - u8 state; /* current state bitfield of auth/assoc process */ + u32 flags; /* various bit flags as defined below */ + u32 flags2; /* various bit flags2 as defined below */ + u8 state; /* current state bitfield of auth/assoc process */ u8 ea[ETH_ALEN]; /* station address */ - uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */ + void *fragbuf[NUMPRIO]; /* defragmentation buffer per prio */ + uint fragresid[NUMPRIO]; /* #bytes unused in frag buffer per prio */ u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */ - /* seqctl of last received frame (for dups) for non-QoS data and - * management */ - u16 seqctl_nonqos; - u16 seqnum[NUMPRIO];/* WME: driver maintained sw seqnum per priority */ + u16 seqctl_nonqos; /* seqctl of last received frame (for dups) for + * non-QoS data and management + */ + u16 seqnum[NUMPRIO]; /* WME: driver maintained sw seqnum per priority */ struct scb_ampdu scb_ampdu; /* AMPDU state including per tid info */ }; diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/srom.c b/trunk/drivers/staging/brcm80211/brcmsmac/srom.c index 90e2ac80c228..f39442ed4ce7 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/srom.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/srom.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -34,19 +33,10 @@ ((u8 *)curmap + PCI_BAR0_SPROM_OFFSET)) #if defined(BCMDBG) -/* 500 ms after write enable/disable toggle */ -#define WRITE_ENABLE_DELAY 500 -/* 20 ms between each word write */ -#define WRITE_WORD_DELAY 20 +#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */ +#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */ #endif -/* - * SROM CRC8 polynomial value: - * - * x^8 + x^7 +x^6 + x^4 + x^2 + 1 - */ -#define SROM_CRC8_POLY 0xAB - /* Maximum srom: 6 Kilobits == 768 bytes */ #define SROM_MAX 768 @@ -270,8 +260,7 @@ /* Temp sense related entries */ #define SROM8_MPWR_RAWTS 90 #define SROM8_TS_SLP_OPT_CORRX 91 -/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, - * IQSWP: IQ CAL swap disable */ +/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */ #define SROM8_FOC_HWIQ_IQSWP 92 /* Temperature delta for PHY calibration */ @@ -360,17 +349,14 @@ #define SROM9_PO_LOFDM40DUP 203 /* SROM flags (see sromvar_t) */ - -/* value continues as described by the next entry */ -#define SRFL_MORE 1 +#define SRFL_MORE 1 /* value continues as described by the next entry */ #define SRFL_NOFFS 2 /* value bits can't be all one's */ #define SRFL_PRHEX 4 /* value is in hexdecimal format */ #define SRFL_PRSIGN 8 /* value is in signed decimal format */ #define SRFL_CCODE 0x10 /* value is in country code format */ #define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ #define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ -/* do not generate a nvram param, entry is for mfgc */ -#define SRFL_NOVAR 0x80 +#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */ /* Max. nvram variable table size */ #define MAXSZ_NVRAM_VARS 4096 @@ -389,18 +375,17 @@ struct brcms_varbuf { unsigned int size; /* current (residual) size in bytes */ }; -/* - * Assumptions: - * - Ethernet address spans across 3 consecutive words +/* Assumptions: + * - Ethernet address spans across 3 consective words * * Table rules: - * - Add multiple entries next to each other if a value spans across multiple - * words (even multiple fields in the same word) with each entry except the - * last having it's SRFL_MORE bit set. - * - Ethernet address entry does not follow above rule and must not have - * SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words. - * - The last entry's name field must be NULL to indicate the end of the table. - * Other entries must have non-NULL name. + * - Add multiple entries next to each other if a value spans across multiple words + * (even multiple fields in the same word) with each entry except the last having + * it's SRFL_MORE bit set. + * - Ethernet address entry does not follow above rule and must not have SRFL_MORE + * bit set. Its SRFL_ETHADDR bit implies it takes multiple words. + * - The last entry's name field must be NULL to indicate the end of the table. Other + * entries must have non-NULL name. */ static const struct brcms_sromvar pci_sromvars[] = { {"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff}, @@ -790,8 +775,6 @@ static const struct brcms_sromvar perpath_pci_sromvars[] = { {NULL, 0, 0, 0, 0} }; -static u8 srom_crc8_table[CRC8_TABLE_SIZE]; - static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b); static int initvars_srom_pci(struct si_pub *sih, void *curmap, char **vars, @@ -827,12 +810,12 @@ static int varbuf_append(struct brcms_varbuf *b, const char *fmt, ...) r = vsnprintf(b->buf, b->size, fmt, ap); va_end(ap); - /* - * C99 snprintf behavior returns r >= size on overflow, - * others return -1 on overflow. All return -1 on format error. - * We need to leave room for 2 null terminations, one for the current - * var string, and one for final null of the var table. So check that - * the strlen written, r, leaves room for 2 chars. + /* C99 snprintf behavior returns r >= size on overflow, + * others return -1 on overflow. + * All return -1 on format error. + * We need to leave room for 2 null terminations, one for the current var + * string, and one for final null of the var table. So check that the + * strlen written, r, leaves room for 2 chars. */ if ((r == -1) || (r > (int)(b->size - 2))) { b->size = 0; @@ -870,7 +853,8 @@ static int varbuf_append(struct brcms_varbuf *b, const char *fmt, ...) * Initialize local vars from the right source for this platform. * Return 0 on success, nonzero on error. */ -int srom_var_init(struct si_pub *sih, void *curmap, char **vars, uint *count) +int srom_var_init(struct si_pub *sih, uint bustype, void *curmap, + char **vars, uint *count) { uint len; @@ -882,7 +866,7 @@ int srom_var_init(struct si_pub *sih, void *curmap, char **vars, uint *count) *vars = NULL; *count = 0; - if (curmap != NULL) + if (curmap != NULL && bustype == PCI_BUS) return initvars_srom_pci(sih, curmap, vars, count); return -EINVAL; @@ -890,15 +874,13 @@ int srom_var_init(struct si_pub *sih, void *curmap, char **vars, uint *count) static inline void ltoh16_buf(u16 *buf, unsigned int size) { - size /= 2; - while (size--) + for (size /= 2; size; size--) *(buf + size) = le16_to_cpu(*(buf + size)); } static inline void htol16_buf(u16 *buf, unsigned int size) { - size /= 2; - while (size--) + for (size /= 2; size; size--) *(buf + size) = cpu_to_le16(*(buf + size)); } @@ -919,21 +901,21 @@ sprom_read_pci(struct si_pub *sih, u16 *sprom, uint wordoff, if (check_crc) { - if (buf[0] == 0xffff) - /* - * The hardware thinks that an srom that starts with - * 0xffff is blank, regardless of the rest of the - * content, so declare it bad. + if (buf[0] == 0xffff) { + /* The hardware thinks that an srom that starts with 0xffff + * is blank, regardless of the rest of the content, so declare + * it bad. */ return -ENODATA; + } /* fixup the endianness so crc8 will pass */ htol16_buf(buf, nwords * 2); - if (crc8(srom_crc8_table, (u8 *) buf, nwords * 2, - CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(srom_crc8_table)) + if (brcmu_crc8((u8 *) buf, nwords * 2, CRC8_INIT_VALUE) != + CRC8_GOOD_VALUE) { /* DBG only pci always read srom4 first, then srom8/9 */ err = -EIO; - + } /* now correct the endianness of the byte array */ ltoh16_buf(buf, nwords * 2); } @@ -948,8 +930,9 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz) int err = 0; otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC); - if (otp == NULL) + if (otp == NULL) { return -ENOMEM; + } err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz); @@ -958,19 +941,20 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz) kfree(otp); /* Check CRC */ - if (buf[0] == 0xffff) + if (buf[0] == 0xffff) { /* The hardware thinks that an srom that starts with 0xffff * is blank, regardless of the rest of the content, so declare * it bad. */ return -ENODATA; + } /* fixup the endianness so crc8 will pass */ htol16_buf(buf, bufsz); - if (crc8(srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2, - CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(srom_crc8_table)) + if (brcmu_crc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) != + CRC8_GOOD_VALUE) { err = -EIO; - + } /* now correct the endianness of the byte array */ ltoh16_buf(buf, bufsz); @@ -1100,10 +1084,8 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b) *(oncount >> 24) (offcount >> 8) */ else if (flags & SRFL_LEDDC) { - u32 w32 = /* oncount */ - (((val >> 8) & 0xff) << 24) | - /* offcount */ - (((val & 0xff)) << 8); + u32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */ + (((val & 0xff)) << 8); /* offcount */ varbuf_append(b, "leddc=%d", w32); } else if (flags & SRFL_PRHEX) varbuf_append(b, "%s=0x%x", name, val); @@ -1137,6 +1119,7 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b) if (pb + srv->off < off) continue; + /* This entry is for mfgc only. Don't generate param for it, */ if (srv->flags & SRFL_NOVAR) continue; @@ -1144,8 +1127,8 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b) val = (w & srv->mask) >> mask_shift(srv->mask); width = mask_width(srv->mask); - /* Cheating: no per-path var is more than - * 1 word */ + /* Cheating: no per-path var is more than 1 word */ + if ((srv->flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1)) continue; @@ -1184,8 +1167,6 @@ static int initvars_srom_pci(struct si_pub *sih, void *curmap, char **vars, return -ENOMEM; sromwindow = (u16 *) SROM_OFFSET(sih); - - crc8_populate_lsb(srom_crc8_table, SROM_CRC8_POLY); if (ai_is_sprom_available(sih)) { err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS, true); @@ -1225,10 +1206,7 @@ static int initvars_srom_pci(struct si_pub *sih, void *curmap, char **vars, /* Bitmask for the sromrev */ sr = 1 << sromrev; - /* - * srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, - * 9 - */ + /* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */ if ((sr & 0x33e) == 0) { err = -EINVAL; goto errout; diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/srom.h b/trunk/drivers/staging/brcm80211/brcmsmac/srom.h index dd51156fb120..efc4d1edd86d 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/srom.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/srom.h @@ -20,8 +20,8 @@ #include "types.h" /* Prototypes */ -extern int srom_var_init(struct si_pub *sih, void *curmap, char **vars, - uint *count); +extern int srom_var_init(struct si_pub *sih, uint bus, void *curmap, + char **vars, uint *count); extern int srom_read(struct si_pub *sih, uint bus, void *curmap, uint byteoff, uint nbytes, u16 *buf, bool check_crc); diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/stf.c b/trunk/drivers/staging/brcm80211/brcmsmac/stf.c index a4c5c637744b..a55ff0101782 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/stf.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/stf.c @@ -22,6 +22,7 @@ #include "phy/phy_hal.h" #include "channel.h" #include "main.h" +#include "bmac.h" #include "stf.h" #define MIN_SPATIAL_EXPANSION 0 @@ -37,7 +38,7 @@ static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val); static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, - u32 rspec); + ratespec_t rspec); #define NSTS_1 1 #define NSTS_2 2 @@ -68,10 +69,7 @@ static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val) } } -/* - * every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to - * turn on/off txchain. - */ +/* every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to turn on/off txchain */ void brcms_c_tempsense_upd(struct brcms_c_info *wlc) { struct brcms_phy_pub *pi = wlc->band->pi; @@ -83,19 +81,21 @@ void brcms_c_tempsense_upd(struct brcms_c_info *wlc) txchain = active_chains & 0xf; if (wlc->stf->txchain == wlc->stf->hw_txchain) { - if (txchain && (txchain < wlc->stf->hw_txchain)) + if (txchain && (txchain < wlc->stf->hw_txchain)) { /* turn off 1 tx chain */ brcms_c_stf_txchain_set(wlc, txchain, true); + } } else if (wlc->stf->txchain < wlc->stf->hw_txchain) { - if (txchain == wlc->stf->hw_txchain) + if (txchain == wlc->stf->hw_txchain) { /* turn back on txchain */ brcms_c_stf_txchain_set(wlc, txchain, true); + } } } void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, - u16 chanspec) + chanspec_t chanspec) { struct tx_power power; u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id; @@ -120,19 +120,16 @@ brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, /* criteria to choose stf mode */ - /* - * the "+3dbm (12 0.25db units)" is to account for the fact that with - * CDD, tx occurs on both chains + /* the "+3dbm (12 0.25db units)" is to account for the fact that with CDD, tx occurs + * on both chains */ if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12)) setbit(ss_algo_channel, PHY_TXC1_MODE_SISO); else setbit(ss_algo_channel, PHY_TXC1_MODE_CDD); - /* - * STBC is ORed into to algo channel as STBC requires per-packet SCB - * capability check so cannot be default mode of operation. One of - * SISO, CDD have to be set + /* STBC is ORed into to algo channel as STBC requires per-packet SCB capability check + * so cannot be default mode of operation. One of SISO, CDD have to be set */ if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12)) setbit(ss_algo_channel, PHY_TXC1_MODE_STBC); @@ -140,8 +137,9 @@ brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val) { - if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) + if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) { return false; + } if ((int_val == ON) && (wlc->stf->txstreams == 1)) return false; @@ -161,8 +159,9 @@ static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val) bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val) { if ((int_val != HT_CAP_RX_STBC_NO) - && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) + && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) { return false; + } if (BRCMS_STF_SS_STBC_RX(wlc)) { if ((int_val != HT_CAP_RX_STBC_NO) @@ -180,13 +179,15 @@ static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts, BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n", wlc->pub->unit, Nsts, core_mask); - if (BRCMS_BITSCNT(core_mask) > wlc->stf->txstreams) + if (BRCMS_BITSCNT(core_mask) > wlc->stf->txstreams) { core_mask = 0; + } if ((BRCMS_BITSCNT(core_mask) == wlc->stf->txstreams) && ((core_mask & ~wlc->stf->txchain) - || !(core_mask & wlc->stf->txchain))) + || !(core_mask & wlc->stf->txchain))) { core_mask = wlc->stf->txchain; + } wlc->stf->txcore[Nsts] = core_mask; /* Nsts = 1..4, txcore index = 1..4 */ @@ -235,10 +236,7 @@ int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force) || !(txchain & wlc->stf->hw_txchain)) return -EINVAL; - /* - * if nrate override is configured to be non-SISO STF mode, reject - * reducing txchain to 1 - */ + /* if nrate override is configured to be non-SISO STF mode, reject reducing txchain to 1 */ txstreams = (u8) BRCMS_BITSCNT(txchain); if (txstreams > MAX_STREAMS_SUPPORTED) return -EINVAL; @@ -291,10 +289,7 @@ int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force) return 0; } -/* - * update wlc->stf->ss_opmode which represents the operational stf_ss mode - * we're using - */ +/* update wlc->stf->ss_opmode which represents the operational stf_ss mode we're using */ int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band) { int ret_code = 0; @@ -303,10 +298,7 @@ int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band) prev_stf_ss = wlc->stf->ss_opmode; - /* - * NOTE: opmode can only be SISO or CDD as STBC is decided on a - * per-packet basis - */ + /* NOTE: opmode can only be SISO or CDD as STBC is decided on a per-packet basis */ if (BRCMS_STBC_CAP_PHY(wlc) && wlc->stf->ss_algosel_auto && (wlc->stf->ss_algo_channel != (u16) -1)) { @@ -348,8 +340,7 @@ int brcms_c_stf_attach(struct brcms_c_info *wlc) if (BRCMS_STBC_CAP_PHY(wlc)) { wlc->stf->ss_algosel_auto = true; - /* Init the default value */ - wlc->stf->ss_algo_channel = (u16) -1; + wlc->stf->ss_algo_channel = (u16) -1; /* Init the default value */ } return 0; } @@ -359,20 +350,18 @@ void brcms_c_stf_detach(struct brcms_c_info *wlc) } /* - * Centralized txant update function. call it whenever wlc->stf->txant and/or - * wlc->stf->txchain change. + * Centralized txant update function. call it whenever wlc->stf->txant and/or wlc->stf->txchain + * change * * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to - * achieve various tx/rx antenna selection schemes + * achieve various tx/rx antenna selection schemes * - * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 - * means auto(last rx). - * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 - * means last rx and do tx-antenna selection for SISO transmissions - * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 - * means last rx and do tx-antenna selection for SISO transmissions - * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 - * means both cores active + * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means auto(last rx) + * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means last rx and + * do tx-antenna selection for SISO transmissions + * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 means last rx and + * do tx-antenna selection for SISO transmissions + * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 means both cores active */ static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) { @@ -387,8 +376,9 @@ static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) if (BRCMS_ISNPHY(wlc->band) && NREV_GE(wlc->band->phyrev, 3) - && NREV_LT(wlc->band->phyrev, 7)) + && NREV_LT(wlc->band->phyrev, 7)) { wlc->stf->phytxant = PHY_TXC_ANT_2; + } } else { if (BRCMS_ISLCNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) @@ -425,20 +415,22 @@ void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc) /* these parameter are intended to be used for all PHY types */ if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) { - if (BRCMS_ISNPHY(wlc->band)) + if (BRCMS_ISNPHY(wlc->band)) { wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY; - else + } else { wlc->stf->hw_txchain = TXCHAIN_DEF; + } } wlc->stf->txchain = wlc->stf->hw_txchain; wlc->stf->txstreams = (u8) BRCMS_BITSCNT(wlc->stf->hw_txchain); if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) { - if (BRCMS_ISNPHY(wlc->band)) + if (BRCMS_ISNPHY(wlc->band)) { wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY; - else + } else { wlc->stf->hw_rxchain = RXCHAIN_DEF; + } } wlc->stf->rxchain = wlc->stf->hw_rxchain; @@ -453,24 +445,24 @@ void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc) } static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, - u32 rspec) + ratespec_t rspec) { u16 phytxant = wlc->stf->phytxant; - if (RSPEC_STF(rspec) != PHY_TXC1_MODE_SISO) + if (RSPEC_STF(rspec) != PHY_TXC1_MODE_SISO) { phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT; - else if (wlc->stf->txant == ANT_TX_DEF) + } else if (wlc->stf->txant == ANT_TX_DEF) phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT; phytxant &= PHY_TXC_ANT_MASK; return phytxant; } -u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec) +u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, ratespec_t rspec) { return _brcms_c_stf_phytxchain_sel(wlc, rspec); } -u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec) +u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, ratespec_t rspec) { u16 phytxant = wlc->stf->phytxant; u16 mask = PHY_TXC_ANT_MASK; diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/stf.h b/trunk/drivers/staging/brcm80211/brcmsmac/stf.h index 19f6580f69be..06c2a399649e 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/stf.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/stf.h @@ -25,7 +25,7 @@ extern void brcms_c_stf_detach(struct brcms_c_info *wlc); extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc); extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, - u16 chanspec); + chanspec_t chanspec); extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band); extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); @@ -35,8 +35,8 @@ extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val); extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc); extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, - u32 rspec); + ratespec_t rspec); extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, - u32 rspec); + ratespec_t rspec); #endif /* _BRCM_STF_H_ */ diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/types.h b/trunk/drivers/staging/brcm80211/brcmsmac/types.h index d44db5674b31..bbf21897ae0e 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/types.h +++ b/trunk/drivers/staging/brcm80211/brcmsmac/types.h @@ -18,15 +18,15 @@ #define _BRCM_TYPES_H_ #include -#include -#if 0 /* Bus types */ +#define SI_BUS 0 /* SOC Interconnect */ +#define PCI_BUS 1 /* PCI target */ #define SDIO_BUS 3 /* SDIO target */ +#define JTAG_BUS 4 /* JTAG */ #define USB_BUS 5 /* USB (does not support R/W REG) */ #define SPI_BUS 6 /* gSPI target */ #define RPC_BUS 7 /* RPC target */ -#endif #define WL_CHAN_FREQ_RANGE_2G 0 #define WL_CHAN_FREQ_RANGE_5GL 1 @@ -36,71 +36,42 @@ #define MAX_DMA_SEGS 4 /* boardflags */ - -/* Board has gpio 9 controlling the PA */ -#define BFL_PACTRL 0x00000002 -/* Not ok to power down the chip pll and oscillator */ -#define BFL_NOPLLDOWN 0x00000020 -/* Board supports the Front End Module */ -#define BFL_FEM 0x00000800 -/* Board has an external LNA in 2.4GHz band */ -#define BFL_EXTLNA 0x00001000 -/* Board has no PA */ -#define BFL_NOPA 0x00010000 -/* Power topology uses BUCKBOOST */ -#define BFL_BUCKBOOST 0x00200000 -/* Board has FEM and switch to share antenna w/ BT */ -#define BFL_FEM_BT 0x00400000 -/* Power topology doesn't use CBUCK */ -#define BFL_NOCBUCK 0x00800000 -/* Power topology uses PALDO */ -#define BFL_PALDO 0x02000000 -/* Board has an external LNA in 5GHz band */ -#define BFL_EXTLNA_5GHz 0x10000000 +#define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */ +#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */ +#define BFL_FEM 0x00000800 /* Board supports the Front End Module */ +#define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ +#define BFL_NOPA 0x00010000 /* Board has no PA */ +#define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */ +#define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */ +#define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */ +#define BFL_PALDO 0x02000000 /* Power topology uses PALDO */ +#define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ /* boardflags2 */ - -/* Board has an external rxbb regulator */ -#define BFL2_RXBB_INT_REG_DIS 0x00000001 -/* Flag to implement alternative A-band PLL settings */ -#define BFL2_APLL_WAR 0x00000002 -/* Board permits enabling TX Power Control */ -#define BFL2_TXPWRCTRL_EN 0x00000004 -/* Board supports the 2X4 diversity switch */ -#define BFL2_2X4_DIV 0x00000008 -/* Board supports 5G band power gain */ -#define BFL2_5G_PWRGAIN 0x00000010 -/* Board overrides ASPM and Clkreq settings */ -#define BFL2_PCIEWAR_OVR 0x00000020 +#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */ +#define BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */ +#define BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */ +#define BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */ +#define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */ +#define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */ #define BFL2_LEGACY 0x00000080 -/* 4321mcm93 board uses Skyworks FEM */ -#define BFL2_SKWRKFEM_BRD 0x00000100 -/* Board has a WAR for clock-harmonic spurs */ -#define BFL2_SPUR_WAR 0x00000200 -/* Flag to narrow G-band PLL loop b/w */ -#define BFL2_GPLL_WAR 0x00000400 -/* Tx CCK pkts on Ant 0 only */ -#define BFL2_SINGLEANT_CCK 0x00001000 -/* WAR to reduce and avoid clock-harmonic spurs in 2G */ -#define BFL2_2G_SPUR_WAR 0x00002000 -/* Flag to widen G-band PLL loop b/w */ -#define BFL2_GPLL_WAR2 0x00010000 +#define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */ +#define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */ +#define BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */ +#define BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */ +#define BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */ +#define BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */ #define BFL2_IPALVLSHIFT_3P3 0x00020000 -/* Use internal envelope detector for TX IQCAL */ -#define BFL2_INTERNDET_TXIQCAL 0x00040000 -/* Keep the buffered Xtal output from radio "ON". Most drivers will turn it - * off without this flag to save power. */ -#define BFL2_XTALBUFOUTEN 0x00080000 +#define BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */ +#define BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio "ON" + * Most drivers will turn it off without this flag + * to save power. + */ -/* - * board specific GPIO assignment, gpio 0-3 are also customer-configurable - * led - */ - -/* bit 9 controls the PA on new 4306 boards */ -#define BOARD_GPIO_PACTRL 0x200 -#define BOARD_GPIO_12 0x1000 -#define BOARD_GPIO_13 0x2000 +/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ +#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ +#define BOARD_GPIO_12 0x1000 /* gpio 12 */ +#define BOARD_GPIO_13 0x2000 /* gpio 13 */ /* **** Core type/rev defaults **** */ #define D11CONF 0x0fffffb0 /* Supported D11 revs: 4, 5, 7-27 @@ -180,53 +151,25 @@ #define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val) #define PHYCONF_IS(val) CONF_IS(PHYTYPE, val) -#define NREV_IS(var, val) \ - (NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val)))) - -#define NREV_GE(var, val) \ - (NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val)))) - -#define NREV_GT(var, val) \ - (NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val)))) - -#define NREV_LT(var, val) \ - (NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val)))) - -#define NREV_LE(var, val) \ - (NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val)))) - -#define LCNREV_IS(var, val) \ - (LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val)))) - -#define LCNREV_GE(var, val) \ - (LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val)))) - -#define LCNREV_GT(var, val) \ - (LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val)))) - -#define LCNREV_LT(var, val) \ - (LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val)))) +#define NREV_IS(var, val) (NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val)))) +#define NREV_GE(var, val) (NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val)))) +#define NREV_GT(var, val) (NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val)))) +#define NREV_LT(var, val) (NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val)))) +#define NREV_LE(var, val) (NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val)))) -#define LCNREV_LE(var, val) \ - (LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val)))) +#define LCNREV_IS(var, val) (LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val)))) +#define LCNREV_GE(var, val) (LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val)))) +#define LCNREV_GT(var, val) (LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val)))) +#define LCNREV_LT(var, val) (LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val)))) +#define LCNREV_LE(var, val) (LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val)))) -#define D11REV_IS(var, val) \ - (D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val)))) +#define D11REV_IS(var, val) (D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val)))) +#define D11REV_GE(var, val) (D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val)))) +#define D11REV_GT(var, val) (D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val)))) +#define D11REV_LT(var, val) (D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val)))) +#define D11REV_LE(var, val) (D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val)))) -#define D11REV_GE(var, val) \ - (D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val)))) - -#define D11REV_GT(var, val) \ - (D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val)))) - -#define D11REV_LT(var, val) \ - (D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val)))) - -#define D11REV_LE(var, val) \ - (D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val)))) - -#define PHYTYPE_IS(var, val)\ - (PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val)))) +#define PHYTYPE_IS(var, val) (PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val)))) /* Finally, early-exit from switch case if anyone wants it... */ @@ -269,18 +212,11 @@ * * *********************************************** */ - -/* Max # of entries in Tx FIFO based on 4kb page size */ -#define NTXD 256 -/* Max # of entries in Rx FIFO based on 4kb page size */ -#define NRXD 256 -/* try to keep this # rbufs posted to the chip */ -#define NRXBUFPOST 32 -/* Maximum SCBs in cache for STA */ -#define MAXSCB 32 - -/* max allowed number of mpdus in an ampdu (2 streams) */ -#define AMPDU_NUM_MPDU 16 +#define NTXD 256 /* Max # of entries in Tx FIFO based on 4kb page size */ +#define NRXD 256 /* Max # of entries in Rx FIFO based on 4kb page size */ +#define NRXBUFPOST 32 /* try to keep this # rbufs posted to the chip */ +#define MAXSCB 32 /* Maximum SCBs in cache for STA */ +#define AMPDU_NUM_MPDU 16 /* max allowed number of mpdus in an ampdu (2 streams) */ /* Count of packet callback structures. either of following * 1. Set to the number of SCBs since a STA @@ -305,8 +241,8 @@ #define BRCMS_AMPDUDATAHIWAT 255 /* bounded rx loops */ -#define RXBND 8 /* max # frames to process in brcms_c_recv() */ -#define TXSBND 8 /* max # tx status to process in wlc_txstatus() */ +#define RXBND 8 /* max # frames to process in brcms_c_recv() */ +#define TXSBND 8 /* max # tx status to process in wlc_txstatus() */ #define BAND_5G(bt) ((bt) == BRCM_BAND_5G) #define BAND_2G(bt) ((bt) == BRCM_BAND_2G) @@ -319,21 +255,21 @@ do { \ #define WL_ERROR_ON() (brcm_msg_level & LOG_ERROR_VAL) -/* - * Register access macros. - * - * These macro's take a pointer to the address to read as one of their - * arguments. The macro itself deduces the size of the IO transaction (u8, u16 - * or u32). Advantage of this approach in combination with using a struct to - * define the registers in a register block, is that access size and access - * location are defined in only one spot. This reduces the risk of the - * programmer trying to use an unsupported transaction size on a register. - * - */ - +/* register access macros */ +#ifndef __BIG_ENDIAN +#ifndef __mips__ +#define R_REG(r) \ + ({\ + sizeof(*(r)) == sizeof(u8) ? \ + readb((u8 *)(r)) : \ + sizeof(*(r)) == sizeof(u16) ? readw((u16 *)(r)) : \ + readl((u32 *)(r)); \ + }) +#else /* __mips__ */ #define R_REG(r) \ ({ \ __typeof(*(r)) __osl_v; \ + __asm__ __volatile__("sync"); \ switch (sizeof(*(r))) { \ case sizeof(u8): \ __osl_v = readb((u8 *)(r)); \ @@ -341,6 +277,39 @@ do { \ case sizeof(u16): \ __osl_v = readw((u16 *)(r)); \ break; \ + case sizeof(u32): \ + __osl_v = \ + readl((u32 *)(r)); \ + break; \ + } \ + __asm__ __volatile__("sync"); \ + __osl_v; \ + }) +#endif /* __mips__ */ + +#define W_REG(r, v) do { \ + switch (sizeof(*(r))) { \ + case sizeof(u8): \ + writeb((u8)(v), (u8 *)(r)); break; \ + case sizeof(u16): \ + writew((u16)(v), (u16 *)(r)); break; \ + case sizeof(u32): \ + writel((u32)(v), (u32 *)(r)); break; \ + }; \ + } while (0) +#else /* __BIG_ENDIAN */ +#define R_REG(r) \ + ({ \ + __typeof(*(r)) __osl_v; \ + switch (sizeof(*(r))) { \ + case sizeof(u8): \ + __osl_v = \ + readb((u8 *)((r)^3)); \ + break; \ + case sizeof(u16): \ + __osl_v = \ + readw((u16 *)((r)^2)); \ + break; \ case sizeof(u32): \ __osl_v = readl((u32 *)(r)); \ break; \ @@ -351,18 +320,19 @@ do { \ #define W_REG(r, v) do { \ switch (sizeof(*(r))) { \ case sizeof(u8): \ - writeb((u8)(v), (u8 *)(r)); \ - break; \ + writeb((u8)(v), \ + (u8 *)((r)^3)); break; \ case sizeof(u16): \ - writew((u16)(v), (u16 *)(r)); \ - break; \ + writew((u16)(v), \ + (u16 *)((r)^2)); break; \ case sizeof(u32): \ - writel((u32)(v), (u32 *)(r)); \ - break; \ + writel((u32)(v), \ + (u32 *)(r)); break; \ } \ } while (0) +#endif /* __BIG_ENDIAN */ -#ifdef CONFIG_BCM47XX +#ifdef __mips__ /* * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder * transactions. As a fix, a read after write is performed on certain places @@ -371,7 +341,7 @@ do { \ #define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); }) #else #define W_REG_FLUSH(r, v) W_REG((r), (v)) -#endif /* CONFIG_BCM47XX */ +#endif /* __mips__ */ #define AND_REG(r, v) W_REG((r), R_REG(r) & (v)) #define OR_REG(r, v) W_REG((r), R_REG(r) | (v)) @@ -380,13 +350,10 @@ do { \ W_REG((r), ((R_REG(r) & ~(mask)) | (val))) /* multi-bool data type: set of bools, mbool is true if any is set */ - -/* set one bool */ -#define mboolset(mb, bit) ((mb) |= (bit)) -/* clear one bool */ -#define mboolclr(mb, bit) ((mb) &= ~(bit)) -/* true if one bool is set */ -#define mboolisset(mb, bit) (((mb) & (bit)) != 0) +typedef u32 mbool; +#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */ +#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */ +#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* true if one bool is set */ #define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) /* forward declarations */ @@ -407,6 +374,23 @@ struct tx_status; struct d11rxhdr; struct brcms_d11rxhdr; struct txpwr_limits; +struct brcms_phy; + +typedef volatile struct intctrlregs intctrlregs_t; +typedef volatile struct pio2regs pio2regs_t; +typedef volatile struct pio2regp pio2regp_t; +typedef volatile struct pio4regs pio4regs_t; +typedef volatile struct pio4regp pio4regp_t; +typedef volatile struct fifo64 fifo64_t; +typedef volatile struct d11regs d11regs_t; +typedef volatile struct dma32diag dma32diag_t; +typedef volatile struct dma64regs dma64regs_t; +typedef struct brcms_rateset wlc_rateset_t; +typedef u32 ratespec_t; +typedef struct chanvec chanvec_t; +typedef s32 fixed; +typedef struct _cs32 cs32; +typedef volatile union pmqreg pmqreg_t; /* brcm_msg_level is a bit vector with defs in defs.h */ extern u32 brcm_msg_level; diff --git a/trunk/drivers/staging/brcm80211/brcmutil/utils.c b/trunk/drivers/staging/brcm80211/brcmutil/utils.c index 6280ec15f340..37b6b7797793 100644 --- a/trunk/drivers/staging/brcm80211/brcmutil/utils.c +++ b/trunk/drivers/staging/brcm80211/brcmutil/utils.c @@ -219,7 +219,7 @@ EXPORT_SYMBOL(brcmu_pktq_pdeq_tail); void brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir, - bool (*fn)(struct sk_buff *, void *), void *arg) + ifpkt_cb_t fn, void *arg) { struct pktq_prec *q; struct sk_buff *p, *prev = NULL; @@ -244,13 +244,14 @@ brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir, } } - if (q->head == NULL) + if (q->head == NULL) { q->tail = NULL; + } } EXPORT_SYMBOL(brcmu_pktq_pflush); void brcmu_pktq_flush(struct pktq *pq, bool dir, - bool (*fn)(struct sk_buff *, void *), void *arg) + ifpkt_cb_t fn, void *arg) { int prec; for (prec = 0; prec < pq->num_prec; prec++) @@ -349,6 +350,21 @@ struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, } EXPORT_SYMBOL(brcmu_pktq_mdeq); +/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ +int brcmu_ether_atoe(char *p, u8 *ea) +{ + int i = 0; + + for (;;) { + ea[i++] = (char)simple_strtoul(p, &p, 16); + if (!*p++ || i == 6) + break; + } + + return i == 6; +} +EXPORT_SYMBOL(brcmu_ether_atoe); + #if defined(BCMDBG) /* pretty hex print a pkt buffer chain */ void brcmu_prpkt(const char *msg, struct sk_buff *p0) @@ -403,23 +419,26 @@ int brcmu_iovar_lencheck(const struct brcmu_iovar *vi, void *arg, int len, case IOVT_UINT16: case IOVT_UINT32: /* all integers are s32 sized args at the ioctl interface */ - if (len < (int)sizeof(int)) + if (len < (int)sizeof(int)) { bcmerror = -EOVERFLOW; + } break; case IOVT_BUFFER: /* buffer must meet minimum length requirement */ - if (len < vi->minlen) + if (len < vi->minlen) { bcmerror = -EOVERFLOW; + } break; case IOVT_VOID: - if (!set) + if (!set) { /* Cannot return nil... */ bcmerror = -ENOTSUPP; - else if (len) + } else if (len) { /* Set is an action w/o parameters */ bcmerror = -ENOBUFS; + } break; default: @@ -431,6 +450,75 @@ int brcmu_iovar_lencheck(const struct brcmu_iovar *vi, void *arg, int len, } EXPORT_SYMBOL(brcmu_iovar_lencheck); +/******************************************************************************* + * crc8 + * + * Computes a crc8 over the input data using the polynomial: + * + * x^8 + x^7 +x^6 + x^4 + x^2 + 1 + * + * The caller provides the initial value (either CRC8_INIT_VALUE + * or the previous returned value) to allow for processing of + * discontiguous blocks of data. When generating the CRC the + * caller is responsible for complementing the final return value + * and inserting it into the byte stream. When checking, a final + * return value of CRC8_GOOD_VALUE indicates a valid CRC. + * + * Reference: Dallas Semiconductor Application Note 27 + * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", + * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., + * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt + * + * **************************************************************************** + */ + +static const u8 crc8_table[256] = { + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F +}; + +u8 brcmu_crc8(u8 *pdata, /* pointer to array of data to process */ + uint nbytes, /* number of input data bytes to process */ + u8 crc /* either CRC8_INIT_VALUE or previous return value */ + ) { + /* loop over the buffer data */ + while (nbytes-- > 0) + crc = crc8_table[(crc ^ *pdata++) & 0xff]; + + return crc; +} +EXPORT_SYMBOL(brcmu_crc8); + /* * Traverse a string of 1-byte tag/1-byte length/variable-length value * triples, returning a pointer to the substring whose first element @@ -517,10 +605,7 @@ brcmu_format_flags(const struct brcmu_bit_desc *bd, u32 flags, char *buf, } EXPORT_SYMBOL(brcmu_format_flags); -/* - * print bytes formatted as hex to a string. return the resulting - * string length - */ +/* print bytes formatted as hex to a string. return the resulting string length */ int brcmu_format_hex(char *str, const void *bytes, int len) { int i; @@ -600,9 +685,10 @@ u16 brcmu_qdbm_to_mw(u8 qdbm) uint factor = 1; int idx = qdbm - QDBM_OFFSET; - if (idx >= QDBM_TABLE_LEN) + if (idx >= QDBM_TABLE_LEN) { /* clamp to max u16 mW value */ return 0xFFFF; + } /* scale the qdBm index up to the range of the table 0-40 * where an offset of 40 qdBm equals a factor of 10 mW. diff --git a/trunk/drivers/staging/brcm80211/brcmutil/wifi.c b/trunk/drivers/staging/brcm80211/brcmutil/wifi.c index 636515cc1924..b9ffe8682a27 100644 --- a/trunk/drivers/staging/brcm80211/brcmutil/wifi.c +++ b/trunk/drivers/staging/brcm80211/brcmutil/wifi.c @@ -21,7 +21,7 @@ * combination could be legal given any set of circumstances. * RETURNS: true is the chanspec is malformed, false if it looks good. */ -bool brcmu_chspec_malformed(u16 chanspec) +bool brcmu_chspec_malformed(chanspec_t chanspec) { /* must be 2G or 5G band */ if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec)) @@ -34,8 +34,9 @@ bool brcmu_chspec_malformed(u16 chanspec) if (CHSPEC_IS20(chanspec)) { if (!CHSPEC_SB_NONE(chanspec)) return true; - } else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) { - return true; + } else { + if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) + return true; } return false; @@ -43,11 +44,11 @@ bool brcmu_chspec_malformed(u16 chanspec) EXPORT_SYMBOL(brcmu_chspec_malformed); /* - * This function returns the channel number that control traffic is being sent - * on, for legacy channels this is just the channel number, for 40MHZ channels - * it is the upper or lower 20MHZ sideband depending on the chanspec selected. + * This function returns the channel number that control traffic is being sent on, for legacy + * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ + * sideband depending on the chanspec selected */ -u8 brcmu_chspec_ctlchan(u16 chspec) +u8 brcmu_chspec_ctlchan(chanspec_t chspec) { u8 ctl_chan; @@ -55,23 +56,17 @@ u8 brcmu_chspec_ctlchan(u16 chspec) if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { return CHSPEC_CHANNEL(chspec); } else { - /* - * we only support 40MHZ with sidebands. chanspec channel holds - * the centre frequency, use that and the side band information - * to reconstruct the control channel number + /* we only support 40MHZ with sidebands */ + /* chanspec channel holds the centre frequency, use that and the + * side band information to reconstruct the control channel number */ - if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) - /* - * control chan is the upper 20 MHZ SB of the - * 40MHZ channel - */ + if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { + /* control chan is the upper 20 MHZ SB of the 40MHZ channel */ ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); - else - /* - * control chan is the lower 20 MHZ SB of the - * 40MHZ channel - */ + } else { + /* control chan is the lower 20 MHZ SB of the 40MHZ channel */ ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); + } } return ctl_chan; diff --git a/trunk/drivers/staging/brcm80211/include/brcmu_utils.h b/trunk/drivers/staging/brcm80211/include/brcmu_utils.h index ff8f3634d282..2d54cc5f4b11 100644 --- a/trunk/drivers/staging/brcm80211/include/brcmu_utils.h +++ b/trunk/drivers/staging/brcm80211/include/brcmu_utils.h @@ -72,6 +72,9 @@ struct pktq { struct pktq_prec q[PKTQ_MAX_PREC]; }; +/* fn(pkt, arg). return true if pkt belongs to if */ +typedef bool(*ifpkt_cb_t) (struct sk_buff *, void *); + /* operations on a specific precedence in packet queue */ #define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) @@ -95,9 +98,8 @@ extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); extern void brcmu_pkt_buf_free_skb(struct sk_buff *skb); /* Empty the queue at particular precedence level */ -/* callback function fn(pkt, arg) returns true if pkt belongs to if */ extern void brcmu_pktq_pflush(struct pktq *pq, int prec, - bool dir, bool (*fn)(struct sk_buff *, void *), void *arg); + bool dir, ifpkt_cb_t fn, void *arg); /* operations on a set of precedences in packet queue */ @@ -125,7 +127,7 @@ extern void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len); /* prec_out may be NULL if caller is not interested in return value */ extern struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out); extern void brcmu_pktq_flush(struct pktq *pq, bool dir, - bool (*fn)(struct sk_buff *, void *), void *arg); + ifpkt_cb_t fn, void *arg); /* externs */ /* packet */ @@ -133,6 +135,9 @@ extern uint brcmu_pktfrombuf(struct sk_buff *p, uint offset, int len, unsigned char *buf); extern uint brcmu_pkttotlen(struct sk_buff *p); +/* ethernet address */ +extern int brcmu_ether_atoe(char *p, u8 *ea); + /* ip address */ struct ipv4_addr; @@ -246,6 +251,8 @@ extern int brcmu_iovar_lencheck(const struct brcmu_iovar *table, void *arg, #define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) /* crc defines */ +#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ +#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ #define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ #define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ @@ -262,10 +269,12 @@ struct brcmu_tlv { u8 data[1]; }; -/* 18-bytes of Ethernet address buffer length */ -#define ETHER_ADDR_STR_LEN 18 +#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ /* externs */ +/* crc */ +extern u8 brcmu_crc8(u8 *p, uint nbytes, u8 crc); + /* format/print */ #if defined(BCMDBG) extern int brcmu_format_flags(const struct brcmu_bit_desc *bd, u32 flags, diff --git a/trunk/drivers/staging/brcm80211/include/brcmu_wifi.h b/trunk/drivers/staging/brcm80211/include/brcmu_wifi.h index 717d88542b72..fde592bd9177 100644 --- a/trunk/drivers/staging/brcm80211/include/brcmu_wifi.h +++ b/trunk/drivers/staging/brcm80211/include/brcmu_wifi.h @@ -20,10 +20,8 @@ #include /* for ETH_ALEN */ #include /* for WLAN_PMKID_LEN */ -/* - * A chanspec (u16) holds the channel number, band, bandwidth and control - * sideband - */ +/* A chanspec holds the channel number, band, bandwidth and control sideband */ +typedef u16 chanspec_t; /* channel defines */ #define CH_UPPER_SB 0x01 @@ -31,16 +29,13 @@ #define CH_EWA_VALID 0x04 #define CH_20MHZ_APART 4 #define CH_10MHZ_APART 2 -#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ +#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ #define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ #define BRCM_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL /* legacy define */ - -/* - * max # supported channels. The max channel no is 216, this is that + 1 - * rounded up to a multiple of NBBY (8). DO NOT MAKE it > 255: channels are - * u8's all over -*/ -#define MAXCHANNEL 224 +#define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216, + * this is that + 1 rounded up to a multiple of NBBY (8). + * DO NOT MAKE it > 255: channels are u8's all over + */ #define WL_CHANSPEC_CHAN_MASK 0x00ff #define WL_CHANSPEC_CHAN_SHIFT 0 @@ -69,30 +64,20 @@ #define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ /* channel defines */ -#define LOWER_20_SB(channel) \ - (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) - -#define UPPER_20_SB(channel) \ - (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ - ((channel) + CH_10MHZ_APART) : 0) - -#define CHSPEC_BANDUNIT(chspec) \ - (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) - -#define CH20MHZ_CHSPEC(channel) \ - (u16)((u16)(channel) | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | \ - (((channel) <= CH_MAX_2G_CHANNEL) ? \ - WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) - -#define NEXT_20MHZ_CHAN(channel) \ - (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ - ((channel) + CH_20MHZ_APART) : 0) - -#define CH40MHZ_CHSPEC(channel, ctlsb) \ - (u16)((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ - ((channel) <= CH_MAX_2G_CHANNEL ? \ - WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) - +#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) +#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ + ((channel) + CH_10MHZ_APART) : 0) +#define CHSPEC_BANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : \ + BAND_2G_INDEX) +#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ + WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ + WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) +#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ + ((channel) + CH_20MHZ_APART) : 0) +#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ + ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ + ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ + WL_CHANSPEC_BAND_5G)) #define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK)) #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) @@ -110,40 +95,22 @@ #define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) #define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) - -#define CHSPEC_IS10(chspec) \ - (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) - -#define CHSPEC_IS20(chspec) \ - (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) - +#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) +#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) #ifndef CHSPEC_IS40 -#define CHSPEC_IS40(chspec) \ - (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) +#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) #endif #endif /* !WL11N_20MHZONLY */ -#define CHSPEC_IS5G(chspec) \ - (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) - -#define CHSPEC_IS2G(chspec) \ - (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) - -#define CHSPEC_SB_NONE(chspec) \ - (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) - -#define CHSPEC_SB_UPPER(chspec) \ - (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) - -#define CHSPEC_SB_LOWER(chspec) \ - (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) - -#define CHSPEC_CTL_CHAN(chspec) \ - ((CHSPEC_SB_LOWER(chspec)) ? \ - (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ - (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) - +#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) +#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) +#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) +#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) +#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) +#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ + (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ + (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) #define CHSPEC2BAND(chspec) (CHSPEC_IS5G(chspec) ? BRCM_BAND_5G : BRCM_BAND_2G) #define CHANSPEC_STR_LEN 8 @@ -175,14 +142,14 @@ * combination could be legal given any set of circumstances. * RETURNS: true is the chanspec is malformed, false if it looks good. */ -extern bool brcmu_chspec_malformed(u16 chanspec); +extern bool brcmu_chspec_malformed(chanspec_t chanspec); /* - * This function returns the channel number that control traffic is being sent - * on, for legacy channels this is just the channel number, for 40MHZ channels - * it is the upper or lower 20MHZ sideband depending on the chanspec selected. + * This function returns the channel number that control traffic is being sent on, for legacy + * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ + * sideband depending on the chanspec selected */ -extern u8 brcmu_chspec_ctlchan(u16 chspec); +extern u8 brcmu_chspec_ctlchan(chanspec_t chspec); /* * Return the channel number for a given frequency and base frequency. @@ -216,13 +183,11 @@ extern int brcmu_mhz2channel(uint freq, uint start_factor); #define CRYPTO_ALGO_NALG 7 /* wireless security bitvec */ - #define WEP_ENABLED 0x0001 #define TKIP_ENABLED 0x0002 #define AES_ENABLED 0x0004 #define WSEC_SWFLAG 0x0008 -/* to go into transition mode without setting wep */ -#define SES_OW_ENABLED 0x0040 +#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */ /* WPA authentication mode bitvec */ #define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ @@ -231,7 +196,7 @@ extern int brcmu_mhz2channel(uint freq, uint start_factor); #define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ #define WPA_AUTH_RESERVED1 0x0008 #define WPA_AUTH_RESERVED2 0x0010 - + /* #define WPA_AUTH_8021X 0x0020 *//* 802.1x, reserved */ #define WPA2_AUTH_RESERVED1 0x0020 #define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ #define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ @@ -253,24 +218,26 @@ extern int brcmu_mhz2channel(uint freq, uint start_factor); #define HT_CAP_RX_STBC_NO 0x0 #define HT_CAP_RX_STBC_ONE_STREAM 0x1 -struct pmkid { +typedef struct _pmkid { u8 BSSID[ETH_ALEN]; u8 PMKID[WLAN_PMKID_LEN]; -}; +} pmkid_t; -struct pmkid_list { +typedef struct _pmkid_list { u32 npmkid; - struct pmkid pmkid[1]; -}; + pmkid_t pmkid[1]; +} pmkid_list_t; -struct pmkid_cand { +typedef struct _pmkid_cand { u8 BSSID[ETH_ALEN]; u8 preauth; -}; +} pmkid_cand_t; -struct pmkid_cand_list { +typedef struct _pmkid_cand_list { u32 npmkid_cand; - struct pmkid_cand pmkid_cand[1]; -}; + pmkid_cand_t pmkid_cand[1]; +} pmkid_cand_list_t; + +typedef u8 ac_bitmap_t; #endif /* _BRCMU_WIFI_H_ */ diff --git a/trunk/drivers/staging/brcm80211/include/chipcommon.h b/trunk/drivers/staging/brcm80211/include/chipcommon.h index fefabc39e646..296582aced69 100644 --- a/trunk/drivers/staging/brcm80211/include/chipcommon.h +++ b/trunk/drivers/staging/brcm80211/include/chipcommon.h @@ -19,7 +19,7 @@ #include "defs.h" /* for PAD macro */ -struct chipcregs { +typedef volatile struct { u32 chipid; /* 0x0 */ u32 capabilities; u32 corecontrol; /* corerev >= 1 */ @@ -214,7 +214,7 @@ struct chipcregs { u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ u32 PAD[100]; u16 sromotp[768]; -}; +} chipcregs_t; /* chipid */ #define CID_ID_MASK 0x0000ffff /* Chip Id mask */ @@ -231,8 +231,7 @@ struct chipcregs { #define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ #define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ #define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ -/* UARTs are driven by internal divided clock */ -#define CC_CAP_UINTCLK 0x00000008 +#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ #define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ #define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ #define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ @@ -249,12 +248,10 @@ struct chipcregs { #define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ #define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ #define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */ -/* Nand flash present, rev >= 35 */ -#define CC_CAP_NFLASH 0x80000000 +#define CC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */ #define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ -/* GSIO (spi/i2c) present, rev >= 37 */ -#define CC_CAP2_GSIO 0x00000002 +#define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */ /* pmucapabilities */ #define PCAP_REV_MASK 0x000000ff diff --git a/trunk/drivers/staging/brcm80211/include/defs.h b/trunk/drivers/staging/brcm80211/include/defs.h index 8e0c559398c1..8b3e17dec150 100644 --- a/trunk/drivers/staging/brcm80211/include/defs.h +++ b/trunk/drivers/staging/brcm80211/include/defs.h @@ -54,12 +54,10 @@ #define WL_NUMRATES 16 /* max # of rates in a rateset */ -struct brcm_rateset { - /* # rates in this set */ - u32 count; - /* rates in 500kbps units w/hi bit set if basic */ - u8 rates[WL_NUMRATES]; -}; +typedef struct wl_rateset { + u32 count; /* # rates in this set */ + u8 rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */ +} wl_rateset_t; #define BRCM_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ @@ -73,12 +71,10 @@ struct brcm_rateset { #define BRCM_GET_PHYLIST 180 /* Bit masks for radio disabled status - returned by WL_GET_RADIO */ - #define WL_RADIO_SW_DISABLE (1<<0) #define WL_RADIO_HW_DISABLE (1<<1) #define WL_RADIO_MPC_DISABLE (1<<2) -/* some countries don't support any channel */ -#define WL_RADIO_COUNTRY_DISABLE (1<<3) +#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */ /* Override bit for SET_TXPWR. if set, ignore other level limits */ #define WL_TXPWR_OVERRIDE (1U<<31) @@ -104,9 +100,7 @@ struct brcm_rateset { /* * Sonics Configuration Space Registers. */ - -/* core sbconfig regs are top 256bytes of regs */ -#define SBCONFIGOFF 0xf00 +#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */ /* cpp contortions to concatenate w/arg prescan */ #ifndef PAD diff --git a/trunk/drivers/staging/brcm80211/include/soc.h b/trunk/drivers/staging/brcm80211/include/soc.h index f23edc5d3072..6e5a705c4937 100644 --- a/trunk/drivers/staging/brcm80211/include/soc.h +++ b/trunk/drivers/staging/brcm80211/include/soc.h @@ -81,8 +81,9 @@ #define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ #define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ #define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ -/* Default component, in ai chips it maps all unused address ranges */ -#define DEF_AI_COMP 0xfff +#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all + * unused address ranges + */ /* Common core control flags */ #define SICF_BIST_EN 0x8000 diff --git a/trunk/drivers/staging/comedi/Kconfig b/trunk/drivers/staging/comedi/Kconfig index 4c77e508066b..5e65dde5845a 100644 --- a/trunk/drivers/staging/comedi/Kconfig +++ b/trunk/drivers/staging/comedi/Kconfig @@ -1244,10 +1244,11 @@ config COMEDI_DT9812 called dt9812. config COMEDI_USBDUX - tristate "ITL USB-DUX-D support" + tristate "ITL USBDUX support" default N ---help--- - Enable support for the Incite Technology Ltd USB-DUX-D Board + Enable support for the University of Stirling USB DAQ and INCITE + Technology Limited driver To compile this driver as a module, choose M here: the module will be called usbdux. @@ -1257,21 +1258,12 @@ config COMEDI_USBDUXFAST select COMEDI_FC default N ---help--- - Enable support for the Incite Technology Ltd USB-DUXfast Board + Enable support for the University of Stirling USB-DUXfast and INCITE + Technology Limited driver To compile this driver as a module, choose M here: the module will be called usbduxfast. -config COMEDI_USBDUXSIGMA - tristate "ITL USB-DUXsigma support" - select COMEDI_FC - default N - ---help--- - Enable support for the Incite Technology Ltd USB-DUXsigma Board - - To compile this driver as a module, choose M here: the module will be - called usbduxsigma. - config COMEDI_VMK80XX tristate "Velleman VM110/VM140 USB Board support" default N diff --git a/trunk/drivers/staging/comedi/comedi_fops.c b/trunk/drivers/staging/comedi/comedi_fops.c index 21d8c1c16cd8..e90e3cceb5f8 100644 --- a/trunk/drivers/staging/comedi/comedi_fops.c +++ b/trunk/drivers/staging/comedi/comedi_fops.c @@ -101,7 +101,7 @@ static int do_insn_ioctl(struct comedi_device *dev, static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd, void *file); -static void do_become_nonbusy(struct comedi_device *dev, +extern void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s); static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s); diff --git a/trunk/drivers/staging/comedi/drivers/Makefile b/trunk/drivers/staging/comedi/drivers/Makefile index 170da6091959..33bf1f5aad45 100644 --- a/trunk/drivers/staging/comedi/drivers/Makefile +++ b/trunk/drivers/staging/comedi/drivers/Makefile @@ -126,7 +126,6 @@ obj-$(CONFIG_COMEDI_QUATECH_DAQP_CS) += quatech_daqp_cs.o obj-$(CONFIG_COMEDI_DT9812) += dt9812.o obj-$(CONFIG_COMEDI_USBDUX) += usbdux.o obj-$(CONFIG_COMEDI_USBDUXFAST) += usbduxfast.o -obj-$(CONFIG_COMEDI_USBDUXSIGMA) += usbduxsigma.o obj-$(CONFIG_COMEDI_VMK80XX) += vmk80xx.o # Comedi NI drivers diff --git a/trunk/drivers/staging/comedi/drivers/adv_pci_dio.c b/trunk/drivers/staging/comedi/drivers/adv_pci_dio.c index 69334f6f64e8..d23799be7ce2 100644 --- a/trunk/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/trunk/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -422,7 +422,7 @@ struct pci_dio_private { unsigned short IDIFiltrHigh[8]; /* IDI's filter value high signal */ }; -static struct pci_dio_private *pci_priv; /* list of allocated cards */ +static struct pci_dio_private *pci_priv = NULL; /* list of allocated cards */ #define devpriv ((struct pci_dio_private *)dev->private) #define this_board ((const struct dio_boardtype *)dev->board_ptr) diff --git a/trunk/drivers/staging/comedi/drivers/ni_labpc.c b/trunk/drivers/staging/comedi/drivers/ni_labpc.c index 721b2be22500..6859af0778cf 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_labpc.c +++ b/trunk/drivers/staging/comedi/drivers/ni_labpc.c @@ -241,10 +241,8 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data); static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd); -#ifdef CONFIG_ISA_DMA_API +#ifdef CONFIG_COMEDI_PCI static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd); -#endif -#ifdef CONFIG_COMEDI_PCI_DRIVERS static int labpc_find_device(struct comedi_device *dev, int bus, int slot); #endif static int labpc_dio_mem_callback(int dir, int port, int data, @@ -461,7 +459,7 @@ static const struct labpc_board_struct labpc_boards[] = { .ai_scan_up = 0, .memory_mapped_io = 0, }, -#ifdef CONFIG_COMEDI_PCI_DRIVERS +#ifdef CONFIG_COMEDI_PCI { .name = "pci-1200", .device_id = 0x161, @@ -505,14 +503,14 @@ static struct comedi_driver driver_labpc = { .offset = sizeof(struct labpc_board_struct), }; -#ifdef CONFIG_COMEDI_PCI_DRIVERS +#ifdef CONFIG_COMEDI_PCI static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = { {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x161)}, {0} }; MODULE_DEVICE_TABLE(pci, labpc_pci_table); -#endif /* CONFIG_COMEDI_PCI_DRIVERS */ +#endif /* CONFIG_COMEDI_PCI */ static inline int labpc_counter_load(struct comedi_device *dev, unsigned long base_address, @@ -722,7 +720,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned long iobase = 0; unsigned int irq = 0; unsigned int dma_chan = 0; -#ifdef CONFIG_COMEDI_PCI_DRIVERS +#ifdef CONFIG_COMEDI_PCI int retval; #endif @@ -744,7 +742,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif break; case pci_bustype: -#ifdef CONFIG_COMEDI_PCI_DRIVERS +#ifdef CONFIG_COMEDI_PCI retval = labpc_find_device(dev, it->options[0], it->options[1]); if (retval < 0) return retval; @@ -774,7 +772,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* adapted from ni_pcimio for finding mite based boards (pc-1200) */ -#ifdef CONFIG_COMEDI_PCI_DRIVERS +#ifdef CONFIG_COMEDI_PCI static int labpc_find_device(struct comedi_device *dev, int bus, int slot) { struct mite_struct *mite; @@ -822,7 +820,7 @@ int labpc_common_detach(struct comedi_device *dev) free_irq(dev->irq, dev); if (thisboard->bustype == isa_bustype && dev->iobase) release_region(dev->iobase, LABPC_SIZE); -#ifdef CONFIG_COMEDI_PCI_DRIVERS +#ifdef CONFIG_COMEDI_PCI if (devpriv->mite) mite_unsetup(devpriv->mite); #endif @@ -2137,7 +2135,7 @@ static void write_caldac(struct comedi_device *dev, unsigned int channel, devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); } -#ifdef CONFIG_COMEDI_PCI_DRIVERS +#ifdef CONFIG_COMEDI_PCI static int __devinit driver_labpc_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { diff --git a/trunk/drivers/staging/comedi/drivers/ni_pcidio.c b/trunk/drivers/staging/comedi/drivers/ni_pcidio.c index 045a4c00f346..8dd3a01d48dd 100644 --- a/trunk/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/trunk/drivers/staging/comedi/drivers/ni_pcidio.c @@ -688,7 +688,7 @@ static void ni_pcidio_print_status(unsigned int flags) static void debug_int(struct comedi_device *dev) { int a, b; - static int n_int; + static int n_int = 0; struct timeval tv; do_gettimeofday(&tv); diff --git a/trunk/drivers/staging/comedi/drivers/usbduxsigma.c b/trunk/drivers/staging/comedi/drivers/usbduxsigma.c deleted file mode 100644 index a8fea9a91733..000000000000 --- a/trunk/drivers/staging/comedi/drivers/usbduxsigma.c +++ /dev/null @@ -1,2880 +0,0 @@ -#define DRIVER_VERSION "v0.5" -#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" -#define DRIVER_DESC "Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com" -/* - comedi/drivers/usbdux.c - Copyright (C) 2011 Bernd Porr, Bernd.Porr@f2s.com - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - 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 for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - */ -/* -Driver: usbduxsigma -Description: University of Stirling USB DAQ & INCITE Technology Limited -Devices: [ITL] USB-DUX (usbduxsigma.o) -Author: Bernd Porr -Updated: 21 Jul 2011 -Status: testing -*/ -/* - * I must give credit here to Chris Baugher who - * wrote the driver for AT-MIO-16d. I used some parts of this - * driver. I also must give credits to David Brownell - * who supported me with the USB development. - * - * Note: the raw data from the A/D converter is 24 bit big endian - * anything else is little endian to/from the dux board - * - * - * Revision history: - * 0.1: inital version - * 0.2: all basic functions implemented, digital I/O only for one port - * 0.3: proper vendor ID and driver name - * 0.4: fixed D/A voltage range - * 0.5: various bug fixes, health check at startup - */ - -/* generates loads of debug info */ -/* #define NOISY_DUX_DEBUGBUG */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "comedi_fc.h" -#include "../comedidev.h" - -#define BOARDNAME "usbduxsigma" - -/* timeout for the USB-transfer in ms*/ -#define BULK_TIMEOUT 1000 - -/* constants for "firmware" upload and download */ -#define USBDUXSUB_FIRMWARE 0xA0 -#define VENDOR_DIR_IN 0xC0 -#define VENDOR_DIR_OUT 0x40 - -/* internal addresses of the 8051 processor */ -#define USBDUXSUB_CPUCS 0xE600 - -/* - * the minor device number, major is 180 only for debugging purposes and to - * upload special firmware (programming the eeprom etc) which is not - * compatible with the comedi framwork - */ -#define USBDUXSUB_MINOR 32 - -/* max lenghth of the transfer-buffer for software upload */ -#define TB_LEN 0x2000 - -/* Input endpoint number: ISO/IRQ */ -#define ISOINEP 6 - -/* Output endpoint number: ISO/IRQ */ -#define ISOOUTEP 2 - -/* This EP sends DUX commands to USBDUX */ -#define COMMAND_OUT_EP 1 - -/* This EP receives the DUX commands from USBDUX */ -#define COMMAND_IN_EP 8 - -/* Output endpoint for PWM */ -#define PWM_EP 4 - -/* 300Hz max frequ under PWM */ -#define MIN_PWM_PERIOD ((long)(1E9/300)) - -/* Default PWM frequency */ -#define PWM_DEFAULT_PERIOD ((long)(1E9/100)) - -/* Number of channels (16 AD and offset)*/ -#define NUMCHANNELS 16 - -/* Size of one A/D value */ -#define SIZEADIN ((sizeof(int32_t))) - -/* - * Size of the async input-buffer IN BYTES, the DIO state is transmitted - * as the first byte. - */ -#define SIZEINBUF (((NUMCHANNELS+1)*SIZEADIN)) - -/* 16 bytes. */ -#define SIZEINSNBUF 16 - -/* Number of DA channels */ -#define NUMOUTCHANNELS 8 - -/* size of one value for the D/A converter: channel and value */ -#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(int16_t))) - -/* - * Size of the output-buffer in bytes - * Actually only the first 4 triplets are used but for the - * high speed mode we need to pad it to 8 (microframes). - */ -#define SIZEOUTBUF ((8*SIZEDAOUT)) - -/* - * Size of the buffer for the dux commands: just now max size is determined - * by the analogue out + command byte + panic bytes... - */ -#define SIZEOFDUXBUFFER ((8*SIZEDAOUT+2)) - -/* Number of in-URBs which receive the data: min=2 */ -#define NUMOFINBUFFERSFULL 5 - -/* Number of out-URBs which send the data: min=2 */ -#define NUMOFOUTBUFFERSFULL 5 - -/* Number of in-URBs which receive the data: min=5 */ -/* must have more buffers due to buggy USB ctr */ -#define NUMOFINBUFFERSHIGH 10 - -/* Number of out-URBs which send the data: min=5 */ -/* must have more buffers due to buggy USB ctr */ -#define NUMOFOUTBUFFERSHIGH 10 - -/* Total number of usbdux devices */ -#define NUMUSBDUX 16 - -/* Analogue in subdevice */ -#define SUBDEV_AD 0 - -/* Analogue out subdevice */ -#define SUBDEV_DA 1 - -/* Digital I/O */ -#define SUBDEV_DIO 2 - -/* timer aka pwm output */ -#define SUBDEV_PWM 3 - -/* number of retries to get the right dux command */ -#define RETRIES 10 - -/**************************************************/ -/* comedi constants */ -static const struct comedi_lrange range_usbdux_ai_range = { 1, { - BIP_RANGE - (2.65) - } -}; - -static const struct comedi_lrange range_usbdux_ao_range = { 1, { - UNI_RANGE - (2.5), - } -}; - -/* - * private structure of one subdevice - */ - -/* - * This is the structure which holds all the data of - * this driver one sub device just now: A/D - */ -struct usbduxsub { - /* attached? */ - int attached; - /* is it associated with a subdevice? */ - int probed; - /* pointer to the usb-device */ - struct usb_device *usbdev; - /* actual number of in-buffers */ - int numOfInBuffers; - /* actual number of out-buffers */ - int numOfOutBuffers; - /* ISO-transfer handling: buffers */ - struct urb **urbIn; - struct urb **urbOut; - /* pwm-transfer handling */ - struct urb *urbPwm; - /* PWM period */ - unsigned int pwmPeriod; - /* PWM internal delay for the GPIF in the FX2 */ - uint8_t pwmDelay; - /* size of the PWM buffer which holds the bit pattern */ - int sizePwmBuf; - /* input buffer for the ISO-transfer */ - int32_t *inBuffer; - /* input buffer for single insn */ - int8_t *insnBuffer; - /* output buffer for single DA outputs */ - int16_t *outBuffer; - /* interface number */ - int ifnum; - /* interface structure in 2.6 */ - struct usb_interface *interface; - /* comedi device for the interrupt context */ - struct comedi_device *comedidev; - /* is it USB_SPEED_HIGH or not? */ - short int high_speed; - /* asynchronous command is running */ - short int ai_cmd_running; - short int ao_cmd_running; - /* pwm is running */ - short int pwm_cmd_running; - /* continous aquisition */ - short int ai_continous; - short int ao_continous; - /* number of samples to acquire */ - int ai_sample_count; - int ao_sample_count; - /* time between samples in units of the timer */ - unsigned int ai_timer; - unsigned int ao_timer; - /* counter between aquisitions */ - unsigned int ai_counter; - unsigned int ao_counter; - /* interval in frames/uframes */ - unsigned int ai_interval; - /* D/A commands */ - uint8_t *dac_commands; - /* commands */ - uint8_t *dux_commands; - struct semaphore sem; -}; - -/* - * The pointer to the private usb-data of the driver is also the private data - * for the comedi-device. This has to be global as the usb subsystem needs - * global variables. The other reason is that this structure must be there - * _before_ any comedi command is issued. The usb subsystem must be initialised - * before comedi can access it. - */ -static struct usbduxsub usbduxsub[NUMUSBDUX]; - -static DEFINE_SEMAPHORE(start_stop_sem); - -/* - * Stops the data acquision - * It should be safe to call this function from any context - */ -static int usbduxsub_unlink_InURBs(struct usbduxsub *usbduxsub_tmp) -{ - int i = 0; - int err = 0; - - if (usbduxsub_tmp && usbduxsub_tmp->urbIn) { - for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) { - if (usbduxsub_tmp->urbIn[i]) { - /* We wait here until all transfers have been - * cancelled. */ - usb_kill_urb(usbduxsub_tmp->urbIn[i]); - } - dev_dbg(&usbduxsub_tmp->interface->dev, - "comedi: usbdux: unlinked InURB %d, err=%d\n", - i, err); - } - } - return err; -} - -/* - * This will stop a running acquisition operation - * Is called from within this driver from both the - * interrupt context and from comedi - */ -static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink) -{ - int ret = 0; - - if (!this_usbduxsub) { - pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n"); - return -EFAULT; - } - dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n"); - - if (do_unlink) { - /* stop aquistion */ - ret = usbduxsub_unlink_InURBs(this_usbduxsub); - } - - this_usbduxsub->ai_cmd_running = 0; - - return ret; -} - -/* - * This will cancel a running acquisition operation. - * This is called by comedi but never from inside the driver. - */ -static int usbdux_ai_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct usbduxsub *this_usbduxsub; - int res = 0; - - /* force unlink of all urbs */ - this_usbduxsub = dev->private; - if (!this_usbduxsub) - return -EFAULT; - - dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n"); - - /* prevent other CPUs from submitting new commands just now */ - down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - /* unlink only if the urb really has been submitted */ - res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running); - up(&this_usbduxsub->sem); - return res; -} - -/* analogue IN - interrupt service routine */ -static void usbduxsub_ai_IsocIrq(struct urb *urb) -{ - int i, err, n; - struct usbduxsub *this_usbduxsub; - struct comedi_device *this_comedidev; - struct comedi_subdevice *s; - int32_t v; - unsigned int dio_state; - - /* the context variable points to the comedi device */ - this_comedidev = urb->context; - /* the private structure of the subdevice is struct usbduxsub */ - this_usbduxsub = this_comedidev->private; - /* subdevice which is the AD converter */ - s = this_comedidev->subdevices + SUBDEV_AD; - - /* first we test if something unusual has just happened */ - switch (urb->status) { - case 0: - /* copy the result in the transfer buffer */ - memcpy(this_usbduxsub->inBuffer, - urb->transfer_buffer, SIZEINBUF); - break; - case -EILSEQ: - /* error in the ISOchronous data */ - /* we don't copy the data into the transfer buffer */ - /* and recycle the last data byte */ - dev_dbg(&urb->dev->dev, - "comedi%d: usbdux: CRC error in ISO IN stream.\n", - this_usbduxsub->comedidev->minor); - - break; - - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -ECONNABORTED: - /* happens after an unlink command */ - if (this_usbduxsub->ai_cmd_running) { - /* we are still running a command */ - /* tell this comedi */ - s->async->events |= COMEDI_CB_EOA; - s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxsub->comedidev, s); - /* stop the transfer w/o unlink */ - usbdux_ai_stop(this_usbduxsub, 0); - } - return; - - default: - /* a real error on the bus */ - /* pass error to comedi if we are really running a command */ - if (this_usbduxsub->ai_cmd_running) { - dev_err(&urb->dev->dev, - "Non-zero urb status received in ai intr " - "context: %d\n", urb->status); - s->async->events |= COMEDI_CB_EOA; - s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxsub->comedidev, s); - /* don't do an unlink here */ - usbdux_ai_stop(this_usbduxsub, 0); - } - return; - } - - /* - * at this point we are reasonably sure that nothing dodgy has happened - * are we running a command? - */ - if (unlikely((!(this_usbduxsub->ai_cmd_running)))) { - /* - * not running a command, do not continue execution if no - * asynchronous command is running in particular not resubmit - */ - return; - } - - urb->dev = this_usbduxsub->usbdev; - - /* resubmit the urb */ - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err < 0)) { - dev_err(&urb->dev->dev, - "comedi_: urb resubmit failed in int-context!" - "err=%d\n", - err); - if (err == -EL2NSYNC) - dev_err(&urb->dev->dev, - "buggy USB host controller or bug in IRQ " - "handler!\n"); - s->async->events |= COMEDI_CB_EOA; - s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxsub->comedidev, s); - /* don't do an unlink here */ - usbdux_ai_stop(this_usbduxsub, 0); - return; - } - - /* get the state of the dio pins to allow external trigger */ - dio_state = be32_to_cpu(this_usbduxsub->inBuffer[0]); - - this_usbduxsub->ai_counter--; - if (likely(this_usbduxsub->ai_counter > 0)) - return; - - /* timer zero, transfer measurements to comedi */ - this_usbduxsub->ai_counter = this_usbduxsub->ai_timer; - - /* test, if we transmit only a fixed number of samples */ - if (!(this_usbduxsub->ai_continous)) { - /* not continous, fixed number of samples */ - this_usbduxsub->ai_sample_count--; - /* all samples received? */ - if (this_usbduxsub->ai_sample_count < 0) { - /* prevent a resubmit next time */ - usbdux_ai_stop(this_usbduxsub, 0); - /* say comedi that the acquistion is over */ - s->async->events |= COMEDI_CB_EOA; - comedi_event(this_usbduxsub->comedidev, s); - return; - } - } - /* get the data from the USB bus and hand it over to comedi */ - n = s->async->cmd.chanlist_len; - for (i = 0; i < n; i++) { - /* transfer data, note first byte is the DIO state */ - v = be32_to_cpu(this_usbduxsub->inBuffer[i+1]); - /* strip status byte */ - v = v & 0x00ffffff; - /* convert to unsigned */ - v = v ^ 0x00800000; - /* write the byte to the buffer */ - err = cfc_write_array_to_buffer(s, &v, sizeof(uint32_t)); - if (unlikely(err == 0)) { - /* buffer overflow */ - usbdux_ai_stop(this_usbduxsub, 0); - return; - } - } - /* tell comedi that data is there */ - s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; - comedi_event(this_usbduxsub->comedidev, s); -} - -static int usbduxsub_unlink_OutURBs(struct usbduxsub *usbduxsub_tmp) -{ - int i = 0; - int err = 0; - - if (usbduxsub_tmp && usbduxsub_tmp->urbOut) { - for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) { - if (usbduxsub_tmp->urbOut[i]) - usb_kill_urb(usbduxsub_tmp->urbOut[i]); - - dev_dbg(&usbduxsub_tmp->interface->dev, - "comedi: usbdux: unlinked OutURB %d: res=%d\n", - i, err); - } - } - return err; -} - -/* This will cancel a running acquisition operation - * in any context. - */ -static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink) -{ - int ret = 0; - - if (!this_usbduxsub) - return -EFAULT; - dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n"); - - if (do_unlink) - ret = usbduxsub_unlink_OutURBs(this_usbduxsub); - - this_usbduxsub->ao_cmd_running = 0; - - return ret; -} - -/* force unlink, is called by comedi */ -static int usbdux_ao_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct usbduxsub *this_usbduxsub = dev->private; - int res = 0; - - if (!this_usbduxsub) - return -EFAULT; - - /* prevent other CPUs from submitting a command just now */ - down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - /* unlink only if it is really running */ - res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running); - up(&this_usbduxsub->sem); - return res; -} - -static void usbduxsub_ao_IsocIrq(struct urb *urb) -{ - int i, ret; - uint8_t *datap; - struct usbduxsub *this_usbduxsub; - struct comedi_device *this_comedidev; - struct comedi_subdevice *s; - - /* the context variable points to the subdevice */ - this_comedidev = urb->context; - /* the private structure of the subdevice is struct usbduxsub */ - this_usbduxsub = this_comedidev->private; - - s = this_comedidev->subdevices + SUBDEV_DA; - - switch (urb->status) { - case 0: - /* success */ - break; - - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -ECONNABORTED: - /* after an unlink command, unplug, ... etc */ - /* no unlink needed here. Already shutting down. */ - if (this_usbduxsub->ao_cmd_running) { - s->async->events |= COMEDI_CB_EOA; - comedi_event(this_usbduxsub->comedidev, s); - usbdux_ao_stop(this_usbduxsub, 0); - } - return; - - default: - /* a real error */ - if (this_usbduxsub->ao_cmd_running) { - dev_err(&urb->dev->dev, - "comedi_: Non-zero urb status received in ao " - "intr context: %d\n", urb->status); - s->async->events |= COMEDI_CB_ERROR; - s->async->events |= COMEDI_CB_EOA; - comedi_event(this_usbduxsub->comedidev, s); - /* we do an unlink if we are in the high speed mode */ - usbdux_ao_stop(this_usbduxsub, 0); - } - return; - } - - /* are we actually running? */ - if (!(this_usbduxsub->ao_cmd_running)) - return; - - /* normal operation: executing a command in this subdevice */ - this_usbduxsub->ao_counter--; - if ((int)this_usbduxsub->ao_counter <= 0) { - /* timer zero */ - this_usbduxsub->ao_counter = this_usbduxsub->ao_timer; - - /* handle non continous aquisition */ - if (!(this_usbduxsub->ao_continous)) { - /* fixed number of samples */ - this_usbduxsub->ao_sample_count--; - if (this_usbduxsub->ao_sample_count < 0) { - /* all samples transmitted */ - usbdux_ao_stop(this_usbduxsub, 0); - s->async->events |= COMEDI_CB_EOA; - comedi_event(this_usbduxsub->comedidev, s); - /* no resubmit of the urb */ - return; - } - } - /* transmit data to the USB bus */ - ((uint8_t *) (urb->transfer_buffer))[0] = - s->async->cmd.chanlist_len; - for (i = 0; i < s->async->cmd.chanlist_len; i++) { - short temp; - if (i >= NUMOUTCHANNELS) - break; - - /* pointer to the DA */ - datap = - (&(((uint8_t *) urb->transfer_buffer)[i * 2 + 1])); - /* get the data from comedi */ - ret = comedi_buf_get(s->async, &temp); - datap[0] = temp; - datap[1] = this_usbduxsub->dac_commands[i]; - /* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */ - /* datap[0],datap[1],datap[2]); */ - if (ret < 0) { - dev_err(&urb->dev->dev, - "comedi: buffer underflow\n"); - s->async->events |= COMEDI_CB_EOA; - s->async->events |= COMEDI_CB_OVERFLOW; - } - /* transmit data to comedi */ - s->async->events |= COMEDI_CB_BLOCK; - comedi_event(this_usbduxsub->comedidev, s); - } - } - urb->transfer_buffer_length = SIZEOUTBUF; - urb->dev = this_usbduxsub->usbdev; - urb->status = 0; - if (this_usbduxsub->ao_cmd_running) { - if (this_usbduxsub->high_speed) { - /* uframes */ - urb->interval = 8; - } else { - /* frames */ - urb->interval = 1; - } - urb->number_of_packets = 1; - urb->iso_frame_desc[0].offset = 0; - urb->iso_frame_desc[0].length = SIZEOUTBUF; - urb->iso_frame_desc[0].status = 0; - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) { - dev_err(&urb->dev->dev, - "comedi_: ao urb resubm failed in int-cont. " - "ret=%d", ret); - if (ret == EL2NSYNC) - dev_err(&urb->dev->dev, - "buggy USB host controller or bug in " - "IRQ handling!\n"); - - s->async->events |= COMEDI_CB_EOA; - s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxsub->comedidev, s); - /* don't do an unlink here */ - usbdux_ao_stop(this_usbduxsub, 0); - } - } -} - -static int usbduxsub_start(struct usbduxsub *usbduxsub) -{ - int errcode = 0; - uint8_t local_transfer_buffer[16]; - - /* 7f92 to zero */ - local_transfer_buffer[0] = 0; - errcode = usb_control_msg(usbduxsub->usbdev, - /* create a pipe for a control transfer */ - usb_sndctrlpipe(usbduxsub->usbdev, 0), - /* bRequest, "Firmware" */ - USBDUXSUB_FIRMWARE, - /* bmRequestType */ - VENDOR_DIR_OUT, - /* Value */ - USBDUXSUB_CPUCS, - /* Index */ - 0x0000, - /* address of the transfer buffer */ - local_transfer_buffer, - /* Length */ - 1, - /* Timeout */ - BULK_TIMEOUT); - if (errcode < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: control msg failed (start)\n"); - return errcode; - } - return 0; -} - -static int usbduxsub_stop(struct usbduxsub *usbduxsub) -{ - int errcode = 0; - - uint8_t local_transfer_buffer[16]; - - /* 7f92 to one */ - local_transfer_buffer[0] = 1; - errcode = usb_control_msg(usbduxsub->usbdev, - usb_sndctrlpipe(usbduxsub->usbdev, 0), - /* bRequest, "Firmware" */ - USBDUXSUB_FIRMWARE, - /* bmRequestType */ - VENDOR_DIR_OUT, - /* Value */ - USBDUXSUB_CPUCS, - /* Index */ - 0x0000, local_transfer_buffer, - /* Length */ - 1, - /* Timeout */ - BULK_TIMEOUT); - if (errcode < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: control msg failed (stop)\n"); - return errcode; - } - return 0; -} - -static int usbduxsub_upload(struct usbduxsub *usbduxsub, - uint8_t *local_transfer_buffer, - unsigned int startAddr, unsigned int len) -{ - int errcode; - - errcode = usb_control_msg(usbduxsub->usbdev, - usb_sndctrlpipe(usbduxsub->usbdev, 0), - /* brequest, firmware */ - USBDUXSUB_FIRMWARE, - /* bmRequestType */ - VENDOR_DIR_OUT, - /* value */ - startAddr, - /* index */ - 0x0000, - /* our local safe buffer */ - local_transfer_buffer, - /* length */ - len, - /* timeout */ - BULK_TIMEOUT); - dev_dbg(&usbduxsub->interface->dev, "comedi_: result=%d\n", errcode); - if (errcode < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: upload failed\n"); - return errcode; - } - return 0; -} - -/* the FX2LP has twice as much as the standard FX2 */ -#define FIRMWARE_MAX_LEN 0x4000 - -static int firmwareUpload(struct usbduxsub *usbduxsub, - const u8 *firmwareBinary, int sizeFirmware) -{ - int ret; - uint8_t *fwBuf; - - if (!firmwareBinary) - return 0; - - if (sizeFirmware > FIRMWARE_MAX_LEN) { - dev_err(&usbduxsub->interface->dev, - "usbduxsigma firmware binary it too large for FX2.\n"); - return -ENOMEM; - } - - /* we generate a local buffer for the firmware */ - fwBuf = kmemdup(firmwareBinary, sizeFirmware, GFP_KERNEL); - if (!fwBuf) { - dev_err(&usbduxsub->interface->dev, - "comedi_: mem alloc for firmware failed\n"); - return -ENOMEM; - } - - ret = usbduxsub_stop(usbduxsub); - if (ret < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: can not stop firmware\n"); - kfree(fwBuf); - return ret; - } - - ret = usbduxsub_upload(usbduxsub, fwBuf, 0, sizeFirmware); - if (ret < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: firmware upload failed\n"); - kfree(fwBuf); - return ret; - } - ret = usbduxsub_start(usbduxsub); - if (ret < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: can not start firmware\n"); - kfree(fwBuf); - return ret; - } - kfree(fwBuf); - return 0; -} - -static int usbduxsub_submit_InURBs(struct usbduxsub *usbduxsub) -{ - int i, errFlag; - - if (!usbduxsub) - return -EFAULT; - - /* Submit all URBs and start the transfer on the bus */ - for (i = 0; i < usbduxsub->numOfInBuffers; i++) { - /* in case of a resubmission after an unlink... */ - usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval; - usbduxsub->urbIn[i]->context = usbduxsub->comedidev; - usbduxsub->urbIn[i]->dev = usbduxsub->usbdev; - usbduxsub->urbIn[i]->status = 0; - usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP; - dev_dbg(&usbduxsub->interface->dev, - "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n", - usbduxsub->comedidev->minor, i, - (usbduxsub->urbIn[i]->context), - (usbduxsub->urbIn[i]->dev), - (usbduxsub->urbIn[i]->interval)); - errFlag = usb_submit_urb(usbduxsub->urbIn[i], GFP_ATOMIC); - if (errFlag) { - dev_err(&usbduxsub->interface->dev, - "comedi_: ai: usb_submit_urb(%d) error %d\n", - i, errFlag); - return errFlag; - } - } - return 0; -} - -static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub) -{ - int i, errFlag; - - if (!usbduxsub) - return -EFAULT; - - for (i = 0; i < usbduxsub->numOfOutBuffers; i++) { - dev_dbg(&usbduxsub->interface->dev, - "comedi_: submitting out-urb[%d]\n", i); - /* in case of a resubmission after an unlink... */ - usbduxsub->urbOut[i]->context = usbduxsub->comedidev; - usbduxsub->urbOut[i]->dev = usbduxsub->usbdev; - usbduxsub->urbOut[i]->status = 0; - usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP; - errFlag = usb_submit_urb(usbduxsub->urbOut[i], GFP_ATOMIC); - if (errFlag) { - dev_err(&usbduxsub->interface->dev, - "comedi_: ao: usb_submit_urb(%d) error %d\n", - i, errFlag); - return errFlag; - } - } - return 0; -} - -static int chanToInterval(int nChannels) -{ - if (nChannels <= 2) - /* 4kHz */ - return 2; - if (nChannels <= 8) - /* 2kHz */ - return 4; - /* 1kHz */ - return 8; -} - -static int usbdux_ai_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd) -{ - int err = 0, tmp, i; - unsigned int tmpTimer; - struct usbduxsub *this_usbduxsub = dev->private; - - if (!(this_usbduxsub->probed)) - return -ENODEV; - - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ai_cmdtest\n", dev->minor); - - /* make sure triggers are valid */ - /* Only immediate triggers are allowed */ - tmp = cmd->start_src; - cmd->start_src &= TRIG_NOW | TRIG_INT; - if (!cmd->start_src || tmp != cmd->start_src) - err++; - - /* trigger should happen timed */ - tmp = cmd->scan_begin_src; - /* start a new _scan_ with a timer */ - cmd->scan_begin_src &= TRIG_TIMER; - if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) - err++; - - /* scanning is continous */ - tmp = cmd->convert_src; - cmd->convert_src &= TRIG_NOW; - if (!cmd->convert_src || tmp != cmd->convert_src) - err++; - - /* issue a trigger when scan is finished and start a new scan */ - tmp = cmd->scan_end_src; - cmd->scan_end_src &= TRIG_COUNT; - if (!cmd->scan_end_src || tmp != cmd->scan_end_src) - err++; - - /* trigger at the end of count events or not, stop condition or not */ - tmp = cmd->stop_src; - cmd->stop_src &= TRIG_COUNT | TRIG_NONE; - if (!cmd->stop_src || tmp != cmd->stop_src) - err++; - - if (err) - return 1; - - /* - * step 2: make sure trigger sources are unique and mutually compatible - * note that mutual compatibility is not an issue here - */ - if (cmd->scan_begin_src != TRIG_FOLLOW && - cmd->scan_begin_src != TRIG_EXT && - cmd->scan_begin_src != TRIG_TIMER) - err++; - if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) - err++; - - if (err) - return 2; - - /* step 3: make sure arguments are trivially compatible */ - if (cmd->start_arg != 0) { - cmd->start_arg = 0; - err++; - } - - if (cmd->scan_begin_src == TRIG_FOLLOW) { - /* internal trigger */ - if (cmd->scan_begin_arg != 0) { - cmd->scan_begin_arg = 0; - err++; - } - } - - if (cmd->scan_begin_src == TRIG_TIMER) { - if (this_usbduxsub->high_speed) { - /* - * In high speed mode microframes are possible. - * However, during one microframe we can roughly - * sample two channels. Thus, the more channels - * are in the channel list the more time we need. - */ - i = chanToInterval(cmd->chanlist_len); - if (cmd->scan_begin_arg < (1000000 / 8 * i)) { - cmd->scan_begin_arg = 1000000 / 8 * i; - err++; - } - /* now calc the real sampling rate with all the - * rounding errors */ - tmpTimer = - ((unsigned int)(cmd->scan_begin_arg / 125000)) * - 125000; - if (cmd->scan_begin_arg != tmpTimer) { - cmd->scan_begin_arg = tmpTimer; - err++; - } - } else { - /* full speed */ - /* 1kHz scans every USB frame */ - if (cmd->scan_begin_arg < 1000000) { - cmd->scan_begin_arg = 1000000; - err++; - } - /* - * calc the real sampling rate with the rounding errors - */ - tmpTimer = ((unsigned int)(cmd->scan_begin_arg / - 1000000)) * 1000000; - if (cmd->scan_begin_arg != tmpTimer) { - cmd->scan_begin_arg = tmpTimer; - err++; - } - } - } - /* the same argument */ - if (cmd->scan_end_arg != cmd->chanlist_len) { - cmd->scan_end_arg = cmd->chanlist_len; - err++; - } - - if (cmd->stop_src == TRIG_COUNT) { - /* any count is allowed */ - } else { - /* TRIG_NONE */ - if (cmd->stop_arg != 0) { - cmd->stop_arg = 0; - err++; - } - } - - if (err) - return 3; - - return 0; -} - -/* - * creates the ADC command for the MAX1271 - * range is the range value from comedi - */ -static void create_adc_command(unsigned int chan, - uint8_t *muxsg0, - uint8_t *muxsg1) -{ - if (chan < 8) - (*muxsg0) = (*muxsg0) | (1 << chan); - else if (chan < 16) - (*muxsg1) = (*muxsg1) | (1 << (chan-8)); -} - - -/* bulk transfers to usbdux */ - -#define SENDADCOMMANDS 0 -#define SENDDACOMMANDS 1 -#define SENDDIOCONFIGCOMMAND 2 -#define SENDDIOBITSCOMMAND 3 -#define SENDSINGLEAD 4 -#define SENDPWMON 7 -#define SENDPWMOFF 8 - -static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type) -{ - int result, nsent; - - this_usbduxsub->dux_commands[0] = cmd_type; -#ifdef NOISY_DUX_DEBUGBUG - printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ", - this_usbduxsub->comedidev->minor); - for (result = 0; result < SIZEOFDUXBUFFER; result++) - printk(" %02x", this_usbduxsub->dux_commands[result]); - printk("\n"); -#endif - result = usb_bulk_msg(this_usbduxsub->usbdev, - usb_sndbulkpipe(this_usbduxsub->usbdev, - COMMAND_OUT_EP), - this_usbduxsub->dux_commands, SIZEOFDUXBUFFER, - &nsent, BULK_TIMEOUT); - if (result < 0) - dev_err(&this_usbduxsub->interface->dev, "comedi%d: " - "could not transmit dux_command to the usb-device, " - "err=%d\n", this_usbduxsub->comedidev->minor, result); - - return result; -} - -static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command) -{ - int result = (-EFAULT); - int nrec; - int i; - - for (i = 0; i < RETRIES; i++) { - result = usb_bulk_msg(this_usbduxsub->usbdev, - usb_rcvbulkpipe(this_usbduxsub->usbdev, - COMMAND_IN_EP), - this_usbduxsub->insnBuffer, SIZEINSNBUF, - &nrec, BULK_TIMEOUT); - if (result < 0) { - dev_err(&this_usbduxsub->interface->dev, "comedi%d: " - "insn: USB error %d " - "while receiving DUX command" - "\n", this_usbduxsub->comedidev->minor, - result); - return result; - } - if (this_usbduxsub->insnBuffer[0] == command) - return result; - } - /* this is only reached if the data has been requested a couple of - * times */ - dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: " - "wrong data returned from firmware: want %d, got %d.\n", - this_usbduxsub->comedidev->minor, command, - this_usbduxsub->insnBuffer[0]); - return -EFAULT; -} - -static int usbdux_ai_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int trignum) -{ - int ret; - struct usbduxsub *this_usbduxsub = dev->private; - if (!this_usbduxsub) - return -EFAULT; - - down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ai_inttrig\n", dev->minor); - - if (trignum != 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ai_inttrig: invalid trignum\n", - dev->minor); - up(&this_usbduxsub->sem); - return -EINVAL; - } - if (!(this_usbduxsub->ai_cmd_running)) { - this_usbduxsub->ai_cmd_running = 1; - ret = usbduxsub_submit_InURBs(this_usbduxsub); - if (ret < 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ai_inttrig: " - "urbSubmit: err=%d\n", dev->minor, ret); - this_usbduxsub->ai_cmd_running = 0; - up(&this_usbduxsub->sem); - return ret; - } - s->async->inttrig = NULL; - } else { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: ai_inttrig but acqu is already running\n", - dev->minor); - } - up(&this_usbduxsub->sem); - return 1; -} - -static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) -{ - struct comedi_cmd *cmd = &s->async->cmd; - unsigned int chan; - int i, ret; - struct usbduxsub *this_usbduxsub = dev->private; - int result; - uint8_t muxsg0 = 0; - uint8_t muxsg1 = 0; - uint8_t sysred = 0; - - if (!this_usbduxsub) - return -EFAULT; - - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ai_cmd\n", dev->minor); - - /* block other CPUs from starting an ai_cmd */ - down(&this_usbduxsub->sem); - - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - if (this_usbduxsub->ai_cmd_running) { - dev_err(&this_usbduxsub->interface->dev, "comedi%d: " - "ai_cmd not possible. Another ai_cmd is running.\n", - dev->minor); - up(&this_usbduxsub->sem); - return -EBUSY; - } - /* set current channel of the running aquisition to zero */ - s->async->cur_chan = 0; - - /* first the number of channels per time step */ - this_usbduxsub->dux_commands[1] = cmd->chanlist_len; - - /* CONFIG0 */ - this_usbduxsub->dux_commands[2] = 0x12; - - /* CONFIG1: 23kHz sampling rate, delay = 0us, */ - this_usbduxsub->dux_commands[3] = 0x03; - - /* CONFIG3: differential channels off */ - this_usbduxsub->dux_commands[4] = 0x00; - - for (i = 0; i < cmd->chanlist_len; i++) { - chan = CR_CHAN(cmd->chanlist[i]); - create_adc_command(chan, &muxsg0, &muxsg1); - if (i >= NUMCHANNELS) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: channel list too long\n", - dev->minor); - break; - } - } - this_usbduxsub->dux_commands[5] = muxsg0; - this_usbduxsub->dux_commands[6] = muxsg1; - this_usbduxsub->dux_commands[7] = sysred; - - dev_dbg(&this_usbduxsub->interface->dev, - "comedi %d: sending commands to the usb device: size=%u\n", - dev->minor, NUMCHANNELS); - - result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS); - if (result < 0) { - up(&this_usbduxsub->sem); - return result; - } - - if (this_usbduxsub->high_speed) { - /* - * every 2 channels get a time window of 125us. Thus, if we - * sample all 16 channels we need 1ms. If we sample only one - * channel we need only 125us - */ - this_usbduxsub->ai_interval = - chanToInterval(cmd->chanlist_len); - this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 * - (this_usbduxsub-> - ai_interval)); - } else { - /* interval always 1ms */ - this_usbduxsub->ai_interval = 1; - this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000; - } - if (this_usbduxsub->ai_timer < 1) { - dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: " - "timer=%d, scan_begin_arg=%d. " - "Not properly tested by cmdtest?\n", dev->minor, - this_usbduxsub->ai_timer, cmd->scan_begin_arg); - up(&this_usbduxsub->sem); - return -EINVAL; - } - this_usbduxsub->ai_counter = this_usbduxsub->ai_timer; - - if (cmd->stop_src == TRIG_COUNT) { - /* data arrives as one packet */ - this_usbduxsub->ai_sample_count = cmd->stop_arg; - this_usbduxsub->ai_continous = 0; - } else { - /* continous aquisition */ - this_usbduxsub->ai_continous = 1; - this_usbduxsub->ai_sample_count = 0; - } - - if (cmd->start_src == TRIG_NOW) { - /* enable this acquisition operation */ - this_usbduxsub->ai_cmd_running = 1; - ret = usbduxsub_submit_InURBs(this_usbduxsub); - if (ret < 0) { - this_usbduxsub->ai_cmd_running = 0; - /* fixme: unlink here?? */ - up(&this_usbduxsub->sem); - return ret; - } - s->async->inttrig = NULL; - } else { - /* TRIG_INT */ - /* don't enable the acquision operation */ - /* wait for an internal signal */ - s->async->inttrig = usbdux_ai_inttrig; - } - up(&this_usbduxsub->sem); - return 0; -} - -/* Mode 0 is used to get a single conversion on demand */ -static int usbdux_ai_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - int i; - int32_t one = 0; - int chan; - int err; - struct usbduxsub *this_usbduxsub = dev->private; - uint8_t muxsg0 = 0; - uint8_t muxsg1 = 0; - uint8_t sysred = 0; - - if (!this_usbduxsub) - return 0; - - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n", - dev->minor, insn->n, insn->subdev); - - down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - if (this_usbduxsub->ai_cmd_running) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: ai_insn_read not possible. " - "Async Command is running.\n", dev->minor); - up(&this_usbduxsub->sem); - return 0; - } - - /* sample one channel */ - /* CONFIG0: chopper on */ - this_usbduxsub->dux_commands[1] = 0x16; - - /* CONFIG1: 2kHz sampling rate */ - this_usbduxsub->dux_commands[2] = 0x80; - - /* CONFIG3: differential channels off */ - this_usbduxsub->dux_commands[3] = 0x00; - - chan = CR_CHAN(insn->chanspec); - create_adc_command(chan, &muxsg0, &muxsg1); - - this_usbduxsub->dux_commands[4] = muxsg0; - this_usbduxsub->dux_commands[5] = muxsg1; - this_usbduxsub->dux_commands[6] = sysred; - - /* adc commands */ - err = send_dux_commands(this_usbduxsub, SENDSINGLEAD); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; - } - - for (i = 0; i < insn->n; i++) { - err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD); - if (err < 0) { - up(&this_usbduxsub->sem); - return 0; - } - /* 32 bits big endian from the A/D converter */ - one = be32_to_cpu(*((int32_t *) - ((this_usbduxsub->insnBuffer)+1))); - /* mask out the staus byte */ - one = one & 0x00ffffff; - /* turn it into an unsigned integer */ - one = one ^ 0x00800000; - data[i] = one; - } - up(&this_usbduxsub->sem); - return i; -} - - - - -static int usbdux_getstatusinfo(struct comedi_device *dev, int chan) -{ - struct usbduxsub *this_usbduxsub = dev->private; - uint8_t sysred = 0; - uint32_t one; - int err; - - if (!this_usbduxsub) - return 0; - - if (this_usbduxsub->ai_cmd_running) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: status read not possible. " - "Async Command is running.\n", dev->minor); - return 0; - } - - /* CONFIG0 */ - this_usbduxsub->dux_commands[1] = 0x12; - - /* CONFIG1: 2kHz sampling rate */ - this_usbduxsub->dux_commands[2] = 0x80; - - /* CONFIG3: differential channels off */ - this_usbduxsub->dux_commands[3] = 0x00; - - if (chan == 1) { - /* ADC offset */ - sysred = sysred | 1; - } else if (chan == 2) { - /* VCC */ - sysred = sysred | 4; - } else if (chan == 3) { - /* temperature */ - sysred = sysred | 8; - } else if (chan == 4) { - /* gain */ - sysred = sysred | 16; - } else if (chan == 5) { - /* ref */ - sysred = sysred | 32; - } - - this_usbduxsub->dux_commands[4] = 0; - this_usbduxsub->dux_commands[5] = 0; - this_usbduxsub->dux_commands[6] = sysred; - - /* adc commands */ - err = send_dux_commands(this_usbduxsub, SENDSINGLEAD); - if (err < 0) - return err; - - err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD); - if (err < 0) - return err; - - /* 32 bits big endian from the A/D converter */ - one = be32_to_cpu(*((int32_t *)((this_usbduxsub->insnBuffer)+1))); - /* mask out the staus byte */ - one = one & 0x00ffffff; - one = one ^ 0x00800000; - - return (int)one; -} - - - - - - -/************************************/ -/* analog out */ - -static int usbdux_ao_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - int i; - int chan = CR_CHAN(insn->chanspec); - struct usbduxsub *this_usbduxsub = dev->private; - - if (!this_usbduxsub) - return -EFAULT; - - down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - for (i = 0; i < insn->n; i++) - data[i] = this_usbduxsub->outBuffer[chan]; - - up(&this_usbduxsub->sem); - return i; -} - -static int usbdux_ao_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - int i, err; - int chan = CR_CHAN(insn->chanspec); - struct usbduxsub *this_usbduxsub = dev->private; - - if (!this_usbduxsub) - return -EFAULT; - - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: ao_insn_write\n", dev->minor); - - down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - if (this_usbduxsub->ao_cmd_running) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: ao_insn_write: " - "ERROR: asynchronous ao_cmd is running\n", dev->minor); - up(&this_usbduxsub->sem); - return 0; - } - - for (i = 0; i < insn->n; i++) { - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n", - dev->minor, chan, i, data[i]); - - /* number of channels: 1 */ - this_usbduxsub->dux_commands[1] = 1; - /* channel number */ - this_usbduxsub->dux_commands[2] = data[i]; - this_usbduxsub->outBuffer[chan] = data[i]; - this_usbduxsub->dux_commands[3] = chan; - err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; - } - } - up(&this_usbduxsub->sem); - - return i; -} - -static int usbdux_ao_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int trignum) -{ - int ret; - struct usbduxsub *this_usbduxsub = dev->private; - - if (!this_usbduxsub) - return -EFAULT; - - down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - if (trignum != 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ao_inttrig: invalid trignum\n", - dev->minor); - return -EINVAL; - } - if (!(this_usbduxsub->ao_cmd_running)) { - this_usbduxsub->ao_cmd_running = 1; - ret = usbduxsub_submit_OutURBs(this_usbduxsub); - if (ret < 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ao_inttrig: submitURB: " - "err=%d\n", dev->minor, ret); - this_usbduxsub->ao_cmd_running = 0; - up(&this_usbduxsub->sem); - return ret; - } - s->async->inttrig = NULL; - } else { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: ao_inttrig but acqu is already running.\n", - dev->minor); - } - up(&this_usbduxsub->sem); - return 1; -} - -static int usbdux_ao_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd) -{ - int err = 0, tmp; - struct usbduxsub *this_usbduxsub = dev->private; - - if (!this_usbduxsub) - return -EFAULT; - - if (!(this_usbduxsub->probed)) - return -ENODEV; - - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ao_cmdtest\n", dev->minor); - - /* make sure triggers are valid */ - /* Only immediate triggers are allowed */ - tmp = cmd->start_src; - cmd->start_src &= TRIG_NOW | TRIG_INT; - if (!cmd->start_src || tmp != cmd->start_src) - err++; - - /* trigger should happen timed */ - tmp = cmd->scan_begin_src; - /* just now we scan also in the high speed mode every frame */ - /* this is due to ehci driver limitations */ - if (0) { /* (this_usbduxsub->high_speed) */ - /* start immidiately a new scan */ - /* the sampling rate is set by the coversion rate */ - cmd->scan_begin_src &= TRIG_FOLLOW; - } else { - /* start a new scan (output at once) with a timer */ - cmd->scan_begin_src &= TRIG_TIMER; - } - if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) - err++; - - /* scanning is continous */ - tmp = cmd->convert_src; - - /* all conversion events happen simultaneously */ - cmd->convert_src &= TRIG_NOW; - - if (!cmd->convert_src || tmp != cmd->convert_src) - err++; - - /* issue a trigger when scan is finished and start a new scan */ - tmp = cmd->scan_end_src; - cmd->scan_end_src &= TRIG_COUNT; - if (!cmd->scan_end_src || tmp != cmd->scan_end_src) - err++; - - /* trigger at the end of count events or not, stop condition or not */ - tmp = cmd->stop_src; - cmd->stop_src &= TRIG_COUNT | TRIG_NONE; - if (!cmd->stop_src || tmp != cmd->stop_src) - err++; - - if (err) - return 1; - - /* - * step 2: make sure trigger sources - * are unique and mutually compatible - * note that mutual compatibility is not an issue here - */ - if (cmd->scan_begin_src != TRIG_FOLLOW && - cmd->scan_begin_src != TRIG_EXT && - cmd->scan_begin_src != TRIG_TIMER) - err++; - if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) - err++; - - if (err) - return 2; - - /* step 3: make sure arguments are trivially compatible */ - - if (cmd->start_arg != 0) { - cmd->start_arg = 0; - err++; - } - - if (cmd->scan_begin_src == TRIG_FOLLOW) { - /* internal trigger */ - if (cmd->scan_begin_arg != 0) { - cmd->scan_begin_arg = 0; - err++; - } - } - - if (cmd->scan_begin_src == TRIG_TIMER) { - /* timer */ - if (cmd->scan_begin_arg < 1000000) { - cmd->scan_begin_arg = 1000000; - err++; - } - } - /* not used now, is for later use */ - if (cmd->convert_src == TRIG_TIMER) { - if (cmd->convert_arg < 125000) { - cmd->convert_arg = 125000; - err++; - } - } - - /* the same argument */ - if (cmd->scan_end_arg != cmd->chanlist_len) { - cmd->scan_end_arg = cmd->chanlist_len; - err++; - } - - if (cmd->stop_src == TRIG_COUNT) { - /* any count is allowed */ - } else { - /* TRIG_NONE */ - if (cmd->stop_arg != 0) { - cmd->stop_arg = 0; - err++; - } - } - - dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: err=%d, " - "scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, " - "convert_arg=%d\n", dev->minor, err, cmd->scan_begin_src, - cmd->scan_begin_arg, cmd->convert_src, cmd->convert_arg); - - if (err) - return 3; - - return 0; -} - -static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) -{ - struct comedi_cmd *cmd = &s->async->cmd; - unsigned int chan, gain; - int i, ret; - struct usbduxsub *this_usbduxsub = dev->private; - - if (!this_usbduxsub) - return -EFAULT; - - down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: %s\n", dev->minor, __func__); - - /* set current channel of the running aquisition to zero */ - s->async->cur_chan = 0; - for (i = 0; i < cmd->chanlist_len; ++i) { - chan = CR_CHAN(cmd->chanlist[i]); - gain = CR_RANGE(cmd->chanlist[i]); - if (i >= NUMOUTCHANNELS) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: %s: channel list too long\n", - dev->minor, __func__); - break; - } - this_usbduxsub->dac_commands[i] = chan; - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: dac command for ch %d is %x\n", - dev->minor, i, this_usbduxsub->dac_commands[i]); - } - - /* we count in steps of 1ms (125us) */ - /* 125us mode not used yet */ - if (0) { /* (this_usbduxsub->high_speed) */ - /* 125us */ - /* timing of the conversion itself: every 125 us */ - this_usbduxsub->ao_timer = cmd->convert_arg / 125000; - } else { - /* 1ms */ - /* timing of the scan: we get all channels at once */ - this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000; - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, " - "convert_src=%d, convert_arg=%d\n", dev->minor, - cmd->scan_begin_src, cmd->scan_begin_arg, - cmd->convert_src, cmd->convert_arg); - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: ao_timer=%d (ms)\n", - dev->minor, this_usbduxsub->ao_timer); - if (this_usbduxsub->ao_timer < 1) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux: ao_timer=%d, " - "scan_begin_arg=%d. " - "Not properly tested by cmdtest?\n", - dev->minor, this_usbduxsub->ao_timer, - cmd->scan_begin_arg); - up(&this_usbduxsub->sem); - return -EINVAL; - } - } - this_usbduxsub->ao_counter = this_usbduxsub->ao_timer; - - if (cmd->stop_src == TRIG_COUNT) { - /* not continous */ - /* counter */ - /* high speed also scans everything at once */ - if (0) { /* (this_usbduxsub->high_speed) */ - this_usbduxsub->ao_sample_count = - (cmd->stop_arg) * (cmd->scan_end_arg); - } else { - /* there's no scan as the scan has been */ - /* perf inside the FX2 */ - /* data arrives as one packet */ - this_usbduxsub->ao_sample_count = cmd->stop_arg; - } - this_usbduxsub->ao_continous = 0; - } else { - /* continous aquisition */ - this_usbduxsub->ao_continous = 1; - this_usbduxsub->ao_sample_count = 0; - } - - if (cmd->start_src == TRIG_NOW) { - /* enable this acquisition operation */ - this_usbduxsub->ao_cmd_running = 1; - ret = usbduxsub_submit_OutURBs(this_usbduxsub); - if (ret < 0) { - this_usbduxsub->ao_cmd_running = 0; - /* fixme: unlink here?? */ - up(&this_usbduxsub->sem); - return ret; - } - s->async->inttrig = NULL; - } else { - /* TRIG_INT */ - /* submit the urbs later */ - /* wait for an internal signal */ - s->async->inttrig = usbdux_ao_inttrig; - } - - up(&this_usbduxsub->sem); - return 0; -} - -static int usbdux_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - int chan = CR_CHAN(insn->chanspec); - - /* The input or output configuration of each digital line is - * configured by a special insn_config instruction. chanspec - * contains the channel to be changed, and data[0] contains the - * value COMEDI_INPUT or COMEDI_OUTPUT. */ - - switch (data[0]) { - case INSN_CONFIG_DIO_OUTPUT: - s->io_bits |= 1 << chan; /* 1 means Out */ - break; - case INSN_CONFIG_DIO_INPUT: - s->io_bits &= ~(1 << chan); - break; - case INSN_CONFIG_DIO_QUERY: - data[1] = - (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; - break; - default: - return -EINVAL; - break; - } - /* we don't tell the firmware here as it would take 8 frames */ - /* to submit the information. We do it in the insn_bits. */ - return insn->n; -} - -static int usbdux_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - - struct usbduxsub *this_usbduxsub = dev->private; - int err; - - if (!this_usbduxsub) - return -EFAULT; - - if (insn->n != 2) - return -EINVAL; - - down(&this_usbduxsub->sem); - - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - /* The commands are 8 bits wide */ - this_usbduxsub->dux_commands[1] = (s->io_bits) & 0x000000FF; - this_usbduxsub->dux_commands[4] = (s->state) & 0x000000FF; - this_usbduxsub->dux_commands[2] = ((s->io_bits) & 0x0000FF00) >> 8; - this_usbduxsub->dux_commands[5] = ((s->state) & 0x0000FF00) >> 8; - this_usbduxsub->dux_commands[3] = ((s->io_bits) & 0x00FF0000) >> 16; - this_usbduxsub->dux_commands[6] = ((s->state) & 0x00FF0000) >> 16; - - /* This command also tells the firmware to return */ - /* the digital input lines */ - err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; - } - err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; - } - - data[1] = (((unsigned int)(this_usbduxsub->insnBuffer[1]))&0xff) | - ((((unsigned int)(this_usbduxsub->insnBuffer[2]))&0xff) << 8) | - ((((unsigned int)(this_usbduxsub->insnBuffer[3]))&0xff) << 16); - - s->state = data[1]; - - up(&this_usbduxsub->sem); - return 2; -} - -/***********************************/ -/* PWM */ - -static int usbduxsub_unlink_PwmURBs(struct usbduxsub *usbduxsub_tmp) -{ - int err = 0; - - if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) { - if (usbduxsub_tmp->urbPwm) - usb_kill_urb(usbduxsub_tmp->urbPwm); - dev_dbg(&usbduxsub_tmp->interface->dev, - "comedi: unlinked PwmURB: res=%d\n", err); - } - return err; -} - -/* This cancels a running acquisition operation - * in any context. - */ -static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink) -{ - int ret = 0; - - if (!this_usbduxsub) - return -EFAULT; - - dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__); - if (do_unlink) - ret = usbduxsub_unlink_PwmURBs(this_usbduxsub); - - this_usbduxsub->pwm_cmd_running = 0; - - return ret; -} - -/* force unlink - is called by comedi */ -static int usbdux_pwm_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct usbduxsub *this_usbduxsub = dev->private; - int res = 0; - - /* unlink only if it is really running */ - res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running); - - dev_dbg(&this_usbduxsub->interface->dev, - "comedi %d: sending pwm off command to the usb device.\n", - dev->minor); - res = send_dux_commands(this_usbduxsub, SENDPWMOFF); - if (res < 0) - return res; - - return res; -} - -static void usbduxsub_pwm_irq(struct urb *urb) -{ - int ret; - struct usbduxsub *this_usbduxsub; - struct comedi_device *this_comedidev; - struct comedi_subdevice *s; - - /* printk(KERN_DEBUG "PWM: IRQ\n"); */ - - /* the context variable points to the subdevice */ - this_comedidev = urb->context; - /* the private structure of the subdevice is struct usbduxsub */ - this_usbduxsub = this_comedidev->private; - - s = this_comedidev->subdevices + SUBDEV_DA; - - switch (urb->status) { - case 0: - /* success */ - break; - - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -ECONNABORTED: - /* - * after an unlink command, unplug, ... etc - * no unlink needed here. Already shutting down. - */ - if (this_usbduxsub->pwm_cmd_running) - usbdux_pwm_stop(this_usbduxsub, 0); - - return; - - default: - /* a real error */ - if (this_usbduxsub->pwm_cmd_running) { - dev_err(&this_usbduxsub->interface->dev, - "comedi_: Non-zero urb status received in " - "pwm intr context: %d\n", urb->status); - usbdux_pwm_stop(this_usbduxsub, 0); - } - return; - } - - /* are we actually running? */ - if (!(this_usbduxsub->pwm_cmd_running)) - return; - - urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf; - urb->dev = this_usbduxsub->usbdev; - urb->status = 0; - if (this_usbduxsub->pwm_cmd_running) { - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi_: pwm urb resubm failed in int-cont. " - "ret=%d", ret); - if (ret == EL2NSYNC) - dev_err(&this_usbduxsub->interface->dev, - "buggy USB host controller or bug in " - "IRQ handling!\n"); - - /* don't do an unlink here */ - usbdux_pwm_stop(this_usbduxsub, 0); - } - } -} - -static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub) -{ - int errFlag; - - if (!usbduxsub) - return -EFAULT; - - dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n"); - - /* in case of a resubmission after an unlink... */ - usb_fill_bulk_urb(usbduxsub->urbPwm, - usbduxsub->usbdev, - usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP), - usbduxsub->urbPwm->transfer_buffer, - usbduxsub->sizePwmBuf, usbduxsub_pwm_irq, - usbduxsub->comedidev); - - errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC); - if (errFlag) { - dev_err(&usbduxsub->interface->dev, - "comedi_: usbduxsigma: pwm: usb_submit_urb error %d\n", - errFlag); - return errFlag; - } - return 0; -} - -static int usbdux_pwm_period(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int period) -{ - struct usbduxsub *this_usbduxsub = dev->private; - int fx2delay = 255; - - if (period < MIN_PWM_PERIOD) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: illegal period setting for pwm.\n", - dev->minor); - return -EAGAIN; - } else { - fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6; - if (fx2delay > 255) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: period %d for pwm is too low.\n", - dev->minor, period); - return -EAGAIN; - } - } - this_usbduxsub->pwmDelay = fx2delay; - this_usbduxsub->pwmPeriod = period; - dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n", - __func__, period, fx2delay); - return 0; -} - -/* is called from insn so there's no need to do all the sanity checks */ -static int usbdux_pwm_start(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - int ret, i; - struct usbduxsub *this_usbduxsub = dev->private; - - dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n", - dev->minor, __func__); - - if (this_usbduxsub->pwm_cmd_running) { - /* already running */ - return 0; - } - - this_usbduxsub->dux_commands[1] = ((uint8_t) this_usbduxsub->pwmDelay); - ret = send_dux_commands(this_usbduxsub, SENDPWMON); - if (ret < 0) - return ret; - - /* initialise the buffer */ - for (i = 0; i < this_usbduxsub->sizePwmBuf; i++) - ((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0; - - this_usbduxsub->pwm_cmd_running = 1; - ret = usbduxsub_submit_PwmURBs(this_usbduxsub); - if (ret < 0) { - this_usbduxsub->pwm_cmd_running = 0; - return ret; - } - return 0; -} - -/* generates the bit pattern for PWM with the optional sign bit */ -static int usbdux_pwm_pattern(struct comedi_device *dev, - struct comedi_subdevice *s, int channel, - unsigned int value, unsigned int sign) -{ - struct usbduxsub *this_usbduxsub = dev->private; - int i, szbuf; - char *pBuf; - char pwm_mask; - char sgn_mask; - char c; - - if (!this_usbduxsub) - return -EFAULT; - - /* this is the DIO bit which carries the PWM data */ - pwm_mask = (1 << channel); - /* this is the DIO bit which carries the optional direction bit */ - sgn_mask = (16 << channel); - /* this is the buffer which will be filled with the with bit */ - /* pattern for one period */ - szbuf = this_usbduxsub->sizePwmBuf; - pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer); - for (i = 0; i < szbuf; i++) { - c = *pBuf; - /* reset bits */ - c = c & (~pwm_mask); - /* set the bit as long as the index is lower than the value */ - if (i < value) - c = c | pwm_mask; - /* set the optional sign bit for a relay */ - if (!sign) { - /* positive value */ - c = c & (~sgn_mask); - } else { - /* negative value */ - c = c | sgn_mask; - } - *(pBuf++) = c; - } - return 1; -} - -static int usbdux_pwm_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct usbduxsub *this_usbduxsub = dev->private; - - if (!this_usbduxsub) - return -EFAULT; - - if ((insn->n) != 1) { - /* - * doesn't make sense to have more than one value here because - * it would just overwrite the PWM buffer a couple of times - */ - return -EINVAL; - } - - /* - * the sign is set via a special INSN only, this gives us 8 bits for - * normal operation - * relay sign 0 by default - */ - return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec), data[0], 0); -} - -static int usbdux_pwm_read(struct comedi_device *x1, - struct comedi_subdevice *x2, struct comedi_insn *x3, - unsigned int *x4) -{ - /* not needed */ - return -EINVAL; -}; - -/* switches on/off PWM */ -static int usbdux_pwm_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct usbduxsub *this_usbduxsub = dev->private; - switch (data[0]) { - case INSN_CONFIG_ARM: - /* switch it on */ - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: %s: pwm on\n", dev->minor, __func__); - /* - * if not zero the PWM is limited to a certain time which is - * not supported here - */ - if (data[1] != 0) - return -EINVAL; - return usbdux_pwm_start(dev, s); - case INSN_CONFIG_DISARM: - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: %s: pwm off\n", dev->minor, __func__); - return usbdux_pwm_cancel(dev, s); - case INSN_CONFIG_GET_PWM_STATUS: - /* - * to check if the USB transmission has failed or in case PWM - * was limited to n cycles to check if it has terminated - */ - data[1] = this_usbduxsub->pwm_cmd_running; - return 0; - case INSN_CONFIG_PWM_SET_PERIOD: - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: %s: setting period\n", dev->minor, - __func__); - return usbdux_pwm_period(dev, s, data[1]); - case INSN_CONFIG_PWM_GET_PERIOD: - data[1] = this_usbduxsub->pwmPeriod; - return 0; - case INSN_CONFIG_PWM_SET_H_BRIDGE: - /* value in the first byte and the sign in the second for a - relay */ - return usbdux_pwm_pattern(dev, s, - /* the channel number */ - CR_CHAN(insn->chanspec), - /* actual PWM data */ - data[1], - /* just a sign */ - (data[2] != 0)); - case INSN_CONFIG_PWM_GET_H_BRIDGE: - /* values are not kept in this driver, nothing to return */ - return -EINVAL; - } - return -EINVAL; -} - -/* end of PWM */ -/*****************************************************************/ - -static void tidy_up(struct usbduxsub *usbduxsub_tmp) -{ - int i; - - if (!usbduxsub_tmp) - return; - dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n"); - - /* shows the usb subsystem that the driver is down */ - if (usbduxsub_tmp->interface) - usb_set_intfdata(usbduxsub_tmp->interface, NULL); - - usbduxsub_tmp->probed = 0; - - if (usbduxsub_tmp->urbIn) { - if (usbduxsub_tmp->ai_cmd_running) { - usbduxsub_tmp->ai_cmd_running = 0; - usbduxsub_unlink_InURBs(usbduxsub_tmp); - } - for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) { - kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer); - usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL; - usb_kill_urb(usbduxsub_tmp->urbIn[i]); - usb_free_urb(usbduxsub_tmp->urbIn[i]); - usbduxsub_tmp->urbIn[i] = NULL; - } - kfree(usbduxsub_tmp->urbIn); - usbduxsub_tmp->urbIn = NULL; - } - if (usbduxsub_tmp->urbOut) { - if (usbduxsub_tmp->ao_cmd_running) { - usbduxsub_tmp->ao_cmd_running = 0; - usbduxsub_unlink_OutURBs(usbduxsub_tmp); - } - for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) { - if (usbduxsub_tmp->urbOut[i]->transfer_buffer) { - kfree(usbduxsub_tmp-> - urbOut[i]->transfer_buffer); - usbduxsub_tmp->urbOut[i]->transfer_buffer = - NULL; - } - if (usbduxsub_tmp->urbOut[i]) { - usb_kill_urb(usbduxsub_tmp->urbOut[i]); - usb_free_urb(usbduxsub_tmp->urbOut[i]); - usbduxsub_tmp->urbOut[i] = NULL; - } - } - kfree(usbduxsub_tmp->urbOut); - usbduxsub_tmp->urbOut = NULL; - } - if (usbduxsub_tmp->urbPwm) { - if (usbduxsub_tmp->pwm_cmd_running) { - usbduxsub_tmp->pwm_cmd_running = 0; - usbduxsub_unlink_PwmURBs(usbduxsub_tmp); - } - kfree(usbduxsub_tmp->urbPwm->transfer_buffer); - usbduxsub_tmp->urbPwm->transfer_buffer = NULL; - usb_kill_urb(usbduxsub_tmp->urbPwm); - usb_free_urb(usbduxsub_tmp->urbPwm); - usbduxsub_tmp->urbPwm = NULL; - } - kfree(usbduxsub_tmp->inBuffer); - usbduxsub_tmp->inBuffer = NULL; - kfree(usbduxsub_tmp->insnBuffer); - usbduxsub_tmp->insnBuffer = NULL; - kfree(usbduxsub_tmp->outBuffer); - usbduxsub_tmp->outBuffer = NULL; - kfree(usbduxsub_tmp->dac_commands); - usbduxsub_tmp->dac_commands = NULL; - kfree(usbduxsub_tmp->dux_commands); - usbduxsub_tmp->dux_commands = NULL; - usbduxsub_tmp->ai_cmd_running = 0; - usbduxsub_tmp->ao_cmd_running = 0; - usbduxsub_tmp->pwm_cmd_running = 0; -} - -static void usbdux_firmware_request_complete_handler(const struct firmware *fw, - void *context) -{ - struct usbduxsub *usbduxsub_tmp = context; - struct usb_device *usbdev = usbduxsub_tmp->usbdev; - int ret; - - if (fw == NULL) { - dev_err(&usbdev->dev, - "Firmware complete handler without firmware!\n"); - return; - } - - /* - * we need to upload the firmware here because fw will be - * freed once we've left this function - */ - ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size); - - if (ret) { - dev_err(&usbdev->dev, - "Could not upload firmware (err=%d)\n", ret); - goto out; - } - comedi_usb_auto_config(usbdev, BOARDNAME); -out: - release_firmware(fw); -} - -/* allocate memory for the urbs and initialise them */ -static int usbduxsigma_probe(struct usb_interface *uinterf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(uinterf); - struct device *dev = &uinterf->dev; - int i; - int index; - int ret; - - dev_dbg(dev, "comedi_: usbdux_: " - "finding a free structure for the usb-device\n"); - - down(&start_stop_sem); - /* look for a free place in the usbdux array */ - index = -1; - for (i = 0; i < NUMUSBDUX; i++) { - if (!(usbduxsub[i].probed)) { - index = i; - break; - } - } - - /* no more space */ - if (index == -1) { - dev_err(dev, "Too many usbduxsigma-devices connected.\n"); - up(&start_stop_sem); - return -EMFILE; - } - dev_dbg(dev, "comedi_: usbdux: " - "usbduxsub[%d] is ready to connect to comedi.\n", index); - - sema_init(&(usbduxsub[index].sem), 1); - /* save a pointer to the usb device */ - usbduxsub[index].usbdev = udev; - - /* save the interface itself */ - usbduxsub[index].interface = uinterf; - /* get the interface number from the interface */ - usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber; - /* hand the private data over to the usb subsystem */ - /* will be needed for disconnect */ - usb_set_intfdata(uinterf, &(usbduxsub[index])); - - dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum); - - /* test if it is high speed (USB 2.0) */ - usbduxsub[index].high_speed = - (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH); - - /* create space for the commands of the DA converter */ - usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL); - if (!usbduxsub[index].dac_commands) { - dev_err(dev, "comedi_: usbduxsigma: " - "error alloc space for dac commands\n"); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - /* create space for the commands going to the usb device */ - usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); - if (!usbduxsub[index].dux_commands) { - dev_err(dev, "comedi_: usbduxsigma: " - "error alloc space for dux commands\n"); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - /* create space for the in buffer and set it to zero */ - usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL); - if (!(usbduxsub[index].inBuffer)) { - dev_err(dev, "comedi_: usbduxsigma: " - "could not alloc space for inBuffer\n"); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - /* create space of the instruction buffer */ - usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL); - if (!(usbduxsub[index].insnBuffer)) { - dev_err(dev, "comedi_: usbduxsigma: " - "could not alloc space for insnBuffer\n"); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - /* create space for the outbuffer */ - usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); - if (!(usbduxsub[index].outBuffer)) { - dev_err(dev, "comedi_: usbduxsigma: " - "could not alloc space for outBuffer\n"); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - /* setting to alternate setting 3: enabling iso ep and bulk ep. */ - i = usb_set_interface(usbduxsub[index].usbdev, - usbduxsub[index].ifnum, 3); - if (i < 0) { - dev_err(dev, "comedi_: usbduxsigma%d: " - "could not set alternate setting 3 in high speed.\n", - index); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENODEV; - } - if (usbduxsub[index].high_speed) - usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH; - else - usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL; - - usbduxsub[index].urbIn = - kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfInBuffers, - GFP_KERNEL); - if (!(usbduxsub[index].urbIn)) { - dev_err(dev, "comedi_: usbduxsigma: " - "Could not alloc. urbIn array\n"); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) { - /* one frame: 1ms */ - usbduxsub[index].urbIn[i] = usb_alloc_urb(1, GFP_KERNEL); - if (usbduxsub[index].urbIn[i] == NULL) { - dev_err(dev, "comedi_: usbduxsigma%d: " - "Could not alloc. urb(%d)\n", index, i); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev; - /* will be filled later with a pointer to the comedi-device */ - /* and ONLY then the urb should be submitted */ - usbduxsub[index].urbIn[i]->context = NULL; - usbduxsub[index].urbIn[i]->pipe = - usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP); - usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP; - usbduxsub[index].urbIn[i]->transfer_buffer = - kzalloc(SIZEINBUF, GFP_KERNEL); - if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) { - dev_err(dev, "comedi_: usbduxsigma%d: " - "could not alloc. transb.\n", index); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq; - usbduxsub[index].urbIn[i]->number_of_packets = 1; - usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF; - usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0; - usbduxsub[index].urbIn[i]->iso_frame_desc[0].length = - SIZEINBUF; - } - - /* out */ - if (usbduxsub[index].high_speed) - usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH; - else - usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL; - - usbduxsub[index].urbOut = - kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfOutBuffers, - GFP_KERNEL); - if (!(usbduxsub[index].urbOut)) { - dev_err(dev, "comedi_: usbduxsigma: " - "Could not alloc. urbOut array\n"); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) { - /* one frame: 1ms */ - usbduxsub[index].urbOut[i] = usb_alloc_urb(1, GFP_KERNEL); - if (usbduxsub[index].urbOut[i] == NULL) { - dev_err(dev, "comedi_: usbduxsigma%d: " - "Could not alloc. urb(%d)\n", index, i); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev; - /* will be filled later with a pointer to the comedi-device */ - /* and ONLY then the urb should be submitted */ - usbduxsub[index].urbOut[i]->context = NULL; - usbduxsub[index].urbOut[i]->pipe = - usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP); - usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP; - usbduxsub[index].urbOut[i]->transfer_buffer = - kzalloc(SIZEOUTBUF, GFP_KERNEL); - if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) { - dev_err(dev, "comedi_: usbduxsigma%d: " - "could not alloc. transb.\n", index); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq; - usbduxsub[index].urbOut[i]->number_of_packets = 1; - usbduxsub[index].urbOut[i]->transfer_buffer_length = - SIZEOUTBUF; - usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0; - usbduxsub[index].urbOut[i]->iso_frame_desc[0].length = - SIZEOUTBUF; - if (usbduxsub[index].high_speed) { - /* uframes */ - usbduxsub[index].urbOut[i]->interval = 8; - } else { - /* frames */ - usbduxsub[index].urbOut[i]->interval = 1; - } - } - - /* pwm */ - if (usbduxsub[index].high_speed) { - /* max bulk ep size in high speed */ - usbduxsub[index].sizePwmBuf = 512; - usbduxsub[index].urbPwm = usb_alloc_urb(0, GFP_KERNEL); - if (usbduxsub[index].urbPwm == NULL) { - dev_err(dev, "comedi_: usbduxsigma%d: " - "Could not alloc. pwm urb\n", index); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - usbduxsub[index].urbPwm->transfer_buffer = - kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL); - if (!(usbduxsub[index].urbPwm->transfer_buffer)) { - dev_err(dev, "comedi_: usbduxsigma%d: " - "could not alloc. transb. for pwm\n", index); - tidy_up(&(usbduxsub[index])); - up(&start_stop_sem); - return -ENOMEM; - } - } else { - usbduxsub[index].urbPwm = NULL; - usbduxsub[index].sizePwmBuf = 0; - } - - usbduxsub[index].ai_cmd_running = 0; - usbduxsub[index].ao_cmd_running = 0; - usbduxsub[index].pwm_cmd_running = 0; - - /* we've reached the bottom of the function */ - usbduxsub[index].probed = 1; - up(&start_stop_sem); - - ret = request_firmware_nowait(THIS_MODULE, - FW_ACTION_HOTPLUG, - "usbduxsigma_firmware.bin", - &udev->dev, - GFP_KERNEL, - usbduxsub + index, - usbdux_firmware_request_complete_handler - ); - - if (ret) { - dev_err(dev, "Could not load firmware (err=%d)\n", ret); - return ret; - } - - dev_info(dev, "comedi_: successfully initialised.\n"); - /* success */ - return 0; -} - -static void usbduxsigma_disconnect(struct usb_interface *intf) -{ - struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf); - struct usb_device *udev = interface_to_usbdev(intf); - - if (!usbduxsub_tmp) { - dev_err(&intf->dev, - "comedi_: disconnect called with null pointer.\n"); - return; - } - if (usbduxsub_tmp->usbdev != udev) { - dev_err(&intf->dev, "comedi_: BUG! wrong ptr!\n"); - return; - } - if (usbduxsub_tmp->ai_cmd_running) - /* we are still running a command */ - usbdux_ai_stop(usbduxsub_tmp, 1); - if (usbduxsub_tmp->ao_cmd_running) - /* we are still running a command */ - usbdux_ao_stop(usbduxsub_tmp, 1); - comedi_usb_auto_unconfig(udev); - down(&start_stop_sem); - down(&usbduxsub_tmp->sem); - tidy_up(usbduxsub_tmp); - up(&usbduxsub_tmp->sem); - up(&start_stop_sem); - dev_info(&intf->dev, "comedi_: disconnected from the usb\n"); -} - -/* is called when comedi-config is called */ -static int usbduxsigma_attach(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - int ret; - int index; - int i; - struct usbduxsub *udev; - - int offset; - - struct comedi_subdevice *s = NULL; - dev->private = NULL; - - down(&start_stop_sem); - /* find a valid device which has been detected by the probe function of - * the usb */ - index = -1; - for (i = 0; i < NUMUSBDUX; i++) { - if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) { - index = i; - break; - } - } - - if (index < 0) { - printk(KERN_ERR "comedi%d: usbduxsigma: error: attach failed," - "dev not connected to the usb bus.\n", dev->minor); - up(&start_stop_sem); - return -ENODEV; - } - - udev = &usbduxsub[index]; - down(&udev->sem); - /* pointer back to the corresponding comedi device */ - udev->comedidev = dev; - - /* trying to upload the firmware into the FX2 */ - if (comedi_aux_data(it->options, 0) && - it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { - firmwareUpload(udev, comedi_aux_data(it->options, 0), - it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]); - } - - dev->board_name = BOARDNAME; - - /* set number of subdevices */ - if (udev->high_speed) { - /* with pwm */ - dev->n_subdevices = 4; - } else { - /* without pwm */ - dev->n_subdevices = 3; - } - - /* allocate space for the subdevices */ - ret = alloc_subdevices(dev, dev->n_subdevices); - if (ret < 0) { - dev_err(&udev->interface->dev, - "comedi%d: no space for subdev\n", dev->minor); - up(&start_stop_sem); - return ret; - } - - /* private structure is also simply the usb-structure */ - dev->private = udev; - - /* the first subdevice is the A/D converter */ - s = dev->subdevices + SUBDEV_AD; - /* the URBs get the comedi subdevice */ - /* which is responsible for reading */ - /* this is the subdevice which reads data */ - dev->read_subdev = s; - /* the subdevice receives as private structure the */ - /* usb-structure */ - s->private = NULL; - /* analog input */ - s->type = COMEDI_SUBD_AI; - /* readable and ref is to ground, 32 bit wide data! */ - s->subdev_flags = SDF_READABLE | SDF_GROUND | - SDF_CMD_READ | SDF_LSAMPL; - /* 16 A/D channels */ - s->n_chan = NUMCHANNELS; - /* length of the channellist */ - s->len_chanlist = NUMCHANNELS; - /* callback functions */ - s->insn_read = usbdux_ai_insn_read; - s->do_cmdtest = usbdux_ai_cmdtest; - s->do_cmd = usbdux_ai_cmd; - s->cancel = usbdux_ai_cancel; - /* max value from the A/D converter (24bit) */ - s->maxdata = 0x00FFFFFF; - /* range table to convert to physical units */ - s->range_table = (&range_usbdux_ai_range); - - /* analog out */ - s = dev->subdevices + SUBDEV_DA; - /* analog out */ - s->type = COMEDI_SUBD_AO; - /* backward pointer */ - dev->write_subdev = s; - /* the subdevice receives as private structure the */ - /* usb-structure */ - s->private = NULL; - /* are writable */ - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; - /* 4 channels */ - s->n_chan = 4; - /* length of the channellist */ - s->len_chanlist = 4; - /* 8 bit resolution */ - s->maxdata = 0x00ff; - /* unipolar range */ - s->range_table = (&range_usbdux_ao_range); - /* callback */ - s->do_cmdtest = usbdux_ao_cmdtest; - s->do_cmd = usbdux_ao_cmd; - s->cancel = usbdux_ao_cancel; - s->insn_read = usbdux_ao_insn_read; - s->insn_write = usbdux_ao_insn_write; - - /* digital I/O */ - s = dev->subdevices + SUBDEV_DIO; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - /* 8 external and 16 internal channels */ - s->n_chan = 24; - s->maxdata = 1; - s->range_table = (&range_digital); - s->insn_bits = usbdux_dio_insn_bits; - s->insn_config = usbdux_dio_insn_config; - /* we don't use it */ - s->private = NULL; - - if (udev->high_speed) { - /* timer / pwm */ - s = dev->subdevices + SUBDEV_PWM; - s->type = COMEDI_SUBD_PWM; - s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; - s->n_chan = 8; - /* this defines the max duty cycle resolution */ - s->maxdata = udev->sizePwmBuf; - s->insn_write = usbdux_pwm_write; - s->insn_read = usbdux_pwm_read; - s->insn_config = usbdux_pwm_config; - usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD); - } - /* finally decide that it's attached */ - udev->attached = 1; - - up(&udev->sem); - - up(&start_stop_sem); - - offset = usbdux_getstatusinfo(dev, 0); - if (offset < 0) - dev_err(&udev->interface->dev, - "Communication to USBDUXSIGMA failed!" - "Check firmware and cabling."); - - dev_info(&udev->interface->dev, - "comedi%d: attached, ADC_zero = %x", dev->minor, offset); - - return 0; -} - -static int usbduxsigma_detach(struct comedi_device *dev) -{ - struct usbduxsub *usbduxsub_tmp; - - if (!dev) { - printk(KERN_ERR - "comedi? usbduxsigma detach: dev=NULL\n"); - return -EFAULT; - } - - usbduxsub_tmp = dev->private; - if (!usbduxsub_tmp) { - printk(KERN_ERR - "comedi?: usbduxsigma detach: private=NULL\n"); - return -EFAULT; - } - - dev_dbg(&usbduxsub_tmp->interface->dev, - "comedi%d: detach usb device\n", - dev->minor); - - down(&usbduxsub_tmp->sem); - /* Don't allow detach to free the private structure */ - /* It's one entry of of usbduxsub[] */ - dev->private = NULL; - usbduxsub_tmp->attached = 0; - usbduxsub_tmp->comedidev = NULL; - dev_info(&usbduxsub_tmp->interface->dev, - "comedi%d: successfully detached.\n", dev->minor); - up(&usbduxsub_tmp->sem); - return 0; -} - -/* main driver struct */ -static struct comedi_driver driver_usbduxsigma = { - .driver_name = "usbduxsigma", - .module = THIS_MODULE, - .attach = usbduxsigma_attach, - .detach = usbduxsigma_detach, -}; - -/* Table with the USB-devices */ -static const struct usb_device_id usbduxsigma_table[] = { - {USB_DEVICE(0x13d8, 0x0020)}, - {USB_DEVICE(0x13d8, 0x0021)}, - {USB_DEVICE(0x13d8, 0x0022)}, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, usbduxsigma_table); - -/* The usbduxsub-driver */ -static struct usb_driver usbduxsigma_driver = { - .name = BOARDNAME, - .probe = usbduxsigma_probe, - .disconnect = usbduxsigma_disconnect, - .id_table = usbduxsigma_table, -}; - -/* Can't use the nice macro as I have also to initialise the USB */ -/* subsystem: */ -/* registering the usb-system _and_ the comedi-driver */ -static int __init init_usbduxsigma(void) -{ - printk(KERN_INFO KBUILD_MODNAME ": " - DRIVER_VERSION ":" DRIVER_DESC "\n"); - usb_register(&usbduxsigma_driver); - comedi_driver_register(&driver_usbduxsigma); - return 0; -} - -/* deregistering the comedi driver and the usb-subsystem */ -static void __exit exit_usbduxsigma(void) -{ - comedi_driver_unregister(&driver_usbduxsigma); - usb_deregister(&usbduxsigma_driver); -} - -module_init(init_usbduxsigma); -module_exit(exit_usbduxsigma); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/cxd2099/Makefile b/trunk/drivers/staging/cxd2099/Makefile index 64cfc77be357..72b14558c119 100644 --- a/trunk/drivers/staging/cxd2099/Makefile +++ b/trunk/drivers/staging/cxd2099/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_DVB_CXD2099) += cxd2099.o -ccflags-y += -Idrivers/media/dvb/dvb-core/ -ccflags-y += -Idrivers/media/dvb/frontends/ -ccflags-y += -Idrivers/media/common/tuners/ +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/ +EXTRA_CFLAGS += -Idrivers/media/common/tuners/ diff --git a/trunk/drivers/staging/easycap/easycap_ioctl.c b/trunk/drivers/staging/easycap/easycap_ioctl.c index 91262fbd69e2..0accab97a7f6 100644 --- a/trunk/drivers/staging/easycap/easycap_ioctl.c +++ b/trunk/drivers/staging/easycap/easycap_ioctl.c @@ -1317,12 +1317,17 @@ long easycap_unlocked_ioctl(struct file *file, struct v4l2_control *pv4l2_control; JOM(8, "VIDIOC_G_CTRL\n"); - pv4l2_control = memdup_user((void __user *)arg, - sizeof(struct v4l2_control)); - if (IS_ERR(pv4l2_control)) { - SAM("ERROR: copy from user failed\n"); + pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL); + if (!pv4l2_control) { + SAM("ERROR: out of memory\n"); mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return PTR_ERR(pv4l2_control); + return -ENOMEM; + } + if (0 != copy_from_user(pv4l2_control, (void __user *)arg, + sizeof(struct v4l2_control))) { + kfree(pv4l2_control); + mutex_unlock(&easycapdc60_dongle[kd].mutex_video); + return -EFAULT; } switch (pv4l2_control->id) { @@ -2351,12 +2356,17 @@ long easycap_unlocked_ioctl(struct file *file, struct v4l2_streamparm *pv4l2_streamparm; JOM(8, "VIDIOC_G_PARM\n"); - pv4l2_streamparm = memdup_user((void __user *)arg, - sizeof(struct v4l2_streamparm)); - if (IS_ERR(pv4l2_streamparm)) { - SAM("ERROR: copy from user failed\n"); + pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL); + if (!pv4l2_streamparm) { + SAM("ERROR: out of memory\n"); + mutex_unlock(&easycapdc60_dongle[kd].mutex_video); + return -ENOMEM; + } + if (copy_from_user(pv4l2_streamparm, + (void __user *)arg, sizeof(struct v4l2_streamparm))) { + kfree(pv4l2_streamparm); mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return PTR_ERR(pv4l2_streamparm); + return -EFAULT; } if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { diff --git a/trunk/drivers/staging/et131x/et1310_eeprom.c b/trunk/drivers/staging/et131x/et1310_eeprom.c index e8102547e133..237584001a8f 100644 --- a/trunk/drivers/staging/et131x/et1310_eeprom.c +++ b/trunk/drivers/staging/et131x/et1310_eeprom.c @@ -150,15 +150,15 @@ static int eeprom_wait_ready(struct pci_dev *pdev, u32 *status) /** * eeprom_write - Write a byte to the ET1310's EEPROM - * @adapter: pointer to our private adapter structure + * @etdev: pointer to our private adapter structure * @addr: the address to write * @data: the value to write * * Returns 1 for a successful write. */ -static int eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data) +static int eeprom_write(struct et131x_adapter *etdev, u32 addr, u8 data) { - struct pci_dev *pdev = adapter->pdev; + struct pci_dev *pdev = etdev->pdev; int index = 0; int retries; int err = 0; @@ -222,7 +222,7 @@ static int eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data) * 1, this is so we do a blind write for load bug. */ if ((status & LBCIF_STATUS_GENERAL_ERROR) - && adapter->pdev->revision == 0) + && etdev->pdev->revision == 0) break; /* @@ -280,7 +280,7 @@ static int eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data) /** * eeprom_read - Read a byte from the ET1310's EEPROM - * @adapter: pointer to our private adapter structure + * @etdev: pointer to our private adapter structure * @addr: the address from which to read * @pdata: a pointer to a byte in which to store the value of the read * @eeprom_id: the ID of the EEPROM @@ -288,9 +288,9 @@ static int eeprom_write(struct et131x_adapter *adapter, u32 addr, u8 data) * * Returns 1 for a successful read */ -static int eeprom_read(struct et131x_adapter *adapter, u32 addr, u8 *pdata) +static int eeprom_read(struct et131x_adapter *etdev, u32 addr, u8 *pdata) { - struct pci_dev *pdev = adapter->pdev; + struct pci_dev *pdev = etdev->pdev; int err; u32 status; @@ -337,9 +337,9 @@ static int eeprom_read(struct et131x_adapter *adapter, u32 addr, u8 *pdata) return (status & LBCIF_STATUS_ACK_ERROR) ? -EIO : 0; } -int et131x_init_eeprom(struct et131x_adapter *adapter) +int et131x_init_eeprom(struct et131x_adapter *etdev) { - struct pci_dev *pdev = adapter->pdev; + struct pci_dev *pdev = etdev->pdev; u8 eestatus; /* We first need to check the EEPROM Status code located at offset @@ -374,7 +374,7 @@ int et131x_init_eeprom(struct et131x_adapter *adapter) * corruption seen with 1310 B Silicon */ for (i = 0; i < 3; i++) - if (eeprom_write(adapter, i, eedata[i]) < 0) + if (eeprom_write(etdev, i, eedata[i]) < 0) write_failed = 1; } if (pdev->revision != 0x01 || write_failed) { @@ -387,21 +387,21 @@ int et131x_init_eeprom(struct et131x_adapter *adapter) * gather additional information that normally would * come from the eeprom, like MAC Address */ - adapter->has_eeprom = 0; + etdev->has_eeprom = 0; return -EIO; } } - adapter->has_eeprom = 1; + etdev->has_eeprom = 1; /* Read the EEPROM for information regarding LED behavior. Refer to * ET1310_phy.c, et131x_xcvr_init(), for its use. */ - eeprom_read(adapter, 0x70, &adapter->eeprom_data[0]); - eeprom_read(adapter, 0x71, &adapter->eeprom_data[1]); + eeprom_read(etdev, 0x70, &etdev->eeprom_data[0]); + eeprom_read(etdev, 0x71, &etdev->eeprom_data[1]); - if (adapter->eeprom_data[0] != 0xcd) + if (etdev->eeprom_data[0] != 0xcd) /* Disable all optional features */ - adapter->eeprom_data[1] = 0x00; + etdev->eeprom_data[1] = 0x00; return 0; } diff --git a/trunk/drivers/staging/et131x/et1310_mac.c b/trunk/drivers/staging/et131x/et1310_mac.c index ab85cb3babdc..656be4b99cf6 100644 --- a/trunk/drivers/staging/et131x/et1310_mac.c +++ b/trunk/drivers/staging/et131x/et1310_mac.c @@ -99,12 +99,12 @@ #define COUNTER_MASK_12_BIT (COUNTER_WRAP_12_BIT - 1) /** - * et1310_config_mac_regs1 - Initialize the first part of MAC regs - * @adapter: pointer to our adapter structure + * ConfigMacRegs1 - Initialize the first part of MAC regs + * @pAdpater: pointer to our adapter structure */ -void et1310_config_mac_regs1(struct et131x_adapter *adapter) +void ConfigMACRegs1(struct et131x_adapter *etdev) { - struct mac_regs __iomem *macregs = &adapter->regs->mac; + struct mac_regs __iomem *pMac = &etdev->regs->mac; u32 station1; u32 station2; u32 ipg; @@ -112,22 +112,22 @@ void et1310_config_mac_regs1(struct et131x_adapter *adapter) /* First we need to reset everything. Write to MAC configuration * register 1 to perform reset. */ - writel(0xC00F0000, ¯egs->cfg1); + writel(0xC00F0000, &pMac->cfg1); /* Next lets configure the MAC Inter-packet gap register */ ipg = 0x38005860; /* IPG1 0x38 IPG2 0x58 B2B 0x60 */ ipg |= 0x50 << 8; /* ifg enforce 0x50 */ - writel(ipg, ¯egs->ipg); + writel(ipg, &pMac->ipg); /* Next lets configure the MAC Half Duplex register */ /* BEB trunc 0xA, Ex Defer, Rexmit 0xF Coll 0x37 */ - writel(0x00A1F037, ¯egs->hfdp); + writel(0x00A1F037, &pMac->hfdp); /* Next lets configure the MAC Interface Control register */ - writel(0, ¯egs->if_ctrl); + writel(0, &pMac->if_ctrl); /* Let's move on to setting up the mii management configuration */ - writel(0x07, ¯egs->mii_mgmt_cfg); /* Clock reset 0x7 */ + writel(0x07, &pMac->mii_mgmt_cfg); /* Clock reset 0x7 */ /* Next lets configure the MAC Station Address register. These * values are read from the EEPROM during initialization and stored @@ -136,49 +136,49 @@ void et1310_config_mac_regs1(struct et131x_adapter *adapter) * station address is used for generating and checking pause control * packets. */ - station2 = (adapter->addr[1] << ET_MAC_STATION_ADDR2_OC2_SHIFT) | - (adapter->addr[0] << ET_MAC_STATION_ADDR2_OC1_SHIFT); - station1 = (adapter->addr[5] << ET_MAC_STATION_ADDR1_OC6_SHIFT) | - (adapter->addr[4] << ET_MAC_STATION_ADDR1_OC5_SHIFT) | - (adapter->addr[3] << ET_MAC_STATION_ADDR1_OC4_SHIFT) | - adapter->addr[2]; - writel(station1, ¯egs->station_addr_1); - writel(station2, ¯egs->station_addr_2); + station2 = (etdev->addr[1] << ET_MAC_STATION_ADDR2_OC2_SHIFT) | + (etdev->addr[0] << ET_MAC_STATION_ADDR2_OC1_SHIFT); + station1 = (etdev->addr[5] << ET_MAC_STATION_ADDR1_OC6_SHIFT) | + (etdev->addr[4] << ET_MAC_STATION_ADDR1_OC5_SHIFT) | + (etdev->addr[3] << ET_MAC_STATION_ADDR1_OC4_SHIFT) | + etdev->addr[2]; + writel(station1, &pMac->station_addr_1); + writel(station2, &pMac->station_addr_2); /* Max ethernet packet in bytes that will passed by the mac without * being truncated. Allow the MAC to pass 4 more than our max packet * size. This is 4 for the Ethernet CRC. * - * Packets larger than (registry_jumbo_packet) that do not contain a + * Packets larger than (RegistryJumboPacket) that do not contain a * VLAN ID will be dropped by the Rx function. */ - writel(adapter->registry_jumbo_packet + 4, ¯egs->max_fm_len); + writel(etdev->RegistryJumboPacket + 4, &pMac->max_fm_len); /* clear out MAC config reset */ - writel(0, ¯egs->cfg1); + writel(0, &pMac->cfg1); } /** - * et1310_config_mac_regs2 - Initialize the second part of MAC regs - * @adapter: pointer to our adapter structure + * ConfigMacRegs2 - Initialize the second part of MAC regs + * @pAdpater: pointer to our adapter structure */ -void et1310_config_mac_regs2(struct et131x_adapter *adapter) +void ConfigMACRegs2(struct et131x_adapter *etdev) { int32_t delay = 0; - struct mac_regs __iomem *mac = &adapter->regs->mac; + struct mac_regs __iomem *pMac = &etdev->regs->mac; u32 cfg1; u32 cfg2; u32 ifctrl; u32 ctl; - ctl = readl(&adapter->regs->txmac.ctl); - cfg1 = readl(&mac->cfg1); - cfg2 = readl(&mac->cfg2); - ifctrl = readl(&mac->if_ctrl); + ctl = readl(&etdev->regs->txmac.ctl); + cfg1 = readl(&pMac->cfg1); + cfg2 = readl(&pMac->cfg2); + ifctrl = readl(&pMac->if_ctrl); /* Set up the if mode bits */ cfg2 &= ~0x300; - if (adapter->linkspeed == TRUEPHY_SPEED_1000MBPS) { + if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS) { cfg2 |= 0x200; /* Phy mode bit */ ifctrl &= ~(1 << 24); @@ -188,12 +188,12 @@ void et1310_config_mac_regs2(struct et131x_adapter *adapter) } /* We need to enable Rx/Tx */ - cfg1 |= CFG1_RX_ENABLE | CFG1_TX_ENABLE | CFG1_TX_FLOW; + cfg1 |= CFG1_RX_ENABLE|CFG1_TX_ENABLE|CFG1_TX_FLOW; /* Initialize loop back to off */ - cfg1 &= ~(CFG1_LOOPBACK | CFG1_RX_FLOW); - if (adapter->flowcontrol == FLOW_RXONLY || adapter->flowcontrol == FLOW_BOTH) + cfg1 &= ~(CFG1_LOOPBACK|CFG1_RX_FLOW); + if (etdev->flowcontrol == FLOW_RXONLY || etdev->flowcontrol == FLOW_BOTH) cfg1 |= CFG1_RX_FLOW; - writel(cfg1, &mac->cfg1); + writel(cfg1, &pMac->cfg1); /* Now we need to initialize the MAC Configuration 2 register */ /* preamble 7, check length, huge frame off, pad crc, crc enable @@ -202,118 +202,118 @@ void et1310_config_mac_regs2(struct et131x_adapter *adapter) cfg2 &= ~0x0021; /* Turn on duplex if needed */ - if (adapter->duplex_mode) + if (etdev->duplex_mode) cfg2 |= 0x01; ifctrl &= ~(1 << 26); - if (!adapter->duplex_mode) + if (!etdev->duplex_mode) ifctrl |= (1<<26); /* Enable ghd */ - writel(ifctrl, &mac->if_ctrl); - writel(cfg2, &mac->cfg2); + writel(ifctrl, &pMac->if_ctrl); + writel(cfg2, &pMac->cfg2); do { udelay(10); delay++; - cfg1 = readl(&mac->cfg1); + cfg1 = readl(&pMac->cfg1); } while ((cfg1 & CFG1_WAIT) != CFG1_WAIT && delay < 100); if (delay == 100) { - dev_warn(&adapter->pdev->dev, + dev_warn(&etdev->pdev->dev, "Syncd bits did not respond correctly cfg1 word 0x%08x\n", cfg1); } - /* Enable txmac */ + /* Enable TXMAC */ ctl |= 0x09; /* TX mac enable, FC disable */ - writel(ctl, &adapter->regs->txmac.ctl); + writel(ctl, &etdev->regs->txmac.ctl); /* Ready to start the RXDMA/TXDMA engine */ - if (adapter->flags & fMP_ADAPTER_LOWER_POWER) { - et131x_rx_dma_enable(adapter); - et131x_tx_dma_enable(adapter); + if (etdev->flags & fMP_ADAPTER_LOWER_POWER) { + et131x_rx_dma_enable(etdev); + et131x_tx_dma_enable(etdev); } } -void et1310_config_rxmac_regs(struct et131x_adapter *adapter) +void ConfigRxMacRegs(struct et131x_adapter *etdev) { - struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac; + struct rxmac_regs __iomem *pRxMac = &etdev->regs->rxmac; u32 sa_lo; u32 sa_hi = 0; u32 pf_ctrl = 0; /* Disable the MAC while it is being configured (also disable WOL) */ - writel(0x8, &rxmac->ctrl); + writel(0x8, &pRxMac->ctrl); /* Initialize WOL to disabled. */ - writel(0, &rxmac->crc0); - writel(0, &rxmac->crc12); - writel(0, &rxmac->crc34); + writel(0, &pRxMac->crc0); + writel(0, &pRxMac->crc12); + writel(0, &pRxMac->crc34); /* We need to set the WOL mask0 - mask4 next. We initialize it to * its default Values of 0x00000000 because there are not WOL masks * as of this time. */ - writel(0, &rxmac->mask0_word0); - writel(0, &rxmac->mask0_word1); - writel(0, &rxmac->mask0_word2); - writel(0, &rxmac->mask0_word3); - - writel(0, &rxmac->mask1_word0); - writel(0, &rxmac->mask1_word1); - writel(0, &rxmac->mask1_word2); - writel(0, &rxmac->mask1_word3); - - writel(0, &rxmac->mask2_word0); - writel(0, &rxmac->mask2_word1); - writel(0, &rxmac->mask2_word2); - writel(0, &rxmac->mask2_word3); - - writel(0, &rxmac->mask3_word0); - writel(0, &rxmac->mask3_word1); - writel(0, &rxmac->mask3_word2); - writel(0, &rxmac->mask3_word3); - - writel(0, &rxmac->mask4_word0); - writel(0, &rxmac->mask4_word1); - writel(0, &rxmac->mask4_word2); - writel(0, &rxmac->mask4_word3); + writel(0, &pRxMac->mask0_word0); + writel(0, &pRxMac->mask0_word1); + writel(0, &pRxMac->mask0_word2); + writel(0, &pRxMac->mask0_word3); + + writel(0, &pRxMac->mask1_word0); + writel(0, &pRxMac->mask1_word1); + writel(0, &pRxMac->mask1_word2); + writel(0, &pRxMac->mask1_word3); + + writel(0, &pRxMac->mask2_word0); + writel(0, &pRxMac->mask2_word1); + writel(0, &pRxMac->mask2_word2); + writel(0, &pRxMac->mask2_word3); + + writel(0, &pRxMac->mask3_word0); + writel(0, &pRxMac->mask3_word1); + writel(0, &pRxMac->mask3_word2); + writel(0, &pRxMac->mask3_word3); + + writel(0, &pRxMac->mask4_word0); + writel(0, &pRxMac->mask4_word1); + writel(0, &pRxMac->mask4_word2); + writel(0, &pRxMac->mask4_word3); /* Lets setup the WOL Source Address */ - sa_lo = (adapter->addr[2] << ET_WOL_LO_SA3_SHIFT) | - (adapter->addr[3] << ET_WOL_LO_SA4_SHIFT) | - (adapter->addr[4] << ET_WOL_LO_SA5_SHIFT) | - adapter->addr[5]; - writel(sa_lo, &rxmac->sa_lo); + sa_lo = (etdev->addr[2] << ET_WOL_LO_SA3_SHIFT) | + (etdev->addr[3] << ET_WOL_LO_SA4_SHIFT) | + (etdev->addr[4] << ET_WOL_LO_SA5_SHIFT) | + etdev->addr[5]; + writel(sa_lo, &pRxMac->sa_lo); - sa_hi = (u32) (adapter->addr[0] << ET_WOL_HI_SA1_SHIFT) | - adapter->addr[1]; - writel(sa_hi, &rxmac->sa_hi); + sa_hi = (u32) (etdev->addr[0] << ET_WOL_HI_SA1_SHIFT) | + etdev->addr[1]; + writel(sa_hi, &pRxMac->sa_hi); /* Disable all Packet Filtering */ - writel(0, &rxmac->pf_ctrl); + writel(0, &pRxMac->pf_ctrl); /* Let's initialize the Unicast Packet filtering address */ - if (adapter->packet_filter & ET131X_PACKET_TYPE_DIRECTED) { - et1310_setup_device_for_unicast(adapter); + if (etdev->PacketFilter & ET131X_PACKET_TYPE_DIRECTED) { + SetupDeviceForUnicast(etdev); pf_ctrl |= 4; /* Unicast filter */ } else { - writel(0, &rxmac->uni_pf_addr1); - writel(0, &rxmac->uni_pf_addr2); - writel(0, &rxmac->uni_pf_addr3); + writel(0, &pRxMac->uni_pf_addr1); + writel(0, &pRxMac->uni_pf_addr2); + writel(0, &pRxMac->uni_pf_addr3); } /* Let's initialize the Multicast hash */ - if (!(adapter->packet_filter & ET131X_PACKET_TYPE_ALL_MULTICAST)) { + if (!(etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST)) { pf_ctrl |= 2; /* Multicast filter */ - et1310_setup_device_for_multicast(adapter); + SetupDeviceForMulticast(etdev); } /* Runt packet filtering. Didn't work in version A silicon. */ pf_ctrl |= (NIC_MIN_PACKET_SIZE + 4) << 16; pf_ctrl |= 8; /* Fragment filter */ - if (adapter->registry_jumbo_packet > 8192) + if (etdev->RegistryJumboPacket > 8192) /* In order to transmit jumbo packets greater than 8k, the * FIFO between RxMAC and RxDMA needs to be reduced in size * to (16k - Jumbo packet size). In order to implement this, @@ -324,18 +324,18 @@ void et1310_config_rxmac_regs(struct et131x_adapter *adapter) * * seg_en on, fc_en off, size 0x10 */ - writel(0x41, &rxmac->mcif_ctrl_max_seg); + writel(0x41, &pRxMac->mcif_ctrl_max_seg); else - writel(0, &rxmac->mcif_ctrl_max_seg); + writel(0, &pRxMac->mcif_ctrl_max_seg); /* Initialize the MCIF water marks */ - writel(0, &rxmac->mcif_water_mark); + writel(0, &pRxMac->mcif_water_mark); /* Initialize the MIF control */ - writel(0, &rxmac->mif_ctrl); + writel(0, &pRxMac->mif_ctrl); /* Initialize the Space Available Register */ - writel(0, &rxmac->space_avail); + writel(0, &pRxMac->space_avail); /* Initialize the the mif_ctrl register * bit 3: Receive code error. One or more nibbles were signaled as @@ -350,10 +350,10 @@ void et1310_config_rxmac_regs(struct et131x_adapter *adapter) * bit 16: Receive frame truncated. * bit 17: Drop packet enable */ - if (adapter->linkspeed == TRUEPHY_SPEED_100MBPS) - writel(0x30038, &rxmac->mif_ctrl); + if (etdev->linkspeed == TRUEPHY_SPEED_100MBPS) + writel(0x30038, &pRxMac->mif_ctrl); else - writel(0x30030, &rxmac->mif_ctrl); + writel(0x30030, &pRxMac->mif_ctrl); /* Finally we initialize RxMac to be enabled & WOL disabled. Packet * filter is always enabled since it is where the runt packets are @@ -361,28 +361,28 @@ void et1310_config_rxmac_regs(struct et131x_adapter *adapter) * dropping doesn't work, so it is disabled in the pf_ctrl register, * but we still leave the packet filter on. */ - writel(pf_ctrl, &rxmac->pf_ctrl); - writel(0x9, &rxmac->ctrl); + writel(pf_ctrl, &pRxMac->pf_ctrl); + writel(0x9, &pRxMac->ctrl); } -void et1310_config_txmac_regs(struct et131x_adapter *adapter) +void ConfigTxMacRegs(struct et131x_adapter *etdev) { - struct txmac_regs *txmac = &adapter->regs->txmac; + struct txmac_regs *txmac = &etdev->regs->txmac; /* We need to update the Control Frame Parameters * cfpt - control frame pause timer set to 64 (0x40) * cfep - control frame extended pause timer set to 0x0 */ - if (adapter->flowcontrol == FLOW_NONE) + if (etdev->flowcontrol == FLOW_NONE) writel(0, &txmac->cf_param); else writel(0x40, &txmac->cf_param); } -void et1310_config_macstat_regs(struct et131x_adapter *adapter) +void ConfigMacStatRegs(struct et131x_adapter *etdev) { struct macstat_regs __iomem *macstat = - &adapter->regs->macstat; + &etdev->regs->macstat; /* Next we need to initialize all the macstat registers to zero on * the device. @@ -444,78 +444,78 @@ void et1310_config_macstat_regs(struct et131x_adapter *adapter) writel(0xFFFE7E8B, &macstat->carry_reg2_mask); } -void et1310_config_flow_control(struct et131x_adapter *adapter) +void ConfigFlowControl(struct et131x_adapter *etdev) { - if (adapter->duplex_mode == 0) { - adapter->flowcontrol = FLOW_NONE; + if (etdev->duplex_mode == 0) { + etdev->flowcontrol = FLOW_NONE; } else { char remote_pause, remote_async_pause; - et1310_phy_access_mii_bit(adapter, - TRUEPHY_BIT_READ, 5, 10, &remote_pause); - et1310_phy_access_mii_bit(adapter, - TRUEPHY_BIT_READ, 5, 11, - &remote_async_pause); + ET1310_PhyAccessMiBit(etdev, + TRUEPHY_BIT_READ, 5, 10, &remote_pause); + ET1310_PhyAccessMiBit(etdev, + TRUEPHY_BIT_READ, 5, 11, + &remote_async_pause); if ((remote_pause == TRUEPHY_BIT_SET) && (remote_async_pause == TRUEPHY_BIT_SET)) { - adapter->flowcontrol = adapter->wanted_flow; + etdev->flowcontrol = etdev->wanted_flow; } else if ((remote_pause == TRUEPHY_BIT_SET) && (remote_async_pause == TRUEPHY_BIT_CLEAR)) { - if (adapter->wanted_flow == FLOW_BOTH) - adapter->flowcontrol = FLOW_BOTH; + if (etdev->wanted_flow == FLOW_BOTH) + etdev->flowcontrol = FLOW_BOTH; else - adapter->flowcontrol = FLOW_NONE; + etdev->flowcontrol = FLOW_NONE; } else if ((remote_pause == TRUEPHY_BIT_CLEAR) && (remote_async_pause == TRUEPHY_BIT_CLEAR)) { - adapter->flowcontrol = FLOW_NONE; + etdev->flowcontrol = FLOW_NONE; } else {/* if (remote_pause == TRUEPHY_CLEAR_BIT && remote_async_pause == TRUEPHY_SET_BIT) */ - if (adapter->wanted_flow == FLOW_BOTH) - adapter->flowcontrol = FLOW_RXONLY; + if (etdev->wanted_flow == FLOW_BOTH) + etdev->flowcontrol = FLOW_RXONLY; else - adapter->flowcontrol = FLOW_NONE; + etdev->flowcontrol = FLOW_NONE; } } } /** - * et1310_update_macstat_host_counters - Update the local copy of the statistics - * @adapter: pointer to the adapter structure + * UpdateMacStatHostCounters - Update the local copy of the statistics + * @etdev: pointer to the adapter structure */ -void et1310_update_macstat_host_counters(struct et131x_adapter *adapter) +void UpdateMacStatHostCounters(struct et131x_adapter *etdev) { - struct ce_stats *stats = &adapter->stats; + struct ce_stats *stats = &etdev->stats; struct macstat_regs __iomem *macstat = - &adapter->regs->macstat; - - stats->tx_collisions += readl(&macstat->tx_total_collisions); - stats->tx_first_collisions += readl(&macstat->tx_single_collisions); - stats->tx_deferred += readl(&macstat->tx_deferred); - stats->tx_excessive_collisions += - readl(&macstat->tx_multiple_collisions); - stats->tx_late_collisions += readl(&macstat->tx_late_collisions); - stats->tx_underflows += readl(&macstat->tx_undersize_frames); - stats->tx_max_pkt_errs += readl(&macstat->tx_oversize_frames); - - stats->rx_align_errs += readl(&macstat->rx_align_errs); - stats->rx_crc_errs += readl(&macstat->rx_code_errs); - stats->rcvd_pkts_dropped += readl(&macstat->rx_drops); - stats->rx_overflows += readl(&macstat->rx_oversize_packets); - stats->rx_code_violations += readl(&macstat->rx_fcs_errs); - stats->rx_length_errs += readl(&macstat->rx_frame_len_errs); - stats->rx_other_errs += readl(&macstat->rx_fragment_packets); + &etdev->regs->macstat; + + stats->collisions += readl(&macstat->tx_total_collisions); + stats->first_collision += readl(&macstat->tx_single_collisions); + stats->tx_deferred += readl(&macstat->tx_deferred); + stats->excessive_collisions += readl(&macstat->tx_multiple_collisions); + stats->late_collisions += readl(&macstat->tx_late_collisions); + stats->tx_uflo += readl(&macstat->tx_undersize_frames); + stats->max_pkt_error += readl(&macstat->tx_oversize_frames); + + stats->alignment_err += readl(&macstat->rx_align_errs); + stats->crc_err += readl(&macstat->rx_code_errs); + stats->norcvbuf += readl(&macstat->rx_drops); + stats->rx_ov_flow += readl(&macstat->rx_oversize_packets); + stats->code_violations += readl(&macstat->rx_fcs_errs); + stats->length_err += readl(&macstat->rx_frame_len_errs); + + stats->other_errors += readl(&macstat->rx_fragment_packets); } /** - * et1310_handle_macstat_interrupt - * @adapter: pointer to the adapter structure + * HandleMacStatInterrupt + * @etdev: pointer to the adapter structure * * One of the MACSTAT counters has wrapped. Update the local copy of * the statistics held in the adapter structure, checking the "wrap" * bit for each counter. */ -void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter) +void HandleMacStatInterrupt(struct et131x_adapter *etdev) { u32 carry_reg1; u32 carry_reg2; @@ -523,11 +523,11 @@ void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter) /* Read the interrupt bits from the register(s). These are Clear On * Write. */ - carry_reg1 = readl(&adapter->regs->macstat.carry_reg1); - carry_reg2 = readl(&adapter->regs->macstat.carry_reg2); + carry_reg1 = readl(&etdev->regs->macstat.carry_reg1); + carry_reg2 = readl(&etdev->regs->macstat.carry_reg2); - writel(carry_reg1, &adapter->regs->macstat.carry_reg1); - writel(carry_reg2, &adapter->regs->macstat.carry_reg2); + writel(carry_reg2, &etdev->regs->macstat.carry_reg1); + writel(carry_reg2, &etdev->regs->macstat.carry_reg2); /* We need to do update the host copy of all the MAC_STAT counters. * For each counter, check it's overflow bit. If the overflow bit is @@ -536,38 +536,38 @@ void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter) * block indicates that one of the counters has wrapped. */ if (carry_reg1 & (1 << 14)) - adapter->stats.rx_code_violations += COUNTER_WRAP_16_BIT; + etdev->stats.code_violations += COUNTER_WRAP_16_BIT; if (carry_reg1 & (1 << 8)) - adapter->stats.rx_align_errs += COUNTER_WRAP_12_BIT; + etdev->stats.alignment_err += COUNTER_WRAP_12_BIT; if (carry_reg1 & (1 << 7)) - adapter->stats.rx_length_errs += COUNTER_WRAP_16_BIT; + etdev->stats.length_err += COUNTER_WRAP_16_BIT; if (carry_reg1 & (1 << 2)) - adapter->stats.rx_other_errs += COUNTER_WRAP_16_BIT; + etdev->stats.other_errors += COUNTER_WRAP_16_BIT; if (carry_reg1 & (1 << 6)) - adapter->stats.rx_crc_errs += COUNTER_WRAP_16_BIT; + etdev->stats.crc_err += COUNTER_WRAP_16_BIT; if (carry_reg1 & (1 << 3)) - adapter->stats.rx_overflows += COUNTER_WRAP_16_BIT; + etdev->stats.rx_ov_flow += COUNTER_WRAP_16_BIT; if (carry_reg1 & (1 << 0)) - adapter->stats.rcvd_pkts_dropped += COUNTER_WRAP_16_BIT; + etdev->stats.norcvbuf += COUNTER_WRAP_16_BIT; if (carry_reg2 & (1 << 16)) - adapter->stats.tx_max_pkt_errs += COUNTER_WRAP_12_BIT; + etdev->stats.max_pkt_error += COUNTER_WRAP_12_BIT; if (carry_reg2 & (1 << 15)) - adapter->stats.tx_underflows += COUNTER_WRAP_12_BIT; + etdev->stats.tx_uflo += COUNTER_WRAP_12_BIT; if (carry_reg2 & (1 << 6)) - adapter->stats.tx_first_collisions += COUNTER_WRAP_12_BIT; + etdev->stats.first_collision += COUNTER_WRAP_12_BIT; if (carry_reg2 & (1 << 8)) - adapter->stats.tx_deferred += COUNTER_WRAP_12_BIT; + etdev->stats.tx_deferred += COUNTER_WRAP_12_BIT; if (carry_reg2 & (1 << 5)) - adapter->stats.tx_excessive_collisions += COUNTER_WRAP_12_BIT; + etdev->stats.excessive_collisions += COUNTER_WRAP_12_BIT; if (carry_reg2 & (1 << 4)) - adapter->stats.tx_late_collisions += COUNTER_WRAP_12_BIT; + etdev->stats.late_collisions += COUNTER_WRAP_12_BIT; if (carry_reg2 & (1 << 2)) - adapter->stats.tx_collisions += COUNTER_WRAP_12_BIT; + etdev->stats.collisions += COUNTER_WRAP_12_BIT; } -void et1310_setup_device_for_multicast(struct et131x_adapter *adapter) +void SetupDeviceForMulticast(struct et131x_adapter *etdev) { - struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac; + struct rxmac_regs __iomem *rxmac = &etdev->regs->rxmac; uint32_t nIndex; uint32_t result; uint32_t hash1 = 0; @@ -581,11 +581,10 @@ void et1310_setup_device_for_multicast(struct et131x_adapter *adapter) * specified) then we should pass NO multi-cast addresses to the * driver. */ - if (adapter->packet_filter & ET131X_PACKET_TYPE_MULTICAST) { + if (etdev->PacketFilter & ET131X_PACKET_TYPE_MULTICAST) { /* Loop through our multicast array and set up the device */ - for (nIndex = 0; nIndex < adapter->multicast_addr_count; - nIndex++) { - result = ether_crc(6, adapter->multicast_list[nIndex]); + for (nIndex = 0; nIndex < etdev->MCAddressCount; nIndex++) { + result = ether_crc(6, etdev->MCList[nIndex]); result = (result & 0x3F800000) >> 23; @@ -605,7 +604,7 @@ void et1310_setup_device_for_multicast(struct et131x_adapter *adapter) } /* Write out the new hash to the device */ - pm_csr = readl(&adapter->regs->global.pm_csr); + pm_csr = readl(&etdev->regs->global.pm_csr); if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) { writel(hash1, &rxmac->multi_hash1); writel(hash2, &rxmac->multi_hash2); @@ -614,9 +613,9 @@ void et1310_setup_device_for_multicast(struct et131x_adapter *adapter) } } -void et1310_setup_device_for_unicast(struct et131x_adapter *adapter) +void SetupDeviceForUnicast(struct et131x_adapter *etdev) { - struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac; + struct rxmac_regs __iomem *rxmac = &etdev->regs->rxmac; u32 uni_pf1; u32 uni_pf2; u32 uni_pf3; @@ -631,22 +630,22 @@ void et1310_setup_device_for_unicast(struct et131x_adapter *adapter) * Set up unicast packet filter reg 3 to be the octets 2 - 5 of the * MAC address for first address */ - uni_pf3 = (adapter->addr[0] << ET_UNI_PF_ADDR2_1_SHIFT) | - (adapter->addr[1] << ET_UNI_PF_ADDR2_2_SHIFT) | - (adapter->addr[0] << ET_UNI_PF_ADDR1_1_SHIFT) | - adapter->addr[1]; - - uni_pf2 = (adapter->addr[2] << ET_UNI_PF_ADDR2_3_SHIFT) | - (adapter->addr[3] << ET_UNI_PF_ADDR2_4_SHIFT) | - (adapter->addr[4] << ET_UNI_PF_ADDR2_5_SHIFT) | - adapter->addr[5]; - - uni_pf1 = (adapter->addr[2] << ET_UNI_PF_ADDR1_3_SHIFT) | - (adapter->addr[3] << ET_UNI_PF_ADDR1_4_SHIFT) | - (adapter->addr[4] << ET_UNI_PF_ADDR1_5_SHIFT) | - adapter->addr[5]; - - pm_csr = readl(&adapter->regs->global.pm_csr); + uni_pf3 = (etdev->addr[0] << ET_UNI_PF_ADDR2_1_SHIFT) | + (etdev->addr[1] << ET_UNI_PF_ADDR2_2_SHIFT) | + (etdev->addr[0] << ET_UNI_PF_ADDR1_1_SHIFT) | + etdev->addr[1]; + + uni_pf2 = (etdev->addr[2] << ET_UNI_PF_ADDR2_3_SHIFT) | + (etdev->addr[3] << ET_UNI_PF_ADDR2_4_SHIFT) | + (etdev->addr[4] << ET_UNI_PF_ADDR2_5_SHIFT) | + etdev->addr[5]; + + uni_pf1 = (etdev->addr[2] << ET_UNI_PF_ADDR1_3_SHIFT) | + (etdev->addr[3] << ET_UNI_PF_ADDR1_4_SHIFT) | + (etdev->addr[4] << ET_UNI_PF_ADDR1_5_SHIFT) | + etdev->addr[5]; + + pm_csr = readl(&etdev->regs->global.pm_csr); if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) { writel(uni_pf1, &rxmac->uni_pf_addr1); writel(uni_pf2, &rxmac->uni_pf_addr2); diff --git a/trunk/drivers/staging/et131x/et1310_phy.c b/trunk/drivers/staging/et131x/et1310_phy.c index c845c27f23db..0bcb7fb6e2c8 100644 --- a/trunk/drivers/staging/et131x/et1310_phy.c +++ b/trunk/drivers/staging/et131x/et1310_phy.c @@ -93,36 +93,39 @@ #include "et131x.h" +/* Prototypes for functions with local scope */ +static void et131x_xcvr_init(struct et131x_adapter *etdev); + /** - * et131x_phy_mii_read - Read from the PHY through the MII Interface on the MAC - * @adapter: pointer to our private adapter structure - * @xcvr_addr: the address of the transceiver - * @xcvr_reg: the register to read + * PhyMiRead - Read from the PHY through the MII Interface on the MAC + * @etdev: pointer to our private adapter structure + * @xcvrAddr: the address of the transceiver + * @xcvrReg: the register to read * @value: pointer to a 16-bit value in which the value will be stored * * Returns 0 on success, errno on failure (as defined in errno.h) */ -int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 xcvr_addr, - u8 xcvr_reg, u16 *value) +int PhyMiRead(struct et131x_adapter *etdev, u8 xcvrAddr, + u8 xcvrReg, u16 *value) { - struct mac_regs __iomem *mac = &adapter->regs->mac; + struct mac_regs __iomem *mac = &etdev->regs->mac; int status = 0; u32 delay; - u32 mii_addr; - u32 mii_cmd; - u32 mii_indicator; + u32 miiAddr; + u32 miiCmd; + u32 miiIndicator; /* Save a local copy of the registers we are dealing with so we can * set them back */ - mii_addr = readl(&mac->mii_mgmt_addr); - mii_cmd = readl(&mac->mii_mgmt_cmd); + miiAddr = readl(&mac->mii_mgmt_addr); + miiCmd = readl(&mac->mii_mgmt_cmd); /* Stop the current operation */ writel(0, &mac->mii_mgmt_cmd); /* Set up the register we need to read from on the correct PHY */ - writel(MII_ADDR(xcvr_addr, xcvr_reg), &mac->mii_mgmt_addr); + writel(MII_ADDR(xcvrAddr, xcvrReg), &mac->mii_mgmt_addr); /* Kick the read cycle off */ delay = 0; @@ -132,15 +135,15 @@ int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 xcvr_addr, do { udelay(50); delay++; - mii_indicator = readl(&mac->mii_mgmt_indicator); - } while ((mii_indicator & MGMT_WAIT) && delay < 50); + miiIndicator = readl(&mac->mii_mgmt_indicator); + } while ((miiIndicator & MGMT_WAIT) && delay < 50); /* If we hit the max delay, we could not read the register */ if (delay == 50) { - dev_warn(&adapter->pdev->dev, - "xcvrReg 0x%08x could not be read\n", xcvr_reg); - dev_warn(&adapter->pdev->dev, "status is 0x%08x\n", - mii_indicator); + dev_warn(&etdev->pdev->dev, + "xcvrReg 0x%08x could not be read\n", xcvrReg); + dev_warn(&etdev->pdev->dev, "status is 0x%08x\n", + miiIndicator); status = -EIO; } @@ -155,43 +158,43 @@ int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 xcvr_addr, /* set the registers we touched back to the state at which we entered * this function */ - writel(mii_addr, &mac->mii_mgmt_addr); - writel(mii_cmd, &mac->mii_mgmt_cmd); + writel(miiAddr, &mac->mii_mgmt_addr); + writel(miiCmd, &mac->mii_mgmt_cmd); return status; } /** - * et131x_mii_write - Write to a PHY register through the MII interface of the MAC - * @adapter: pointer to our private adapter structure - * @xcvr_reg: the register to read + * MiWrite - Write to a PHY register through the MII interface of the MAC + * @etdev: pointer to our private adapter structure + * @xcvrReg: the register to read * @value: 16-bit value to write * * FIXME: one caller in netdev still * * Return 0 on success, errno on failure (as defined in errno.h) */ -int et131x_mii_write(struct et131x_adapter *adapter, u8 xcvr_reg, u16 value) +int MiWrite(struct et131x_adapter *etdev, u8 xcvrReg, u16 value) { - struct mac_regs __iomem *mac = &adapter->regs->mac; + struct mac_regs __iomem *mac = &etdev->regs->mac; int status = 0; - u8 xcvr_addr = adapter->stats.xcvr_addr; + u8 xcvrAddr = etdev->stats.xcvr_addr; u32 delay; - u32 mii_addr; - u32 mii_cmd; - u32 mii_indicator; + u32 miiAddr; + u32 miiCmd; + u32 miiIndicator; /* Save a local copy of the registers we are dealing with so we can * set them back */ - mii_addr = readl(&mac->mii_mgmt_addr); - mii_cmd = readl(&mac->mii_mgmt_cmd); + miiAddr = readl(&mac->mii_mgmt_addr); + miiCmd = readl(&mac->mii_mgmt_cmd); /* Stop the current operation */ writel(0, &mac->mii_mgmt_cmd); /* Set up the register we need to write to on the correct PHY */ - writel(MII_ADDR(xcvr_addr, xcvr_reg), &mac->mii_mgmt_addr); + writel(MII_ADDR(xcvrAddr, xcvrReg), &mac->mii_mgmt_addr); /* Add the value to write to the registers to the mac */ writel(value, &mac->mii_mgmt_ctrl); @@ -200,44 +203,43 @@ int et131x_mii_write(struct et131x_adapter *adapter, u8 xcvr_reg, u16 value) do { udelay(50); delay++; - mii_indicator = readl(&mac->mii_mgmt_indicator); - } while ((mii_indicator & MGMT_BUSY) && delay < 100); + miiIndicator = readl(&mac->mii_mgmt_indicator); + } while ((miiIndicator & MGMT_BUSY) && delay < 100); /* If we hit the max delay, we could not write the register */ if (delay == 100) { - u16 tmp; + u16 TempValue; - dev_warn(&adapter->pdev->dev, - "xcvrReg 0x%08x could not be written", xcvr_reg); - dev_warn(&adapter->pdev->dev, "status is 0x%08x\n", - mii_indicator); - dev_warn(&adapter->pdev->dev, "command is 0x%08x\n", + dev_warn(&etdev->pdev->dev, + "xcvrReg 0x%08x could not be written", xcvrReg); + dev_warn(&etdev->pdev->dev, "status is 0x%08x\n", + miiIndicator); + dev_warn(&etdev->pdev->dev, "command is 0x%08x\n", readl(&mac->mii_mgmt_cmd)); - et131x_mii_read(adapter, xcvr_reg, &tmp); + MiRead(etdev, xcvrReg, &TempValue); status = -EIO; } /* Stop the write operation */ writel(0, &mac->mii_mgmt_cmd); - /* - * set the registers we touched back to the state at which we entered + /* set the registers we touched back to the state at which we entered * this function */ - writel(mii_addr, &mac->mii_mgmt_addr); - writel(mii_cmd, &mac->mii_mgmt_cmd); + writel(miiAddr, &mac->mii_mgmt_addr); + writel(miiCmd, &mac->mii_mgmt_cmd); return status; } /** * et131x_xcvr_find - Find the PHY ID - * @adapter: pointer to our private adapter structure + * @etdev: pointer to our private adapter structure * * Returns 0 on success, errno on failure (as defined in errno.h) */ -int et131x_xcvr_find(struct et131x_adapter *adapter) +int et131x_xcvr_find(struct et131x_adapter *etdev) { u8 xcvr_addr; u16 idr1; @@ -247,32 +249,32 @@ int et131x_xcvr_find(struct et131x_adapter *adapter) /* We need to get xcvr id and address we just get the first one */ for (xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++) { /* Read the ID from the PHY */ - et131x_phy_mii_read(adapter, xcvr_addr, - (u8) offsetof(struct mi_regs, idr1), - &idr1); - et131x_phy_mii_read(adapter, xcvr_addr, - (u8) offsetof(struct mi_regs, idr2), - &idr2); + PhyMiRead(etdev, xcvr_addr, + (u8) offsetof(struct mi_regs, idr1), + &idr1); + PhyMiRead(etdev, xcvr_addr, + (u8) offsetof(struct mi_regs, idr2), + &idr2); xcvr_id = (u32) ((idr1 << 16) | idr2); if (idr1 != 0 && idr1 != 0xffff) { - adapter->stats.xcvr_id = xcvr_id; - adapter->stats.xcvr_addr = xcvr_addr; + etdev->stats.xcvr_id = xcvr_id; + etdev->stats.xcvr_addr = xcvr_addr; return 0; } } return -ENODEV; } -void et1310_phy_reset(struct et131x_adapter *adapter) +void ET1310_PhyReset(struct et131x_adapter *etdev) { - et131x_mii_write(adapter, PHY_CONTROL, 0x8000); + MiWrite(etdev, PHY_CONTROL, 0x8000); } /** - * et1310_phy_power_down - PHY power control - * @adapter: device to control + * ET1310_PhyPowerDown - PHY power control + * @etdev: device to control * @down: true for off/false for back on * * one hundred, ten, one thousand megs @@ -280,77 +282,81 @@ void et1310_phy_reset(struct et131x_adapter *adapter) * Can't you see that this code processed * Phy power, phy power.. */ -void et1310_phy_power_down(struct et131x_adapter *adapter, bool down) + +void ET1310_PhyPowerDown(struct et131x_adapter *etdev, bool down) { u16 data; - et131x_mii_read(adapter, PHY_CONTROL, &data); + MiRead(etdev, PHY_CONTROL, &data); data &= ~0x0800; /* Power UP */ if (down) /* Power DOWN */ data |= 0x0800; - et131x_mii_write(adapter, PHY_CONTROL, data); + MiWrite(etdev, PHY_CONTROL, data); } /** - * et1310_phy_auto_neg - autonegotiate control - * @adapter: device to control + * ET130_PhyAutoNEg - autonegotiate control + * @etdev: device to control * @enabe: autoneg on/off * * Set up the autonegotiation state according to whether we will be * negotiating the state or forcing a speed. */ -static void et1310_phy_auto_neg(struct et131x_adapter *adapter, bool enable) + +static void ET1310_PhyAutoNeg(struct et131x_adapter *etdev, bool enable) { u16 data; - et131x_mii_read(adapter, PHY_CONTROL, &data); + MiRead(etdev, PHY_CONTROL, &data); data &= ~0x1000; /* Autonegotiation OFF */ if (enable) data |= 0x1000; /* Autonegotiation ON */ - et131x_mii_write(adapter, PHY_CONTROL, data); + MiWrite(etdev, PHY_CONTROL, data); } /** - * et1310_phy_duplex_mode - duplex control - * @adapter: device to control + * ET130_PhyDuplexMode - duplex control + * @etdev: device to control * @duplex: duplex on/off * * Set up the duplex state on the PHY */ -static void et1310_phy_duplex_mode(struct et131x_adapter *adapter, u16 duplex) + +static void ET1310_PhyDuplexMode(struct et131x_adapter *etdev, u16 duplex) { u16 data; - et131x_mii_read(adapter, PHY_CONTROL, &data); + MiRead(etdev, PHY_CONTROL, &data); data &= ~0x100; /* Set Half Duplex */ if (duplex == TRUEPHY_DUPLEX_FULL) data |= 0x100; /* Set Full Duplex */ - et131x_mii_write(adapter, PHY_CONTROL, data); + MiWrite(etdev, PHY_CONTROL, data); } /** - * et1310_phy_speed_select - speed control - * @adapter: device to control + * ET130_PhySpeedSelect - speed control + * @etdev: device to control * @duplex: duplex on/off * * Set the speed of our PHY. */ -static void et1310_phy_speed_select(struct et131x_adapter *adapter, u16 speed) + +static void ET1310_PhySpeedSelect(struct et131x_adapter *etdev, u16 speed) { u16 data; static const u16 bits[3] = {0x0000, 0x2000, 0x0040}; /* Read the PHY control register */ - et131x_mii_read(adapter, PHY_CONTROL, &data); + MiRead(etdev, PHY_CONTROL, &data); /* Clear all Speed settings (Bits 6, 13) */ data &= ~0x2040; /* Write back the new speed */ - et131x_mii_write(adapter, PHY_CONTROL, data | bits[speed]); + MiWrite(etdev, PHY_CONTROL, data | bits[speed]); } /** - * et1310_phy_link_status - read link state - * @adapter: device to read + * ET1310_PhyLinkStatus - read link state + * @etdev: device to read * @link_status: reported link state * @autoneg: reported autonegotiation state (complete/incomplete/disabled) * @linkspeed: returnedlink speed in use @@ -364,7 +370,8 @@ static void et1310_phy_speed_select(struct et131x_adapter *adapter, u16 speed) * I know your link speed * I see all the setting that you'd rather keep */ -static void et1310_phy_link_status(struct et131x_adapter *adapter, + +static void ET1310_PhyLinkStatus(struct et131x_adapter *etdev, u8 *link_status, u32 *autoneg, u32 *linkspeed, @@ -377,10 +384,10 @@ static void et1310_phy_link_status(struct et131x_adapter *adapter, u16 vmi_phystatus = 0; u16 control = 0; - et131x_mii_read(adapter, PHY_STATUS, &mistatus); - et131x_mii_read(adapter, PHY_1000_STATUS, &is1000BaseT); - et131x_mii_read(adapter, PHY_PHY_STATUS, &vmi_phystatus); - et131x_mii_read(adapter, PHY_CONTROL, &control); + MiRead(etdev, PHY_STATUS, &mistatus); + MiRead(etdev, PHY_1000_STATUS, &is1000BaseT); + MiRead(etdev, PHY_PHY_STATUS, &vmi_phystatus); + MiRead(etdev, PHY_CONTROL, &control); *link_status = (vmi_phystatus & 0x0040) ? 1 : 0; *autoneg = (control & 0x1000) ? ((vmi_phystatus & 0x0020) ? @@ -398,26 +405,26 @@ static void et1310_phy_link_status(struct et131x_adapter *adapter, TRUEPHY_POLARITY_INVERTED : TRUEPHY_POLARITY_NORMAL; } -static void et1310_phy_and_or_reg(struct et131x_adapter *adapter, - u16 regnum, u16 and_mask, u16 or_mask) +static void ET1310_PhyAndOrReg(struct et131x_adapter *etdev, + u16 regnum, u16 andMask, u16 orMask) { u16 reg; - et131x_mii_read(adapter, regnum, ®); - reg &= and_mask; - reg |= or_mask; - et131x_mii_write(adapter, regnum, reg); + MiRead(etdev, regnum, ®); + reg &= andMask; + reg |= orMask; + MiWrite(etdev, regnum, reg); } -/* Still used from _mac for BIT_READ */ -void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, u16 action, - u16 regnum, u16 bitnum, u8 *value) +/* Still used from _mac for BIT_READ */ +void ET1310_PhyAccessMiBit(struct et131x_adapter *etdev, u16 action, + u16 regnum, u16 bitnum, u8 *value) { u16 reg; u16 mask = 0x0001 << bitnum; /* Read the requested register */ - et131x_mii_read(adapter, regnum, ®); + MiRead(etdev, regnum, ®); switch (action) { case TRUEPHY_BIT_READ: @@ -425,11 +432,11 @@ void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, u16 action, break; case TRUEPHY_BIT_SET: - et131x_mii_write(adapter, regnum, reg | mask); + MiWrite(etdev, regnum, reg | mask); break; case TRUEPHY_BIT_CLEAR: - et131x_mii_write(adapter, regnum, reg & ~mask); + MiWrite(etdev, regnum, reg & ~mask); break; default: @@ -437,13 +444,13 @@ void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, u16 action, } } -void et1310_phy_advertise_1000BaseT(struct et131x_adapter *adapter, +void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *etdev, u16 duplex) { u16 data; /* Read the PHY 1000 Base-T Control Register */ - et131x_mii_read(adapter, PHY_1000_CONTROL, &data); + MiRead(etdev, PHY_1000_CONTROL, &data); /* Clear Bits 8,9 */ data &= ~0x0300; @@ -470,16 +477,16 @@ void et1310_phy_advertise_1000BaseT(struct et131x_adapter *adapter, } /* Write back advertisement */ - et131x_mii_write(adapter, PHY_1000_CONTROL, data); + MiWrite(etdev, PHY_1000_CONTROL, data); } -static void et1310_phy_advertise_100BaseT(struct et131x_adapter *adapter, - u16 duplex) +static void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *etdev, + u16 duplex) { u16 data; /* Read the Autonegotiation Register (10/100) */ - et131x_mii_read(adapter, PHY_AUTO_ADVERTISEMENT, &data); + MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); /* Clear bits 7,8 */ data &= ~0x0180; @@ -507,16 +514,16 @@ static void et1310_phy_advertise_100BaseT(struct et131x_adapter *adapter, } /* Write back advertisement */ - et131x_mii_write(adapter, PHY_AUTO_ADVERTISEMENT, data); + MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); } -static void et1310_phy_advertise_10BaseT(struct et131x_adapter *adapter, +static void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *etdev, u16 duplex) { u16 data; /* Read the Autonegotiation Register (10/100) */ - et131x_mii_read(adapter, PHY_AUTO_ADVERTISEMENT, &data); + MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); /* Clear bits 5,6 */ data &= ~0x0060; @@ -544,32 +551,48 @@ static void et1310_phy_advertise_10BaseT(struct et131x_adapter *adapter, } /* Write back advertisement */ - et131x_mii_write(adapter, PHY_AUTO_ADVERTISEMENT, data); + MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); +} + +/** + * et131x_setphy_normal - Set PHY for normal operation. + * @etdev: pointer to our private adapter structure + * + * Used by Power Management to force the PHY into 10 Base T half-duplex mode, + * when going to D3 in WOL mode. Also used during initialization to set the + * PHY for normal operation. + */ +void et131x_setphy_normal(struct et131x_adapter *etdev) +{ + /* Make sure the PHY is powered up */ + ET1310_PhyPowerDown(etdev, 0); + et131x_xcvr_init(etdev); } + /** * et131x_xcvr_init - Init the phy if we are setting it into force mode - * @adapter: pointer to our private adapter structure + * @etdev: pointer to our private adapter structure * */ -static void et131x_xcvr_init(struct et131x_adapter *adapter) +static void et131x_xcvr_init(struct et131x_adapter *etdev) { u16 imr; u16 isr; u16 lcr2; /* Zero out the adapter structure variable representing BMSR */ - adapter->bmsr = 0; + etdev->bmsr = 0; - et131x_mii_read(adapter, (u8) offsetof(struct mi_regs, isr), &isr); - et131x_mii_read(adapter, (u8) offsetof(struct mi_regs, imr), &imr); + MiRead(etdev, (u8) offsetof(struct mi_regs, isr), &isr); + MiRead(etdev, (u8) offsetof(struct mi_regs, imr), &imr); /* Set the link status interrupt only. Bad behavior when link status * and auto neg are set, we run into a nested interrupt problem */ imr |= 0x0105; - et131x_mii_write(adapter, (u8) offsetof(struct mi_regs, imr), imr); + MiWrite(etdev, (u8) offsetof(struct mi_regs, imr), imr); /* Set the LED behavior such that LED 1 indicates speed (off = * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates @@ -579,150 +602,133 @@ static void et131x_xcvr_init(struct et131x_adapter *adapter) * vendors; The LED behavior is now determined by vendor data in the * EEPROM. However, the above description is the default. */ - if ((adapter->eeprom_data[1] & 0x4) == 0) { - et131x_mii_read(adapter, (u8) offsetof(struct mi_regs, lcr2), + if ((etdev->eeprom_data[1] & 0x4) == 0) { + MiRead(etdev, (u8) offsetof(struct mi_regs, lcr2), &lcr2); lcr2 &= 0x00FF; lcr2 |= 0xA000; /* led link */ - if ((adapter->eeprom_data[1] & 0x8) == 0) + if ((etdev->eeprom_data[1] & 0x8) == 0) lcr2 |= 0x0300; else lcr2 |= 0x0400; - et131x_mii_write(adapter, (u8) offsetof(struct mi_regs, lcr2), + MiWrite(etdev, (u8) offsetof(struct mi_regs, lcr2), lcr2); } /* Determine if we need to go into a force mode and set it */ - if (adapter->ai_force_speed == 0 && adapter->ai_force_duplex == 0) { - if (adapter->wanted_flow == FLOW_TXONLY || - adapter->wanted_flow == FLOW_BOTH) - et1310_phy_access_mii_bit(adapter, + if (etdev->AiForceSpeed == 0 && etdev->AiForceDpx == 0) { + if (etdev->wanted_flow == FLOW_TXONLY || + etdev->wanted_flow == FLOW_BOTH) + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_SET, 4, 11, NULL); else - et1310_phy_access_mii_bit(adapter, + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 11, NULL); - if (adapter->wanted_flow == FLOW_BOTH) - et1310_phy_access_mii_bit(adapter, + if (etdev->wanted_flow == FLOW_BOTH) + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_SET, 4, 10, NULL); else - et1310_phy_access_mii_bit(adapter, + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 10, NULL); /* Set the phy to autonegotiation */ - et1310_phy_auto_neg(adapter, true); + ET1310_PhyAutoNeg(etdev, true); /* NOTE - Do we need this? */ - et1310_phy_access_mii_bit(adapter, TRUEPHY_BIT_SET, 0, 9, NULL); + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_SET, 0, 9, NULL); return; } - et1310_phy_auto_neg(adapter, false); + ET1310_PhyAutoNeg(etdev, false); /* Set to the correct force mode. */ - if (adapter->ai_force_duplex != 1) { - if (adapter->wanted_flow == FLOW_TXONLY || - adapter->wanted_flow == FLOW_BOTH) - et1310_phy_access_mii_bit(adapter, + if (etdev->AiForceDpx != 1) { + if (etdev->wanted_flow == FLOW_TXONLY || + etdev->wanted_flow == FLOW_BOTH) + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_SET, 4, 11, NULL); else - et1310_phy_access_mii_bit(adapter, + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 11, NULL); - if (adapter->wanted_flow == FLOW_BOTH) - et1310_phy_access_mii_bit(adapter, + if (etdev->wanted_flow == FLOW_BOTH) + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_SET, 4, 10, NULL); else - et1310_phy_access_mii_bit(adapter, + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 10, NULL); } else { - et1310_phy_access_mii_bit(adapter, TRUEPHY_BIT_CLEAR, - 4, 10, NULL); - et1310_phy_access_mii_bit(adapter, TRUEPHY_BIT_CLEAR, - 4, 11, NULL); + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 10, NULL); + ET1310_PhyAccessMiBit(etdev, TRUEPHY_BIT_CLEAR, 4, 11, NULL); } - et1310_phy_power_down(adapter, 1); - switch (adapter->ai_force_speed) { + ET1310_PhyPowerDown(etdev, 1); + switch (etdev->AiForceSpeed) { case 10: /* First we need to turn off all other advertisement */ - et1310_phy_advertise_1000BaseT(adapter, TRUEPHY_ADV_DUPLEX_NONE); - et1310_phy_advertise_100BaseT(adapter, TRUEPHY_ADV_DUPLEX_NONE); - if (adapter->ai_force_duplex == 1) { + ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + if (etdev->AiForceDpx == 1) { /* Set our advertise values accordingly */ - et1310_phy_advertise_10BaseT(adapter, + ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF); - } else if (adapter->ai_force_duplex == 2) { + } else if (etdev->AiForceDpx == 2) { /* Set our advertise values accordingly */ - et1310_phy_advertise_10BaseT(adapter, + ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); } else { /* Disable autoneg */ - et1310_phy_auto_neg(adapter, false); + ET1310_PhyAutoNeg(etdev, false); /* Disable rest of the advertisements */ - et1310_phy_advertise_10BaseT(adapter, + ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); /* Force 10 Mbps */ - et1310_phy_speed_select(adapter, TRUEPHY_SPEED_10MBPS); + ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_10MBPS); /* Force Full duplex */ - et1310_phy_duplex_mode(adapter, TRUEPHY_DUPLEX_FULL); + ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL); } break; case 100: /* first we need to turn off all other advertisement */ - et1310_phy_advertise_1000BaseT(adapter, TRUEPHY_ADV_DUPLEX_NONE); - et1310_phy_advertise_10BaseT(adapter, TRUEPHY_ADV_DUPLEX_NONE); - if (adapter->ai_force_duplex == 1) { + ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + if (etdev->AiForceDpx == 1) { /* Set our advertise values accordingly */ - et1310_phy_advertise_100BaseT(adapter, + ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF); /* Set speed */ - et1310_phy_speed_select(adapter, TRUEPHY_SPEED_100MBPS); - } else if (adapter->ai_force_duplex == 2) { + ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS); + } else if (etdev->AiForceDpx == 2) { /* Set our advertise values accordingly */ - et1310_phy_advertise_100BaseT(adapter, + ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); } else { /* Disable autoneg */ - et1310_phy_auto_neg(adapter, false); + ET1310_PhyAutoNeg(etdev, false); /* Disable other advertisement */ - et1310_phy_advertise_100BaseT(adapter, + ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); /* Force 100 Mbps */ - et1310_phy_speed_select(adapter, TRUEPHY_SPEED_100MBPS); + ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS); /* Force Full duplex */ - et1310_phy_duplex_mode(adapter, TRUEPHY_DUPLEX_FULL); + ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL); } break; case 1000: /* first we need to turn off all other advertisement */ - et1310_phy_advertise_100BaseT(adapter, TRUEPHY_ADV_DUPLEX_NONE); - et1310_phy_advertise_10BaseT(adapter, TRUEPHY_ADV_DUPLEX_NONE); + ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); + ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); /* set our advertise values accordingly */ - et1310_phy_advertise_1000BaseT(adapter, TRUEPHY_ADV_DUPLEX_FULL); + ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); break; } - et1310_phy_power_down(adapter, 0); + ET1310_PhyPowerDown(etdev, 0); } -/** - * et131x_setphy_normal - Set PHY for normal operation. - * @adapter: pointer to our private adapter structure - * - * Used by Power Management to force the PHY into 10 Base T half-duplex mode, - * when going to D3 in WOL mode. Also used during initialization to set the - * PHY for normal operation. - */ -void et131x_setphy_normal(struct et131x_adapter *adapter) -{ - /* Make sure the PHY is powered up */ - et1310_phy_power_down(adapter, 0); - et131x_xcvr_init(adapter); -} - -void et131x_mii_check(struct et131x_adapter *adapter, +void et131x_Mii_check(struct et131x_adapter *etdev, u16 bmsr, u16 bmsr_ints) { u8 link_status; @@ -732,104 +738,127 @@ void et131x_mii_check(struct et131x_adapter *adapter, u32 mdi_mdix; u32 masterslave; u32 polarity; + unsigned long flags; if (bmsr_ints & MI_BMSR_LINK_STATUS) { if (bmsr & MI_BMSR_LINK_STATUS) { - adapter->boot_coma = 20; - netif_carrier_on(adapter->netdev); + etdev->boot_coma = 20; + + /* Update our state variables and indicate the + * connected state + */ + spin_lock_irqsave(&etdev->Lock, flags); + + etdev->MediaState = NETIF_STATUS_MEDIA_CONNECT; + + spin_unlock_irqrestore(&etdev->Lock, flags); + + netif_carrier_on(etdev->netdev); } else { - dev_warn(&adapter->pdev->dev, + dev_warn(&etdev->pdev->dev, "Link down - cable problem ?\n"); - if (adapter->linkspeed == TRUEPHY_SPEED_10MBPS) { + if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) { /* NOTE - Is there a way to query this without * TruePHY? - * && TRU_QueryCoreType(adapter->hTruePhy, 0) == + * && TRU_QueryCoreType(etdev->hTruePhy, 0) == * EMI_TRUEPHY_A13O) { */ - u16 register18; - - et131x_mii_read(adapter, 0x12, ®ister18); - et131x_mii_write(adapter, 0x12, register18 | 0x4); - et131x_mii_write(adapter, 0x10, - register18 | 0x8402); - et131x_mii_write(adapter, 0x11, register18 | 511); - et131x_mii_write(adapter, 0x12, register18); + u16 Register18; + + MiRead(etdev, 0x12, &Register18); + MiWrite(etdev, 0x12, Register18 | 0x4); + MiWrite(etdev, 0x10, Register18 | 0x8402); + MiWrite(etdev, 0x11, Register18 | 511); + MiWrite(etdev, 0x12, Register18); } - netif_carrier_off(adapter->netdev); + /* For the first N seconds of life, we are in "link + * detection" When we are in this state, we should + * only report "connected". When the LinkDetection + * Timer expires, we can report disconnected (handled + * in the LinkDetectionDPC). + */ + if ((etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) { + spin_lock_irqsave(&etdev->Lock, flags); + etdev->MediaState = + NETIF_STATUS_MEDIA_DISCONNECT; + spin_unlock_irqrestore(&etdev->Lock, + flags); + + netif_carrier_off(etdev->netdev); + } - adapter->linkspeed = 0; - adapter->duplex_mode = 0; + etdev->linkspeed = 0; + etdev->duplex_mode = 0; /* Free the packets being actively sent & stopped */ - et131x_free_busy_send_packets(adapter); + et131x_free_busy_send_packets(etdev); /* Re-initialize the send structures */ - et131x_init_send(adapter); + et131x_init_send(etdev); /* Reset the RFD list and re-start RU */ - et131x_reset_recv(adapter); + et131x_reset_recv(etdev); /* * Bring the device back to the state it was during * init prior to autonegotiation being complete. This * way, when we get the auto-neg complete interrupt, - * we can complete init by calling config_mac_regs2. + * we can complete init by calling ConfigMacREGS2. */ - et131x_soft_reset(adapter); + et131x_soft_reset(etdev); /* Setup ET1310 as per the documentation */ - et131x_adapter_setup(adapter); + et131x_adapter_setup(etdev); /* Setup the PHY into coma mode until the cable is * plugged back in */ - if (adapter->registry_phy_coma == 1) - et1310_enable_phy_coma(adapter); + if (etdev->RegistryPhyComa == 1) + EnablePhyComa(etdev); } } if ((bmsr_ints & MI_BMSR_AUTO_NEG_COMPLETE) || - (adapter->ai_force_duplex == 3 && (bmsr_ints & MI_BMSR_LINK_STATUS))) { + (etdev->AiForceDpx == 3 && (bmsr_ints & MI_BMSR_LINK_STATUS))) { if ((bmsr & MI_BMSR_AUTO_NEG_COMPLETE) || - adapter->ai_force_duplex == 3) { - et1310_phy_link_status(adapter, + etdev->AiForceDpx == 3) { + ET1310_PhyLinkStatus(etdev, &link_status, &autoneg_status, &speed, &duplex, &mdi_mdix, &masterslave, &polarity); - adapter->linkspeed = speed; - adapter->duplex_mode = duplex; + etdev->linkspeed = speed; + etdev->duplex_mode = duplex; - adapter->boot_coma = 20; + etdev->boot_coma = 20; - if (adapter->linkspeed == TRUEPHY_SPEED_10MBPS) { + if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) { /* * NOTE - Is there a way to query this without * TruePHY? - * && TRU_QueryCoreType(adapter->hTruePhy, 0)== + * && TRU_QueryCoreType(etdev->hTruePhy, 0)== * EMI_TRUEPHY_A13O) { */ - u16 register18; - - et131x_mii_read(adapter, 0x12, ®ister18); - et131x_mii_write(adapter, 0x12, register18 | 0x4); - et131x_mii_write(adapter, 0x10, - register18 | 0x8402); - et131x_mii_write(adapter, 0x11, register18 | 511); - et131x_mii_write(adapter, 0x12, register18); + u16 Register18; + + MiRead(etdev, 0x12, &Register18); + MiWrite(etdev, 0x12, Register18 | 0x4); + MiWrite(etdev, 0x10, Register18 | 0x8402); + MiWrite(etdev, 0x11, Register18 | 511); + MiWrite(etdev, 0x12, Register18); } - et1310_config_flow_control(adapter); + ConfigFlowControl(etdev); - if (adapter->linkspeed == TRUEPHY_SPEED_1000MBPS && - adapter->registry_jumbo_packet > 2048) - et1310_phy_and_or_reg(adapter, 0x16, 0xcfff, + if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS && + etdev->RegistryJumboPacket > 2048) + ET1310_PhyAndOrReg(etdev, 0x16, 0xcfff, 0x2000); - et131x_set_rx_dma_timer(adapter); - et1310_config_mac_regs2(adapter); + SetRxDmaTimer(etdev); + ConfigMACRegs2(etdev); } } } @@ -839,8 +868,9 @@ void et131x_mii_check(struct et131x_adapter *adapter, * primarily by the routines above (although there are a few places elsewhere * in the driver where this level of access is required). */ -static const u16 config_phy[25][2] = { - /* Reg Value Register */ + +static const u16 ConfigPhy[25][2] = { + /* Reg Value Register */ /* Addr */ {0x880B, 0x0926}, /* AfeIfCreg4B1000Msbs */ {0x880C, 0x0926}, /* AfeIfCreg4B100Msbs */ @@ -876,74 +906,74 @@ static const u16 config_phy[25][2] = { {0x8010, 46}, /* IdlguardTime */ {0, 0} + }; /* condensed version of the phy initialization routine */ -void et1310_phy_init(struct et131x_adapter *adapter) +void ET1310_PhyInit(struct et131x_adapter *etdev) { u16 data, index; + if (etdev == NULL) + return; + /* get the identity (again ?) */ - et131x_mii_read(adapter, PHY_ID_1, &data); - et131x_mii_read(adapter, PHY_ID_2, &data); + MiRead(etdev, PHY_ID_1, &data); + MiRead(etdev, PHY_ID_2, &data); /* what does this do/achieve ? */ - /* should read 0002 */ - et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, &data); - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, 0x0006); + MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */ + MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0006); /* read modem register 0402, should I do something with the return data ? */ - et131x_mii_write(adapter, PHY_INDEX_REG, 0x0402); - et131x_mii_read(adapter, PHY_DATA_REG, &data); + MiWrite(etdev, PHY_INDEX_REG, 0x0402); + MiRead(etdev, PHY_DATA_REG, &data); /* what does this do/achieve ? */ - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, 0x0002); + MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002); /* get the identity (again ?) */ - et131x_mii_read(adapter, PHY_ID_1, &data); - et131x_mii_read(adapter, PHY_ID_2, &data); + MiRead(etdev, PHY_ID_1, &data); + MiRead(etdev, PHY_ID_2, &data); /* what does this achieve ? */ - /* should read 0002 */ - et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, &data); - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, 0x0006); + MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */ + MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0006); /* read modem register 0402, should I do something with the return data? */ - et131x_mii_write(adapter, PHY_INDEX_REG, 0x0402); - et131x_mii_read(adapter, PHY_DATA_REG, &data); + MiWrite(etdev, PHY_INDEX_REG, 0x0402); + MiRead(etdev, PHY_DATA_REG, &data); - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, 0x0002); + MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002); /* what does this achieve (should return 0x1040) */ - et131x_mii_read(adapter, PHY_CONTROL, &data); - /* should read 0002 */ - et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, &data); - et131x_mii_write(adapter, PHY_CONTROL, 0x1840); + MiRead(etdev, PHY_CONTROL, &data); + MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */ + MiWrite(etdev, PHY_CONTROL, 0x1840); - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, 0x0007); + MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0007); /* here the writing of the array starts.... */ index = 0; - while (config_phy[index][0] != 0x0000) { + while (ConfigPhy[index][0] != 0x0000) { /* write value */ - et131x_mii_write(adapter, PHY_INDEX_REG, config_phy[index][0]); - et131x_mii_write(adapter, PHY_DATA_REG, config_phy[index][1]); + MiWrite(etdev, PHY_INDEX_REG, ConfigPhy[index][0]); + MiWrite(etdev, PHY_DATA_REG, ConfigPhy[index][1]); /* read it back */ - et131x_mii_write(adapter, PHY_INDEX_REG, config_phy[index][0]); - et131x_mii_read(adapter, PHY_DATA_REG, &data); + MiWrite(etdev, PHY_INDEX_REG, ConfigPhy[index][0]); + MiRead(etdev, PHY_DATA_REG, &data); /* do a check on the value read back ? */ index++; } /* here the writing of the array ends... */ - et131x_mii_read(adapter, PHY_CONTROL, &data); /* 0x1840 */ - /* should read 0007 */ - et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, &data); - et131x_mii_write(adapter, PHY_CONTROL, 0x1040); - et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, 0x0002); + MiRead(etdev, PHY_CONTROL, &data); /* 0x1840 */ + MiRead(etdev, PHY_MPHY_CONTROL_REG, &data);/* should read 0007 */ + MiWrite(etdev, PHY_CONTROL, 0x1040); + MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002); } diff --git a/trunk/drivers/staging/et131x/et1310_pm.c b/trunk/drivers/staging/et131x/et1310_pm.c index 5ebf0645c1ce..29d4d66d345f 100644 --- a/trunk/drivers/staging/et131x/et1310_pm.c +++ b/trunk/drivers/staging/et131x/et1310_pm.c @@ -87,8 +87,8 @@ #include "et131x.h" /** - * et1310_enable_phy_coma - called when network cable is unplugged - * @adapter: pointer to our adapter structure + * EnablePhyComa - called when network cable is unplugged + * @etdev: pointer to our adapter structure * * driver receive an phy status change interrupt while in D0 and check that * phy_status is down. @@ -106,75 +106,75 @@ * indicating linkup status, call the MPDisablePhyComa routine to * restore JAGCore and gigE PHY */ -void et1310_enable_phy_coma(struct et131x_adapter *adapter) +void EnablePhyComa(struct et131x_adapter *etdev) { unsigned long flags; u32 pmcsr; - pmcsr = readl(&adapter->regs->global.pm_csr); + pmcsr = readl(&etdev->regs->global.pm_csr); /* Save the GbE PHY speed and duplex modes. Need to restore this * when cable is plugged back in */ - adapter->pdown_speed = adapter->ai_force_speed; - adapter->pdown_duplex = adapter->ai_force_duplex; + etdev->pdown_speed = etdev->AiForceSpeed; + etdev->pdown_duplex = etdev->AiForceDpx; /* Stop sending packets. */ - spin_lock_irqsave(&adapter->send_hw_lock, flags); - adapter->flags |= fMP_ADAPTER_LOWER_POWER; - spin_unlock_irqrestore(&adapter->send_hw_lock, flags); + spin_lock_irqsave(&etdev->send_hw_lock, flags); + etdev->flags |= fMP_ADAPTER_LOWER_POWER; + spin_unlock_irqrestore(&etdev->send_hw_lock, flags); /* Wait for outstanding Receive packets */ /* Gate off JAGCore 3 clock domains */ pmcsr &= ~ET_PMCSR_INIT; - writel(pmcsr, &adapter->regs->global.pm_csr); + writel(pmcsr, &etdev->regs->global.pm_csr); /* Program gigE PHY in to Coma mode */ pmcsr |= ET_PM_PHY_SW_COMA; - writel(pmcsr, &adapter->regs->global.pm_csr); + writel(pmcsr, &etdev->regs->global.pm_csr); } /** - * et1310_disable_phy_coma - Disable the Phy Coma Mode - * @adapter: pointer to our adapter structure + * DisablePhyComa - Disable the Phy Coma Mode + * @etdev: pointer to our adapter structure */ -void et1310_disable_phy_coma(struct et131x_adapter *adapter) +void DisablePhyComa(struct et131x_adapter *etdev) { u32 pmcsr; - pmcsr = readl(&adapter->regs->global.pm_csr); + pmcsr = readl(&etdev->regs->global.pm_csr); /* Disable phy_sw_coma register and re-enable JAGCore clocks */ pmcsr |= ET_PMCSR_INIT; pmcsr &= ~ET_PM_PHY_SW_COMA; - writel(pmcsr, &adapter->regs->global.pm_csr); + writel(pmcsr, &etdev->regs->global.pm_csr); /* Restore the GbE PHY speed and duplex modes; * Reset JAGCore; re-configure and initialize JAGCore and gigE PHY */ - adapter->ai_force_speed = adapter->pdown_speed; - adapter->ai_force_duplex = adapter->pdown_duplex; + etdev->AiForceSpeed = etdev->pdown_speed; + etdev->AiForceDpx = etdev->pdown_duplex; /* Re-initialize the send structures */ - et131x_init_send(adapter); + et131x_init_send(etdev); /* Reset the RFD list and re-start RU */ - et131x_reset_recv(adapter); + et131x_reset_recv(etdev); /* Bring the device back to the state it was during init prior to * autonegotiation being complete. This way, when we get the auto-neg * complete interrupt, we can complete init by calling ConfigMacREGS2. */ - et131x_soft_reset(adapter); + et131x_soft_reset(etdev); /* setup et1310 as per the documentation ?? */ - et131x_adapter_setup(adapter); + et131x_adapter_setup(etdev); /* Allow Tx to restart */ - adapter->flags &= ~fMP_ADAPTER_LOWER_POWER; + etdev->flags &= ~fMP_ADAPTER_LOWER_POWER; /* Need to re-enable Rx. */ - et131x_rx_dma_enable(adapter); + et131x_rx_dma_enable(etdev); } diff --git a/trunk/drivers/staging/et131x/et1310_rx.c b/trunk/drivers/staging/et131x/et1310_rx.c index e6458dbef934..7e386e07ff97 100644 --- a/trunk/drivers/staging/et131x/et1310_rx.c +++ b/trunk/drivers/staging/et131x/et1310_rx.c @@ -88,22 +88,22 @@ #include "et1310_rx.h" #include "et131x.h" -static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit) +static inline u32 bump_fbr(u32 *fbr, u32 limit) { - u32 tmp_free_buff_ring = *free_buff_ring; - tmp_free_buff_ring++; + u32 v = *fbr; + v++; /* This works for all cases where limit < 1024. The 1023 case works because 1023++ is 1024 which means the if condition is not taken but the carry of the bit into the wrap bit toggles the wrap value correctly */ - if ((tmp_free_buff_ring & ET_DMA10_MASK) > limit) { - tmp_free_buff_ring &= ~ET_DMA10_MASK; - tmp_free_buff_ring ^= ET_DMA10_WRAP; + if ((v & ET_DMA10_MASK) > limit) { + v &= ~ET_DMA10_MASK; + v ^= ET_DMA10_WRAP; } /* For the 1023 case */ - tmp_free_buff_ring &= (ET_DMA10_MASK|ET_DMA10_WRAP); - *free_buff_ring = tmp_free_buff_ring; - return tmp_free_buff_ring; + v &= (ET_DMA10_MASK|ET_DMA10_WRAP); + *fbr = v; + return v; } /** @@ -119,7 +119,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) { u32 i, j; u32 bufsize; - u32 pktstat_ringsize, fbr_chunksize; + u32 pktStatRingSize, FBRChunkSize; struct rx_ring *rx_ring; /* Setup some convenience pointers */ @@ -149,42 +149,42 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) * the number of entries halves. FBR0 increases in size, however. */ - if (adapter->registry_jumbo_packet < 2048) { + if (adapter->RegistryJumboPacket < 2048) { #ifdef USE_FBR0 - rx_ring->fbr0_buffsize = 256; - rx_ring->fbr0_num_entries = 512; + rx_ring->Fbr0BufferSize = 256; + rx_ring->Fbr0NumEntries = 512; #endif - rx_ring->fbr1_buffsize = 2048; - rx_ring->fbr1_num_entries = 512; - } else if (adapter->registry_jumbo_packet < 4096) { + rx_ring->Fbr1BufferSize = 2048; + rx_ring->Fbr1NumEntries = 512; + } else if (adapter->RegistryJumboPacket < 4096) { #ifdef USE_FBR0 - rx_ring->fbr0_buffsize = 512; - rx_ring->fbr0_num_entries = 1024; + rx_ring->Fbr0BufferSize = 512; + rx_ring->Fbr0NumEntries = 1024; #endif - rx_ring->fbr1_buffsize = 4096; - rx_ring->fbr1_num_entries = 512; + rx_ring->Fbr1BufferSize = 4096; + rx_ring->Fbr1NumEntries = 512; } else { #ifdef USE_FBR0 - rx_ring->fbr0_buffsize = 1024; - rx_ring->fbr0_num_entries = 768; + rx_ring->Fbr0BufferSize = 1024; + rx_ring->Fbr0NumEntries = 768; #endif - rx_ring->fbr1_buffsize = 16384; - rx_ring->fbr1_num_entries = 128; + rx_ring->Fbr1BufferSize = 16384; + rx_ring->Fbr1NumEntries = 128; } #ifdef USE_FBR0 - adapter->rx_ring.psr_num_entries = adapter->rx_ring.fbr0_num_entries + - adapter->rx_ring.fbr1_num_entries; + adapter->rx_ring.PsrNumEntries = adapter->rx_ring.Fbr0NumEntries + + adapter->rx_ring.Fbr1NumEntries; #else - adapter->rx_ring.psr_num_entries = adapter->rx_ring.fbr1_num_entries; + adapter->rx_ring.PsrNumEntries = adapter->rx_ring.Fbr1NumEntries; #endif /* Allocate an area of memory for Free Buffer Ring 1 */ - bufsize = (sizeof(struct fbr_desc) * rx_ring->fbr1_num_entries) + 0xfff; - rx_ring->fbr1_ring_virtaddr = pci_alloc_consistent(adapter->pdev, - bufsize, - &rx_ring->fbr1_ring_physaddr); - if (!rx_ring->fbr1_ring_virtaddr) { + bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr1NumEntries) + 0xfff; + rx_ring->pFbr1RingVa = pci_alloc_consistent(adapter->pdev, + bufsize, + &rx_ring->pFbr1RingPa); + if (!rx_ring->pFbr1RingVa) { dev_err(&adapter->pdev->dev, "Cannot alloc memory for Free Buffer Ring 1\n"); return -ENOMEM; @@ -197,24 +197,23 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) * are ever returned, make sure the high part is retrieved here * before storing the adjusted address. */ - rx_ring->fbr1_real_physaddr = rx_ring->fbr1_ring_physaddr; + rx_ring->Fbr1Realpa = rx_ring->pFbr1RingPa; /* Align Free Buffer Ring 1 on a 4K boundary */ et131x_align_allocated_memory(adapter, - &rx_ring->fbr1_real_physaddr, - &rx_ring->fbr1_offset, 0x0FFF); + &rx_ring->Fbr1Realpa, + &rx_ring->Fbr1offset, 0x0FFF); - rx_ring->fbr1_ring_virtaddr = - (void *)((u8 *) rx_ring->fbr1_ring_virtaddr + - rx_ring->fbr1_offset); + rx_ring->pFbr1RingVa = (void *)((u8 *) rx_ring->pFbr1RingVa + + rx_ring->Fbr1offset); #ifdef USE_FBR0 /* Allocate an area of memory for Free Buffer Ring 0 */ - bufsize = (sizeof(struct fbr_desc) * rx_ring->fbr0_num_entries) + 0xfff; - rx_ring->fbr0_ring_virtaddr = pci_alloc_consistent(adapter->pdev, - bufsize, - &rx_ring->fbr0_ring_physaddr); - if (!rx_ring->fbr0_ring_virtaddr) { + bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr0NumEntries) + 0xfff; + rx_ring->pFbr0RingVa = pci_alloc_consistent(adapter->pdev, + bufsize, + &rx_ring->pFbr0RingPa); + if (!rx_ring->pFbr0RingVa) { dev_err(&adapter->pdev->dev, "Cannot alloc memory for Free Buffer Ring 0\n"); return -ENOMEM; @@ -227,21 +226,22 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) * are ever returned, make sure the high part is retrieved here before * storing the adjusted address. */ - rx_ring->fbr0_real_physaddr = rx_ring->fbr0_ring_physaddr; + rx_ring->Fbr0Realpa = rx_ring->pFbr0RingPa; /* Align Free Buffer Ring 0 on a 4K boundary */ et131x_align_allocated_memory(adapter, - &rx_ring->fbr0_real_physaddr, - &rx_ring->fbr0_offset, 0x0FFF); + &rx_ring->Fbr0Realpa, + &rx_ring->Fbr0offset, 0x0FFF); - rx_ring->fbr0_ring_virtaddr = - (void *)((u8 *) rx_ring->fbr0_ring_virtaddr + - rx_ring->fbr0_offset); + rx_ring->pFbr0RingVa = (void *)((u8 *) rx_ring->pFbr0RingVa + + rx_ring->Fbr0offset); #endif - for (i = 0; i < (rx_ring->fbr1_num_entries / FBR_CHUNKS); i++) { - u64 fbr1_offset; - u64 fbr1_tmp_physaddr; - u32 fbr1_align; + + for (i = 0; i < (rx_ring->Fbr1NumEntries / FBR_CHUNKS); + i++) { + u64 Fbr1Offset; + u64 Fbr1TempPa; + u32 Fbr1Align; /* This code allocates an area of memory big enough for N * free buffers + (buffer_size - 1) so that the buffers can @@ -250,29 +250,29 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) * the size of FBR0. By allocating N buffers at once, we * reduce this overhead. */ - if (rx_ring->fbr1_buffsize > 4096) - fbr1_align = 4096; + if (rx_ring->Fbr1BufferSize > 4096) + Fbr1Align = 4096; else - fbr1_align = rx_ring->fbr1_buffsize; + Fbr1Align = rx_ring->Fbr1BufferSize; - fbr_chunksize = - (FBR_CHUNKS * rx_ring->fbr1_buffsize) + fbr1_align - 1; - rx_ring->fbr1_mem_virtaddrs[i] = - pci_alloc_consistent(adapter->pdev, fbr_chunksize, - &rx_ring->fbr1_mem_physaddrs[i]); + FBRChunkSize = + (FBR_CHUNKS * rx_ring->Fbr1BufferSize) + Fbr1Align - 1; + rx_ring->Fbr1MemVa[i] = + pci_alloc_consistent(adapter->pdev, FBRChunkSize, + &rx_ring->Fbr1MemPa[i]); - if (!rx_ring->fbr1_mem_virtaddrs[i]) { + if (!rx_ring->Fbr1MemVa[i]) { dev_err(&adapter->pdev->dev, "Could not alloc memory\n"); return -ENOMEM; } /* See NOTE in "Save Physical Address" comment above */ - fbr1_tmp_physaddr = rx_ring->fbr1_mem_physaddrs[i]; + Fbr1TempPa = rx_ring->Fbr1MemPa[i]; et131x_align_allocated_memory(adapter, - &fbr1_tmp_physaddr, - &fbr1_offset, (fbr1_align - 1)); + &Fbr1TempPa, + &Fbr1Offset, (Fbr1Align - 1)); for (j = 0; j < FBR_CHUNKS; j++) { u32 index = (i * FBR_CHUNKS) + j; @@ -281,18 +281,17 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) * access later */ rx_ring->fbr[1]->virt[index] = - (u8 *) rx_ring->fbr1_mem_virtaddrs[i] + - (j * rx_ring->fbr1_buffsize) + fbr1_offset; + (u8 *) rx_ring->Fbr1MemVa[i] + + (j * rx_ring->Fbr1BufferSize) + Fbr1Offset; /* now store the physical address in the descriptor * so the device can access it */ rx_ring->fbr[1]->bus_high[index] = - (u32) (fbr1_tmp_physaddr >> 32); - rx_ring->fbr[1]->bus_low[index] = - (u32) fbr1_tmp_physaddr; + (u32) (Fbr1TempPa >> 32); + rx_ring->fbr[1]->bus_low[index] = (u32) Fbr1TempPa; - fbr1_tmp_physaddr += rx_ring->fbr1_buffsize; + Fbr1TempPa += rx_ring->Fbr1BufferSize; rx_ring->fbr[1]->buffer1[index] = rx_ring->fbr[1]->virt[index]; @@ -303,43 +302,42 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) #ifdef USE_FBR0 /* Same for FBR0 (if in use) */ - for (i = 0; i < (rx_ring->fbr0_num_entries / FBR_CHUNKS); i++) { - u64 fbr0_offset; - u64 fbr0_tmp_physaddr; + for (i = 0; i < (rx_ring->Fbr0NumEntries / FBR_CHUNKS); + i++) { + u64 Fbr0Offset; + u64 Fbr0TempPa; - fbr_chunksize = - ((FBR_CHUNKS + 1) * rx_ring->fbr0_buffsize) - 1; - rx_ring->fbr0_mem_virtaddrs[i] = - pci_alloc_consistent(adapter->pdev, fbr_chunksize, - &rx_ring->fbr0_mem_physaddrs[i]); + FBRChunkSize = ((FBR_CHUNKS + 1) * rx_ring->Fbr0BufferSize) - 1; + rx_ring->Fbr0MemVa[i] = + pci_alloc_consistent(adapter->pdev, FBRChunkSize, + &rx_ring->Fbr0MemPa[i]); - if (!rx_ring->fbr0_mem_virtaddrs[i]) { + if (!rx_ring->Fbr0MemVa[i]) { dev_err(&adapter->pdev->dev, "Could not alloc memory\n"); return -ENOMEM; } /* See NOTE in "Save Physical Address" comment above */ - fbr0_tmp_physaddr = rx_ring->fbr0_mem_physaddrs[i]; + Fbr0TempPa = rx_ring->Fbr0MemPa[i]; et131x_align_allocated_memory(adapter, - &fbr0_tmp_physaddr, - &fbr0_offset, - rx_ring->fbr0_buffsize - 1); + &Fbr0TempPa, + &Fbr0Offset, + rx_ring->Fbr0BufferSize - 1); for (j = 0; j < FBR_CHUNKS; j++) { u32 index = (i * FBR_CHUNKS) + j; rx_ring->fbr[0]->virt[index] = - (u8 *) rx_ring->fbr0_mem_virtaddrs[i] + - (j * rx_ring->fbr0_buffsize) + fbr0_offset; + (u8 *) rx_ring->Fbr0MemVa[i] + + (j * rx_ring->Fbr0BufferSize) + Fbr0Offset; rx_ring->fbr[0]->bus_high[index] = - (u32) (fbr0_tmp_physaddr >> 32); - rx_ring->fbr[0]->bus_low[index] = - (u32) fbr0_tmp_physaddr; + (u32) (Fbr0TempPa >> 32); + rx_ring->fbr[0]->bus_low[index] = (u32) Fbr0TempPa; - fbr0_tmp_physaddr += rx_ring->fbr0_buffsize; + Fbr0TempPa += rx_ring->Fbr0BufferSize; rx_ring->fbr[0]->buffer1[index] = rx_ring->fbr[0]->virt[index]; @@ -350,20 +348,19 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) #endif /* Allocate an area of memory for FIFO of Packet Status ring entries */ - pktstat_ringsize = - sizeof(struct pkt_stat_desc) * adapter->rx_ring.psr_num_entries; + pktStatRingSize = + sizeof(struct pkt_stat_desc) * adapter->rx_ring.PsrNumEntries; - rx_ring->ps_ring_virtaddr = pci_alloc_consistent(adapter->pdev, - pktstat_ringsize, - &rx_ring->ps_ring_physaddr); + rx_ring->pPSRingVa = pci_alloc_consistent(adapter->pdev, + pktStatRingSize, + &rx_ring->pPSRingPa); - if (!rx_ring->ps_ring_virtaddr) { + if (!rx_ring->pPSRingVa) { dev_err(&adapter->pdev->dev, "Cannot alloc memory for Packet Status Ring\n"); return -ENOMEM; } - printk(KERN_INFO "Packet Status Ring %lx\n", - (unsigned long) rx_ring->ps_ring_physaddr); + printk(KERN_INFO "PSR %lx\n", (unsigned long) rx_ring->pPSRingPa); /* * NOTE : pci_alloc_consistent(), used above to alloc DMA regions, @@ -381,7 +378,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) "Cannot alloc memory for Status Block\n"); return -ENOMEM; } - rx_ring->num_rfd = NIC_DEFAULT_NUM_RFD; + rx_ring->NumRfd = NIC_DEFAULT_NUM_RFD; printk(KERN_INFO "PRS %lx\n", (unsigned long)rx_ring->rx_status_bus); /* Recv @@ -390,7 +387,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) * freed to the lookaside list. * RFDs will be allocated from this pool. */ - rx_ring->recv_lookaside = kmem_cache_create(adapter->netdev->name, + rx_ring->RecvLookaside = kmem_cache_create(adapter->netdev->name, sizeof(struct rfd), 0, SLAB_CACHE_DMA | @@ -402,7 +399,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) /* The RFDs are going to be put on lists later on, so initialize the * lists now. */ - INIT_LIST_HEAD(&rx_ring->recv_list); + INIT_LIST_HEAD(&rx_ring->RecvList); return 0; } @@ -414,7 +411,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) { u32 index; u32 bufsize; - u32 pktstat_ringsize; + u32 pktStatRingSize; struct rfd *rfd; struct rx_ring *rx_ring; @@ -422,104 +419,100 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) rx_ring = &adapter->rx_ring; /* Free RFDs and associated packet descriptors */ - WARN_ON(rx_ring->num_ready_recv != rx_ring->num_rfd); + WARN_ON(rx_ring->nReadyRecv != rx_ring->NumRfd); - while (!list_empty(&rx_ring->recv_list)) { - rfd = (struct rfd *) list_entry(rx_ring->recv_list.next, + while (!list_empty(&rx_ring->RecvList)) { + rfd = (struct rfd *) list_entry(rx_ring->RecvList.next, struct rfd, list_node); list_del(&rfd->list_node); rfd->skb = NULL; - kmem_cache_free(adapter->rx_ring.recv_lookaside, rfd); + kmem_cache_free(adapter->rx_ring.RecvLookaside, rfd); } /* Free Free Buffer Ring 1 */ - if (rx_ring->fbr1_ring_virtaddr) { + if (rx_ring->pFbr1RingVa) { /* First the packet memory */ for (index = 0; index < - (rx_ring->fbr1_num_entries / FBR_CHUNKS); index++) { - if (rx_ring->fbr1_mem_virtaddrs[index]) { - u32 fbr1_align; + (rx_ring->Fbr1NumEntries / FBR_CHUNKS); index++) { + if (rx_ring->Fbr1MemVa[index]) { + u32 Fbr1Align; - if (rx_ring->fbr1_buffsize > 4096) - fbr1_align = 4096; + if (rx_ring->Fbr1BufferSize > 4096) + Fbr1Align = 4096; else - fbr1_align = rx_ring->fbr1_buffsize; + Fbr1Align = rx_ring->Fbr1BufferSize; bufsize = - (rx_ring->fbr1_buffsize * FBR_CHUNKS) + - fbr1_align - 1; + (rx_ring->Fbr1BufferSize * FBR_CHUNKS) + + Fbr1Align - 1; pci_free_consistent(adapter->pdev, - bufsize, - rx_ring->fbr1_mem_virtaddrs[index], - rx_ring->fbr1_mem_physaddrs[index]); + bufsize, + rx_ring->Fbr1MemVa[index], + rx_ring->Fbr1MemPa[index]); - rx_ring->fbr1_mem_virtaddrs[index] = NULL; + rx_ring->Fbr1MemVa[index] = NULL; } } /* Now the FIFO itself */ - rx_ring->fbr1_ring_virtaddr = (void *)((u8 *) - rx_ring->fbr1_ring_virtaddr - rx_ring->fbr1_offset); + rx_ring->pFbr1RingVa = (void *)((u8 *) + rx_ring->pFbr1RingVa - rx_ring->Fbr1offset); - bufsize = (sizeof(struct fbr_desc) * rx_ring->fbr1_num_entries) + bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr1NumEntries) + 0xfff; pci_free_consistent(adapter->pdev, bufsize, - rx_ring->fbr1_ring_virtaddr, - rx_ring->fbr1_ring_physaddr); + rx_ring->pFbr1RingVa, rx_ring->pFbr1RingPa); - rx_ring->fbr1_ring_virtaddr = NULL; + rx_ring->pFbr1RingVa = NULL; } #ifdef USE_FBR0 /* Now the same for Free Buffer Ring 0 */ - if (rx_ring->fbr0_ring_virtaddr) { + if (rx_ring->pFbr0RingVa) { /* First the packet memory */ for (index = 0; index < - (rx_ring->fbr0_num_entries / FBR_CHUNKS); index++) { - if (rx_ring->fbr0_mem_virtaddrs[index]) { + (rx_ring->Fbr0NumEntries / FBR_CHUNKS); index++) { + if (rx_ring->Fbr0MemVa[index]) { bufsize = - (rx_ring->fbr0_buffsize * + (rx_ring->Fbr0BufferSize * (FBR_CHUNKS + 1)) - 1; pci_free_consistent(adapter->pdev, - bufsize, - rx_ring->fbr0_mem_virtaddrs[index], - rx_ring->fbr0_mem_physaddrs[index]); + bufsize, + rx_ring->Fbr0MemVa[index], + rx_ring->Fbr0MemPa[index]); - rx_ring->fbr0_mem_virtaddrs[index] = NULL; + rx_ring->Fbr0MemVa[index] = NULL; } } /* Now the FIFO itself */ - rx_ring->fbr0_ring_virtaddr = (void *)((u8 *) - rx_ring->fbr0_ring_virtaddr - rx_ring->fbr0_offset); + rx_ring->pFbr0RingVa = (void *)((u8 *) + rx_ring->pFbr0RingVa - rx_ring->Fbr0offset); - bufsize = (sizeof(struct fbr_desc) * rx_ring->fbr0_num_entries) + bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr0NumEntries) + 0xfff; pci_free_consistent(adapter->pdev, bufsize, - rx_ring->fbr0_ring_virtaddr, - rx_ring->fbr0_ring_physaddr); + rx_ring->pFbr0RingVa, rx_ring->pFbr0RingPa); - rx_ring->fbr0_ring_virtaddr = NULL; + rx_ring->pFbr0RingVa = NULL; } #endif /* Free Packet Status Ring */ - if (rx_ring->ps_ring_virtaddr) { - pktstat_ringsize = - sizeof(struct pkt_stat_desc) * - adapter->rx_ring.psr_num_entries; + if (rx_ring->pPSRingVa) { + pktStatRingSize = + sizeof(struct pkt_stat_desc) * adapter->rx_ring.PsrNumEntries; - pci_free_consistent(adapter->pdev, pktstat_ringsize, - rx_ring->ps_ring_virtaddr, - rx_ring->ps_ring_physaddr); + pci_free_consistent(adapter->pdev, pktStatRingSize, + rx_ring->pPSRingVa, rx_ring->pPSRingPa); - rx_ring->ps_ring_virtaddr = NULL; + rx_ring->pPSRingVa = NULL; } /* Free area of memory for the writeback of status information */ @@ -536,7 +529,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) /* Destroy the lookaside (RFD) pool */ if (adapter->flags & fMP_ADAPTER_RECV_LOOKASIDE) { - kmem_cache_destroy(rx_ring->recv_lookaside); + kmem_cache_destroy(rx_ring->RecvLookaside); adapter->flags &= ~fMP_ADAPTER_RECV_LOOKASIDE; } @@ -548,7 +541,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) kfree(rx_ring->fbr[1]); /* Reset Counters */ - rx_ring->num_ready_recv = 0; + rx_ring->nReadyRecv = 0; } /** @@ -569,8 +562,8 @@ int et131x_init_recv(struct et131x_adapter *adapter) rx_ring = &adapter->rx_ring; /* Setup each RFD */ - for (rfdct = 0; rfdct < rx_ring->num_rfd; rfdct++) { - rfd = kmem_cache_alloc(rx_ring->recv_lookaside, + for (rfdct = 0; rfdct < rx_ring->NumRfd; rfdct++) { + rfd = kmem_cache_alloc(rx_ring->RecvLookaside, GFP_ATOMIC | GFP_DMA); if (!rfd) { @@ -582,21 +575,21 @@ int et131x_init_recv(struct et131x_adapter *adapter) rfd->skb = NULL; - /* Add this RFD to the recv_list */ - list_add_tail(&rfd->list_node, &rx_ring->recv_list); + /* Add this RFD to the RecvList */ + list_add_tail(&rfd->list_node, &rx_ring->RecvList); /* Increment both the available RFD's, and the total RFD's. */ - rx_ring->num_ready_recv++; + rx_ring->nReadyRecv++; numrfd++; } if (numrfd > NIC_MIN_NUM_RFD) status = 0; - rx_ring->num_rfd = numrfd; + rx_ring->NumRfd = numrfd; if (status != 0) { - kmem_cache_free(rx_ring->recv_lookaside, rfd); + kmem_cache_free(rx_ring->RecvLookaside, rfd); dev_err(&adapter->pdev->dev, "Allocation problems in et131x_init_recv\n"); } @@ -604,20 +597,20 @@ int et131x_init_recv(struct et131x_adapter *adapter) } /** - * et131x_config_rx_dma_regs - Start of Rx_DMA init sequence - * @adapter: pointer to our adapter structure + * ConfigRxDmaRegs - Start of Rx_DMA init sequence + * @etdev: pointer to our adapter structure */ -void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) +void ConfigRxDmaRegs(struct et131x_adapter *etdev) { - struct rxdma_regs __iomem *rx_dma = &adapter->regs->rxdma; - struct rx_ring *rx_local = &adapter->rx_ring; + struct rxdma_regs __iomem *rx_dma = &etdev->regs->rxdma; + struct rx_ring *rx_local = &etdev->rx_ring; struct fbr_desc *fbr_entry; u32 entry; u32 psr_num_des; unsigned long flags; /* Halt RXDMA to perform the reconfigure. */ - et131x_rx_dma_disable(adapter); + et131x_rx_dma_disable(etdev); /* Load the completion writeback physical address * @@ -635,24 +628,24 @@ void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) /* Set the address and parameters of the packet status ring into the * 1310's registers */ - writel((u32) ((u64)rx_local->ps_ring_physaddr >> 32), + writel((u32) ((u64)rx_local->pPSRingPa >> 32), &rx_dma->psr_base_hi); - writel((u32) rx_local->ps_ring_physaddr, &rx_dma->psr_base_lo); - writel(rx_local->psr_num_entries - 1, &rx_dma->psr_num_des); + writel((u32) rx_local->pPSRingPa, &rx_dma->psr_base_lo); + writel(rx_local->PsrNumEntries - 1, &rx_dma->psr_num_des); writel(0, &rx_dma->psr_full_offset); psr_num_des = readl(&rx_dma->psr_num_des) & 0xFFF; writel((psr_num_des * LO_MARK_PERCENT_FOR_PSR) / 100, &rx_dma->psr_min_des); - spin_lock_irqsave(&adapter->rcv_lock, flags); + spin_lock_irqsave(&etdev->rcv_lock, flags); /* These local variables track the PSR in the adapter structure */ rx_local->local_psr_full = 0; /* Now's the best time to initialize FBR1 contents */ - fbr_entry = (struct fbr_desc *) rx_local->fbr1_ring_virtaddr; - for (entry = 0; entry < rx_local->fbr1_num_entries; entry++) { + fbr_entry = (struct fbr_desc *) rx_local->pFbr1RingVa; + for (entry = 0; entry < rx_local->Fbr1NumEntries; entry++) { fbr_entry->addr_hi = rx_local->fbr[1]->bus_high[entry]; fbr_entry->addr_lo = rx_local->fbr[1]->bus_low[entry]; fbr_entry->word2 = entry; @@ -662,43 +655,39 @@ void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) /* Set the address and parameters of Free buffer ring 1 (and 0 if * required) into the 1310's registers */ - writel((u32) (rx_local->fbr1_real_physaddr >> 32), - &rx_dma->fbr1_base_hi); - writel((u32) rx_local->fbr1_real_physaddr, &rx_dma->fbr1_base_lo); - writel(rx_local->fbr1_num_entries - 1, &rx_dma->fbr1_num_des); + writel((u32) (rx_local->Fbr1Realpa >> 32), &rx_dma->fbr1_base_hi); + writel((u32) rx_local->Fbr1Realpa, &rx_dma->fbr1_base_lo); + writel(rx_local->Fbr1NumEntries - 1, &rx_dma->fbr1_num_des); writel(ET_DMA10_WRAP, &rx_dma->fbr1_full_offset); /* This variable tracks the free buffer ring 1 full position, so it * has to match the above. */ - rx_local->local_fbr1_full = ET_DMA10_WRAP; - writel( - ((rx_local->fbr1_num_entries * LO_MARK_PERCENT_FOR_RX) / 100) - 1, - &rx_dma->fbr1_min_des); + rx_local->local_Fbr1_full = ET_DMA10_WRAP; + writel(((rx_local->Fbr1NumEntries * LO_MARK_PERCENT_FOR_RX) / 100) - 1, + &rx_dma->fbr1_min_des); #ifdef USE_FBR0 /* Now's the best time to initialize FBR0 contents */ - fbr_entry = (struct fbr_desc *) rx_local->fbr0_ring_virtaddr; - for (entry = 0; entry < rx_local->fbr0_num_entries; entry++) { + fbr_entry = (struct fbr_desc *) rx_local->pFbr0RingVa; + for (entry = 0; entry < rx_local->Fbr0NumEntries; entry++) { fbr_entry->addr_hi = rx_local->fbr[0]->bus_high[entry]; fbr_entry->addr_lo = rx_local->fbr[0]->bus_low[entry]; fbr_entry->word2 = entry; fbr_entry++; } - writel((u32) (rx_local->fbr0_real_physaddr >> 32), - &rx_dma->fbr0_base_hi); - writel((u32) rx_local->fbr0_real_physaddr, &rx_dma->fbr0_base_lo); - writel(rx_local->fbr0_num_entries - 1, &rx_dma->fbr0_num_des); + writel((u32) (rx_local->Fbr0Realpa >> 32), &rx_dma->fbr0_base_hi); + writel((u32) rx_local->Fbr0Realpa, &rx_dma->fbr0_base_lo); + writel(rx_local->Fbr0NumEntries - 1, &rx_dma->fbr0_num_des); writel(ET_DMA10_WRAP, &rx_dma->fbr0_full_offset); /* This variable tracks the free buffer ring 0 full position, so it * has to match the above. */ - rx_local->local_fbr0_full = ET_DMA10_WRAP; - writel( - ((rx_local->fbr0_num_entries * LO_MARK_PERCENT_FOR_RX) / 100) - 1, - &rx_dma->fbr0_min_des); + rx_local->local_Fbr0_full = ET_DMA10_WRAP; + writel(((rx_local->Fbr0NumEntries * LO_MARK_PERCENT_FOR_RX) / 100) - 1, + &rx_dma->fbr0_min_des); #endif /* Program the number of packets we will receive before generating an @@ -715,36 +704,36 @@ void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) */ writel(PARM_RX_TIME_INT_DEF, &rx_dma->max_pkt_time); - spin_unlock_irqrestore(&adapter->rcv_lock, flags); + spin_unlock_irqrestore(&etdev->rcv_lock, flags); } /** - * et131x_set_rx_dma_timer - Set the heartbeat timer according to line rate. - * @adapter: pointer to our adapter structure + * SetRxDmaTimer - Set the heartbeat timer according to line rate. + * @etdev: pointer to our adapter structure */ -void et131x_set_rx_dma_timer(struct et131x_adapter *adapter) +void SetRxDmaTimer(struct et131x_adapter *etdev) { /* For version B silicon, we do not use the RxDMA timer for 10 and 100 * Mbits/s line rates. We do not enable and RxDMA interrupt coalescing. */ - if ((adapter->linkspeed == TRUEPHY_SPEED_100MBPS) || - (adapter->linkspeed == TRUEPHY_SPEED_10MBPS)) { - writel(0, &adapter->regs->rxdma.max_pkt_time); - writel(1, &adapter->regs->rxdma.num_pkt_done); + if ((etdev->linkspeed == TRUEPHY_SPEED_100MBPS) || + (etdev->linkspeed == TRUEPHY_SPEED_10MBPS)) { + writel(0, &etdev->regs->rxdma.max_pkt_time); + writel(1, &etdev->regs->rxdma.num_pkt_done); } } /** * NICReturnRFD - Recycle a RFD and put it back onto the receive list - * @adapter: pointer to our adapter + * @etdev: pointer to our adapter * @rfd: pointer to the RFD */ -static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd) +void nic_return_rfd(struct et131x_adapter *etdev, struct rfd *rfd) { - struct rx_ring *rx_local = &adapter->rx_ring; - struct rxdma_regs __iomem *rx_dma = &adapter->regs->rxdma; - u16 buff_index = rfd->bufferindex; - u8 ring_index = rfd->ringindex; + struct rx_ring *rx_local = &etdev->rx_ring; + struct rxdma_regs __iomem *rx_dma = &etdev->regs->rxdma; + u16 bi = rfd->bufferindex; + u8 ri = rfd->ringindex; unsigned long flags; /* We don't use any of the OOB data besides status. Otherwise, we @@ -752,79 +741,79 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd) */ if ( #ifdef USE_FBR0 - (ring_index == 0 && buff_index < rx_local->fbr0_num_entries) || + (ri == 0 && bi < rx_local->Fbr0NumEntries) || #endif - (ring_index == 1 && buff_index < rx_local->fbr1_num_entries)) { - spin_lock_irqsave(&adapter->fbr_lock, flags); + (ri == 1 && bi < rx_local->Fbr1NumEntries)) { + spin_lock_irqsave(&etdev->FbrLock, flags); - if (ring_index == 1) { + if (ri == 1) { struct fbr_desc *next = - (struct fbr_desc *) (rx_local->fbr1_ring_virtaddr) + - INDEX10(rx_local->local_fbr1_full); + (struct fbr_desc *) (rx_local->pFbr1RingVa) + + INDEX10(rx_local->local_Fbr1_full); /* Handle the Free Buffer Ring advancement here. Write * the PA / Buffer Index for the returned buffer into * the oldest (next to be freed)FBR entry */ - next->addr_hi = rx_local->fbr[1]->bus_high[buff_index]; - next->addr_lo = rx_local->fbr[1]->bus_low[buff_index]; - next->word2 = buff_index; + next->addr_hi = rx_local->fbr[1]->bus_high[bi]; + next->addr_lo = rx_local->fbr[1]->bus_low[bi]; + next->word2 = bi; - writel(bump_free_buff_ring(&rx_local->local_fbr1_full, - rx_local->fbr1_num_entries - 1), + writel(bump_fbr(&rx_local->local_Fbr1_full, + rx_local->Fbr1NumEntries - 1), &rx_dma->fbr1_full_offset); } #ifdef USE_FBR0 else { struct fbr_desc *next = (struct fbr_desc *) - rx_local->fbr0_ring_virtaddr + - INDEX10(rx_local->local_fbr0_full); + rx_local->pFbr0RingVa + + INDEX10(rx_local->local_Fbr0_full); /* Handle the Free Buffer Ring advancement here. Write * the PA / Buffer Index for the returned buffer into * the oldest (next to be freed) FBR entry */ - next->addr_hi = rx_local->fbr[0]->bus_high[buff_index]; - next->addr_lo = rx_local->fbr[0]->bus_low[buff_index]; - next->word2 = buff_index; + next->addr_hi = rx_local->fbr[0]->bus_high[bi]; + next->addr_lo = rx_local->fbr[0]->bus_low[bi]; + next->word2 = bi; - writel(bump_free_buff_ring(&rx_local->local_fbr0_full, - rx_local->fbr0_num_entries - 1), + writel(bump_fbr(&rx_local->local_Fbr0_full, + rx_local->Fbr0NumEntries - 1), &rx_dma->fbr0_full_offset); } #endif - spin_unlock_irqrestore(&adapter->fbr_lock, flags); + spin_unlock_irqrestore(&etdev->FbrLock, flags); } else { - dev_err(&adapter->pdev->dev, - "%s illegal Buffer Index returned\n", __func__); + dev_err(&etdev->pdev->dev, + "NICReturnRFD illegal Buffer Index returned\n"); } /* The processing on this RFD is done, so put it back on the tail of * our list */ - spin_lock_irqsave(&adapter->rcv_lock, flags); - list_add_tail(&rfd->list_node, &rx_local->recv_list); - rx_local->num_ready_recv++; - spin_unlock_irqrestore(&adapter->rcv_lock, flags); + spin_lock_irqsave(&etdev->rcv_lock, flags); + list_add_tail(&rfd->list_node, &rx_local->RecvList); + rx_local->nReadyRecv++; + spin_unlock_irqrestore(&etdev->rcv_lock, flags); - WARN_ON(rx_local->num_ready_recv > rx_local->num_rfd); + WARN_ON(rx_local->nReadyRecv > rx_local->NumRfd); } /** * et131x_rx_dma_disable - Stop of Rx_DMA on the ET1310 - * @adapter: pointer to our adapter structure + * @etdev: pointer to our adapter structure */ -void et131x_rx_dma_disable(struct et131x_adapter *adapter) +void et131x_rx_dma_disable(struct et131x_adapter *etdev) { u32 csr; /* Setup the receive dma configuration register */ - writel(0x00002001, &adapter->regs->rxdma.csr); - csr = readl(&adapter->regs->rxdma.csr); + writel(0x00002001, &etdev->regs->rxdma.csr); + csr = readl(&etdev->regs->rxdma.csr); if ((csr & 0x00020000) == 0) { /* Check halt status (bit 17) */ udelay(5); - csr = readl(&adapter->regs->rxdma.csr); + csr = readl(&etdev->regs->rxdma.csr); if ((csr & 0x00020000) == 0) - dev_err(&adapter->pdev->dev, + dev_err(&etdev->pdev->dev, "RX Dma failed to enter halt state. CSR 0x%08x\n", csr); } @@ -832,36 +821,36 @@ void et131x_rx_dma_disable(struct et131x_adapter *adapter) /** * et131x_rx_dma_enable - re-start of Rx_DMA on the ET1310. - * @adapter: pointer to our adapter structure + * @etdev: pointer to our adapter structure */ -void et131x_rx_dma_enable(struct et131x_adapter *adapter) +void et131x_rx_dma_enable(struct et131x_adapter *etdev) { /* Setup the receive dma configuration register for normal operation */ u32 csr = 0x2000; /* FBR1 enable */ - if (adapter->rx_ring.fbr1_buffsize == 4096) + if (etdev->rx_ring.Fbr1BufferSize == 4096) csr |= 0x0800; - else if (adapter->rx_ring.fbr1_buffsize == 8192) + else if (etdev->rx_ring.Fbr1BufferSize == 8192) csr |= 0x1000; - else if (adapter->rx_ring.fbr1_buffsize == 16384) + else if (etdev->rx_ring.Fbr1BufferSize == 16384) csr |= 0x1800; #ifdef USE_FBR0 csr |= 0x0400; /* FBR0 enable */ - if (adapter->rx_ring.fbr0_buffsize == 256) + if (etdev->rx_ring.Fbr0BufferSize == 256) csr |= 0x0100; - else if (adapter->rx_ring.fbr0_buffsize == 512) + else if (etdev->rx_ring.Fbr0BufferSize == 512) csr |= 0x0200; - else if (adapter->rx_ring.fbr0_buffsize == 1024) + else if (etdev->rx_ring.Fbr0BufferSize == 1024) csr |= 0x0300; #endif - writel(csr, &adapter->regs->rxdma.csr); + writel(csr, &etdev->regs->rxdma.csr); - csr = readl(&adapter->regs->rxdma.csr); + csr = readl(&etdev->regs->rxdma.csr); if ((csr & 0x00020000) != 0) { udelay(5); - csr = readl(&adapter->regs->rxdma.csr); + csr = readl(&etdev->regs->rxdma.csr); if ((csr & 0x00020000) != 0) { - dev_err(&adapter->pdev->dev, + dev_err(&etdev->pdev->dev, "RX Dma failed to exit halt state. CSR 0x%08x\n", csr); } @@ -870,18 +859,18 @@ void et131x_rx_dma_enable(struct et131x_adapter *adapter) /** * nic_rx_pkts - Checks the hardware for available packets - * @adapter: pointer to our adapter + * @etdev: pointer to our adapter * * Returns rfd, a pointer to our MPRFD. * * Checks the hardware for available packets, using completion ring - * If packets are available, it gets an RFD from the recv_list, attaches + * If packets are available, it gets an RFD from the RecvList, attaches * the packet to it, puts the RFD in the RecvPendList, and also returns * the pointer to the RFD. */ -static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) +struct rfd *nic_rx_pkts(struct et131x_adapter *etdev) { - struct rx_ring *rx_local = &adapter->rx_ring; + struct rx_ring *rx_local = &etdev->rx_ring; struct rx_status_block *status; struct pkt_stat_desc *psr; struct rfd *rfd; @@ -889,8 +878,8 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) u8 *buf; unsigned long flags; struct list_head *element; - u8 ring_index; - u16 buff_index; + u8 rindex; + u16 bindex; u32 len; u32 word0; u32 word1; @@ -900,7 +889,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) * Status Ring, and also the two Free Buffer rings. */ status = rx_local->rx_status_block; - word1 = status->word1 >> 16; /* Get the useful bits */ + word1 = status->Word1 >> 16; /* Get the useful bits */ /* Check the PSR and wrap bits do not match */ if ((word1 & 0x1FFF) == (rx_local->local_psr_full & 0x1FFF)) @@ -908,7 +897,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) return NULL; /* The packet status ring indicates that data is available. */ - psr = (struct pkt_stat_desc *) (rx_local->ps_ring_virtaddr) + + psr = (struct pkt_stat_desc *) (rx_local->pPSRingVa) + (rx_local->local_psr_full & 0xFFF); /* Grab any information that is required once the PSR is @@ -916,66 +905,65 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) * accurate */ len = psr->word1 & 0xFFFF; - ring_index = (psr->word1 >> 26) & 0x03; - buff_index = (psr->word1 >> 16) & 0x3FF; + rindex = (psr->word1 >> 26) & 0x03; + bindex = (psr->word1 >> 16) & 0x3FF; word0 = psr->word0; /* Indicate that we have used this PSR entry. */ /* FIXME wrap 12 */ add_12bit(&rx_local->local_psr_full, 1); - if ( - (rx_local->local_psr_full & 0xFFF) > rx_local->psr_num_entries - 1) { + if ((rx_local->local_psr_full & 0xFFF) > rx_local->PsrNumEntries - 1) { /* Clear psr full and toggle the wrap bit */ rx_local->local_psr_full &= ~0xFFF; rx_local->local_psr_full ^= 0x1000; } writel(rx_local->local_psr_full, - &adapter->regs->rxdma.psr_full_offset); + &etdev->regs->rxdma.psr_full_offset); #ifndef USE_FBR0 - if (ring_index != 1) + if (rindex != 1) return NULL; #endif #ifdef USE_FBR0 - if (ring_index > 1 || - (ring_index == 0 && - buff_index > rx_local->fbr0_num_entries - 1) || - (ring_index == 1 && - buff_index > rx_local->fbr1_num_entries - 1)) + if (rindex > 1 || + (rindex == 0 && + bindex > rx_local->Fbr0NumEntries - 1) || + (rindex == 1 && + bindex > rx_local->Fbr1NumEntries - 1)) #else - if (ring_index != 1 || buff_index > rx_local->fbr1_num_entries - 1) + if (rindex != 1 || bindex > rx_local->Fbr1NumEntries - 1) #endif { /* Illegal buffer or ring index cannot be used by S/W*/ - dev_err(&adapter->pdev->dev, + dev_err(&etdev->pdev->dev, "NICRxPkts PSR Entry %d indicates " "length of %d and/or bad bi(%d)\n", rx_local->local_psr_full & 0xFFF, - len, buff_index); + len, bindex); return NULL; } /* Get and fill the RFD. */ - spin_lock_irqsave(&adapter->rcv_lock, flags); + spin_lock_irqsave(&etdev->rcv_lock, flags); rfd = NULL; - element = rx_local->recv_list.next; + element = rx_local->RecvList.next; rfd = (struct rfd *) list_entry(element, struct rfd, list_node); if (rfd == NULL) { - spin_unlock_irqrestore(&adapter->rcv_lock, flags); + spin_unlock_irqrestore(&etdev->rcv_lock, flags); return NULL; } list_del(&rfd->list_node); - rx_local->num_ready_recv--; + rx_local->nReadyRecv--; - spin_unlock_irqrestore(&adapter->rcv_lock, flags); + spin_unlock_irqrestore(&etdev->rcv_lock, flags); - rfd->bufferindex = buff_index; - rfd->ringindex = ring_index; + rfd->bufferindex = bindex; + rfd->ringindex = rindex; /* In V1 silicon, there is a bug which screws up filtering of * runt packets. Therefore runt packet filtering is disabled @@ -983,18 +971,18 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) * also counted here. */ if (len < (NIC_MIN_PACKET_SIZE + 4)) { - adapter->stats.rx_other_errs++; + etdev->stats.other_errors++; len = 0; } if (len) { - if (adapter->replica_phy_loopbk == 1) { - buf = rx_local->fbr[ring_index]->virt[buff_index]; + if (etdev->ReplicaPhyLoopbk == 1) { + buf = rx_local->fbr[rindex]->virt[bindex]; - if (memcmp(&buf[6], adapter->addr, ETH_ALEN) == 0) { + if (memcmp(&buf[6], etdev->addr, ETH_ALEN) == 0) { if (memcmp(&buf[42], "Replica packet", ETH_HLEN)) { - adapter->replica_phy_loopbk_passfail = 1; + etdev->ReplicaPhyLoopbkPF = 1; } } } @@ -1009,33 +997,31 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) * filters. Generally filter is 0x2b when in * promiscuous mode. */ - if ((adapter->packet_filter & - ET131X_PACKET_TYPE_MULTICAST) - && !(adapter->packet_filter & - ET131X_PACKET_TYPE_PROMISCUOUS) - && !(adapter->packet_filter & - ET131X_PACKET_TYPE_ALL_MULTICAST)) { - buf = rx_local->fbr[ring_index]-> - virt[buff_index]; + if ((etdev->PacketFilter & ET131X_PACKET_TYPE_MULTICAST) + && !(etdev->PacketFilter & ET131X_PACKET_TYPE_PROMISCUOUS) + && !(etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST)) { + buf = rx_local->fbr[rindex]-> + virt[bindex]; /* Loop through our list to see if the * destination address of this packet * matches one in our list. */ - for (i = 0; i < adapter->multicast_addr_count; + for (i = 0; + i < etdev->MCAddressCount; i++) { if (buf[0] == - adapter->multicast_list[i][0] + etdev->MCList[i][0] && buf[1] == - adapter->multicast_list[i][1] + etdev->MCList[i][1] && buf[2] == - adapter->multicast_list[i][2] + etdev->MCList[i][2] && buf[3] == - adapter->multicast_list[i][3] + etdev->MCList[i][3] && buf[4] == - adapter->multicast_list[i][4] + etdev->MCList[i][4] && buf[5] == - adapter->multicast_list[i][5]) { + etdev->MCList[i][5]) { break; } } @@ -1048,21 +1034,21 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) * so we free our RFD when we return * from this function. */ - if (i == adapter->multicast_addr_count) + if (i == etdev->MCAddressCount) len = 0; } if (len > 0) - adapter->stats.multicast_pkts_rcvd++; + etdev->stats.multircv++; } else if (word0 & ALCATEL_BROADCAST_PKT) - adapter->stats.broadcast_pkts_rcvd++; + etdev->stats.brdcstrcv++; else /* Not sure what this counter measures in * promiscuous mode. Perhaps we should check * the MAC address to see if it is directed * to us in promiscuous mode. */ - adapter->stats.unicast_pkts_rcvd++; + etdev->stats.unircv++; } if (len > 0) { @@ -1073,19 +1059,19 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) skb = dev_alloc_skb(rfd->len + 2); if (!skb) { - dev_err(&adapter->pdev->dev, + dev_err(&etdev->pdev->dev, "Couldn't alloc an SKB for Rx\n"); return NULL; } - adapter->net_stats.rx_bytes += rfd->len; + etdev->net_stats.rx_bytes += rfd->len; memcpy(skb_put(skb, rfd->len), - rx_local->fbr[ring_index]->virt[buff_index], + rx_local->fbr[rindex]->virt[bindex], rfd->len); - skb->dev = adapter->netdev; - skb->protocol = eth_type_trans(skb, adapter->netdev); + skb->dev = etdev->netdev; + skb->protocol = eth_type_trans(skb, etdev->netdev); skb->ip_summed = CHECKSUM_NONE; netif_rx(skb); @@ -1093,28 +1079,29 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) rfd->len = 0; } - nic_return_rfd(adapter, rfd); + nic_return_rfd(etdev, rfd); return rfd; } /** * et131x_reset_recv - Reset the receive list - * @adapter: pointer to our adapter + * @etdev: pointer to our adapter * * Assumption, Rcv spinlock has been acquired. */ -void et131x_reset_recv(struct et131x_adapter *adapter) +void et131x_reset_recv(struct et131x_adapter *etdev) { - WARN_ON(list_empty(&adapter->rx_ring.recv_list)); + WARN_ON(list_empty(&etdev->rx_ring.RecvList)); + } /** * et131x_handle_recv_interrupt - Interrupt handler for receive processing - * @adapter: pointer to our adapter + * @etdev: pointer to our adapter * * Assumption, Rcv spinlock has been acquired. */ -void et131x_handle_recv_interrupt(struct et131x_adapter *adapter) +void et131x_handle_recv_interrupt(struct et131x_adapter *etdev) { struct rfd *rfd = NULL; u32 count = 0; @@ -1122,13 +1109,13 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *adapter) /* Process up to available RFD's */ while (count < NUM_PACKETS_HANDLED) { - if (list_empty(&adapter->rx_ring.recv_list)) { - WARN_ON(adapter->rx_ring.num_ready_recv != 0); + if (list_empty(&etdev->rx_ring.RecvList)) { + WARN_ON(etdev->rx_ring.nReadyRecv != 0); done = false; break; } - rfd = nic_rx_pkts(adapter); + rfd = nic_rx_pkts(etdev); if (rfd == NULL) break; @@ -1138,28 +1125,28 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *adapter) * If length is zero, return the RFD in order to advance the * Free buffer ring. */ - if (!adapter->packet_filter || - !netif_carrier_ok(adapter->netdev) || + if (!etdev->PacketFilter || + !netif_carrier_ok(etdev->netdev) || rfd->len == 0) continue; /* Increment the number of packets we received */ - adapter->net_stats.rx_packets++; + etdev->net_stats.rx_packets++; /* Set the status on the packet, either resources or success */ - if (adapter->rx_ring.num_ready_recv < RFD_LOW_WATER_MARK) { - dev_warn(&adapter->pdev->dev, + if (etdev->rx_ring.nReadyRecv < RFD_LOW_WATER_MARK) { + dev_warn(&etdev->pdev->dev, "RFD's are running out\n"); } count++; } if (count == NUM_PACKETS_HANDLED || !done) { - adapter->rx_ring.unfinished_receives = true; + etdev->rx_ring.UnfinishedReceives = true; writel(PARM_TX_TIME_INT_DEF * NANO_IN_A_MICRO, - &adapter->regs->global.watchdog_timer); + &etdev->regs->global.watchdog_timer); } else /* Watchdog timer will disable itself if appropriate. */ - adapter->rx_ring.unfinished_receives = false; + etdev->rx_ring.UnfinishedReceives = false; } diff --git a/trunk/drivers/staging/et131x/et1310_rx.h b/trunk/drivers/staging/et131x/et1310_rx.h index 1448aa90996e..e8c653d37a76 100644 --- a/trunk/drivers/staging/et131x/et1310_rx.h +++ b/trunk/drivers/staging/et131x/et1310_rx.h @@ -174,8 +174,8 @@ struct pkt_stat_desc { * DMA engine it sits in free memory, and is pointed to by 0x101c / 0x1020 */ struct rx_status_block { - u32 word0; - u32 word1; + u32 Word0; + u32 Word1; }; /* @@ -190,54 +190,54 @@ struct fbr_lookup { }; /* - * struct rx_ring is the sructure representing the adaptor's local + * struct rx_ring is the ssructure representing the adaptor's local * reference(s) to the rings */ struct rx_ring { #ifdef USE_FBR0 - void *fbr0_ring_virtaddr; - dma_addr_t fbr0_ring_physaddr; - void *fbr0_mem_virtaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; - dma_addr_t fbr0_mem_physaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; - uint64_t fbr0_real_physaddr; - uint64_t fbr0_offset; - u32 local_fbr0_full; - u32 fbr0_num_entries; - u32 fbr0_buffsize; + void *pFbr0RingVa; + dma_addr_t pFbr0RingPa; + void *Fbr0MemVa[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; + dma_addr_t Fbr0MemPa[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; + uint64_t Fbr0Realpa; + uint64_t Fbr0offset; + u32 local_Fbr0_full; + u32 Fbr0NumEntries; + u32 Fbr0BufferSize; #endif - void *fbr1_ring_virtaddr; - dma_addr_t fbr1_ring_physaddr; - void *fbr1_mem_virtaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; - dma_addr_t fbr1_mem_physaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; - uint64_t fbr1_real_physaddr; - uint64_t fbr1_offset; + void *pFbr1RingVa; + dma_addr_t pFbr1RingPa; + void *Fbr1MemVa[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; + dma_addr_t Fbr1MemPa[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; + uint64_t Fbr1Realpa; + uint64_t Fbr1offset; struct fbr_lookup *fbr[2]; /* One per ring */ - u32 local_fbr1_full; - u32 fbr1_num_entries; - u32 fbr1_buffsize; + u32 local_Fbr1_full; + u32 Fbr1NumEntries; + u32 Fbr1BufferSize; - void *ps_ring_virtaddr; - dma_addr_t ps_ring_physaddr; + void *pPSRingVa; + dma_addr_t pPSRingPa; u32 local_psr_full; - u32 psr_num_entries; + u32 PsrNumEntries; struct rx_status_block *rx_status_block; dma_addr_t rx_status_bus; - struct list_head recv_buff_pool; + struct list_head RecvBufferPool; /* RECV */ - struct list_head recv_list; - u32 num_ready_recv; + struct list_head RecvList; + u32 nReadyRecv; - u32 num_rfd; + u32 NumRfd; - bool unfinished_receives; + bool UnfinishedReceives; - struct list_head recv_packet_pool; + struct list_head RecvPacketPool; /* lookaside lists */ - struct kmem_cache *recv_lookaside; + struct kmem_cache *RecvLookaside; }; #endif /* __ET1310_RX_H__ */ diff --git a/trunk/drivers/staging/et131x/et1310_tx.c b/trunk/drivers/staging/et131x/et1310_tx.c index f8211048f6b8..8fb3051fe288 100644 --- a/trunk/drivers/staging/et131x/et1310_tx.c +++ b/trunk/drivers/staging/et131x/et1310_tx.c @@ -88,6 +88,12 @@ #include "et1310_tx.h" #include "et131x.h" +static inline void et131x_free_send_packet(struct et131x_adapter *etdev, + struct tcb *tcb); +static int et131x_send_packet(struct sk_buff *skb, + struct et131x_adapter *etdev); +static int nic_send_packet(struct et131x_adapter *etdev, struct tcb *tcb); + /** * et131x_tx_dma_memory_alloc * @adapter: pointer to our private adapter structure @@ -180,60 +186,60 @@ void et131x_tx_dma_memory_free(struct et131x_adapter *adapter) } /** - * et131x_config_tx_dma_regs - Set up the tx dma section of the JAGCore. - * @adapter: pointer to our private adapter structure + * ConfigTxDmaRegs - Set up the tx dma section of the JAGCore. + * @etdev: pointer to our private adapter structure * * Configure the transmit engine with the ring buffers we have created * and prepare it for use. */ -void et131x_config_tx_dma_regs(struct et131x_adapter *adapter) +void ConfigTxDmaRegs(struct et131x_adapter *etdev) { - struct txdma_regs __iomem *txdma = &adapter->regs->txdma; + struct txdma_regs __iomem *txdma = &etdev->regs->txdma; /* Load the hardware with the start of the transmit descriptor ring. */ - writel((u32) ((u64)adapter->tx_ring.tx_desc_ring_pa >> 32), + writel((u32) ((u64)etdev->tx_ring.tx_desc_ring_pa >> 32), &txdma->pr_base_hi); - writel((u32) adapter->tx_ring.tx_desc_ring_pa, + writel((u32) etdev->tx_ring.tx_desc_ring_pa, &txdma->pr_base_lo); /* Initialise the transmit DMA engine */ writel(NUM_DESC_PER_RING_TX - 1, &txdma->pr_num_des); /* Load the completion writeback physical address */ - writel((u32)((u64)adapter->tx_ring.tx_status_pa >> 32), + writel((u32)((u64)etdev->tx_ring.tx_status_pa >> 32), &txdma->dma_wb_base_hi); - writel((u32)adapter->tx_ring.tx_status_pa, &txdma->dma_wb_base_lo); + writel((u32)etdev->tx_ring.tx_status_pa, &txdma->dma_wb_base_lo); - *adapter->tx_ring.tx_status = 0; + *etdev->tx_ring.tx_status = 0; writel(0, &txdma->service_request); - adapter->tx_ring.send_idx = 0; + etdev->tx_ring.send_idx = 0; } /** * et131x_tx_dma_disable - Stop of Tx_DMA on the ET1310 - * @adapter: pointer to our adapter structure + * @etdev: pointer to our adapter structure */ -void et131x_tx_dma_disable(struct et131x_adapter *adapter) +void et131x_tx_dma_disable(struct et131x_adapter *etdev) { /* Setup the tramsmit dma configuration register */ writel(ET_TXDMA_CSR_HALT|ET_TXDMA_SNGL_EPKT, - &adapter->regs->txdma.csr); + &etdev->regs->txdma.csr); } /** * et131x_tx_dma_enable - re-start of Tx_DMA on the ET1310. - * @adapter: pointer to our adapter structure + * @etdev: pointer to our adapter structure * * Mainly used after a return to the D0 (full-power) state from a lower state. */ -void et131x_tx_dma_enable(struct et131x_adapter *adapter) +void et131x_tx_dma_enable(struct et131x_adapter *etdev) { /* Setup the transmit dma configuration register for normal * operation */ writel(ET_TXDMA_SNGL_EPKT|(PARM_DMA_CACHE_DEF << ET_TXDMA_CACHE_SHIFT), - &adapter->regs->txdma.csr); + &etdev->regs->txdma.csr); } /** @@ -270,14 +276,139 @@ void et131x_init_send(struct et131x_adapter *adapter) tx_ring->send_tail = NULL; } +/** + * et131x_send_packets - This function is called by the OS to send packets + * @skb: the packet(s) to send + * @netdev:device on which to TX the above packet(s) + * + * Return 0 in almost all cases; non-zero value in extreme hard failure only + */ +int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev) +{ + int status = 0; + struct et131x_adapter *etdev = NULL; + + etdev = netdev_priv(netdev); + + /* Send these packets + * + * NOTE: The Linux Tx entry point is only given one packet at a time + * to Tx, so the PacketCount and it's array used makes no sense here + */ + + /* TCB is not available */ + if (etdev->tx_ring.used >= NUM_TCB) { + /* NOTE: If there's an error on send, no need to queue the + * packet under Linux; if we just send an error up to the + * netif layer, it will resend the skb to us. + */ + status = -ENOMEM; + } else { + /* We need to see if the link is up; if it's not, make the + * netif layer think we're good and drop the packet + */ + if ((etdev->flags & fMP_ADAPTER_FAIL_SEND_MASK) || + !netif_carrier_ok(netdev)) { + dev_kfree_skb_any(skb); + skb = NULL; + + etdev->net_stats.tx_dropped++; + } else { + status = et131x_send_packet(skb, etdev); + if (status != 0 && status != -ENOMEM) { + /* On any other error, make netif think we're + * OK and drop the packet + */ + dev_kfree_skb_any(skb); + skb = NULL; + etdev->net_stats.tx_dropped++; + } + } + } + return status; +} + +/** + * et131x_send_packet - Do the work to send a packet + * @skb: the packet(s) to send + * @etdev: a pointer to the device's private adapter structure + * + * Return 0 in almost all cases; non-zero value in extreme hard failure only. + * + * Assumption: Send spinlock has been acquired + */ +static int et131x_send_packet(struct sk_buff *skb, + struct et131x_adapter *etdev) +{ + int status; + struct tcb *tcb = NULL; + u16 *shbufva; + unsigned long flags; + + /* All packets must have at least a MAC address and a protocol type */ + if (skb->len < ETH_HLEN) + return -EIO; + + /* Get a TCB for this packet */ + spin_lock_irqsave(&etdev->TCBReadyQLock, flags); + + tcb = etdev->tx_ring.tcb_qhead; + + if (tcb == NULL) { + spin_unlock_irqrestore(&etdev->TCBReadyQLock, flags); + return -ENOMEM; + } + + etdev->tx_ring.tcb_qhead = tcb->next; + + if (etdev->tx_ring.tcb_qhead == NULL) + etdev->tx_ring.tcb_qtail = NULL; + + spin_unlock_irqrestore(&etdev->TCBReadyQLock, flags); + + tcb->skb = skb; + + if (skb->data != NULL && skb->len - skb->data_len >= 6) { + shbufva = (u16 *) skb->data; + + if ((shbufva[0] == 0xffff) && + (shbufva[1] == 0xffff) && (shbufva[2] == 0xffff)) { + tcb->flags |= fMP_DEST_BROAD; + } else if ((shbufva[0] & 0x3) == 0x0001) { + tcb->flags |= fMP_DEST_MULTI; + } + } + + tcb->next = NULL; + + /* Call the NIC specific send handler. */ + status = nic_send_packet(etdev, tcb); + + if (status != 0) { + spin_lock_irqsave(&etdev->TCBReadyQLock, flags); + + if (etdev->tx_ring.tcb_qtail) + etdev->tx_ring.tcb_qtail->next = tcb; + else + /* Apparently ready Q is empty. */ + etdev->tx_ring.tcb_qhead = tcb; + + etdev->tx_ring.tcb_qtail = tcb; + spin_unlock_irqrestore(&etdev->TCBReadyQLock, flags); + return status; + } + WARN_ON(etdev->tx_ring.used > NUM_TCB); + return 0; +} + /** * nic_send_packet - NIC specific send handler for version B silicon. - * @adapter: pointer to our adapter + * @etdev: pointer to our adapter * @tcb: pointer to struct tcb * * Returns 0 or errno. */ -static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) +static int nic_send_packet(struct et131x_adapter *etdev, struct tcb *tcb) { u32 i; struct tx_desc desc[24]; /* 24 x 16 byte */ @@ -331,7 +462,7 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) * subsystem) */ desc[frag++].addr_lo = - pci_map_single(adapter->pdev, + pci_map_single(etdev->pdev, skb->data, skb->len - skb->data_len, @@ -350,7 +481,7 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) * subsystem) */ desc[frag++].addr_lo = - pci_map_single(adapter->pdev, + pci_map_single(etdev->pdev, skb->data, ((skb->len - skb->data_len) / 2), @@ -369,7 +500,7 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) * subsystem) */ desc[frag++].addr_lo = - pci_map_single(adapter->pdev, + pci_map_single(etdev->pdev, skb->data + ((skb->len - skb->data_len) / 2), @@ -389,7 +520,7 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) * addressable (as defined by the pci/dma subsystem) */ desc[frag++].addr_lo = - pci_map_page(adapter->pdev, + pci_map_page(etdev->pdev, frags[i - 1].page, frags[i - 1].page_offset, frags[i - 1].size, @@ -400,11 +531,11 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) if (frag == 0) return -EIO; - if (adapter->linkspeed == TRUEPHY_SPEED_1000MBPS) { - if (++adapter->tx_ring.since_irq == PARM_TX_NUM_BUFS_DEF) { + if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS) { + if (++etdev->tx_ring.since_irq == PARM_TX_NUM_BUFS_DEF) { /* Last element & Interrupt flag */ desc[frag - 1].flags = 0x5; - adapter->tx_ring.since_irq = 0; + etdev->tx_ring.since_irq = 0; } else { /* Last element */ desc[frag - 1].flags = 0x1; } @@ -413,13 +544,13 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) desc[0].flags |= 2; /* First element flag */ - tcb->index_start = adapter->tx_ring.send_idx; + tcb->index_start = etdev->tx_ring.send_idx; tcb->stale = 0; - spin_lock_irqsave(&adapter->send_hw_lock, flags); + spin_lock_irqsave(&etdev->send_hw_lock, flags); thiscopy = NUM_DESC_PER_RING_TX - - INDEX10(adapter->tx_ring.send_idx); + INDEX10(etdev->tx_ring.send_idx); if (thiscopy >= frag) { remainder = 0; @@ -428,210 +559,87 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) remainder = frag - thiscopy; } - memcpy(adapter->tx_ring.tx_desc_ring + - INDEX10(adapter->tx_ring.send_idx), desc, + memcpy(etdev->tx_ring.tx_desc_ring + + INDEX10(etdev->tx_ring.send_idx), desc, sizeof(struct tx_desc) * thiscopy); - add_10bit(&adapter->tx_ring.send_idx, thiscopy); + add_10bit(&etdev->tx_ring.send_idx, thiscopy); - if (INDEX10(adapter->tx_ring.send_idx) == 0 || - INDEX10(adapter->tx_ring.send_idx) == NUM_DESC_PER_RING_TX) { - adapter->tx_ring.send_idx &= ~ET_DMA10_MASK; - adapter->tx_ring.send_idx ^= ET_DMA10_WRAP; + if (INDEX10(etdev->tx_ring.send_idx) == 0 || + INDEX10(etdev->tx_ring.send_idx) == NUM_DESC_PER_RING_TX) { + etdev->tx_ring.send_idx &= ~ET_DMA10_MASK; + etdev->tx_ring.send_idx ^= ET_DMA10_WRAP; } if (remainder) { - memcpy(adapter->tx_ring.tx_desc_ring, + memcpy(etdev->tx_ring.tx_desc_ring, desc + thiscopy, sizeof(struct tx_desc) * remainder); - add_10bit(&adapter->tx_ring.send_idx, remainder); + add_10bit(&etdev->tx_ring.send_idx, remainder); } - if (INDEX10(adapter->tx_ring.send_idx) == 0) { - if (adapter->tx_ring.send_idx) + if (INDEX10(etdev->tx_ring.send_idx) == 0) { + if (etdev->tx_ring.send_idx) tcb->index = NUM_DESC_PER_RING_TX - 1; else tcb->index = ET_DMA10_WRAP|(NUM_DESC_PER_RING_TX - 1); } else - tcb->index = adapter->tx_ring.send_idx - 1; + tcb->index = etdev->tx_ring.send_idx - 1; - spin_lock(&adapter->tcb_send_qlock); + spin_lock(&etdev->TCBSendQLock); - if (adapter->tx_ring.send_tail) - adapter->tx_ring.send_tail->next = tcb; + if (etdev->tx_ring.send_tail) + etdev->tx_ring.send_tail->next = tcb; else - adapter->tx_ring.send_head = tcb; + etdev->tx_ring.send_head = tcb; - adapter->tx_ring.send_tail = tcb; + etdev->tx_ring.send_tail = tcb; WARN_ON(tcb->next != NULL); - adapter->tx_ring.used++; + etdev->tx_ring.used++; - spin_unlock(&adapter->tcb_send_qlock); + spin_unlock(&etdev->TCBSendQLock); /* Write the new write pointer back to the device. */ - writel(adapter->tx_ring.send_idx, - &adapter->regs->txdma.service_request); + writel(etdev->tx_ring.send_idx, + &etdev->regs->txdma.service_request); /* For Gig only, we use Tx Interrupt coalescing. Enable the software * timer to wake us up if this packet isn't followed by N more. */ - if (adapter->linkspeed == TRUEPHY_SPEED_1000MBPS) { + if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS) { writel(PARM_TX_TIME_INT_DEF * NANO_IN_A_MICRO, - &adapter->regs->global.watchdog_timer); + &etdev->regs->global.watchdog_timer); } - spin_unlock_irqrestore(&adapter->send_hw_lock, flags); + spin_unlock_irqrestore(&etdev->send_hw_lock, flags); return 0; } -/** - * send_packet - Do the work to send a packet - * @skb: the packet(s) to send - * @adapter: a pointer to the device's private adapter structure - * - * Return 0 in almost all cases; non-zero value in extreme hard failure only. - * - * Assumption: Send spinlock has been acquired - */ -static int send_packet(struct sk_buff *skb, struct et131x_adapter *adapter) -{ - int status; - struct tcb *tcb = NULL; - u16 *shbufva; - unsigned long flags; - - /* All packets must have at least a MAC address and a protocol type */ - if (skb->len < ETH_HLEN) - return -EIO; - - /* Get a TCB for this packet */ - spin_lock_irqsave(&adapter->tcb_ready_qlock, flags); - - tcb = adapter->tx_ring.tcb_qhead; - - if (tcb == NULL) { - spin_unlock_irqrestore(&adapter->tcb_ready_qlock, flags); - return -ENOMEM; - } - - adapter->tx_ring.tcb_qhead = tcb->next; - - if (adapter->tx_ring.tcb_qhead == NULL) - adapter->tx_ring.tcb_qtail = NULL; - - spin_unlock_irqrestore(&adapter->tcb_ready_qlock, flags); - - tcb->skb = skb; - - if (skb->data != NULL && skb->len - skb->data_len >= 6) { - shbufva = (u16 *) skb->data; - - if ((shbufva[0] == 0xffff) && - (shbufva[1] == 0xffff) && (shbufva[2] == 0xffff)) { - tcb->flags |= fMP_DEST_BROAD; - } else if ((shbufva[0] & 0x3) == 0x0001) { - tcb->flags |= fMP_DEST_MULTI; - } - } - - tcb->next = NULL; - - /* Call the NIC specific send handler. */ - status = nic_send_packet(adapter, tcb); - - if (status != 0) { - spin_lock_irqsave(&adapter->tcb_ready_qlock, flags); - - if (adapter->tx_ring.tcb_qtail) - adapter->tx_ring.tcb_qtail->next = tcb; - else - /* Apparently ready Q is empty. */ - adapter->tx_ring.tcb_qhead = tcb; - - adapter->tx_ring.tcb_qtail = tcb; - spin_unlock_irqrestore(&adapter->tcb_ready_qlock, flags); - return status; - } - WARN_ON(adapter->tx_ring.used > NUM_TCB); - return 0; -} - -/** - * et131x_send_packets - This function is called by the OS to send packets - * @skb: the packet(s) to send - * @netdev:device on which to TX the above packet(s) - * - * Return 0 in almost all cases; non-zero value in extreme hard failure only - */ -int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev) -{ - int status = 0; - struct et131x_adapter *adapter = NULL; - - adapter = netdev_priv(netdev); - - /* Send these packets - * - * NOTE: The Linux Tx entry point is only given one packet at a time - * to Tx, so the PacketCount and it's array used makes no sense here - */ - - /* TCB is not available */ - if (adapter->tx_ring.used >= NUM_TCB) { - /* NOTE: If there's an error on send, no need to queue the - * packet under Linux; if we just send an error up to the - * netif layer, it will resend the skb to us. - */ - status = -ENOMEM; - } else { - /* We need to see if the link is up; if it's not, make the - * netif layer think we're good and drop the packet - */ - if ((adapter->flags & fMP_ADAPTER_FAIL_SEND_MASK) || - !netif_carrier_ok(netdev)) { - dev_kfree_skb_any(skb); - skb = NULL; - - adapter->net_stats.tx_dropped++; - } else { - status = send_packet(skb, adapter); - if (status != 0 && status != -ENOMEM) { - /* On any other error, make netif think we're - * OK and drop the packet - */ - dev_kfree_skb_any(skb); - skb = NULL; - adapter->net_stats.tx_dropped++; - } - } - } - return status; -} /** - * free_send_packet - Recycle a struct tcb - * @adapter: pointer to our adapter + * et131x_free_send_packet - Recycle a struct tcb + * @etdev: pointer to our adapter * @tcb: pointer to struct tcb * * Complete the packet if necessary * Assumption - Send spinlock has been acquired */ -static inline void free_send_packet(struct et131x_adapter *adapter, +inline void et131x_free_send_packet(struct et131x_adapter *etdev, struct tcb *tcb) { unsigned long flags; struct tx_desc *desc = NULL; - struct net_device_stats *stats = &adapter->net_stats; + struct net_device_stats *stats = &etdev->net_stats; if (tcb->flags & fMP_DEST_BROAD) - atomic_inc(&adapter->stats.broadcast_pkts_xmtd); + atomic_inc(&etdev->stats.brdcstxmt); else if (tcb->flags & fMP_DEST_MULTI) - atomic_inc(&adapter->stats.multicast_pkts_xmtd); + atomic_inc(&etdev->stats.multixmt); else - atomic_inc(&adapter->stats.unicast_pkts_xmtd); + atomic_inc(&etdev->stats.unixmt); if (tcb->skb) { stats->tx_bytes += tcb->skb->len; @@ -641,10 +649,10 @@ static inline void free_send_packet(struct et131x_adapter *adapter, * they point to */ do { - desc = (struct tx_desc *)(adapter->tx_ring.tx_desc_ring + + desc = (struct tx_desc *)(etdev->tx_ring.tx_desc_ring + INDEX10(tcb->index_start)); - pci_unmap_single(adapter->pdev, + pci_unmap_single(etdev->pdev, desc->addr_lo, desc->len_vlan, PCI_DMA_TODEVICE); @@ -654,7 +662,7 @@ static inline void free_send_packet(struct et131x_adapter *adapter, tcb->index_start &= ~ET_DMA10_MASK; tcb->index_start ^= ET_DMA10_WRAP; } - } while (desc != (adapter->tx_ring.tx_desc_ring + + } while (desc != (etdev->tx_ring.tx_desc_ring + INDEX10(tcb->index))); dev_kfree_skb_any(tcb->skb); @@ -663,127 +671,127 @@ static inline void free_send_packet(struct et131x_adapter *adapter, memset(tcb, 0, sizeof(struct tcb)); /* Add the TCB to the Ready Q */ - spin_lock_irqsave(&adapter->tcb_ready_qlock, flags); + spin_lock_irqsave(&etdev->TCBReadyQLock, flags); - adapter->net_stats.tx_packets++; + etdev->net_stats.tx_packets++; - if (adapter->tx_ring.tcb_qtail) - adapter->tx_ring.tcb_qtail->next = tcb; + if (etdev->tx_ring.tcb_qtail) + etdev->tx_ring.tcb_qtail->next = tcb; else /* Apparently ready Q is empty. */ - adapter->tx_ring.tcb_qhead = tcb; + etdev->tx_ring.tcb_qhead = tcb; - adapter->tx_ring.tcb_qtail = tcb; + etdev->tx_ring.tcb_qtail = tcb; - spin_unlock_irqrestore(&adapter->tcb_ready_qlock, flags); - WARN_ON(adapter->tx_ring.used < 0); + spin_unlock_irqrestore(&etdev->TCBReadyQLock, flags); + WARN_ON(etdev->tx_ring.used < 0); } /** * et131x_free_busy_send_packets - Free and complete the stopped active sends - * @adapter: pointer to our adapter + * @etdev: pointer to our adapter * * Assumption - Send spinlock has been acquired */ -void et131x_free_busy_send_packets(struct et131x_adapter *adapter) +void et131x_free_busy_send_packets(struct et131x_adapter *etdev) { struct tcb *tcb; unsigned long flags; u32 freed = 0; /* Any packets being sent? Check the first TCB on the send list */ - spin_lock_irqsave(&adapter->tcb_send_qlock, flags); + spin_lock_irqsave(&etdev->TCBSendQLock, flags); - tcb = adapter->tx_ring.send_head; + tcb = etdev->tx_ring.send_head; while (tcb != NULL && freed < NUM_TCB) { struct tcb *next = tcb->next; - adapter->tx_ring.send_head = next; + etdev->tx_ring.send_head = next; if (next == NULL) - adapter->tx_ring.send_tail = NULL; + etdev->tx_ring.send_tail = NULL; - adapter->tx_ring.used--; + etdev->tx_ring.used--; - spin_unlock_irqrestore(&adapter->tcb_send_qlock, flags); + spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); freed++; - free_send_packet(adapter, tcb); + et131x_free_send_packet(etdev, tcb); - spin_lock_irqsave(&adapter->tcb_send_qlock, flags); + spin_lock_irqsave(&etdev->TCBSendQLock, flags); - tcb = adapter->tx_ring.send_head; + tcb = etdev->tx_ring.send_head; } WARN_ON(freed == NUM_TCB); - spin_unlock_irqrestore(&adapter->tcb_send_qlock, flags); + spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); - adapter->tx_ring.used = 0; + etdev->tx_ring.used = 0; } /** * et131x_handle_send_interrupt - Interrupt handler for sending processing - * @adapter: pointer to our adapter + * @etdev: pointer to our adapter * * Re-claim the send resources, complete sends and get more to send from * the send wait queue. * * Assumption - Send spinlock has been acquired */ -void et131x_handle_send_interrupt(struct et131x_adapter *adapter) +void et131x_handle_send_interrupt(struct et131x_adapter *etdev) { unsigned long flags; u32 serviced; struct tcb *tcb; u32 index; - serviced = readl(&adapter->regs->txdma.new_service_complete); + serviced = readl(&etdev->regs->txdma.new_service_complete); index = INDEX10(serviced); /* Has the ring wrapped? Process any descriptors that do not have * the same "wrap" indicator as the current completion indicator */ - spin_lock_irqsave(&adapter->tcb_send_qlock, flags); + spin_lock_irqsave(&etdev->TCBSendQLock, flags); - tcb = adapter->tx_ring.send_head; + tcb = etdev->tx_ring.send_head; while (tcb && ((serviced ^ tcb->index) & ET_DMA10_WRAP) && index < INDEX10(tcb->index)) { - adapter->tx_ring.used--; - adapter->tx_ring.send_head = tcb->next; + etdev->tx_ring.used--; + etdev->tx_ring.send_head = tcb->next; if (tcb->next == NULL) - adapter->tx_ring.send_tail = NULL; + etdev->tx_ring.send_tail = NULL; - spin_unlock_irqrestore(&adapter->tcb_send_qlock, flags); - free_send_packet(adapter, tcb); - spin_lock_irqsave(&adapter->tcb_send_qlock, flags); + spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); + et131x_free_send_packet(etdev, tcb); + spin_lock_irqsave(&etdev->TCBSendQLock, flags); /* Goto the next packet */ - tcb = adapter->tx_ring.send_head; + tcb = etdev->tx_ring.send_head; } while (tcb && !((serviced ^ tcb->index) & ET_DMA10_WRAP) && index > (tcb->index & ET_DMA10_MASK)) { - adapter->tx_ring.used--; - adapter->tx_ring.send_head = tcb->next; + etdev->tx_ring.used--; + etdev->tx_ring.send_head = tcb->next; if (tcb->next == NULL) - adapter->tx_ring.send_tail = NULL; + etdev->tx_ring.send_tail = NULL; - spin_unlock_irqrestore(&adapter->tcb_send_qlock, flags); - free_send_packet(adapter, tcb); - spin_lock_irqsave(&adapter->tcb_send_qlock, flags); + spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); + et131x_free_send_packet(etdev, tcb); + spin_lock_irqsave(&etdev->TCBSendQLock, flags); /* Goto the next packet */ - tcb = adapter->tx_ring.send_head; + tcb = etdev->tx_ring.send_head; } /* Wake up the queue when we hit a low-water mark */ - if (adapter->tx_ring.used <= NUM_TCB / 3) - netif_wake_queue(adapter->netdev); + if (etdev->tx_ring.used <= NUM_TCB / 3) + netif_wake_queue(etdev->netdev); - spin_unlock_irqrestore(&adapter->tcb_send_qlock, flags); + spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); } diff --git a/trunk/drivers/staging/et131x/et131x.h b/trunk/drivers/staging/et131x/et131x.h index 91fafc0331e5..48ebac0e55ce 100644 --- a/trunk/drivers/staging/et131x/et131x.h +++ b/trunk/drivers/staging/et131x/et131x.h @@ -49,10 +49,11 @@ */ /* et131x_eeprom.c */ -int et131x_init_eeprom(struct et131x_adapter *adapter); +int et131x_init_eeprom(struct et131x_adapter *etdev); /* et131x_initpci.c */ -void et131x_configure_global_regs(struct et131x_adapter *adapter); +void ConfigGlobalRegs(struct et131x_adapter *pAdapter); +void ConfigMMCRegs(struct et131x_adapter *pAdapter); void et131x_enable_interrupts(struct et131x_adapter *adapter); void et131x_disable_interrupts(struct et131x_adapter *adapter); void et131x_align_allocated_memory(struct et131x_adapter *adapter, @@ -70,33 +71,33 @@ irqreturn_t et131x_isr(int irq, void *dev_id); void et131x_isr_handler(struct work_struct *work); /* et1310_mac.c */ -void et1310_config_mac_regs1(struct et131x_adapter *adapter); -void et1310_config_mac_regs2(struct et131x_adapter *adapter); -void et1310_config_rxmac_regs(struct et131x_adapter *adapter); -void et1310_config_txmac_regs(struct et131x_adapter *adapter); -void et1310_config_macstat_regs(struct et131x_adapter *adapter); -void et1310_config_flow_control(struct et131x_adapter *adapter); -void et1310_update_macstat_host_counters(struct et131x_adapter *adapter); -void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter); -void et1310_setup_device_for_multicast(struct et131x_adapter *adapter); -void et1310_setup_device_for_unicast(struct et131x_adapter *adapter); +void ConfigMACRegs1(struct et131x_adapter *adapter); +void ConfigMACRegs2(struct et131x_adapter *adapter); +void ConfigRxMacRegs(struct et131x_adapter *adapter); +void ConfigTxMacRegs(struct et131x_adapter *adapter); +void ConfigMacStatRegs(struct et131x_adapter *adapter); +void ConfigFlowControl(struct et131x_adapter *adapter); +void UpdateMacStatHostCounters(struct et131x_adapter *adapter); +void HandleMacStatInterrupt(struct et131x_adapter *adapter); +void SetupDeviceForMulticast(struct et131x_adapter *adapter); +void SetupDeviceForUnicast(struct et131x_adapter *adapter); /* et131x_netdev.c */ struct net_device *et131x_device_alloc(void); -/* et1310_pm.c */ -void et1310_enable_phy_coma(struct et131x_adapter *adapter); -void et1310_disable_phy_coma(struct et131x_adapter *adapter); +/* et131x_pm.c */ +void EnablePhyComa(struct et131x_adapter *adapter); +void DisablePhyComa(struct et131x_adapter *adapter); -/* et1310_phy.c */ -void et1310_phy_init(struct et131x_adapter *adapter); -void et1310_phy_reset(struct et131x_adapter *adapter); -void et1310_phy_power_down(struct et131x_adapter *adapter, bool down); -void et1310_phy_advertise_1000BaseT(struct et131x_adapter *adapter, - u16 duplex); -void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, - u16 action, - u16 regnum, u16 bitnum, u8 *value); +/* et131x_phy.c */ +void ET1310_PhyInit(struct et131x_adapter *adapter); +void ET1310_PhyReset(struct et131x_adapter *adapter); +void ET1310_PhyPowerDown(struct et131x_adapter *adapter, bool down); +void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *adapter, + u16 duplex); +void ET1310_PhyAccessMiBit(struct et131x_adapter *adapter, + u16 action, + u16 regnum, u16 bitnum, u8 *value); int et131x_xcvr_find(struct et131x_adapter *adapter); void et131x_setphy_normal(struct et131x_adapter *adapter); @@ -104,18 +105,23 @@ void et131x_setphy_normal(struct et131x_adapter *adapter); /* static inline function does not work because et131x_adapter is not always * defined */ -int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 xcvrAddr, +int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr, u8 xcvrReg, u16 *value); -#define et131x_mii_read(adapter, xcvrReg, value) \ - et131x_phy_mii_read((adapter), \ - (adapter)->stats.xcvr_addr, \ - (xcvrReg), (value)) +#define MiRead(adapter, xcvrReg, value) \ + PhyMiRead((adapter), (adapter)->stats.xcvr_addr, (xcvrReg), (value)) -int32_t et131x_mii_write(struct et131x_adapter *adapter, +int32_t MiWrite(struct et131x_adapter *adapter, u8 xcvReg, u16 value); -void et131x_mii_check(struct et131x_adapter *pAdapter, +void et131x_Mii_check(struct et131x_adapter *pAdapter, u16 bmsr, u16 bmsr_ints); +/* This last is not strictly required (the driver could call the TPAL + * version instead), but this sets the adapter up correctly, and calls the + * access routine indirectly. This protects the driver from changes in TPAL. + */ +void SetPhy_10BaseTHalfDuplex(struct et131x_adapter *adapter); + + /* et1310_rx.c */ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter); void et131x_rx_dma_memory_free(struct et131x_adapter *adapter); @@ -125,8 +131,8 @@ void et131x_rfd_resources_free(struct et131x_adapter *adapter, struct rfd *rfd); int et131x_init_recv(struct et131x_adapter *adapter); -void et131x_config_rx_dma_regs(struct et131x_adapter *adapter); -void et131x_set_rx_dma_timer(struct et131x_adapter *adapter); +void ConfigRxDmaRegs(struct et131x_adapter *adapter); +void SetRxDmaTimer(struct et131x_adapter *adapter); void et131x_rx_dma_disable(struct et131x_adapter *adapter); void et131x_rx_dma_enable(struct et131x_adapter *adapter); @@ -137,7 +143,7 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *adapter); /* et131x_tx.c */ int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter); void et131x_tx_dma_memory_free(struct et131x_adapter *adapter); -void et131x_config_tx_dma_regs(struct et131x_adapter *adapter); +void ConfigTxDmaRegs(struct et131x_adapter *adapter); void et131x_init_send(struct et131x_adapter *adapter); void et131x_tx_dma_disable(struct et131x_adapter *adapter); void et131x_tx_dma_enable(struct et131x_adapter *adapter); diff --git a/trunk/drivers/staging/et131x/et131x_adapter.h b/trunk/drivers/staging/et131x/et131x_adapter.h index 762e07ca3ee2..408c50ba4f2b 100644 --- a/trunk/drivers/staging/et131x/et131x_adapter.h +++ b/trunk/drivers/staging/et131x/et131x_adapter.h @@ -105,39 +105,40 @@ struct ce_stats { * MUST have 32, then we'll need another way to perform atomic * operations */ - u32 unicast_pkts_rcvd; - atomic_t unicast_pkts_xmtd; - u32 multicast_pkts_rcvd; - atomic_t multicast_pkts_xmtd; - u32 broadcast_pkts_rcvd; - atomic_t broadcast_pkts_xmtd; - u32 rcvd_pkts_dropped; + u32 unircv; /* # multicast packets received */ + atomic_t unixmt; /* # multicast packets for Tx */ + u32 multircv; /* # multicast packets received */ + atomic_t multixmt; /* # multicast packets for Tx */ + u32 brdcstrcv; /* # broadcast packets received */ + atomic_t brdcstxmt; /* # broadcast packets for Tx */ + u32 norcvbuf; /* # Rx packets discarded */ + u32 noxmtbuf; /* # Tx packets discarded */ /* Transceiver state informations. */ - u8 xcvr_addr; - u32 xcvr_id; + u8 xcvr_addr; + u32 xcvr_id; /* Tx Statistics. */ - u32 tx_underflows; + u32 tx_uflo; /* Tx Underruns */ - u32 tx_collisions; - u32 tx_excessive_collisions; - u32 tx_first_collisions; - u32 tx_late_collisions; - u32 tx_max_pkt_errs; - u32 tx_deferred; + u32 collisions; + u32 excessive_collisions; + u32 first_collision; + u32 late_collisions; + u32 max_pkt_error; + u32 tx_deferred; /* Rx Statistics. */ - u32 rx_overflows; + u32 rx_ov_flow; /* Rx Overflow */ - u32 rx_length_errs; - u32 rx_align_errs; - u32 rx_crc_errs; - u32 rx_code_violations; - u32 rx_other_errs; + u32 length_err; + u32 alignment_err; + u32 crc_err; + u32 code_violations; + u32 other_errors; - u32 synchronous_iterations; - u32 interrupt_status; + u32 SynchrounousIterations; + u32 InterruptStatus; }; @@ -150,7 +151,7 @@ struct et131x_adapter { /* Flags that indicate current state of the adapter */ u32 flags; - u32 hw_errs; + u32 HwErrCount; /* Configuration */ u8 rom_addr[ETH_ALEN]; @@ -159,46 +160,52 @@ struct et131x_adapter { u8 eeprom_data[2]; /* Spinlocks */ - spinlock_t lock; + spinlock_t Lock; - spinlock_t tcb_send_qlock; - spinlock_t tcb_ready_qlock; + spinlock_t TCBSendQLock; + spinlock_t TCBReadyQLock; spinlock_t send_hw_lock; spinlock_t rcv_lock; - spinlock_t rcv_pend_lock; - spinlock_t fbr_lock; + spinlock_t RcvPendLock; + spinlock_t FbrLock; - spinlock_t phy_lock; + spinlock_t PHYLock; /* Packet Filter and look ahead size */ - u32 packet_filter; + u32 PacketFilter; u32 linkspeed; u32 duplex_mode; /* multicast list */ - u32 multicast_addr_count; - u8 multicast_list[NIC_MAX_MCAST_LIST][ETH_ALEN]; + u32 MCAddressCount; + u8 MCList[NIC_MAX_MCAST_LIST][ETH_ALEN]; /* Pointer to the device's PCI register space */ struct address_map __iomem *regs; /* Registry parameters */ - u8 speed_duplex; /* speed/duplex */ + u8 SpeedDuplex; /* speed/duplex */ u8 wanted_flow; /* Flow we want for 802.3x flow control */ - u8 registry_phy_coma; /* Phy Coma mode enable/disable */ + u8 RegistryPhyComa; /* Phy Coma mode enable/disable */ - u32 registry_rx_mem_end; /* Size of internal rx memory */ - u32 registry_jumbo_packet; /* Max supported ethernet packet size */ + u32 RegistryRxMemEnd; /* Size of internal rx memory */ + u32 RegistryJumboPacket; /* Max supported ethernet packet size */ /* Derived from the registry: */ - u8 ai_force_duplex; /* duplex setting */ - u16 ai_force_speed; /* 'Speed', user over-ride of line speed */ + u8 AiForceDpx; /* duplex setting */ + u16 AiForceSpeed; /* 'Speed', user over-ride of line speed */ u8 flowcontrol; /* flow control validated by the far-end */ + enum { + NETIF_STATUS_INVALID = 0, + NETIF_STATUS_MEDIA_CONNECT, + NETIF_STATUS_MEDIA_DISCONNECT, + NETIF_STATUS_MAX + } MediaState; /* Minimize init-time */ - struct timer_list error_timer; + struct timer_list ErrorTimer; /* variable putting the phy into coma mode when boot up with no cable * plugged in after 5 seconds @@ -212,7 +219,7 @@ struct et131x_adapter { u16 pdown_speed; u8 pdown_duplex; - u32 cached_mask_value; + u32 CachedMaskValue; /* Xcvr status at last poll */ u16 bmsr; @@ -224,8 +231,8 @@ struct et131x_adapter { struct rx_ring rx_ring; /* Loopback specifics */ - u8 replica_phy_loopbk; /* Replica Enable */ - u8 replica_phy_loopbk_passfail; /* Replica Enable Pass/Fail */ + u8 ReplicaPhyLoopbk; /* Replica Enable */ + u8 ReplicaPhyLoopbkPF; /* Replica Enable Pass/Fail */ /* Stats */ struct ce_stats stats; diff --git a/trunk/drivers/staging/et131x/et131x_initpci.c b/trunk/drivers/staging/et131x/et131x_initpci.c index 072cfb52a656..8c8d6b87a252 100644 --- a/trunk/drivers/staging/et131x/et131x_initpci.c +++ b/trunk/drivers/staging/et131x/et131x_initpci.c @@ -263,55 +263,76 @@ static int et131x_pci_init(struct et131x_adapter *adapter, */ void et131x_error_timer_handler(unsigned long data) { - struct et131x_adapter *adapter = (struct et131x_adapter *) data; + struct et131x_adapter *etdev = (struct et131x_adapter *) data; u32 pm_csr; - pm_csr = readl(&adapter->regs->global.pm_csr); + pm_csr = readl(&etdev->regs->global.pm_csr); if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) - et1310_update_macstat_host_counters(adapter); + UpdateMacStatHostCounters(etdev); else - dev_err(&adapter->pdev->dev, + dev_err(&etdev->pdev->dev, "No interrupts, in PHY coma, pm_csr = 0x%x\n", pm_csr); - if (!(adapter->bmsr & MI_BMSR_LINK_STATUS) && - adapter->registry_phy_coma && - adapter->boot_coma < 11) { - adapter->boot_coma++; + if (!(etdev->bmsr & MI_BMSR_LINK_STATUS) && + etdev->RegistryPhyComa && + etdev->boot_coma < 11) { + etdev->boot_coma++; } - if (adapter->boot_coma == 10) { - if (!(adapter->bmsr & MI_BMSR_LINK_STATUS) - && adapter->registry_phy_coma) { + if (etdev->boot_coma == 10) { + if (!(etdev->bmsr & MI_BMSR_LINK_STATUS) + && etdev->RegistryPhyComa) { if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) { /* NOTE - This was originally a 'sync with * interrupt'. How to do that under Linux? */ - et131x_enable_interrupts(adapter); - et1310_enable_phy_coma(adapter); + et131x_enable_interrupts(etdev); + EnablePhyComa(etdev); } } } /* This is a periodic timer, so reschedule */ - mod_timer(&adapter->error_timer, jiffies + + mod_timer(&etdev->ErrorTimer, jiffies + TX_ERROR_PERIOD * HZ / 1000); } +/** + * et131x_link_detection_handler + * + * Timer function for link up at driver load time + */ +void et131x_link_detection_handler(unsigned long data) +{ + struct et131x_adapter *etdev = (struct et131x_adapter *) data; + unsigned long flags; + + if (etdev->MediaState == 0) { + spin_lock_irqsave(&etdev->Lock, flags); + + etdev->MediaState = NETIF_STATUS_MEDIA_DISCONNECT; + + spin_unlock_irqrestore(&etdev->Lock, flags); + + netif_carrier_off(etdev->netdev); + } +} + /** * et131x_configure_global_regs - configure JAGCore global regs - * @adapter: pointer to our adapter structure + * @etdev: pointer to our adapter structure * * Used to configure the global registers on the JAGCore */ -void et131x_configure_global_regs(struct et131x_adapter *adapter) +void ConfigGlobalRegs(struct et131x_adapter *etdev) { - struct global_regs __iomem *regs = &adapter->regs->global; + struct global_regs __iomem *regs = &etdev->regs->global; writel(0, ®s->rxq_start_addr); writel(INTERNAL_MEM_SIZE - 1, ®s->txq_end_addr); - if (adapter->registry_jumbo_packet < 2048) { + if (etdev->RegistryJumboPacket < 2048) { /* Tx / RxDMA and Tx/Rx MAC interfaces have a 1k word * block of RAM that the driver can split between Tx * and Rx as it desires. Our default is to split it @@ -319,7 +340,7 @@ void et131x_configure_global_regs(struct et131x_adapter *adapter) */ writel(PARM_RX_MEM_END_DEF, ®s->rxq_end_addr); writel(PARM_RX_MEM_END_DEF + 1, ®s->txq_start_addr); - } else if (adapter->registry_jumbo_packet < 8192) { + } else if (etdev->RegistryJumboPacket < 8192) { /* For jumbo packets > 2k but < 8k, split 50-50. */ writel(INTERNAL_MEM_RX_OFFSET, ®s->rxq_end_addr); writel(INTERNAL_MEM_RX_OFFSET + 1, ®s->txq_start_addr); @@ -345,62 +366,63 @@ void et131x_configure_global_regs(struct et131x_adapter *adapter) writel(0, ®s->watchdog_timer); } + /** * et131x_adapter_setup - Set the adapter up as per cassini+ documentation * @adapter: pointer to our private adapter structure * * Returns 0 on success, errno on failure (as defined in errno.h) */ -int et131x_adapter_setup(struct et131x_adapter *adapter) +int et131x_adapter_setup(struct et131x_adapter *etdev) { int status = 0; /* Configure the JAGCore */ - et131x_configure_global_regs(adapter); + ConfigGlobalRegs(etdev); - et1310_config_mac_regs1(adapter); + ConfigMACRegs1(etdev); /* Configure the MMC registers */ /* All we need to do is initialize the Memory Control Register */ - writel(ET_MMC_ENABLE, &adapter->regs->mmc.mmc_ctrl); + writel(ET_MMC_ENABLE, &etdev->regs->mmc.mmc_ctrl); - et1310_config_rxmac_regs(adapter); - et1310_config_txmac_regs(adapter); + ConfigRxMacRegs(etdev); + ConfigTxMacRegs(etdev); - et131x_config_rx_dma_regs(adapter); - et131x_config_tx_dma_regs(adapter); + ConfigRxDmaRegs(etdev); + ConfigTxDmaRegs(etdev); - et1310_config_macstat_regs(adapter); + ConfigMacStatRegs(etdev); /* Move the following code to Timer function?? */ - status = et131x_xcvr_find(adapter); + status = et131x_xcvr_find(etdev); if (status != 0) - dev_warn(&adapter->pdev->dev, "Could not find the xcvr\n"); + dev_warn(&etdev->pdev->dev, "Could not find the xcvr\n"); /* Prepare the TRUEPHY library. */ - et1310_phy_init(adapter); + ET1310_PhyInit(etdev); /* Reset the phy now so changes take place */ - et1310_phy_reset(adapter); + ET1310_PhyReset(etdev); /* Power down PHY */ - et1310_phy_power_down(adapter, 1); + ET1310_PhyPowerDown(etdev, 1); /* * We need to turn off 1000 base half dulplex, the mac does not * support it. For the 10/100 part, turn off all gig advertisement */ - if (adapter->pdev->device != ET131X_PCI_DEVICE_ID_FAST) - et1310_phy_advertise_1000BaseT(adapter, TRUEPHY_ADV_DUPLEX_FULL); + if (etdev->pdev->device != ET131X_PCI_DEVICE_ID_FAST) + ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL); else - et1310_phy_advertise_1000BaseT(adapter, TRUEPHY_ADV_DUPLEX_NONE); + ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE); /* Power up PHY */ - et1310_phy_power_down(adapter, 0); + ET1310_PhyPowerDown(etdev, 0); - et131x_setphy_normal(adapter); - return status; + et131x_setphy_normal(etdev); +; return status; } /** @@ -495,14 +517,18 @@ void et131x_adapter_memory_free(struct et131x_adapter *adapter) et131x_rx_dma_memory_free(adapter); } + + /** * et131x_adapter_init - * @adapter: pointer to the private adapter struct + * @etdev: pointer to the private adapter struct * @pdev: pointer to the PCI device * * Initialize the data structures for the et131x_adapter object and link * them together with the platform provided device structures. */ + + static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev, struct pci_dev *pdev) { @@ -510,43 +536,43 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev, static const u8 duplex[] = { 0, 1, 2, 1, 2, 2 }; static const u16 speed[] = { 0, 10, 10, 100, 100, 1000 }; - struct et131x_adapter *adapter; + struct et131x_adapter *etdev; /* Setup the fundamental net_device and private adapter structure * elements */ SET_NETDEV_DEV(netdev, &pdev->dev); /* Allocate private adapter struct and copy in relevant information */ - adapter = netdev_priv(netdev); - adapter->pdev = pci_dev_get(pdev); - adapter->netdev = netdev; + etdev = netdev_priv(netdev); + etdev->pdev = pci_dev_get(pdev); + etdev->netdev = netdev; /* Do the same for the netdev struct */ netdev->irq = pdev->irq; netdev->base_addr = pci_resource_start(pdev, 0); /* Initialize spinlocks here */ - spin_lock_init(&adapter->lock); - spin_lock_init(&adapter->tcb_send_qlock); - spin_lock_init(&adapter->tcb_ready_qlock); - spin_lock_init(&adapter->send_hw_lock); - spin_lock_init(&adapter->rcv_lock); - spin_lock_init(&adapter->rcv_pend_lock); - spin_lock_init(&adapter->fbr_lock); - spin_lock_init(&adapter->phy_lock); + spin_lock_init(&etdev->Lock); + spin_lock_init(&etdev->TCBSendQLock); + spin_lock_init(&etdev->TCBReadyQLock); + spin_lock_init(&etdev->send_hw_lock); + spin_lock_init(&etdev->rcv_lock); + spin_lock_init(&etdev->RcvPendLock); + spin_lock_init(&etdev->FbrLock); + spin_lock_init(&etdev->PHYLock); /* Parse configuration parameters into the private adapter struct */ if (et131x_speed_set) - dev_info(&adapter->pdev->dev, + dev_info(&etdev->pdev->dev, "Speed set manually to : %d\n", et131x_speed_set); - adapter->speed_duplex = et131x_speed_set; - adapter->registry_jumbo_packet = 1514; /* 1514-9216 */ + etdev->SpeedDuplex = et131x_speed_set; + etdev->RegistryJumboPacket = 1514; /* 1514-9216 */ /* Set the MAC address to a default */ - memcpy(adapter->addr, default_mac, ETH_ALEN); + memcpy(etdev->addr, default_mac, ETH_ALEN); - /* Decode speed_duplex + /* Decode SpeedDuplex * * Set up as if we are auto negotiating always and then change if we * go into force mode @@ -554,14 +580,14 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev, * If we are the 10/100 device, and gigabit is somehow requested then * knock it down to 100 full. */ - if (adapter->pdev->device == ET131X_PCI_DEVICE_ID_FAST && - adapter->speed_duplex == 5) - adapter->speed_duplex = 4; + if (etdev->pdev->device == ET131X_PCI_DEVICE_ID_FAST && + etdev->SpeedDuplex == 5) + etdev->SpeedDuplex = 4; - adapter->ai_force_speed = speed[adapter->speed_duplex]; - adapter->ai_force_duplex = duplex[adapter->speed_duplex]; /* Auto FDX */ + etdev->AiForceSpeed = speed[etdev->SpeedDuplex]; + etdev->AiForceDpx = duplex[etdev->SpeedDuplex]; /* Auto FDX */ - return adapter; + return etdev; } /** @@ -576,6 +602,7 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev, * contained in the pci_device_id table. This routine is the equivalent to * a device insertion routine. */ + static int __devinit et131x_pci_setup(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -690,14 +717,14 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, et131x_adapter_setup(adapter); /* Create a timer to count errors received by the NIC */ - init_timer(&adapter->error_timer); + init_timer(&adapter->ErrorTimer); - adapter->error_timer.expires = jiffies + TX_ERROR_PERIOD * HZ / 1000; - adapter->error_timer.function = et131x_error_timer_handler; - adapter->error_timer.data = (unsigned long)adapter; + adapter->ErrorTimer.expires = jiffies + TX_ERROR_PERIOD * HZ / 1000; + adapter->ErrorTimer.function = et131x_error_timer_handler; + adapter->ErrorTimer.data = (unsigned long)adapter; /* Initialize link state */ - netif_carrier_off(adapter->netdev); + et131x_link_detection_handler((unsigned long)adapter); /* Initialize variable for counting how long we do not have link status */ @@ -747,6 +774,7 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, * PCI subsystem detects that a PCI device which matches the information * contained in the pci_device_id table has been removed. */ + static void __devexit et131x_pci_remove(struct pci_dev *pdev) { struct net_device *netdev; @@ -787,6 +815,7 @@ static struct pci_driver et131x_driver = { .resume = NULL, /* et131x_pci_resume */ }; + /** * et131x_init_module - The "main" entry point called on driver initialization * diff --git a/trunk/drivers/staging/et131x/et131x_isr.c b/trunk/drivers/staging/et131x/et131x_isr.c index 7cfd213fb136..9c33209c8409 100644 --- a/trunk/drivers/staging/et131x/et131x_isr.c +++ b/trunk/drivers/staging/et131x/et131x_isr.c @@ -124,7 +124,7 @@ void et131x_enable_interrupts(struct et131x_adapter *adapter) else mask = INT_MASK_ENABLE_NO_FLOW; - adapter->cached_mask_value = mask; + adapter->CachedMaskValue = mask; writel(mask, &adapter->regs->global.int_mask); } @@ -138,7 +138,7 @@ void et131x_enable_interrupts(struct et131x_adapter *adapter) void et131x_disable_interrupts(struct et131x_adapter *adapter) { /* Disable all global interrupts */ - adapter->cached_mask_value = INT_MASK_DISABLE; + adapter->CachedMaskValue = INT_MASK_DISABLE; writel(INT_MASK_DISABLE, &adapter->regs->global.int_mask); } @@ -200,7 +200,7 @@ irqreturn_t et131x_isr(int irq, void *dev_id) if (++tcb->stale > 1) status |= ET_INTR_TXDMA_ISR; - if (adapter->rx_ring.unfinished_receives) + if (adapter->rx_ring.UnfinishedReceives) status |= ET_INTR_RXDMA_XFR_DONE; else if (tcb == NULL) writel(0, &adapter->regs->global.watchdog_timer); @@ -222,7 +222,7 @@ irqreturn_t et131x_isr(int irq, void *dev_id) * DPC. We will clear the software copy of that in that * routine. */ - adapter->stats.interrupt_status = status; + adapter->stats.InterruptStatus = status; /* Schedule the ISR handler as a bottom-half task in the * kernel's tq_immediate queue, and mark the queue for @@ -242,10 +242,10 @@ irqreturn_t et131x_isr(int irq, void *dev_id) */ void et131x_isr_handler(struct work_struct *work) { - struct et131x_adapter *adapter = + struct et131x_adapter *etdev = container_of(work, struct et131x_adapter, task); - u32 status = adapter->stats.interrupt_status; - struct address_map __iomem *iomem = adapter->regs; + u32 status = etdev->stats.InterruptStatus; + struct address_map __iomem *iomem = etdev->regs; /* * These first two are by far the most common. Once handled, we clear @@ -254,11 +254,11 @@ void et131x_isr_handler(struct work_struct *work) */ /* Handle all the completed Transmit interrupts */ if (status & ET_INTR_TXDMA_ISR) - et131x_handle_send_interrupt(adapter); + et131x_handle_send_interrupt(etdev); /* Handle all the completed Receives interrupts */ if (status & ET_INTR_RXDMA_XFR_DONE) - et131x_handle_recv_interrupt(adapter); + et131x_handle_recv_interrupt(etdev); status &= 0xffffffd7; @@ -270,7 +270,7 @@ void et131x_isr_handler(struct work_struct *work) /* Following read also clears the register (COR) */ txdma_err = readl(&iomem->txdma.tx_dma_error); - dev_warn(&adapter->pdev->dev, + dev_warn(&etdev->pdev->dev, "TXDMA_ERR interrupt, error = %d\n", txdma_err); } @@ -295,8 +295,8 @@ void et131x_isr_handler(struct work_struct *work) /* If the user has flow control on, then we will * send a pause packet, otherwise just exit */ - if (adapter->flowcontrol == FLOW_TXONLY || - adapter->flowcontrol == FLOW_BOTH) { + if (etdev->flowcontrol == FLOW_TXONLY || + etdev->flowcontrol == FLOW_BOTH) { u32 pm_csr; /* Tell the device to send a pause packet via @@ -345,7 +345,7 @@ void et131x_isr_handler(struct work_struct *work) */ /* TRAP();*/ - dev_warn(&adapter->pdev->dev, + dev_warn(&etdev->pdev->dev, "RxDMA_ERR interrupt, error %x\n", readl(&iomem->txmac.tx_test)); } @@ -359,7 +359,7 @@ void et131x_isr_handler(struct work_struct *work) * message when we are in DBG mode, otherwise we * will ignore it. */ - dev_err(&adapter->pdev->dev, "WAKE_ON_LAN interrupt\n"); + dev_err(&etdev->pdev->dev, "WAKE_ON_LAN interrupt\n"); } /* Handle the PHY interrupt */ @@ -379,26 +379,25 @@ void et131x_isr_handler(struct work_struct *work) * so, disable it because we will not be able * to read PHY values until we are out. */ - et1310_disable_phy_coma(adapter); + DisablePhyComa(etdev); } /* Read the PHY ISR to clear the reason for the * interrupt. */ - et131x_mii_read(adapter, - (uint8_t) offsetof(struct mi_regs, isr), - &myisr); + MiRead(etdev, (uint8_t) offsetof(struct mi_regs, isr), + &myisr); - if (!adapter->replica_phy_loopbk) { - et131x_mii_read(adapter, + if (!etdev->ReplicaPhyLoopbk) { + MiRead(etdev, (uint8_t) offsetof(struct mi_regs, bmsr), &bmsr_data); - bmsr_ints = adapter->bmsr ^ bmsr_data; - adapter->bmsr = bmsr_data; + bmsr_ints = etdev->bmsr ^ bmsr_data; + etdev->bmsr = bmsr_data; /* Do all the cable in / cable out stuff */ - et131x_mii_check(adapter, bmsr_data, bmsr_ints); + et131x_Mii_check(etdev, bmsr_data, bmsr_ints); } } @@ -416,7 +415,7 @@ void et131x_isr_handler(struct work_struct *work) * a nutshell, the whole Tx path will have to be reset * and re-configured afterwards. */ - dev_warn(&adapter->pdev->dev, + dev_warn(&etdev->pdev->dev, "TXMAC interrupt, error 0x%08x\n", err); @@ -434,14 +433,14 @@ void et131x_isr_handler(struct work_struct *work) * set the flag to cause us to reset so we can solve * this issue. */ - /* MP_SET_FLAG( adapter, + /* MP_SET_FLAG( etdev, fMP_ADAPTER_HARDWARE_ERROR); */ - dev_warn(&adapter->pdev->dev, + dev_warn(&etdev->pdev->dev, "RXMAC interrupt, error 0x%08x. Requesting reset\n", readl(&iomem->rxmac.err_reg)); - dev_warn(&adapter->pdev->dev, + dev_warn(&etdev->pdev->dev, "Enable 0x%08x, Diag 0x%08x\n", readl(&iomem->rxmac.ctrl), readl(&iomem->rxmac.rxq_diag)); @@ -461,7 +460,7 @@ void et131x_isr_handler(struct work_struct *work) * to maintain the top, software managed bits of the * counter(s). */ - et1310_handle_macstat_interrupt(adapter); + HandleMacStatInterrupt(etdev); } /* Handle SLV Timeout Interrupt */ @@ -477,5 +476,5 @@ void et131x_isr_handler(struct work_struct *work) */ } } - et131x_enable_interrupts(adapter); + et131x_enable_interrupts(etdev); } diff --git a/trunk/drivers/staging/et131x/et131x_netdev.c b/trunk/drivers/staging/et131x/et131x_netdev.c index 7555a241ed23..5f25bbad36b6 100644 --- a/trunk/drivers/staging/et131x/et131x_netdev.c +++ b/trunk/drivers/staging/et131x/et131x_netdev.c @@ -100,18 +100,15 @@ static struct net_device_stats *et131x_stats(struct net_device *netdev) struct net_device_stats *stats = &adapter->net_stats; struct ce_stats *devstat = &adapter->stats; - stats->rx_errors = devstat->rx_length_errs + - devstat->rx_align_errs + - devstat->rx_crc_errs + - devstat->rx_code_violations + - devstat->rx_other_errs; - stats->tx_errors = devstat->tx_max_pkt_errs; - stats->multicast = devstat->multicast_pkts_rcvd; - stats->collisions = devstat->tx_collisions; - - stats->rx_length_errors = devstat->rx_length_errs; - stats->rx_over_errors = devstat->rx_overflows; - stats->rx_crc_errors = devstat->rx_crc_errs; + stats->rx_errors = devstat->length_err + devstat->alignment_err + + devstat->crc_err + devstat->code_violations + devstat->other_errors; + stats->tx_errors = devstat->max_pkt_error; + stats->multicast = devstat->multircv; + stats->collisions = devstat->collisions; + + stats->rx_length_errors = devstat->length_err; + stats->rx_over_errors = devstat->rx_ov_flow; + stats->rx_crc_errors = devstat->crc_err; /* NOTE: These stats don't have corresponding values in CE_STATS, * so we're going to have to update these directly from within the @@ -147,13 +144,13 @@ int et131x_open(struct net_device *netdev) struct et131x_adapter *adapter = netdev_priv(netdev); /* Start the timer to track NIC errors */ - add_timer(&adapter->error_timer); + add_timer(&adapter->ErrorTimer); /* Register our IRQ */ result = request_irq(netdev->irq, et131x_isr, IRQF_SHARED, netdev->name, netdev); if (result) { - dev_err(&adapter->pdev->dev, "could not register IRQ %d\n", + dev_err(&adapter->pdev->dev, "c ould not register IRQ %d\n", netdev->irq); return result; } @@ -182,9 +179,6 @@ int et131x_close(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); - /* Save the timestamp for the TX watchdog, prevent a timeout */ - netdev->trans_start = jiffies; - /* First thing is to stop the queue */ netif_stop_queue(netdev); @@ -200,7 +194,7 @@ int et131x_close(struct net_device *netdev) free_irq(netdev->irq, netdev); /* Stop the error timer */ - del_timer_sync(&adapter->error_timer); + del_timer_sync(&adapter->ErrorTimer); return 0; } @@ -215,19 +209,19 @@ int et131x_close(struct net_device *netdev) int et131x_ioctl_mii(struct net_device *netdev, struct ifreq *reqbuf, int cmd) { int status = 0; - struct et131x_adapter *adapter = netdev_priv(netdev); + struct et131x_adapter *etdev = netdev_priv(netdev); struct mii_ioctl_data *data = if_mii(reqbuf); switch (cmd) { case SIOCGMIIPHY: - data->phy_id = adapter->stats.xcvr_addr; + data->phy_id = etdev->stats.xcvr_addr; break; case SIOCGMIIREG: if (!capable(CAP_NET_ADMIN)) status = -EPERM; else - status = et131x_mii_read(adapter, + status = MiRead(etdev, data->reg_num, &data->val_out); break; @@ -235,7 +229,7 @@ int et131x_ioctl_mii(struct net_device *netdev, struct ifreq *reqbuf, int cmd) if (!capable(CAP_NET_ADMIN)) status = -EPERM; else - status = et131x_mii_write(adapter, data->reg_num, + status = MiWrite(etdev, data->reg_num, data->val_in); break; @@ -281,7 +275,7 @@ int et131x_ioctl(struct net_device *netdev, struct ifreq *reqbuf, int cmd) int et131x_set_packet_filter(struct et131x_adapter *adapter) { int status = 0; - uint32_t filter = adapter->packet_filter; + uint32_t filter = adapter->PacketFilter; u32 ctrl; u32 pf_ctrl; @@ -307,14 +301,14 @@ int et131x_set_packet_filter(struct et131x_adapter *adapter) if (filter & ET131X_PACKET_TYPE_ALL_MULTICAST) pf_ctrl &= ~2; /* Multicast filter bit */ else { - et1310_setup_device_for_multicast(adapter); + SetupDeviceForMulticast(adapter); pf_ctrl |= 2; ctrl &= ~0x04; } /* Set us up with Unicast packet filtering */ if (filter & ET131X_PACKET_TYPE_DIRECTED) { - et1310_setup_device_for_unicast(adapter); + SetupDeviceForUnicast(adapter); pf_ctrl |= 4; ctrl &= ~0x04; } @@ -343,67 +337,67 @@ int et131x_set_packet_filter(struct et131x_adapter *adapter) void et131x_multicast(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); - uint32_t packet_filter = 0; + uint32_t PacketFilter = 0; unsigned long flags; struct netdev_hw_addr *ha; int i; - spin_lock_irqsave(&adapter->lock, flags); + spin_lock_irqsave(&adapter->Lock, flags); /* Before we modify the platform-independent filter flags, store them * locally. This allows us to determine if anything's changed and if * we even need to bother the hardware */ - packet_filter = adapter->packet_filter; + PacketFilter = adapter->PacketFilter; /* Clear the 'multicast' flag locally; because we only have a single * flag to check multicast, and multiple multicast addresses can be * set, this is the easiest way to determine if more than one * multicast address is being set. */ - packet_filter &= ~ET131X_PACKET_TYPE_MULTICAST; + PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; /* Check the net_device flags and set the device independent flags * accordingly */ if (netdev->flags & IFF_PROMISC) - adapter->packet_filter |= ET131X_PACKET_TYPE_PROMISCUOUS; + adapter->PacketFilter |= ET131X_PACKET_TYPE_PROMISCUOUS; else - adapter->packet_filter &= ~ET131X_PACKET_TYPE_PROMISCUOUS; + adapter->PacketFilter &= ~ET131X_PACKET_TYPE_PROMISCUOUS; if (netdev->flags & IFF_ALLMULTI) - adapter->packet_filter |= ET131X_PACKET_TYPE_ALL_MULTICAST; + adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; if (netdev_mc_count(netdev) > NIC_MAX_MCAST_LIST) - adapter->packet_filter |= ET131X_PACKET_TYPE_ALL_MULTICAST; + adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; if (netdev_mc_count(netdev) < 1) { - adapter->packet_filter &= ~ET131X_PACKET_TYPE_ALL_MULTICAST; - adapter->packet_filter &= ~ET131X_PACKET_TYPE_MULTICAST; + adapter->PacketFilter &= ~ET131X_PACKET_TYPE_ALL_MULTICAST; + adapter->PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; } else - adapter->packet_filter |= ET131X_PACKET_TYPE_MULTICAST; + adapter->PacketFilter |= ET131X_PACKET_TYPE_MULTICAST; /* Set values in the private adapter struct */ i = 0; netdev_for_each_mc_addr(ha, netdev) { if (i == NIC_MAX_MCAST_LIST) break; - memcpy(adapter->multicast_list[i++], ha->addr, ETH_ALEN); + memcpy(adapter->MCList[i++], ha->addr, ETH_ALEN); } - adapter->multicast_addr_count = i; + adapter->MCAddressCount = i; /* Are the new flags different from the previous ones? If not, then no * action is required * - * NOTE - This block will always update the multicast_list with the - * hardware, even if the addresses aren't the same. + * NOTE - This block will always update the MCList with the hardware, + * even if the addresses aren't the same. */ - if (packet_filter != adapter->packet_filter) { + if (PacketFilter != adapter->PacketFilter) { /* Call the device's filter function */ et131x_set_packet_filter(adapter); } - spin_unlock_irqrestore(&adapter->lock, flags); + spin_unlock_irqrestore(&adapter->Lock, flags); } /** @@ -448,70 +442,47 @@ int et131x_tx(struct sk_buff *skb, struct net_device *netdev) */ void et131x_tx_timeout(struct net_device *netdev) { - struct et131x_adapter *adapter = netdev_priv(netdev); + struct et131x_adapter *etdev = netdev_priv(netdev); struct tcb *tcb; unsigned long flags; - /* If the device is closed, ignore the timeout */ - if (~(adapter->flags & fMP_ADAPTER_INTERRUPT_IN_USE)); - return; - /* Any nonrecoverable hardware error? * Checks adapter->flags for any failure in phy reading */ - if (adapter->flags & fMP_ADAPTER_NON_RECOVER_ERROR) + if (etdev->flags & fMP_ADAPTER_NON_RECOVER_ERROR) return; /* Hardware failure? */ - if (adapter->flags & fMP_ADAPTER_HARDWARE_ERROR) { - dev_err(&adapter->pdev->dev, "hardware error - reset\n"); + if (etdev->flags & fMP_ADAPTER_HARDWARE_ERROR) { + dev_err(&etdev->pdev->dev, "hardware error - reset\n"); return; } /* Is send stuck? */ - spin_lock_irqsave(&adapter->tcb_send_qlock, flags); + spin_lock_irqsave(&etdev->TCBSendQLock, flags); - tcb = adapter->tx_ring.send_head; + tcb = etdev->tx_ring.send_head; if (tcb != NULL) { tcb->count++; if (tcb->count > NIC_SEND_HANG_THRESHOLD) { - spin_unlock_irqrestore(&adapter->tcb_send_qlock, + spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); - dev_warn(&adapter->pdev->dev, + dev_warn(&etdev->pdev->dev, "Send stuck - reset. tcb->WrIndex %x, flags 0x%08x\n", tcb->index, tcb->flags); - adapter->net_stats.tx_errors++; + et131x_close(netdev); + et131x_open(netdev); - /* perform reset */ - /* First thing is to stop the queue */ - netif_stop_queue(netdev); - - /* Stop the Tx and Rx DMA engines */ - et131x_rx_dma_disable(adapter); - et131x_tx_dma_disable(adapter); - - /* Disable device interrupts */ - et131x_disable_interrupts(adapter); - - /* Enable the Tx and Rx DMA engines (if not already enabled) */ - et131x_rx_dma_enable(adapter); - et131x_tx_dma_enable(adapter); - - /* Enable device interrupts */ - et131x_enable_interrupts(adapter); - - /* We're ready to move some data, so start the queue */ - netif_start_queue(netdev); return; } } - spin_unlock_irqrestore(&adapter->tcb_send_qlock, flags); + spin_unlock_irqrestore(&etdev->TCBSendQLock, flags); } /** @@ -549,7 +520,7 @@ int et131x_change_mtu(struct net_device *netdev, int new_mtu) et131x_adapter_memory_free(adapter); /* Set the config parameter for Jumbo Packet support */ - adapter->registry_jumbo_packet = new_mtu + 14; + adapter->RegistryJumboPacket = new_mtu + 14; et131x_soft_reset(adapter); /* Alloc and init Rx DMA memory */ @@ -619,6 +590,7 @@ int et131x_set_mac_addr(struct net_device *netdev, void *new_mac) /* Set the new MAC */ /* netdev->set_mac_address = &new_mac; */ + /* netdev->mtu = new_mtu; */ memcpy(netdev->dev_addr, address->sa_data, netdev->addr_len); @@ -628,6 +600,10 @@ int et131x_set_mac_addr(struct net_device *netdev, void *new_mac) /* Free Rx DMA memory */ et131x_adapter_memory_free(adapter); + /* Set the config parameter for Jumbo Packet support */ + /* adapter->RegistryJumboPacket = new_mtu + 14; */ + /* blux: not needet here, we'll change the MAC */ + et131x_soft_reset(adapter); /* Alloc and init Rx DMA memory */ @@ -692,12 +668,13 @@ struct net_device *et131x_device_alloc(void) return NULL; } - /* - * Setup the function registration table (and other data) for a + /* Setup the function registration table (and other data) for a * net_device */ + /* netdev->init = &et131x_init; */ + /* netdev->set_config = &et131x_config; */ netdev->watchdog_timeo = ET131X_TX_TIMEOUT; - netdev->netdev_ops = &et131x_netdev_ops; + netdev->netdev_ops = &et131x_netdev_ops; /* netdev->ethtool_ops = &et131x_ethtool_ops; */ diff --git a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h index adb436ed2511..3b0130fe6083 100644 --- a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h +++ b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h @@ -68,16 +68,6 @@ struct ft1000_info { char netdevname[IFNAMSIZ]; }; -struct pcmcia_device; -struct net_device; -extern struct net_device *init_ft1000_card(struct pcmcia_device *link, - void *ft1000_reset); -extern void stop_ft1000_card(struct net_device *dev); -extern int card_download(struct net_device *dev, const u8 *pFileStart, - size_t FileLength); -extern void ft1000InitProc(struct net_device *dev); -extern void ft1000CleanupProc(struct net_device *dev); - extern u16 ft1000_read_dpram(struct net_device *dev, int offset); extern void card_bootload(struct net_device *dev); extern u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index); diff --git a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c index f376ca43720d..6a1c1d4dcca2 100644 --- a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c +++ b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c @@ -41,12 +41,14 @@ MODULE_LICENSE("GPL"); /*====================================================================*/ +struct net_device *init_ft1000_card(struct pcmcia_device *link, + void *ft1000_reset); +void stop_ft1000_card(struct net_device *); + static int ft1000_config(struct pcmcia_device *link); static void ft1000_detach(struct pcmcia_device *link); static int ft1000_attach(struct pcmcia_device *link); -#include "ft1000.h" - /*====================================================================*/ static void ft1000_reset(struct pcmcia_device *link) @@ -73,7 +75,7 @@ static void ft1000_detach(struct pcmcia_device *link) free_netdev(dev); } -static int ft1000_confcheck(struct pcmcia_device *link, void *priv_data) +int ft1000_confcheck(struct pcmcia_device *link, void *priv_data) { return pcmcia_request_io(link); } diff --git a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c index f8b8e71284d9..c956857e2d58 100644 --- a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c +++ b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c @@ -287,8 +287,7 @@ u16 hdr_checksum(struct pseudo_hdr *pHdr) return chksum; } -int card_download(struct net_device *dev, const u8 *pFileStart, - size_t FileLength) +int card_download(struct net_device *dev, const u8 *pFileStart, u32 FileLength) { struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev); int Status = SUCCESS; diff --git a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index b3d743a3d308..990b2afb3d6b 100644 --- a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -56,11 +56,16 @@ #include #include "ft1000.h" -static const struct firmware *fw_entry; +int card_download(struct net_device *dev, const u8 *pFileStart, u32 FileLength); + +void ft1000InitProc(struct net_device *dev); +void ft1000CleanupProc(struct net_device *dev); + +const struct firmware *fw_entry; static void ft1000_hbchk(u_long data); static struct timer_list poll_timer = { - .function = ft1000_hbchk + function:ft1000_hbchk }; static u16 cmdbuffer[1024]; @@ -783,7 +788,7 @@ static void ft1000_hbchk(u_long data) // Output: // //--------------------------------------------------------------------------- -static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype) +void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype) { struct ft1000_info *info = netdev_priv(dev); int i; @@ -868,8 +873,7 @@ static void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, // = 1 (successful) // //--------------------------------------------------------------------------- -static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer, - int maxsz, u16 *pnxtph) +bool ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16 *pnxtph) { struct ft1000_info *info = netdev_priv(dev); u16 size; @@ -962,7 +966,7 @@ static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer, // none // //--------------------------------------------------------------------------- -static void ft1000_proc_drvmsg(struct net_device *dev) +void ft1000_proc_drvmsg(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); u16 msgtype; @@ -1241,7 +1245,7 @@ static void ft1000_proc_drvmsg(struct net_device *dev) // SUCCESS // //--------------------------------------------------------------------------- -static int ft1000_parse_dpram_msg(struct net_device *dev) +int ft1000_parse_dpram_msg(struct net_device *dev) { struct ft1000_info *info = netdev_priv(dev); u16 doorbell; @@ -1542,7 +1546,7 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) // SUCCESS // //--------------------------------------------------------------------------- -static int ft1000_copy_up_pkt(struct net_device *dev) +int ft1000_copy_up_pkt(struct net_device *dev) { u16 tempword; struct ft1000_info *info = netdev_priv(dev); @@ -1730,7 +1734,7 @@ static int ft1000_copy_up_pkt(struct net_device *dev) // SUCCESS // //--------------------------------------------------------------------------- -static int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) +int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len) { struct ft1000_info *info = netdev_priv(dev); union { @@ -2098,7 +2102,7 @@ static const struct ethtool_ops ops = { }; struct net_device *init_ft1000_card(struct pcmcia_device *link, - void *ft1000_reset) + void *ft1000_reset) { struct ft1000_info *info; struct net_device *dev; diff --git a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c index 7faeadad1fff..9e728b3415e3 100644 --- a/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c +++ b/trunk/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c @@ -48,8 +48,8 @@ } \ len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i]) -static int ft1000ReadProc(char *page, char **start, off_t off, - int count, int *eof, void *data) +int ft1000ReadProc(char *page, char **start, off_t off, + int count, int *eof, void *data) { struct net_device *dev; int len; diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index aaf44c359827..3f303ea14337 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -485,7 +485,7 @@ void card_send_command(struct ft1000_device *ft1000dev, void *ptempbuffer, DEBUG("card_send_command: enter card_send_command... size=%d\n", size); - commandbuf = kmalloc(size + 2, GFP_KERNEL); + commandbuf = (unsigned char *)kmalloc(size + 2, GFP_KERNEL); memcpy((void *)commandbuf + 2, (void *)ptempbuffer, size); ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL); diff --git a/trunk/drivers/staging/go7007/Makefile b/trunk/drivers/staging/go7007/Makefile index 6ee837c56706..60a91853570d 100644 --- a/trunk/drivers/staging/go7007/Makefile +++ b/trunk/drivers/staging/go7007/Makefile @@ -20,11 +20,15 @@ go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ s2250-y := s2250-board.o # Uncomment when the saa7134 patches get into upstream +#ifneq ($(CONFIG_VIDEO_SAA7134),) #obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o -#ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/video/saa7134 -DSAA7134_MPEG_GO7007=3 +#EXTRA_CFLAGS += -Idrivers/media/video/saa7134 -DSAA7134_MPEG_GO7007=3 +#endif # S2250 needs cypress ezusb loader from dvb-usb -ccflags-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD:m=y) += -Idrivers/media/dvb/dvb-usb +ifneq ($(CONFIG_VIDEO_GO7007_USB_S2250_BOARD),) +ccflags-y := -Idrivers/media/dvb/dvb-usb +endif ccflags-y += -Idrivers/media/dvb/frontends ccflags-y += -Idrivers/media/dvb/dvb-core diff --git a/trunk/drivers/staging/go7007/wis-tw2804.c b/trunk/drivers/staging/go7007/wis-tw2804.c index 9134f03e3cf0..5b218c55842a 100644 --- a/trunk/drivers/staging/go7007/wis-tw2804.c +++ b/trunk/drivers/staging/go7007/wis-tw2804.c @@ -33,7 +33,8 @@ struct wis_tw2804 { int hue; }; -static u8 global_registers[] = { +static u8 global_registers[] = +{ 0x39, 0x00, 0x3a, 0xff, 0x3b, 0x84, @@ -44,7 +45,8 @@ static u8 global_registers[] = { 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ }; -static u8 channel_registers[] = { +static u8 channel_registers[] = +{ 0x01, 0xc4, 0x02, 0xa5, 0x03, 0x20, diff --git a/trunk/drivers/staging/hv/hv.c b/trunk/drivers/staging/hv/hv.c index 2192d7885d48..824f81679ae8 100644 --- a/trunk/drivers/staging/hv/hv.c +++ b/trunk/drivers/staging/hv/hv.c @@ -111,7 +111,7 @@ static u64 do_hypercall(u64 control, void *input, void *output) u64 hv_status = 0; u64 input_address = (input) ? virt_to_phys(input) : 0; u64 output_address = (output) ? virt_to_phys(output) : 0; - void *hypercall_page = hv_context.hypercall_page; + volatile void *hypercall_page = hv_context.hypercall_page; __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); __asm__ __volatile__("call *%3" : "=a" (hv_status) : @@ -132,7 +132,7 @@ static u64 do_hypercall(u64 control, void *input, void *output) u64 output_address = (output) ? virt_to_phys(output) : 0; u32 output_address_hi = output_address >> 32; u32 output_address_lo = output_address & 0xFFFFFFFF; - void *hypercall_page = hv_context.hypercall_page; + volatile void *hypercall_page = hv_context.hypercall_page; __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), "=a"(hv_status_lo) : "d" (control_hi), diff --git a/trunk/drivers/staging/hv/hv_mouse.c b/trunk/drivers/staging/hv/hv_mouse.c index 9f3fbeeed8df..d957fc228019 100644 --- a/trunk/drivers/staging/hv/hv_mouse.c +++ b/trunk/drivers/staging/hv/hv_mouse.c @@ -54,7 +54,7 @@ struct hv_input_dev_info { (SYNTHHID_INPUT_VERSION_MAJOR << 16)) -#pragma pack(push, 1) +#pragma pack(push,1) /* * Message types in the synthetic input protocol */ @@ -120,8 +120,8 @@ struct synthhid_input_report { #pragma pack(pop) -#define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE) -#define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE) +#define INPUTVSC_SEND_RING_BUFFER_SIZE 10*PAGE_SIZE +#define INPUTVSC_RECV_RING_BUFFER_SIZE 10*PAGE_SIZE #define NBITS(x) (((x)/BITS_PER_LONG)+1) @@ -509,22 +509,22 @@ static void mousevsc_on_channel_callback(void *context) desc = (struct vmpacket_descriptor *)buffer; switch (desc->type) { - case VM_PKT_COMP: - mousevsc_on_send_completion( - device, desc); - break; - - case VM_PKT_DATA_INBAND: - mousevsc_on_receive( - device, desc); - break; - - default: - pr_err("unhandled packet type %d, tid %llx len %d\n", - desc->type, - req_id, - bytes_recvd); - break; + case VM_PKT_COMP: + mousevsc_on_send_completion( + device, desc); + break; + + case VM_PKT_DATA_INBAND: + mousevsc_on_receive( + device, desc); + break; + + default: + pr_err("unhandled packet type %d, tid %llx len %d\n", + desc->type, + req_id, + bytes_recvd); + break; } /* reset */ @@ -960,7 +960,7 @@ static void __exit mousevsc_exit(void) * installed and/or configured. We don't do anything else with the table, but * it needs to be present. */ -static const struct pci_device_id microsoft_hv_pci_table[] = { +const static struct pci_device_id microsoft_hv_pci_table[] = { { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */ { 0 } }; diff --git a/trunk/drivers/staging/hv/tools/hv_kvp_daemon.c b/trunk/drivers/staging/hv/tools/hv_kvp_daemon.c index 11224eddcdc2..a4a407f7052a 100644 --- a/trunk/drivers/staging/hv/tools/hv_kvp_daemon.c +++ b/trunk/drivers/staging/hv/tools/hv_kvp_daemon.c @@ -116,16 +116,7 @@ void kvp_get_os_info(void) uname(&uts_buf); os_build = uts_buf.release; - processor_arch = uts_buf.machine; - - /* - * The current windows host (win7) expects the build - * string to be of the form: x.y.z - * Strip additional information we may have. - */ - p = strchr(os_build, '-'); - if (p) - *p = '\0'; + processor_arch= uts_buf.machine; file = fopen("/etc/SuSE-release", "r"); if (file != NULL) @@ -273,20 +264,22 @@ static int kvp_get_domain_name(char *buffer, int length) { struct addrinfo hints, *info ; + gethostname(buffer, length); int error = 0; - gethostname(buffer, length); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */ hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; - error = getaddrinfo(buffer, NULL, &hints, &info); + error = getaddrinfo(buffer, "http", &hints, &info); if (error != 0) { strcpy(buffer, "getaddrinfo failed\n"); - return error; + error = 1; + goto get_domain_done; } strcpy(buffer, info->ai_canonname); +get_domain_done: freeaddrinfo(info); return error; } diff --git a/trunk/drivers/staging/hv/vmbus_drv.c b/trunk/drivers/staging/hv/vmbus_drv.c index 67a4f336df9c..1c949f5fb716 100644 --- a/trunk/drivers/staging/hv/vmbus_drv.c +++ b/trunk/drivers/staging/hv/vmbus_drv.c @@ -768,7 +768,7 @@ MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table); static int __init hv_acpi_init(void) { - int ret, t; + int ret; init_completion(&probe_event); @@ -781,25 +781,16 @@ static int __init hv_acpi_init(void) if (ret) return ret; - t = wait_for_completion_timeout(&probe_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + wait_for_completion(&probe_event); if (irq <= 0) { - ret = -ENODEV; - goto cleanup; + acpi_bus_unregister_driver(&vmbus_acpi_driver); + return -ENODEV; } ret = vmbus_bus_init(irq); if (ret) - goto cleanup; - - return 0; - -cleanup: - acpi_bus_unregister_driver(&vmbus_acpi_driver); + acpi_bus_unregister_driver(&vmbus_acpi_driver); return ret; } diff --git a/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio b/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio index c19dbf4ab249..467c49a47258 100644 --- a/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio +++ b/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio @@ -2,7 +2,7 @@ What: /sys/bus/iio/devices/deviceX KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: - Hardware chip or device accessed by one communication port. + Hardware chip or device accessed by on communication port. Corresponds to a grouping of sensor channels. X is the IIO index of the device. @@ -711,24 +711,3 @@ Contact: linux-iio@xxxxxxxxxxxxxxx Description: This attribute is used to read the amount of quadrature error present in the device at a given time. - -What: /sys/.../iio:deviceX/ac_excitation_en -KernelVersion: 3.1.0 -Contact: linux-iio@vger.kernel.org -Description: - This attribute, if available, is used to enable the AC - excitation mode found on some converters. In ac excitation mode, - the polarity of the excitation voltage is reversed on - alternate cycles, to eliminate DC errors. - -What: /sys/.../iio:deviceX/bridge_switch_en -KernelVersion: 3.1.0 -Contact: linux-iio@vger.kernel.org -Description: - This attribute, if available, is used to close or open the - bridge power down switch found on some converters. - In bridge applications, such as strain gauges and load cells, - the bridge itself consumes the majority of the current in the - system. To minimize the current consumption of the system, - the bridge can be disconnected (when it is not being used - using the bridge_switch_en attribute. diff --git a/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a b/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a deleted file mode 100644 index 863d3856718a..000000000000 --- a/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio-adc-ad7280a +++ /dev/null @@ -1,21 +0,0 @@ -What: /sys/bus/iio/devices/deviceX/inY-inZ_balance_switch_en -KernelVersion: 3.0.0 -Contact: linux-iio@vger.kernel.org -Description: - Writing 1 enables the cell balance output switch corresponding - to input Y. Writing 0 disables it. If the inY-inZ_balance_timer - is set to a none zero value, the corresponding switch will - enable for the programmed amount of time, before it - automatically disables. - -What: /sys/bus/iio/devices/deviceX/inY-inZ_balance_timer -KernelVersion: 3.0.0 -Contact: linux-iio@vger.kernel.org -Description: - The inY-inZ_balance_timer file allows the user to program - individual times for each cell balance output. The AD7280A - allows the user to set the timer to a value from 0 minutes to - 36.9 minutes. The resolution of the timer is 71.5 sec. - The value written is the on-time in milliseconds. When the - timer value is set 0, the timer is disabled. The cell balance - outputs are controlled only by inY-inZ_balance_switch_en. diff --git a/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933 b/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933 deleted file mode 100644 index 79c7e88c64cd..000000000000 --- a/trunk/drivers/staging/iio/Documentation/sysfs-bus-iio-impedance-analyzer-ad5933 +++ /dev/null @@ -1,30 +0,0 @@ -What: /sys/bus/iio/devices/iio:deviceX/outY_freq_start -KernelVersion: 3.1.0 -Contact: linux-iio@vger.kernel.org -Description: - Frequency sweep start frequency in Hz. - -What: /sys/bus/iio/devices/iio:deviceX/outY_freq_increment -KernelVersion: 3.1.0 -Contact: linux-iio@vger.kernel.org -Description: - Frequency increment in Hz (step size) between consecutive - frequency points along the sweep. - -What: /sys/bus/iio/devices/iio:deviceX/outY_freq_points -KernelVersion: 3.1.0 -Contact: linux-iio@vger.kernel.org -Description: - Number of frequency points (steps) in the frequency sweep. - This value, in conjunction with the outY_freq_start and the - outY_freq_increment, determines the frequency sweep range - for the sweep operation. - -What: /sys/bus/iio/devices/iio:deviceX/outY_settling_cycles -KernelVersion: 3.1.0 -Contact: linux-iio@vger.kernel.org -Description: - Number of output excitation cycles (settling time cycles) - that are allowed to pass through the unknown impedance, - after each frequency increment, and before the ADC is triggered - to perform a conversion sequence of the response signal. diff --git a/trunk/drivers/staging/iio/Kconfig b/trunk/drivers/staging/iio/Kconfig index 75265678348f..d329635fb5c4 100644 --- a/trunk/drivers/staging/iio/Kconfig +++ b/trunk/drivers/staging/iio/Kconfig @@ -62,7 +62,6 @@ source "drivers/staging/iio/addac/Kconfig" source "drivers/staging/iio/dac/Kconfig" source "drivers/staging/iio/dds/Kconfig" source "drivers/staging/iio/gyro/Kconfig" -source "drivers/staging/iio/impedance-analyzer/Kconfig" source "drivers/staging/iio/imu/Kconfig" source "drivers/staging/iio/light/Kconfig" source "drivers/staging/iio/magnetometer/Kconfig" diff --git a/trunk/drivers/staging/iio/Makefile b/trunk/drivers/staging/iio/Makefile index eaff649faf95..bb5c95c7d694 100644 --- a/trunk/drivers/staging/iio/Makefile +++ b/trunk/drivers/staging/iio/Makefile @@ -16,7 +16,6 @@ obj-y += addac/ obj-y += dac/ obj-y += dds/ obj-y += gyro/ -obj-y += impedance-analyzer/ obj-y += imu/ obj-y += light/ obj-y += magnetometer/ diff --git a/trunk/drivers/staging/iio/accel/accel.h b/trunk/drivers/staging/iio/accel/accel.h new file mode 100644 index 000000000000..50651f835cea --- /dev/null +++ b/trunk/drivers/staging/iio/accel/accel.h @@ -0,0 +1,87 @@ + +#include "../sysfs.h" + +/* Accelerometer types of attribute */ +#define IIO_DEV_ATTR_ACCEL_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_X_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_x_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_Y_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_y_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_Z_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_z_offset, _mode, _show, _store, _addr) + +#define IIO_CONST_ATTR_ACCEL_SCALE(_string) \ + IIO_CONST_ATTR(accel_scale, _string) + +#define IIO_DEV_ATTR_ACCEL_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_X_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_x_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_Y_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_y_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_Z_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_z_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_CALIBBIAS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_calibbias, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_x_calibbias, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_y_calibbias, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_Z_CALIBBIAS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_z_calibbias, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_CALIBSCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_calibscale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_X_CALIBSCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_x_calibscale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_Y_CALIBSCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_y_calibscale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL_Z_CALIBSCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(accel_z_calibscale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACCEL(_show, _addr) \ + IIO_DEVICE_ATTR(accel_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_X(_show, _addr) \ + IIO_DEVICE_ATTR(accel_x_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_Y(_show, _addr) \ + IIO_DEVICE_ATTR(accel_y_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_Z(_show, _addr) \ + IIO_DEVICE_ATTR(accel_z_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \ + IIO_DEVICE_ATTR(accel_xy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_PEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_peak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_XPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_xpeak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_YPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_ypeak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_ZPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_zpeak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_xypeak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_XYZPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_xyzpeak, S_IRUGO, _show, NULL, _addr) diff --git a/trunk/drivers/staging/iio/accel/adis16201_core.c b/trunk/drivers/staging/iio/accel/adis16201_core.c index 16b388bf8991..2fd01aecdf96 100644 --- a/trunk/drivers/staging/iio/accel/adis16201_core.c +++ b/trunk/drivers/staging/iio/accel/adis16201_core.c @@ -18,6 +18,10 @@ #include "../sysfs.h" #include "../ring_generic.h" +#include "accel.h" +#include "inclinometer.h" +#include "../adc/adc.h" + #include "adis16201.h" enum adis16201_chan { diff --git a/trunk/drivers/staging/iio/accel/adis16201_ring.c b/trunk/drivers/staging/iio/accel/adis16201_ring.c index 4b433c53e5c5..66e708ddf8b2 100644 --- a/trunk/drivers/staging/iio/accel/adis16201_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16201_ring.c @@ -1,12 +1,17 @@ #include +#include #include +#include #include #include #include +#include #include "../iio.h" +#include "../sysfs.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "accel.h" +#include "../trigger.h" #include "adis16201.h" @@ -33,12 +38,10 @@ static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx) xfers[i].cs_change = 1; xfers[i].len = 2; xfers[i].delay_usecs = 20; - if (i < ADIS16201_OUTPUTS) { - xfers[i].tx_buf = st->tx + 2 * i; - st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT + - 2 * i); - st->tx[2 * i + 1] = 0; - } + xfers[i].tx_buf = st->tx + 2 * i; + st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT + + 2 * i); + st->tx[2 * i + 1] = 0; if (i >= 1) xfers[i].rx_buf = rx + 2 * (i - 1); spi_message_add_tail(&xfers[i], &msg); @@ -59,7 +62,7 @@ static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx) static irqreturn_t adis16201_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct adis16201_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; diff --git a/trunk/drivers/staging/iio/accel/adis16201_trigger.c b/trunk/drivers/staging/iio/accel/adis16201_trigger.c index f448258884c5..3a95c083b452 100644 --- a/trunk/drivers/staging/iio/accel/adis16201_trigger.c +++ b/trunk/drivers/staging/iio/accel/adis16201_trigger.c @@ -1,8 +1,13 @@ #include +#include +#include +#include #include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../trigger.h" #include "adis16201.h" @@ -18,11 +23,6 @@ static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16201_set_irq(indio_dev, state); } -static const struct iio_trigger_ops adis16201_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16201_data_rdy_trigger_set_state, -}; - int adis16201_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -41,8 +41,9 @@ int adis16201_probe_trigger(struct iio_dev *indio_dev) if (ret) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16201_trigger_ops; + st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; + st->trig->set_trigger_state = &adis16201_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/trunk/drivers/staging/iio/accel/adis16203_core.c b/trunk/drivers/staging/iio/accel/adis16203_core.c index a7c06b957bec..cf5d15da76ad 100644 --- a/trunk/drivers/staging/iio/accel/adis16203_core.c +++ b/trunk/drivers/staging/iio/accel/adis16203_core.c @@ -16,7 +16,10 @@ #include "../iio.h" #include "../sysfs.h" +#include "accel.h" +#include "inclinometer.h" #include "../ring_generic.h" +#include "../adc/adc.h" #include "adis16203.h" diff --git a/trunk/drivers/staging/iio/accel/adis16203_ring.c b/trunk/drivers/staging/iio/accel/adis16203_ring.c index 993e239f9426..d2c07c527467 100644 --- a/trunk/drivers/staging/iio/accel/adis16203_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16203_ring.c @@ -1,12 +1,20 @@ #include +#include +#include +#include #include +#include #include #include #include +#include +#include #include "../iio.h" +#include "../sysfs.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "accel.h" +#include "../trigger.h" #include "adis16203.h" /** @@ -59,7 +67,7 @@ static int adis16203_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16203_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct adis16203_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; diff --git a/trunk/drivers/staging/iio/accel/adis16203_trigger.c b/trunk/drivers/staging/iio/accel/adis16203_trigger.c index 50165f9ddc52..3caf3e8bc9d9 100644 --- a/trunk/drivers/staging/iio/accel/adis16203_trigger.c +++ b/trunk/drivers/staging/iio/accel/adis16203_trigger.c @@ -1,8 +1,14 @@ #include +#include +#include +#include #include +#include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../trigger.h" #include "adis16203.h" @@ -18,11 +24,6 @@ static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16203_set_irq(indio_dev, state); } -static const struct iio_trigger_ops adis16203_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16203_data_rdy_trigger_set_state, -}; - int adis16203_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -43,8 +44,9 @@ int adis16203_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16203_trigger_ops; + st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; + st->trig->set_trigger_state = &adis16203_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/trunk/drivers/staging/iio/accel/adis16204_core.c b/trunk/drivers/staging/iio/accel/adis16204_core.c index 6a64b2b723de..3e2b62654b7d 100644 --- a/trunk/drivers/staging/iio/accel/adis16204_core.c +++ b/trunk/drivers/staging/iio/accel/adis16204_core.c @@ -21,6 +21,8 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" +#include "accel.h" +#include "../adc/adc.h" #include "adis16204.h" @@ -297,15 +299,12 @@ static int adis16204_initial_setup(struct iio_dev *indio_dev) err_ret: return ret; } - -/* Unique to this driver currently */ -#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \ - IIO_DEVICE_ATTR(accel_xy, S_IRUGO, _show, NULL, _addr) -#define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \ - IIO_DEVICE_ATTR(accel_xypeak, S_IRUGO, _show, NULL, _addr) - static IIO_DEV_ATTR_ACCEL_XY(adis16204_read_14bit_signed, ADIS16204_XY_RSS_OUT); +static IIO_DEV_ATTR_ACCEL_XPEAK(adis16204_read_14bit_signed, + ADIS16204_X_PEAK_OUT); +static IIO_DEV_ATTR_ACCEL_YPEAK(adis16204_read_14bit_signed, + ADIS16204_Y_PEAK_OUT); static IIO_DEV_ATTR_ACCEL_XYPEAK(adis16204_read_14bit_signed, ADIS16204_XY_PEAK_OUT); static IIO_CONST_ATTR(accel_xy_scale, "0.017125"); @@ -320,16 +319,13 @@ enum adis16204_channel { accel_y, }; -static u8 adis16204_addresses[5][3] = { +static u8 adis16204_addresses[5][2] = { [in_supply] = { ADIS16204_SUPPLY_OUT }, [in_aux] = { ADIS16204_AUX_ADC }, [temp] = { ADIS16204_TEMP_OUT }, - [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL, - ADIS16204_X_PEAK_OUT }, - [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL, - ADIS16204_Y_PEAK_OUT }, + [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL }, + [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL }, }; - static int adis16204_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, @@ -339,7 +335,6 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, int bits; u8 addr; s16 val16; - int addrind; switch (mask) { case 0: @@ -394,16 +389,15 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, *val = 25; return IIO_VAL_INT; case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): - case (1 << IIO_CHAN_INFO_PEAK_SEPARATE): - if (mask == (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE)) { + switch (chan->type) { + case IIO_ACCEL: bits = 12; - addrind = 1; - } else { /* PEAK_SEPARATE */ - bits = 14; - addrind = 2; - } + break; + default: + return -EINVAL; + }; mutex_lock(&indio_dev->mlock); - addr = adis16204_addresses[chan->address][addrind]; + addr = adis16204_addresses[chan->address][1]; ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16); if (ret) { mutex_unlock(&indio_dev->mlock); @@ -459,22 +453,21 @@ static struct iio_chan_spec adis16204_channels[] = { IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_PEAK_SEPARATE), + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), accel_x, ADIS16204_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_PEAK_SEPARATE), + (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), accel_y, ADIS16204_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN_SOFT_TIMESTAMP(5), }; - static struct attribute *adis16204_attributes[] = { &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_accel_xy.dev_attr.attr, + &iio_dev_attr_accel_xpeak.dev_attr.attr, + &iio_dev_attr_accel_ypeak.dev_attr.attr, &iio_dev_attr_accel_xypeak.dev_attr.attr, &iio_const_attr_accel_xy_scale.dev_attr.attr, NULL diff --git a/trunk/drivers/staging/iio/accel/adis16204_ring.c b/trunk/drivers/staging/iio/accel/adis16204_ring.c index 847f43858f50..852df06684d8 100644 --- a/trunk/drivers/staging/iio/accel/adis16204_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16204_ring.c @@ -1,12 +1,20 @@ #include +#include +#include +#include #include +#include #include #include #include +#include +#include #include "../iio.h" +#include "../sysfs.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "accel.h" +#include "../trigger.h" #include "adis16204.h" /** @@ -57,7 +65,7 @@ static int adis16204_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16204_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct adis16204_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; int i = 0; diff --git a/trunk/drivers/staging/iio/accel/adis16204_trigger.c b/trunk/drivers/staging/iio/accel/adis16204_trigger.c index 55b661c98d2d..01f73b9b8886 100644 --- a/trunk/drivers/staging/iio/accel/adis16204_trigger.c +++ b/trunk/drivers/staging/iio/accel/adis16204_trigger.c @@ -1,8 +1,14 @@ #include +#include +#include +#include #include +#include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../trigger.h" #include "adis16204.h" @@ -18,11 +24,6 @@ static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16204_set_irq(indio_dev, state); } -static const struct iio_trigger_ops adis16204_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16204_data_rdy_trigger_set_state, -}; - int adis16204_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -43,8 +44,9 @@ int adis16204_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16204_trigger_ops; + st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; + st->trig->set_trigger_state = &adis16204_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/trunk/drivers/staging/iio/accel/adis16209_core.c b/trunk/drivers/staging/iio/accel/adis16209_core.c index bd3d55714ed6..bec1fa8de9b9 100644 --- a/trunk/drivers/staging/iio/accel/adis16209_core.c +++ b/trunk/drivers/staging/iio/accel/adis16209_core.c @@ -18,6 +18,9 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" +#include "accel.h" +#include "inclinometer.h" +#include "../adc/adc.h" #include "adis16209.h" diff --git a/trunk/drivers/staging/iio/accel/adis16209_ring.c b/trunk/drivers/staging/iio/accel/adis16209_ring.c index f889fe72f33a..45017d3f02f5 100644 --- a/trunk/drivers/staging/iio/accel/adis16209_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16209_ring.c @@ -1,12 +1,20 @@ #include +#include +#include +#include #include +#include #include #include #include +#include +#include #include "../iio.h" +#include "../sysfs.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "accel.h" +#include "../trigger.h" #include "adis16209.h" /** @@ -57,7 +65,7 @@ static int adis16209_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16209_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct adis16209_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; diff --git a/trunk/drivers/staging/iio/accel/adis16209_trigger.c b/trunk/drivers/staging/iio/accel/adis16209_trigger.c index 8df8a9791d5e..6df7b47ec7b4 100644 --- a/trunk/drivers/staging/iio/accel/adis16209_trigger.c +++ b/trunk/drivers/staging/iio/accel/adis16209_trigger.c @@ -1,8 +1,14 @@ #include +#include +#include +#include #include +#include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../trigger.h" #include "adis16209.h" @@ -27,11 +33,6 @@ static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16209_set_irq(indio_dev, state); } -static const struct iio_trigger_ops adis16209_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16209_data_rdy_trigger_set_state, -}; - int adis16209_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -51,8 +52,9 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev) if (ret) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16209_trigger_ops; + st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; + st->trig->set_trigger_state = &adis16209_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/trunk/drivers/staging/iio/accel/adis16220_core.c b/trunk/drivers/staging/iio/accel/adis16220_core.c index 18b0830b82f9..bf9ba07c0383 100644 --- a/trunk/drivers/staging/iio/accel/adis16220_core.c +++ b/trunk/drivers/staging/iio/accel/adis16220_core.c @@ -6,6 +6,9 @@ * Licensed under the GPL-2 or later. */ +#include +#include +#include #include #include #include @@ -13,10 +16,12 @@ #include #include #include -#include +#include #include "../iio.h" #include "../sysfs.h" +#include "accel.h" +#include "../adc/adc.h" #include "adis16220.h" @@ -24,15 +29,16 @@ /** * adis16220_spi_write_reg_8() - write single byte to a register - * @indio_dev: iio device associated with child of actual device + * @dev: device associated with child of actual device (iio_dev or iio_trig) * @reg_address: the address of the register to be written * @val: the value to write **/ -static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev, +static int adis16220_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val) { int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16220_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -47,17 +53,18 @@ static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev, /** * adis16220_spi_write_reg_16() - write 2 bytes to a pair of registers - * @indio_dev: iio device associated with child of actual device + * @dev: device associated with child of actual device (iio_dev or iio_trig) * @reg_address: the address of the lower of the two registers. Second register * is assumed to have address one greater. * @val: value to be written **/ -static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev, +static int adis16220_spi_write_reg_16(struct device *dev, u8 lower_reg_address, u16 value) { int ret; struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16220_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { { @@ -70,6 +77,7 @@ static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev, .tx_buf = st->tx + 2, .bits_per_word = 8, .len = 2, + .cs_change = 1, .delay_usecs = 35, }, }; @@ -91,16 +99,17 @@ static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev, /** * adis16220_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @indio_dev: iio device associated with child of actual device + * @dev: device associated with child of actual device (iio_dev or iio_trig) * @reg_address: the address of the lower of the two registers. Second register * is assumed to have address one greater. * @val: somewhere to pass back the value read **/ -static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev, - u8 lower_reg_address, - u16 *val) +static int adis16220_spi_read_reg_16(struct device *dev, + u8 lower_reg_address, + u16 *val) { struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16220_state *st = iio_priv(indio_dev); int ret; struct spi_transfer xfers[] = { @@ -140,23 +149,52 @@ static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev, return ret; } -static ssize_t adis16220_read_16bit(struct device *dev, +static ssize_t adis16220_spi_read_signed(struct device *dev, + struct device_attribute *attr, + char *buf, + unsigned bits) +{ + int ret; + s16 val = 0; + unsigned shift = 16 - bits; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = adis16220_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); + if (ret) + return ret; + + val = ((s16)(val << shift) >> shift); + return sprintf(buf, "%d\n", val); +} + +static ssize_t adis16220_read_12bit_unsigned(struct device *dev, struct device_attribute *attr, char *buf) { + int ret; + u16 val = 0; struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = adis16220_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val & 0x0FFF); +} + +static ssize_t adis16220_read_16bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ struct iio_dev *indio_dev = dev_get_drvdata(dev); ssize_t ret; - s16 val = 0; /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); - ret = adis16220_spi_read_reg_16(indio_dev, this_attr->address, - (u16 *)&val); + ret = adis16220_spi_read_signed(dev, attr, buf, 16); mutex_unlock(&indio_dev->mlock); - if (ret) - return ret; - return sprintf(buf, "%d\n", val); + + return ret; } static ssize_t adis16220_write_16bit(struct device *dev, @@ -164,7 +202,6 @@ static ssize_t adis16220_write_16bit(struct device *dev, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; long val; @@ -172,34 +209,34 @@ static ssize_t adis16220_write_16bit(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) goto error_ret; - ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val); + ret = adis16220_spi_write_reg_16(dev, this_attr->address, val); error_ret: return ret ? ret : len; } -static int adis16220_capture(struct iio_dev *indio_dev) +static int adis16220_capture(struct device *dev) { int ret; - ret = adis16220_spi_write_reg_16(indio_dev, + ret = adis16220_spi_write_reg_16(dev, ADIS16220_GLOB_CMD, 0xBF08); /* initiates a manual data capture */ if (ret) - dev_err(&indio_dev->dev, "problem beginning capture"); + dev_err(dev, "problem beginning capture"); msleep(10); /* delay for capture to finish */ return ret; } -static int adis16220_reset(struct iio_dev *indio_dev) +static int adis16220_reset(struct device *dev) { int ret; - ret = adis16220_spi_write_reg_8(indio_dev, + ret = adis16220_spi_write_reg_8(dev, ADIS16220_GLOB_CMD, ADIS16220_GLOB_CMD_SW_RESET); if (ret) - dev_err(&indio_dev->dev, "problem resetting device"); + dev_err(dev, "problem resetting device"); return ret; } @@ -208,84 +245,72 @@ static ssize_t adis16220_write_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - bool val; - int ret; - - ret = strtobool(buf, &val); - if (ret) - return ret; - if (!val) - return -EINVAL; - - ret = adis16220_reset(indio_dev); - if (ret) - return ret; - return len; + if (len < 1) + return -1; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return adis16220_reset(dev) == 0 ? len : -EIO; + } + return -1; } static ssize_t adis16220_write_capture(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); - bool val; - int ret; - - ret = strtobool(buf, &val); - if (ret) - return ret; - if (!val) - return -EINVAL; - ret = adis16220_capture(indio_dev); - if (ret) - return ret; - - return len; + if (len < 1) + return -1; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return adis16220_capture(dev) == 0 ? len : -EIO; + } + return -1; } -static int adis16220_check_status(struct iio_dev *indio_dev) +static int adis16220_check_status(struct device *dev) { u16 status; int ret; - ret = adis16220_spi_read_reg_16(indio_dev, ADIS16220_DIAG_STAT, - &status); + ret = adis16220_spi_read_reg_16(dev, ADIS16220_DIAG_STAT, &status); if (ret < 0) { - dev_err(&indio_dev->dev, "Reading status failed\n"); + dev_err(dev, "Reading status failed\n"); goto error_ret; } ret = status & 0x7F; if (status & ADIS16220_DIAG_STAT_VIOLATION) - dev_err(&indio_dev->dev, - "Capture period violation/interruption\n"); + dev_err(dev, "Capture period violation/interruption\n"); if (status & ADIS16220_DIAG_STAT_SPI_FAIL) - dev_err(&indio_dev->dev, "SPI failure\n"); + dev_err(dev, "SPI failure\n"); if (status & ADIS16220_DIAG_STAT_FLASH_UPT) - dev_err(&indio_dev->dev, "Flash update failed\n"); + dev_err(dev, "Flash update failed\n"); if (status & ADIS16220_DIAG_STAT_POWER_HIGH) - dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); + dev_err(dev, "Power supply above 3.625V\n"); if (status & ADIS16220_DIAG_STAT_POWER_LOW) - dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); + dev_err(dev, "Power supply below 3.15V\n"); error_ret: return ret; } -static int adis16220_self_test(struct iio_dev *indio_dev) +static int adis16220_self_test(struct device *dev) { int ret; - ret = adis16220_spi_write_reg_16(indio_dev, + ret = adis16220_spi_write_reg_16(dev, ADIS16220_MSC_CTRL, ADIS16220_MSC_CTRL_SELF_TEST_EN); if (ret) { - dev_err(&indio_dev->dev, "problem starting self test"); + dev_err(dev, "problem starting self test"); goto err_ret; } - adis16220_check_status(indio_dev); + adis16220_check_status(dev); err_ret: return ret; @@ -294,23 +319,24 @@ static int adis16220_self_test(struct iio_dev *indio_dev) static int adis16220_initial_setup(struct iio_dev *indio_dev) { int ret; + struct device *dev = &indio_dev->dev; /* Do self test */ - ret = adis16220_self_test(indio_dev); + ret = adis16220_self_test(dev); if (ret) { - dev_err(&indio_dev->dev, "self test failure"); + dev_err(dev, "self test failure"); goto err_ret; } /* Read status register to check the result */ - ret = adis16220_check_status(indio_dev); + ret = adis16220_check_status(dev); if (ret) { - adis16220_reset(indio_dev); - dev_err(&indio_dev->dev, "device not playing ball -> reset"); + adis16220_reset(dev); + dev_err(dev, "device not playing ball -> reset"); msleep(ADIS16220_STARTUP_DELAY); - ret = adis16220_check_status(indio_dev); + ret = adis16220_check_status(dev); if (ret) { - dev_err(&indio_dev->dev, "giving up"); + dev_err(dev, "giving up"); goto err_ret; } } @@ -355,7 +381,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, count = ADIS16220_CAPTURE_SIZE - off; /* write the begin position of capture buffer */ - ret = adis16220_spi_write_reg_16(indio_dev, + ret = adis16220_spi_write_reg_16(&indio_dev->dev, ADIS16220_CAPT_PNTR, off > 1); if (ret) @@ -454,6 +480,24 @@ static struct bin_attribute adc2_bin = { .size = ADIS16220_CAPTURE_SIZE, }; +static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16220_read_12bit_unsigned, + ADIS16220_CAPT_SUPPLY); +static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.0012207"); +static IIO_DEV_ATTR_ACCEL(adis16220_read_16bit, ADIS16220_CAPT_BUFA); +static IIO_DEVICE_ATTR(accel_peak_raw, S_IRUGO, adis16220_read_16bit, + NULL, ADIS16220_CAPT_PEAKA); +static IIO_DEV_ATTR_ACCEL_OFFSET(S_IWUSR | S_IRUGO, + adis16220_read_16bit, + adis16220_write_16bit, + ADIS16220_ACCL_NULL); +static IIO_CONST_ATTR_ACCEL_SCALE("0.18704223545"); +static IIO_DEV_ATTR_TEMP_RAW(adis16220_read_12bit_unsigned); +static IIO_CONST_ATTR_TEMP_OFFSET("25"); +static IIO_CONST_ATTR_TEMP_SCALE("-0.47"); + +static IIO_DEV_ATTR_IN_RAW(1, adis16220_read_16bit, ADIS16220_CAPT_BUF1); +static IIO_DEV_ATTR_IN_RAW(2, adis16220_read_16bit, ADIS16220_CAPT_BUF2); + static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16220_write_reset, 0); @@ -470,142 +514,21 @@ static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO, adis16220_write_16bit, ADIS16220_CAPT_PNTR); -enum adis16220_channel { - in_supply, in_1, in_2, accel, temp -}; - -struct adis16220_address_spec { - u8 addr; - u8 bits; - bool sign; -}; - -/* Address / bits / signed */ -static const struct adis16220_address_spec adis16220_addresses[][3] = { - [in_supply] = { { ADIS16220_CAPT_SUPPLY, 12, 0 }, }, - [in_1] = { { ADIS16220_CAPT_BUF1, 16, 1 }, - { ADIS16220_AIN1_NULL, 16, 1 }, - { ADIS16220_CAPT_PEAK1, 16, 1 }, }, - [in_2] = { { ADIS16220_CAPT_BUF2, 16, 1 }, - { ADIS16220_AIN2_NULL, 16, 1 }, - { ADIS16220_CAPT_PEAK2, 16, 1 }, }, - [accel] = { { ADIS16220_CAPT_BUFA, 16, 1 }, - { ADIS16220_ACCL_NULL, 16, 1 }, - { ADIS16220_CAPT_PEAKA, 16, 1 }, }, - [temp] = { { ADIS16220_CAPT_TEMP, 12, 0 }, } -}; - -static int adis16220_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - int ret = -EINVAL; - int addrind = 0; - u16 uval; - s16 sval; - u8 bits; - - switch (mask) { - case 0: - addrind = 0; - break; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): - if (chan->type == IIO_TEMP) { - *val = 25; - return IIO_VAL_INT; - } - addrind = 1; - break; - case (1 << IIO_CHAN_INFO_PEAK_SEPARATE): - addrind = 2; - break; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): - *val = 0; - switch (chan->type) { - case IIO_TEMP: - *val2 = -470000; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_ACCEL: - *val2 = 1887042; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_IN: - if (chan->channel == 0) - *val2 = 0012221; - else /* Should really be dependent on VDD */ - *val2 = 305; - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - default: - return -EINVAL; - } - if (adis16220_addresses[chan->address][addrind].sign) { - ret = adis16220_spi_read_reg_16(indio_dev, - adis16220_addresses[chan - ->address] - [addrind].addr, - &sval); - if (ret) - return ret; - bits = adis16220_addresses[chan->address][addrind].bits; - sval &= (1 << bits) - 1; - sval = (s16)(sval << (16 - bits)) >> (16 - bits); - *val = sval; - return IIO_VAL_INT; - } else { - ret = adis16220_spi_read_reg_16(indio_dev, - adis16220_addresses[chan - ->address] - [addrind].addr, - &uval); - if (ret) - return ret; - bits = adis16220_addresses[chan->address][addrind].bits; - uval &= (1 << bits) - 1; - *val = uval; - return IIO_VAL_INT; - } -} - -static const struct iio_chan_spec adis16220_channels[] = { - { - .type = IIO_IN, - .indexed = 1, - .channel = 0, - .extend_name = "supply", - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - .address = in_supply, - }, { - .type = IIO_ACCEL, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_PEAK_SEPARATE), - .address = accel, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - .address = temp, - }, { - .type = IIO_IN, - .indexed = 1, - .channel = 1, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - .address = in_1, - }, { - .type = IIO_IN, - .indexed = 1, - .channel = 2, - .address = in_2, - } -}; +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100200"); static struct attribute *adis16220_attributes[] = { + &iio_dev_attr_in0_supply_raw.dev_attr.attr, + &iio_const_attr_in0_supply_scale.dev_attr.attr, + &iio_dev_attr_accel_raw.dev_attr.attr, + &iio_dev_attr_accel_offset.dev_attr.attr, + &iio_dev_attr_accel_peak_raw.dev_attr.attr, + &iio_const_attr_accel_scale.dev_attr.attr, + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_dev_attr_in1_raw.dev_attr.attr, + &iio_dev_attr_in2_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_reset.dev_attr.attr, &iio_dev_attr_capture.dev_attr.attr, &iio_dev_attr_capture_count.dev_attr.attr, @@ -619,9 +542,7 @@ static const struct attribute_group adis16220_attribute_group = { static const struct iio_info adis16220_info = { .attrs = &adis16220_attribute_group, .driver_module = THIS_MODULE, - .read_raw = &adis16220_read_raw, }; - static int __devinit adis16220_probe(struct spi_device *spi) { int ret, regdone = 0; @@ -646,8 +567,6 @@ static int __devinit adis16220_probe(struct spi_device *spi) indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16220_info; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = adis16220_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16220_channels); ret = iio_device_register(indio_dev); if (ret) diff --git a/trunk/drivers/staging/iio/accel/adis16240_core.c b/trunk/drivers/staging/iio/accel/adis16240_core.c index 237da463c67e..aee8b69173c4 100644 --- a/trunk/drivers/staging/iio/accel/adis16240_core.c +++ b/trunk/drivers/staging/iio/accel/adis16240_core.c @@ -21,6 +21,8 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" +#include "accel.h" +#include "../adc/adc.h" #include "adis16240.h" diff --git a/trunk/drivers/staging/iio/accel/adis16240_ring.c b/trunk/drivers/staging/iio/accel/adis16240_ring.c index 051ba643d340..c812a34dacaf 100644 --- a/trunk/drivers/staging/iio/accel/adis16240_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16240_ring.c @@ -1,12 +1,20 @@ #include +#include +#include +#include #include +#include #include #include #include +#include +#include #include "../iio.h" +#include "../sysfs.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "accel.h" +#include "../trigger.h" #include "adis16240.h" /** @@ -54,7 +62,7 @@ static int adis16240_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16240_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct adis16240_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; diff --git a/trunk/drivers/staging/iio/accel/adis16240_trigger.c b/trunk/drivers/staging/iio/accel/adis16240_trigger.c index 13f1d142eea3..17135fc33c99 100644 --- a/trunk/drivers/staging/iio/accel/adis16240_trigger.c +++ b/trunk/drivers/staging/iio/accel/adis16240_trigger.c @@ -1,8 +1,14 @@ #include +#include +#include +#include #include +#include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../trigger.h" #include "adis16240.h" @@ -27,11 +33,6 @@ static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16240_set_irq(indio_dev, state); } -static const struct iio_trigger_ops adis16240_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16240_data_rdy_trigger_set_state, -}; - int adis16240_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -52,8 +53,9 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16240_trigger_ops; + st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; + st->trig->set_trigger_state = &adis16240_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/trunk/drivers/staging/iio/accel/inclinometer.h b/trunk/drivers/staging/iio/accel/inclinometer.h new file mode 100644 index 000000000000..faf73d7892e0 --- /dev/null +++ b/trunk/drivers/staging/iio/accel/inclinometer.h @@ -0,0 +1,25 @@ +/* + * Inclinometer related attributes + */ +#include "../sysfs.h" + +#define IIO_DEV_ATTR_INCLI_X(_show, _addr) \ + IIO_DEVICE_ATTR(incli_x_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_INCLI_Y(_show, _addr) \ + IIO_DEVICE_ATTR(incli_y_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_INCLI_Z(_show, _addr) \ + IIO_DEVICE_ATTR(incli_z_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_INCLI_X_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(incli_x_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_INCLI_Y_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(incli_y_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_INCLI_Z_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(incli_z_offset, _mode, _show, _store, _addr) + +#define IIO_CONST_ATTR_INCLI_SCALE(_string) \ + IIO_CONST_ATTR(incli_scale, _string) diff --git a/trunk/drivers/staging/iio/accel/kxsd9.c b/trunk/drivers/staging/iio/accel/kxsd9.c index 3f2d047f58e9..c8a358a5df87 100644 --- a/trunk/drivers/staging/iio/accel/kxsd9.c +++ b/trunk/drivers/staging/iio/accel/kxsd9.c @@ -24,6 +24,8 @@ #include "../iio.h" #include "../sysfs.h" +#include "../adc/adc.h" +#include "accel.h" #define KXSD9_REG_X 0x00 #define KXSD9_REG_Y 0x02 @@ -32,6 +34,10 @@ #define KXSD9_REG_RESET 0x0a #define KXSD9_REG_CTRL_C 0x0c +#define KXSD9_FS_8 0x00 +#define KXSD9_FS_6 0x01 +#define KXSD9_FS_4 0x02 +#define KXSD9_FS_2 0x03 #define KXSD9_FS_MASK 0x03 #define KXSD9_REG_CTRL_B 0x0d @@ -40,8 +46,13 @@ #define KXSD9_READ(a) (0x80 | (a)) #define KXSD9_WRITE(a) (a) +#define KXSD9_SCALE_2G "0.011978" +#define KXSD9_SCALE_4G "0.023927" +#define KXSD9_SCALE_6G "0.035934" +#define KXSD9_SCALE_8G "0.047853" + #define KXSD9_STATE_RX_SIZE 2 -#define KXSD9_STATE_TX_SIZE 2 +#define KXSD9_STATE_TX_SIZE 4 /** * struct kxsd9_state - device related storage * @buf_lock: protect the rx and tx buffers. @@ -56,70 +67,170 @@ struct kxsd9_state { u8 tx[KXSD9_STATE_TX_SIZE]; }; -#define KXSD9_SCALE_2G "0.011978" -#define KXSD9_SCALE_4G "0.023927" -#define KXSD9_SCALE_6G "0.035934" -#define KXSD9_SCALE_8G "0.047853" +/* This may want to move to mili g to allow for non integer ranges */ +static ssize_t kxsd9_read_scale(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + ssize_t len = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct kxsd9_state *st = iio_priv(indio_dev); + struct spi_transfer xfer = { + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .tx_buf = st->tx, + .rx_buf = st->rx, + }; + struct spi_message msg; + + mutex_lock(&st->buf_lock); + st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C); + st->tx[1] = 0; + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->us, &msg); + if (ret) + goto error_ret; + + switch (st->rx[1] & KXSD9_FS_MASK) { + case KXSD9_FS_8: + len += sprintf(buf, "%s\n", KXSD9_SCALE_8G); + break; + case KXSD9_FS_6: + len += sprintf(buf, "%s\n", KXSD9_SCALE_6G); + break; + case KXSD9_FS_4: + len += sprintf(buf, "%s\n", KXSD9_SCALE_4G); + break; + case KXSD9_FS_2: + len += sprintf(buf, "%s\n", KXSD9_SCALE_2G); + break; + } -/* reverse order */ -static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 }; +error_ret: + mutex_unlock(&st->buf_lock); -static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) + return ret ? ret : len; +} +static ssize_t kxsd9_write_scale(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) { - int ret, i; + + struct spi_message msg; + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct kxsd9_state *st = iio_priv(indio_dev); - bool foundit = false; - - for (i = 0; i < 4; i++) - if (micro == kxsd9_micro_scales[i]) { - foundit = true; - break; - } - if (!foundit) + u8 val; + struct spi_transfer xfers[] = { + { + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .tx_buf = st->tx, + .rx_buf = st->rx, + }, { + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .tx_buf = st->tx, + }, + }; + + if (!strncmp(buf, KXSD9_SCALE_8G, + strlen(buf) < strlen(KXSD9_SCALE_8G) + ? strlen(buf) : strlen(KXSD9_SCALE_8G))) + val = KXSD9_FS_8; + else if (!strncmp(buf, KXSD9_SCALE_6G, + strlen(buf) < strlen(KXSD9_SCALE_6G) + ? strlen(buf) : strlen(KXSD9_SCALE_6G))) + val = KXSD9_FS_6; + else if (!strncmp(buf, KXSD9_SCALE_4G, + strlen(buf) < strlen(KXSD9_SCALE_4G) + ? strlen(buf) : strlen(KXSD9_SCALE_4G))) + val = KXSD9_FS_4; + else if (!strncmp(buf, KXSD9_SCALE_2G, + strlen(buf) < strlen(KXSD9_SCALE_2G) + ? strlen(buf) : strlen(KXSD9_SCALE_2G))) + val = KXSD9_FS_2; + else return -EINVAL; mutex_lock(&st->buf_lock); - ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); + st->tx[0] = KXSD9_READ(KXSD9_REG_CTRL_C); + st->tx[1] = 0; + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + ret = spi_sync(st->us, &msg); if (ret) goto error_ret; st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C); - st->tx[1] = (ret & ~KXSD9_FS_MASK) | i; + st->tx[1] = (st->rx[1] & ~KXSD9_FS_MASK) | val; - ret = spi_write(st->us, st->tx, 2); + spi_message_init(&msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); error_ret: mutex_unlock(&st->buf_lock); - return ret; + return ret ? ret : len; } -static int kxsd9_read(struct iio_dev *indio_dev, u8 address) +static ssize_t kxsd9_read_accel(struct device *dev, + struct device_attribute *attr, + char *buf) { struct spi_message msg; int ret; + ssize_t len = 0; + u16 val; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct kxsd9_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { { .bits_per_word = 8, .len = 1, + .cs_change = 0, .delay_usecs = 200, .tx_buf = st->tx, }, { .bits_per_word = 8, .len = 2, + .cs_change = 1, .rx_buf = st->rx, }, }; mutex_lock(&st->buf_lock); - st->tx[0] = KXSD9_READ(address); + st->tx[0] = KXSD9_READ(this_attr->address); spi_message_init(&msg); spi_message_add_tail(&xfers[0], &msg); spi_message_add_tail(&xfers[1], &msg); ret = spi_sync(st->us, &msg); if (ret) - return ret; - return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); + goto error_ret; + val = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); + len = sprintf(buf, "%d\n", val); +error_ret: + mutex_unlock(&st->buf_lock); + + return ret ? ret : len; } +static IIO_DEV_ATTR_ACCEL_X(kxsd9_read_accel, KXSD9_REG_X); +static IIO_DEV_ATTR_ACCEL_Y(kxsd9_read_accel, KXSD9_REG_Y); +static IIO_DEV_ATTR_ACCEL_Z(kxsd9_read_accel, KXSD9_REG_Z); +static IIO_DEV_ATTR_IN_RAW(0, kxsd9_read_accel, KXSD9_REG_AUX); + +static IIO_DEVICE_ATTR(accel_scale, + S_IRUGO | S_IWUSR, + kxsd9_read_scale, + kxsd9_write_scale, + 0); + static IIO_CONST_ATTR(accel_scale_available, KXSD9_SCALE_2G " " KXSD9_SCALE_4G " " @@ -127,94 +238,48 @@ static IIO_CONST_ATTR(accel_scale_available, KXSD9_SCALE_8G); static struct attribute *kxsd9_attributes[] = { + &iio_dev_attr_accel_x_raw.dev_attr.attr, + &iio_dev_attr_accel_y_raw.dev_attr.attr, + &iio_dev_attr_accel_z_raw.dev_attr.attr, + &iio_dev_attr_in0_raw.dev_attr.attr, + &iio_dev_attr_accel_scale.dev_attr.attr, &iio_const_attr_accel_scale_available.dev_attr.attr, NULL, }; -static int kxsd9_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - int ret = -EINVAL; - - if (mask == (1 << IIO_CHAN_INFO_SCALE_SHARED)) { - /* Check no integer component */ - if (val) - return -EINVAL; - ret = kxsd9_write_scale(indio_dev, val2); - } - - return ret; -} - -static int kxsd9_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) -{ - int ret = -EINVAL; - struct kxsd9_state *st = iio_priv(indio_dev); - - switch (mask) { - case 0: - ret = kxsd9_read(indio_dev, chan->address); - if (ret < 0) - goto error_ret; - *val = ret; - break; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): - ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); - if (ret) - goto error_ret; - *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK]; - ret = IIO_VAL_INT_PLUS_MICRO; - break; - }; - -error_ret: - return ret; -}; -#define KXSD9_ACCEL_CHAN(axis) \ - { \ - .type = IIO_ACCEL, \ - .modified = 1, \ - .channel2 = IIO_MOD_##axis, \ - .info_mask = 1 << IIO_CHAN_INFO_SCALE_SHARED, \ - .address = KXSD9_REG_##axis, \ - } - -static struct iio_chan_spec kxsd9_channels[] = { - KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z), - { - .type = IIO_IN, - .indexed = 1, - .address = KXSD9_REG_AUX, - } -}; - static const struct attribute_group kxsd9_attribute_group = { .attrs = kxsd9_attributes, }; static int __devinit kxsd9_power_up(struct kxsd9_state *st) { - int ret; - + struct spi_transfer xfers[2] = { + { + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .tx_buf = st->tx, + }, { + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .tx_buf = st->tx + 2, + }, + }; + struct spi_message msg; st->tx[0] = 0x0d; st->tx[1] = 0x40; - ret = spi_write(st->us, st->tx, 2); - if (ret) - return ret; + st->tx[2] = 0x0c; + st->tx[3] = 0x9b; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); - st->tx[0] = 0x0c; - st->tx[1] = 0x9b; - return spi_write(st->us, st->tx, 2); + return spi_sync(st->us, &msg); }; static const struct iio_info kxsd9_info = { - .read_raw = &kxsd9_read_raw, - .write_raw = &kxsd9_write_raw, .attrs = &kxsd9_attribute_group, .driver_module = THIS_MODULE, }; @@ -235,9 +300,7 @@ static int __devinit kxsd9_probe(struct spi_device *spi) st->us = spi; mutex_init(&st->buf_lock); - indio_dev->channels = kxsd9_channels; - indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); - indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->dev.parent = &spi->dev; indio_dev->info = &kxsd9_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -265,10 +328,6 @@ static int __devexit kxsd9_remove(struct spi_device *spi) return 0; } -static const struct spi_device_id kxsd9_id[] = { - {"kxsd9", 0} -}; - static struct spi_driver kxsd9_driver = { .driver = { .name = "kxsd9", @@ -276,7 +335,6 @@ static struct spi_driver kxsd9_driver = { }, .probe = kxsd9_probe, .remove = __devexit_p(kxsd9_remove), - .id_table = kxsd9_id, }; static __init int kxsd9_spi_init(void) diff --git a/trunk/drivers/staging/iio/accel/lis3l02dq_core.c b/trunk/drivers/staging/iio/accel/lis3l02dq_core.c index 7f946aa01404..a29dfd27d440 100644 --- a/trunk/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/trunk/drivers/staging/iio/accel/lis3l02dq_core.c @@ -26,6 +26,8 @@ #include "../sysfs.h" #include "../ring_generic.h" +#include "accel.h" + #include "lis3l02dq.h" /* At the moment the spi framework doesn't allow global setting of cs_change. @@ -452,54 +454,54 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private) if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_Z, + IIO_EV_MOD_Z, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_Z, + IIO_EV_MOD_Z, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_Y, + IIO_EV_MOD_Y, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_Y, + IIO_EV_MOD_Y, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_X, + IIO_EV_MOD_X, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_X, + IIO_EV_MOD_X, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); diff --git a/trunk/drivers/staging/iio/accel/lis3l02dq_ring.c b/trunk/drivers/staging/iio/accel/lis3l02dq_ring.c index 5c6fe13408b1..8d5c8ac7db51 100644 --- a/trunk/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/trunk/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -1,15 +1,19 @@ #include +#include #include #include +#include #include #include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../ring_sw.h" #include "../kfifo_buf.h" +#include "accel.h" #include "../trigger.h" -#include "../trigger_consumer.h" #include "lis3l02dq.h" /** @@ -161,7 +165,7 @@ static int lis3l02dq_get_ring_element(struct iio_dev *indio_dev, static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct iio_ring_buffer *ring = indio_dev->ring; int len = 0; size_t datasize = ring->access->get_bytes_per_datum(ring); @@ -302,12 +306,6 @@ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig) return 0; } -static const struct iio_trigger_ops lis3l02dq_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state, - .try_reenable = &lis3l02dq_trig_try_reen, -}; - int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -320,8 +318,10 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) } st->trig->dev.parent = &st->us->dev; - st->trig->ops = &lis3l02dq_trigger_ops; + st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; + st->trig->set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state; + st->trig->try_reenable = &lis3l02dq_trig_try_reen; ret = iio_trigger_register(st->trig); if (ret) goto error_free_trig; diff --git a/trunk/drivers/staging/iio/accel/sca3000_core.c b/trunk/drivers/staging/iio/accel/sca3000_core.c index d5684fc29cdf..603f5bca797c 100644 --- a/trunk/drivers/staging/iio/accel/sca3000_core.c +++ b/trunk/drivers/staging/iio/accel/sca3000_core.c @@ -22,6 +22,7 @@ #include "../sysfs.h" #include "../ring_generic.h" +#include "accel.h" #include "sca3000.h" enum sca3000_variant { @@ -421,7 +422,7 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR, /* More standard attributes */ -static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0); +static IIO_DEV_ATTR_REV(sca3000_show_rev); #define SCA3000_INFO_MASK \ (1 << IIO_CHAN_INFO_SCALE_SHARED) @@ -815,36 +816,36 @@ static irqreturn_t sca3000_event_handler(int irq, void *private) if (val & SCA3000_INT_STATUS_FREE_FALL) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_MOD_X_AND_Y_AND_Z, IIO_EV_TYPE_MAG, IIO_EV_DIR_FALLING), last_timestamp); if (val & SCA3000_INT_STATUS_Y_TRIGGER) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_Y, + IIO_EV_MOD_Y, IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), last_timestamp); if (val & SCA3000_INT_STATUS_X_TRIGGER) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_X, + IIO_EV_MOD_X, IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), last_timestamp); if (val & SCA3000_INT_STATUS_Z_TRIGGER) iio_push_event(indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_ACCEL, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, 0, - IIO_MOD_Z, + IIO_EV_MOD_Z, IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), last_timestamp); diff --git a/trunk/drivers/staging/iio/accel/sca3000_ring.c b/trunk/drivers/staging/iio/accel/sca3000_ring.c index 0b736dbe818c..a704c75fffc2 100644 --- a/trunk/drivers/staging/iio/accel/sca3000_ring.c +++ b/trunk/drivers/staging/iio/accel/sca3000_ring.c @@ -10,7 +10,9 @@ */ #include +#include #include +#include #include #include #include @@ -22,6 +24,7 @@ #include "../sysfs.h" #include "../ring_generic.h" #include "../ring_hw.h" +#include "accel.h" #include "sca3000.h" /* RFC / future work @@ -223,6 +226,74 @@ static IIO_DEVICE_ATTR(75_percent, S_IRUGO | S_IWUSR, sca3000_set_ring_int, SCA3000_INT_MASK_RING_THREE_QUARTER); + +/** + * sca3000_show_ring_bpse() -sysfs function to query bits per sample from ring + * @dev: ring buffer device + * @attr: this device attribute + * @buf: buffer to write to + **/ +static ssize_t sca3000_show_ring_bpse(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int len = 0, ret; + struct iio_ring_buffer *ring = dev_get_drvdata(dev); + struct iio_dev *indio_dev = ring->indio_dev; + struct sca3000_state *st = iio_priv(indio_dev); + + mutex_lock(&st->lock); + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + if (st->rx[0] & SCA3000_RING_BUF_8BIT) + len = sprintf(buf, "s8/8\n"); + else + len = sprintf(buf, "s11/16\n"); +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +/** + * sca3000_store_ring_bpse() - bits per scan element + * @dev: ring buffer device + * @attr: attribute called from + * @buf: input from userspace + * @len: length of input + **/ +static ssize_t sca3000_store_ring_bpse(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_ring_buffer *ring = dev_get_drvdata(dev); + struct iio_dev *indio_dev = ring->indio_dev; + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + if (sysfs_streq(buf, "s8/8")) { + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + st->rx[0] | SCA3000_RING_BUF_8BIT); + st->bpse = 8; + } else if (sysfs_streq(buf, "s11/16")) { + ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE, + st->rx[0] & ~SCA3000_RING_BUF_8BIT); + st->bpse = 11; + } else + ret = -EINVAL; +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + static ssize_t sca3000_show_buffer_scale(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/trunk/drivers/staging/iio/adc/Kconfig b/trunk/drivers/staging/iio/adc/Kconfig index 25566c624671..b39f2e1c1fe6 100644 --- a/trunk/drivers/staging/iio/adc/Kconfig +++ b/trunk/drivers/staging/iio/adc/Kconfig @@ -161,20 +161,6 @@ config AD7816 Say yes here to build support for Analog Devices AD7816/7/8 temperature sensors and ADC. -config AD7192 - tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver" - depends on SPI - select IIO_RING_BUFFER - select IIO_SW_RING - select IIO_TRIGGER - help - Say yes here to build support for Analog Devices AD7190, - AD7192 or AD7195 SPI analog to digital convertors (ADC). - If unsure, say N (but it's safe to say "Y"). - - To compile this driver as a module, choose M here: the - module will be called ad7192. - config ADT75 tristate "Analog Devices ADT75 temperature sensor driver" depends on I2C @@ -196,16 +182,6 @@ config ADT7410 Say yes here to build support for Analog Devices ADT7410 temperature sensors. -config AD7280 - tristate "Analog Devices AD7280A Lithium Ion Battery Monitoring System" - depends on SPI - help - Say yes here to build support for Analog Devices AD7280A - Lithium Ion Battery Monitoring System. - - To compile this driver as a module, choose M here: the - module will be called ad7280a - config MAX1363 tristate "Maxim max1363 ADC driver" depends on I2C diff --git a/trunk/drivers/staging/iio/adc/Makefile b/trunk/drivers/staging/iio/adc/Makefile index 990d3fada305..f02035139979 100644 --- a/trunk/drivers/staging/iio/adc/Makefile +++ b/trunk/drivers/staging/iio/adc/Makefile @@ -37,8 +37,6 @@ obj-$(CONFIG_AD7745) += ad7745.o obj-$(CONFIG_AD7780) += ad7780.o obj-$(CONFIG_AD7793) += ad7793.o obj-$(CONFIG_AD7816) += ad7816.o -obj-$(CONFIG_AD7192) += ad7192.o obj-$(CONFIG_ADT75) += adt75.o obj-$(CONFIG_ADT7310) += adt7310.o obj-$(CONFIG_ADT7410) += adt7410.o -obj-$(CONFIG_AD7280) += ad7280a.o diff --git a/trunk/drivers/staging/iio/adc/ad7150.c b/trunk/drivers/staging/iio/adc/ad7150.c index 5a1e15f6aec9..04017ef6688a 100644 --- a/trunk/drivers/staging/iio/adc/ad7150.c +++ b/trunk/drivers/staging/iio/adc/ad7150.c @@ -617,8 +617,6 @@ static IIO_DEV_ATTR_POWERDOWN_TIMER(S_IRUGO | S_IWUSR, ad7150_store_powerdown_timer); static struct attribute *ad7150_attributes[] = { - &iio_dev_attr_available_conversion_modes.dev_attr.attr, - &iio_dev_attr_conversion_mode.dev_attr.attr, &iio_dev_attr_available_threshold_modes.dev_attr.attr, &iio_dev_attr_threshold_mode.dev_attr.attr, &iio_dev_attr_ch1_threshold.dev_attr.attr, @@ -654,14 +652,14 @@ static irqreturn_t ad7150_event_handler(int irq, void *private) if ((int_status & AD7150_STATUS_OUT1) && !(chip->old_state & AD7150_STATUS_OUT1)) iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, + IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); else if ((!(int_status & AD7150_STATUS_OUT1)) && (chip->old_state & AD7150_STATUS_OUT1)) iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, + IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), @@ -669,14 +667,14 @@ static irqreturn_t ad7150_event_handler(int irq, void *private) if ((int_status & AD7150_STATUS_OUT2) && !(chip->old_state & AD7150_STATUS_OUT2)) iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, + IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, 1, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); else if ((!(int_status & AD7150_STATUS_OUT2)) && (chip->old_state & AD7150_STATUS_OUT2)) iio_push_event(indio_dev, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN, + IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, 1, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), diff --git a/trunk/drivers/staging/iio/adc/ad7192.c b/trunk/drivers/staging/iio/adc/ad7192.c deleted file mode 100644 index adf6d95dd34f..000000000000 --- a/trunk/drivers/staging/iio/adc/ad7192.c +++ /dev/null @@ -1,1184 +0,0 @@ -/* - * AD7190 AD7192 AD7195 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../iio.h" -#include "../sysfs.h" -#include "../ring_generic.h" -#include "../ring_sw.h" -#include "../trigger.h" -#include "../trigger_consumer.h" - -#include "ad7192.h" - -/* Registers */ -#define AD7192_REG_COMM 0 /* Communications Register (WO, 8-bit) */ -#define AD7192_REG_STAT 0 /* Status Register (RO, 8-bit) */ -#define AD7192_REG_MODE 1 /* Mode Register (RW, 24-bit */ -#define AD7192_REG_CONF 2 /* Configuration Register (RW, 24-bit) */ -#define AD7192_REG_DATA 3 /* Data Register (RO, 24/32-bit) */ -#define AD7192_REG_ID 4 /* ID Register (RO, 8-bit) */ -#define AD7192_REG_GPOCON 5 /* GPOCON Register (RO, 8-bit) */ -#define AD7192_REG_OFFSET 6 /* Offset Register (RW, 16-bit - * (AD7792)/24-bit (AD7192)) */ -#define AD7192_REG_FULLSALE 7 /* Full-Scale Register - * (RW, 16-bit (AD7792)/24-bit (AD7192)) */ - -/* Communications Register Bit Designations (AD7192_REG_COMM) */ -#define AD7192_COMM_WEN (1 << 7) /* Write Enable */ -#define AD7192_COMM_WRITE (0 << 6) /* Write Operation */ -#define AD7192_COMM_READ (1 << 6) /* Read Operation */ -#define AD7192_COMM_ADDR(x) (((x) & 0x7) << 3) /* Register Address */ -#define AD7192_COMM_CREAD (1 << 2) /* Continuous Read of Data Register */ - -/* Status Register Bit Designations (AD7192_REG_STAT) */ -#define AD7192_STAT_RDY (1 << 7) /* Ready */ -#define AD7192_STAT_ERR (1 << 6) /* Error (Overrange, Underrange) */ -#define AD7192_STAT_NOREF (1 << 5) /* Error no external reference */ -#define AD7192_STAT_PARITY (1 << 4) /* Parity */ -#define AD7192_STAT_CH3 (1 << 2) /* Channel 3 */ -#define AD7192_STAT_CH2 (1 << 1) /* Channel 2 */ -#define AD7192_STAT_CH1 (1 << 0) /* Channel 1 */ - -/* Mode Register Bit Designations (AD7192_REG_MODE) */ -#define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */ -#define AD7192_MODE_DAT_STA (1 << 20) /* Status Register transmission */ -#define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */ -#define AD7192_MODE_SINC3 (1 << 15) /* SINC3 Filter Select */ -#define AD7192_MODE_ACX (1 << 14) /* AC excitation enable(AD7195 only)*/ -#define AD7192_MODE_ENPAR (1 << 13) /* Parity Enable */ -#define AD7192_MODE_CLKDIV (1 << 12) /* Clock divide by 2 (AD7190/2 only)*/ -#define AD7192_MODE_SCYCLE (1 << 11) /* Single cycle conversion */ -#define AD7192_MODE_REJ60 (1 << 10) /* 50/60Hz notch filter */ -#define AD7192_MODE_RATE(x) ((x) & 0x3FF) /* Filter Update Rate Select */ - -/* Mode Register: AD7192_MODE_SEL options */ -#define AD7192_MODE_CONT 0 /* Continuous Conversion Mode */ -#define AD7192_MODE_SINGLE 1 /* Single Conversion Mode */ -#define AD7192_MODE_IDLE 2 /* Idle Mode */ -#define AD7192_MODE_PWRDN 3 /* Power-Down Mode */ -#define AD7192_MODE_CAL_INT_ZERO 4 /* Internal Zero-Scale Calibration */ -#define AD7192_MODE_CAL_INT_FULL 5 /* Internal Full-Scale Calibration */ -#define AD7192_MODE_CAL_SYS_ZERO 6 /* System Zero-Scale Calibration */ -#define AD7192_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */ - -/* Mode Register: AD7192_MODE_CLKSRC options */ -#define AD7192_CLK_EXT_MCLK1_2 0 /* External 4.92 MHz Clock connected - * from MCLK1 to MCLK2 */ -#define AD7192_CLK_EXT_MCLK2 1 /* External Clock applied to MCLK2 */ -#define AD7192_CLK_INT 2 /* Internal 4.92 MHz Clock not - * available at the MCLK2 pin */ -#define AD7192_CLK_INT_CO 3 /* Internal 4.92 MHz Clock available - * at the MCLK2 pin */ - - -/* Configuration Register Bit Designations (AD7192_REG_CONF) */ - -#define AD7192_CONF_CHOP (1 << 23) /* CHOP enable */ -#define AD7192_CONF_REFSEL (1 << 20) /* REFIN1/REFIN2 Reference Select */ -#define AD7192_CONF_CHAN(x) (((x) & 0xFF) << 8) /* Channel select */ -#define AD7192_CONF_BURN (1 << 7) /* Burnout current enable */ -#define AD7192_CONF_REFDET (1 << 6) /* Reference detect enable */ -#define AD7192_CONF_BUF (1 << 4) /* Buffered Mode Enable */ -#define AD7192_CONF_UNIPOLAR (1 << 3) /* Unipolar/Bipolar Enable */ -#define AD7192_CONF_GAIN(x) ((x) & 0x7) /* Gain Select */ - -#define AD7192_CH_AIN1P_AIN2M 0 /* AIN1(+) - AIN2(-) */ -#define AD7192_CH_AIN3P_AIN4M 1 /* AIN3(+) - AIN4(-) */ -#define AD7192_CH_TEMP 2 /* Temp Sensor */ -#define AD7192_CH_AIN2P_AIN2M 3 /* AIN2(+) - AIN2(-) */ -#define AD7192_CH_AIN1 4 /* AIN1 - AINCOM */ -#define AD7192_CH_AIN2 5 /* AIN2 - AINCOM */ -#define AD7192_CH_AIN3 6 /* AIN3 - AINCOM */ -#define AD7192_CH_AIN4 7 /* AIN4 - AINCOM */ - -/* ID Register Bit Designations (AD7192_REG_ID) */ -#define ID_AD7190 0x4 -#define ID_AD7192 0x0 -#define ID_AD7195 0x6 -#define AD7192_ID_MASK 0x0F - -/* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */ -#define AD7192_GPOCON_BPDSW (1 << 6) /* Bridge power-down switch enable */ -#define AD7192_GPOCON_GP32EN (1 << 5) /* Digital Output P3 and P2 enable */ -#define AD7192_GPOCON_GP10EN (1 << 4) /* Digital Output P1 and P0 enable */ -#define AD7192_GPOCON_P3DAT (1 << 3) /* P3 state */ -#define AD7192_GPOCON_P2DAT (1 << 2) /* P2 state */ -#define AD7192_GPOCON_P1DAT (1 << 1) /* P1 state */ -#define AD7192_GPOCON_P0DAT (1 << 0) /* P0 state */ - -#define AD7192_INT_FREQ_MHz 4915200 - -/* NOTE: - * The AD7190/2/5 features a dual use data out ready DOUT/RDY output. - * In order to avoid contentions on the SPI bus, it's therefore necessary - * to use spi bus locking. - * - * The DOUT/RDY output must also be wired to an interrupt capable GPIO. - */ - -struct ad7192_state { - struct spi_device *spi; - struct iio_trigger *trig; - struct regulator *reg; - struct ad7192_platform_data *pdata; - wait_queue_head_t wq_data_avail; - bool done; - bool irq_dis; - u16 int_vref_mv; - u32 mclk; - u32 f_order; - u32 mode; - u32 conf; - u32 scale_avail[8][2]; - u32 available_scan_masks[9]; - u8 gpocon; - u8 devid; - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - */ - u8 data[4] ____cacheline_aligned; -}; - -static int __ad7192_write_reg(struct ad7192_state *st, bool locked, - bool cs_change, unsigned char reg, - unsigned size, unsigned val) -{ - u8 *data = st->data; - struct spi_transfer t = { - .tx_buf = data, - .len = size + 1, - .cs_change = cs_change, - }; - struct spi_message m; - - data[0] = AD7192_COMM_WRITE | AD7192_COMM_ADDR(reg); - - switch (size) { - case 3: - data[1] = val >> 16; - data[2] = val >> 8; - data[3] = val; - break; - case 2: - data[1] = val >> 8; - data[2] = val; - break; - case 1: - data[1] = val; - break; - default: - return -EINVAL; - } - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - - if (locked) - return spi_sync_locked(st->spi, &m); - else - return spi_sync(st->spi, &m); -} - -static int ad7192_write_reg(struct ad7192_state *st, - unsigned reg, unsigned size, unsigned val) -{ - return __ad7192_write_reg(st, false, false, reg, size, val); -} - -static int __ad7192_read_reg(struct ad7192_state *st, bool locked, - bool cs_change, unsigned char reg, - int *val, unsigned size) -{ - u8 *data = st->data; - int ret; - struct spi_transfer t[] = { - { - .tx_buf = data, - .len = 1, - }, { - .rx_buf = data, - .len = size, - .cs_change = cs_change, - }, - }; - struct spi_message m; - - data[0] = AD7192_COMM_READ | AD7192_COMM_ADDR(reg); - - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - if (locked) - ret = spi_sync_locked(st->spi, &m); - else - ret = spi_sync(st->spi, &m); - - if (ret < 0) - return ret; - - switch (size) { - case 3: - *val = data[0] << 16 | data[1] << 8 | data[2]; - break; - case 2: - *val = data[0] << 8 | data[1]; - break; - case 1: - *val = data[0]; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int ad7192_read_reg(struct ad7192_state *st, - unsigned reg, int *val, unsigned size) -{ - return __ad7192_read_reg(st, 0, 0, reg, val, size); -} - -static int ad7192_read(struct ad7192_state *st, unsigned ch, - unsigned len, int *val) -{ - int ret; - st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | - AD7192_CONF_CHAN(1 << ch); - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | - AD7192_MODE_SEL(AD7192_MODE_SINGLE); - - ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); - - spi_bus_lock(st->spi->master); - st->done = false; - - ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode); - if (ret < 0) - goto out; - - st->irq_dis = false; - enable_irq(st->spi->irq); - wait_event_interruptible(st->wq_data_avail, st->done); - - ret = __ad7192_read_reg(st, 1, 0, AD7192_REG_DATA, val, len); -out: - spi_bus_unlock(st->spi->master); - - return ret; -} - -static int ad7192_calibrate(struct ad7192_state *st, unsigned mode, unsigned ch) -{ - int ret; - - st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | - AD7192_CONF_CHAN(1 << ch); - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | AD7192_MODE_SEL(mode); - - ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); - - spi_bus_lock(st->spi->master); - st->done = false; - - ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, - (st->devid != ID_AD7195) ? - st->mode | AD7192_MODE_CLKDIV : - st->mode); - if (ret < 0) - goto out; - - st->irq_dis = false; - enable_irq(st->spi->irq); - wait_event_interruptible(st->wq_data_avail, st->done); - - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | - AD7192_MODE_SEL(AD7192_MODE_IDLE); - - ret = __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode); -out: - spi_bus_unlock(st->spi->master); - - return ret; -} - -static const u8 ad7192_calib_arr[8][2] = { - {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN1}, - {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN1}, - {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN2}, - {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN2}, - {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN3}, - {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN3}, - {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN4}, - {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN4} -}; - -static int ad7192_calibrate_all(struct ad7192_state *st) -{ - int i, ret; - - for (i = 0; i < ARRAY_SIZE(ad7192_calib_arr); i++) { - ret = ad7192_calibrate(st, ad7192_calib_arr[i][0], - ad7192_calib_arr[i][1]); - if (ret) - goto out; - } - - return 0; -out: - dev_err(&st->spi->dev, "Calibration failed\n"); - return ret; -} - -static int ad7192_setup(struct ad7192_state *st) -{ - struct iio_dev *indio_dev = spi_get_drvdata(st->spi); - struct ad7192_platform_data *pdata = st->pdata; - unsigned long long scale_uv; - int i, ret, id; - u8 ones[6]; - - /* reset the serial interface */ - memset(&ones, 0xFF, 6); - ret = spi_write(st->spi, &ones, 6); - if (ret < 0) - goto out; - msleep(1); /* Wait for at least 500us */ - - /* write/read test for device presence */ - ret = ad7192_read_reg(st, AD7192_REG_ID, &id, 1); - if (ret) - goto out; - - id &= AD7192_ID_MASK; - - if (id != st->devid) - dev_warn(&st->spi->dev, "device ID query failed (0x%X)\n", id); - - switch (pdata->clock_source_sel) { - case AD7192_CLK_EXT_MCLK1_2: - case AD7192_CLK_EXT_MCLK2: - st->mclk = AD7192_INT_FREQ_MHz; - break; - case AD7192_CLK_INT: - case AD7192_CLK_INT_CO: - if (pdata->ext_clk_Hz) - st->mclk = pdata->ext_clk_Hz; - else - st->mclk = AD7192_INT_FREQ_MHz; - break; - default: - ret = -EINVAL; - goto out; - } - - st->mode = AD7192_MODE_SEL(AD7192_MODE_IDLE) | - AD7192_MODE_CLKSRC(pdata->clock_source_sel) | - AD7192_MODE_RATE(480); - - st->conf = AD7192_CONF_GAIN(0); - - if (pdata->rej60_en) - st->mode |= AD7192_MODE_REJ60; - - if (pdata->sinc3_en) - st->mode |= AD7192_MODE_SINC3; - - if (pdata->refin2_en && (st->devid != ID_AD7195)) - st->conf |= AD7192_CONF_REFSEL; - - if (pdata->chop_en) { - st->conf |= AD7192_CONF_CHOP; - if (pdata->sinc3_en) - st->f_order = 3; /* SINC 3rd order */ - else - st->f_order = 4; /* SINC 4th order */ - } else { - st->f_order = 1; - } - - if (pdata->buf_en) - st->conf |= AD7192_CONF_BUF; - - if (pdata->unipolar_en) - st->conf |= AD7192_CONF_UNIPOLAR; - - if (pdata->burnout_curr_en) - st->conf |= AD7192_CONF_BURN; - - ret = ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode); - if (ret) - goto out; - - ret = ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); - if (ret) - goto out; - - ret = ad7192_calibrate_all(st); - if (ret) - goto out; - - /* Populate available ADC input ranges */ - for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { - scale_uv = ((u64)st->int_vref_mv * 100000000) - >> (indio_dev->channels[0].scan_type.realbits - - ((st->conf & AD7192_CONF_UNIPOLAR) ? 0 : 1)); - scale_uv >>= i; - - st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10; - st->scale_avail[i][0] = scale_uv; - } - - return 0; -out: - dev_err(&st->spi->dev, "setup failed\n"); - return ret; -} - -static int ad7192_scan_from_ring(struct ad7192_state *st, unsigned ch, int *val) -{ - struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring; - int ret; - s64 dat64[2]; - u32 *dat32 = (u32 *)dat64; - - if (!(ring->scan_mask & (1 << ch))) - return -EBUSY; - - ret = ring->access->read_last(ring, (u8 *) &dat64); - if (ret) - return ret; - - *val = *dat32; - - return 0; -} - -static int ad7192_ring_preenable(struct iio_dev *indio_dev) -{ - struct ad7192_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; - size_t d_size; - unsigned channel; - - if (!ring->scan_count) - return -EINVAL; - - channel = __ffs(ring->scan_mask); - - d_size = ring->scan_count * - indio_dev->channels[0].scan_type.storagebits / 8; - - if (ring->scan_timestamp) { - d_size += sizeof(s64); - - if (d_size % sizeof(s64)) - d_size += sizeof(s64) - (d_size % sizeof(s64)); - } - - if (indio_dev->ring->access->set_bytes_per_datum) - indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, - d_size); - - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | - AD7192_MODE_SEL(AD7192_MODE_CONT); - st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) | - AD7192_CONF_CHAN(1 << indio_dev->channels[channel].address); - - ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf); - - spi_bus_lock(st->spi->master); - __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode); - - st->irq_dis = false; - enable_irq(st->spi->irq); - - return 0; -} - -static int ad7192_ring_postdisable(struct iio_dev *indio_dev) -{ - struct ad7192_state *st = iio_priv(indio_dev); - - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | - AD7192_MODE_SEL(AD7192_MODE_IDLE); - - st->done = false; - wait_event_interruptible(st->wq_data_avail, st->done); - - if (!st->irq_dis) - disable_irq_nosync(st->spi->irq); - - __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode); - - return spi_bus_unlock(st->spi->master); -} - -/** - * ad7192_trigger_handler() bh of trigger launched polling to ring buffer - **/ -static irqreturn_t ad7192_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct iio_ring_buffer *ring = indio_dev->ring; - struct ad7192_state *st = iio_priv(indio_dev); - s64 dat64[2]; - s32 *dat32 = (s32 *)dat64; - - if (ring->scan_count) - __ad7192_read_reg(st, 1, 1, AD7192_REG_DATA, - dat32, - indio_dev->channels[0].scan_type.realbits/8); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - dat64[1] = pf->timestamp; - - ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - st->irq_dis = false; - enable_irq(st->spi->irq); - - return IRQ_HANDLED; -} - -static const struct iio_ring_setup_ops ad7192_ring_setup_ops = { - .preenable = &ad7192_ring_preenable, - .postenable = &iio_triggered_ring_postenable, - .predisable = &iio_triggered_ring_predisable, - .postdisable = &ad7192_ring_postdisable, -}; - -static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - int ret; - - indio_dev->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) { - ret = -ENOMEM; - goto error_ret; - } - /* Effectively select the ring buffer implementation */ - indio_dev->ring->access = &ring_sw_access_funcs; - indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, - &ad7192_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "ad7192_consumer%d", - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - - /* Ring buffer functions - here trigger setup related */ - indio_dev->ring->setup_ops = &ad7192_ring_setup_ops; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_RING_TRIGGERED; - return 0; - -error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->ring); -error_ret: - return ret; -} - -static void ad7192_ring_cleanup(struct iio_dev *indio_dev) -{ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); -} - -/** - * ad7192_data_rdy_trig_poll() the event handler for the data rdy trig - **/ -static irqreturn_t ad7192_data_rdy_trig_poll(int irq, void *private) -{ - struct ad7192_state *st = iio_priv(private); - - st->done = true; - wake_up_interruptible(&st->wq_data_avail); - disable_irq_nosync(irq); - st->irq_dis = true; - iio_trigger_poll(st->trig, iio_get_time_ns()); - - return IRQ_HANDLED; -} - -static int ad7192_probe_trigger(struct iio_dev *indio_dev) -{ - struct ad7192_state *st = iio_priv(indio_dev); - int ret; - - st->trig = iio_allocate_trigger("%s-dev%d", - spi_get_device_id(st->spi)->name, - indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - ret = request_irq(st->spi->irq, - ad7192_data_rdy_trig_poll, - IRQF_TRIGGER_LOW, - spi_get_device_id(st->spi)->name, - indio_dev); - if (ret) - goto error_free_trig; - - disable_irq_nosync(st->spi->irq); - st->irq_dis = true; - st->trig->dev.parent = &st->spi->dev; - st->trig->owner = THIS_MODULE; - st->trig->private_data = indio_dev; - - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(st->spi->irq, indio_dev); -error_free_trig: - iio_free_trigger(st->trig); -error_ret: - return ret; -} - -static void ad7192_remove_trigger(struct iio_dev *indio_dev) -{ - struct ad7192_state *st = iio_priv(indio_dev); - - iio_trigger_unregister(st->trig); - free_irq(st->spi->irq, indio_dev); - iio_free_trigger(st->trig); -} - -static ssize_t ad7192_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", st->mclk / - (st->f_order * 1024 * AD7192_MODE_RATE(st->mode))); -} - -static ssize_t ad7192_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(indio_dev); - unsigned long lval; - int div, ret; - - ret = strict_strtoul(buf, 10, &lval); - if (ret) - return ret; - - mutex_lock(&indio_dev->mlock); - if (iio_ring_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - - div = st->mclk / (lval * st->f_order * 1024); - if (div < 1 || div > 1023) { - ret = -EINVAL; - goto out; - } - - st->mode &= ~AD7192_MODE_RATE(-1); - st->mode |= AD7192_MODE_RATE(div); - ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode); - -out: - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - ad7192_read_frequency, - ad7192_write_frequency); - - -static ssize_t ad7192_show_scale_available(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(indio_dev); - int i, len = 0; - - for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) - len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0], - st->scale_avail[i][1]); - - len += sprintf(buf + len, "\n"); - - return len; -} - -static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available, - S_IRUGO, ad7192_show_scale_available, NULL, 0); - -static IIO_DEVICE_ATTR(in_scale_available, S_IRUGO, - ad7192_show_scale_available, NULL, 0); - -static ssize_t ad7192_show_ac_excitation(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX)); -} - -static ssize_t ad7192_show_bridge_switch(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(indio_dev); - - return sprintf(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW)); -} - -static ssize_t ad7192_set(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - bool val; - - ret = strtobool(buf, &val); - if (ret < 0) - return ret; - - mutex_lock(&indio_dev->mlock); - if (iio_ring_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - - switch (this_attr->address) { - case AD7192_REG_GPOCON: - if (val) - st->gpocon |= AD7192_GPOCON_BPDSW; - else - st->gpocon &= ~AD7192_GPOCON_BPDSW; - - ad7192_write_reg(st, AD7192_REG_GPOCON, 1, st->gpocon); - break; - case AD7192_REG_MODE: - if (val) - st->mode |= AD7192_MODE_ACX; - else - st->mode &= ~AD7192_MODE_ACX; - - ad7192_write_reg(st, AD7192_REG_GPOCON, 3, st->mode); - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(bridge_switch_en, S_IRUGO | S_IWUSR, - ad7192_show_bridge_switch, ad7192_set, - AD7192_REG_GPOCON); - -static IIO_DEVICE_ATTR(ac_excitation_en, S_IRUGO | S_IWUSR, - ad7192_show_ac_excitation, ad7192_set, - AD7192_REG_MODE); - -static struct attribute *ad7192_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_dev_attr_in_m_in_scale_available.dev_attr.attr, - &iio_dev_attr_in_scale_available.dev_attr.attr, - &iio_dev_attr_bridge_switch_en.dev_attr.attr, - &iio_dev_attr_ac_excitation_en.dev_attr.attr, - NULL -}; - -static mode_t ad7192_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(dev_info); - - mode_t mode = attr->mode; - - if ((st->devid != ID_AD7195) && - (attr == &iio_dev_attr_ac_excitation_en.dev_attr.attr)) - mode = 0; - - return mode; -} - -static const struct attribute_group ad7192_attribute_group = { - .attrs = ad7192_attributes, - .is_visible = ad7192_attr_is_visible, -}; - -static int ad7192_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad7192_state *st = iio_priv(indio_dev); - int ret, smpl = 0; - bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR); - - switch (m) { - case 0: - mutex_lock(&indio_dev->mlock); - if (iio_ring_enabled(indio_dev)) - ret = ad7192_scan_from_ring(st, - chan->scan_index, &smpl); - else - ret = ad7192_read(st, chan->address, - chan->scan_type.realbits / 8, &smpl); - mutex_unlock(&indio_dev->mlock); - - if (ret < 0) - return ret; - - *val = (smpl >> chan->scan_type.shift) & - ((1 << (chan->scan_type.realbits)) - 1); - - switch (chan->type) { - case IIO_IN: - case IIO_IN_DIFF: - if (!unipolar) - *val -= (1 << (chan->scan_type.realbits - 1)); - break; - case IIO_TEMP: - *val -= 0x800000; - *val /= 2815; /* temp Kelvin */ - *val -= 273; /* temp Celsius */ - break; - default: - return -EINVAL; - } - return IIO_VAL_INT; - - case (1 << IIO_CHAN_INFO_SCALE_SHARED): - mutex_lock(&indio_dev->mlock); - *val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0]; - *val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1]; - mutex_unlock(&indio_dev->mlock); - - return IIO_VAL_INT_PLUS_NANO; - - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): - *val = 1000; - - return IIO_VAL_INT; - } - - return -EINVAL; -} - -static int ad7192_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad7192_state *st = iio_priv(indio_dev); - int ret, i; - unsigned int tmp; - - mutex_lock(&indio_dev->mlock); - if (iio_ring_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - - switch (mask) { - case (1 << IIO_CHAN_INFO_SCALE_SHARED): - ret = -EINVAL; - for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) - if (val2 == st->scale_avail[i][1]) { - tmp = st->conf; - st->conf &= ~AD7192_CONF_GAIN(-1); - st->conf |= AD7192_CONF_GAIN(i); - - if (tmp != st->conf) { - ad7192_write_reg(st, AD7192_REG_CONF, - 3, st->conf); - ad7192_calibrate_all(st); - } - ret = 0; - } - - default: - ret = -EINVAL; - } - - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int ad7192_validate_trigger(struct iio_dev *indio_dev, - struct iio_trigger *trig) -{ - if (indio_dev->trig != trig) - return -EINVAL; - - return 0; -} - -static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask) -{ - return IIO_VAL_INT_PLUS_NANO; -} - -static const struct iio_info ad7192_info = { - .read_raw = &ad7192_read_raw, - .write_raw = &ad7192_write_raw, - .write_raw_get_fmt = &ad7192_write_raw_get_fmt, - .attrs = &ad7192_attribute_group, - .validate_trigger = ad7192_validate_trigger, - .driver_module = THIS_MODULE, -}; - -#define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \ - { .type = IIO_IN_DIFF, \ - .indexed = 1, \ - .extend_name = _name, \ - .channel = _chan, \ - .channel2 = _chan2, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ - .address = _address, \ - .scan_index = _si, \ - .scan_type = IIO_ST('s', 24, 32, 0)} - -#define AD7192_CHAN(_chan, _address, _si) \ - { .type = IIO_IN, \ - .indexed = 1, \ - .channel = _chan, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ - .address = _address, \ - .scan_index = _si, \ - .scan_type = IIO_ST('s', 24, 32, 0)} - -#define AD7192_CHAN_TEMP(_chan, _address, _si) \ - { .type = IIO_TEMP, \ - .indexed = 1, \ - .channel = _chan, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ - .address = _address, \ - .scan_index = _si, \ - .scan_type = IIO_ST('s', 24, 32, 0)} - -static struct iio_chan_spec ad7192_channels[] = { - AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0), - AD7192_CHAN_DIFF(3, 4, NULL, AD7192_CH_AIN3P_AIN4M, 1), - AD7192_CHAN_TEMP(0, AD7192_CH_TEMP, 2), - AD7192_CHAN_DIFF(2, 2, "shorted", AD7192_CH_AIN2P_AIN2M, 3), - AD7192_CHAN(1, AD7192_CH_AIN1, 4), - AD7192_CHAN(2, AD7192_CH_AIN2, 5), - AD7192_CHAN(3, AD7192_CH_AIN3, 6), - AD7192_CHAN(4, AD7192_CH_AIN4, 7), - IIO_CHAN_SOFT_TIMESTAMP(8), -}; - -static int __devinit ad7192_probe(struct spi_device *spi) -{ - struct ad7192_platform_data *pdata = spi->dev.platform_data; - struct ad7192_state *st; - struct iio_dev *indio_dev; - int ret, i , voltage_uv = 0, regdone = 0; - - if (!pdata) { - dev_err(&spi->dev, "no platform data?\n"); - return -ENODEV; - } - - if (!spi->irq) { - dev_err(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } - - indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) - return -ENOMEM; - - st = iio_priv(indio_dev); - - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - goto error_put_reg; - - voltage_uv = regulator_get_voltage(st->reg); - } - - st->pdata = pdata; - - if (pdata && pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (voltage_uv) - st->int_vref_mv = voltage_uv / 1000; - else - dev_warn(&spi->dev, "reference voltage undefined\n"); - - spi_set_drvdata(spi, indio_dev); - st->spi = spi; - st->devid = spi_get_device_id(spi)->driver_data; - indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = ad7192_channels; - indio_dev->num_channels = ARRAY_SIZE(ad7192_channels); - indio_dev->available_scan_masks = st->available_scan_masks; - indio_dev->info = &ad7192_info; - - for (i = 0; i < indio_dev->num_channels; i++) - st->available_scan_masks[i] = (1 << i) | (1 << - indio_dev->channels[indio_dev->num_channels - 1]. - scan_index); - - init_waitqueue_head(&st->wq_data_avail); - - ret = ad7192_register_ring_funcs_and_init(indio_dev); - if (ret) - goto error_disable_reg; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring; - regdone = 1; - - ret = ad7192_probe_trigger(indio_dev); - if (ret) - goto error_unreg_ring; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_remove_trigger; - - ret = ad7192_setup(st); - if (ret) - goto error_uninitialize_ring; - - return 0; - -error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); -error_remove_trigger: - ad7192_remove_trigger(indio_dev); -error_unreg_ring: - ad7192_ring_cleanup(indio_dev); -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); - - return ret; -} - -static int ad7192_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7192_state *st = iio_priv(indio_dev); - - iio_ring_buffer_unregister(indio_dev->ring); - ad7192_remove_trigger(indio_dev); - ad7192_ring_cleanup(indio_dev); - - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - - iio_device_unregister(indio_dev); - - return 0; -} - -static const struct spi_device_id ad7192_id[] = { - {"ad7190", ID_AD7190}, - {"ad7192", ID_AD7192}, - {"ad7195", ID_AD7195}, - {} -}; - -static struct spi_driver ad7192_driver = { - .driver = { - .name = "ad7192", - .owner = THIS_MODULE, - }, - .probe = ad7192_probe, - .remove = __devexit_p(ad7192_remove), - .id_table = ad7192_id, -}; - -static int __init ad7192_init(void) -{ - return spi_register_driver(&ad7192_driver); -} -module_init(ad7192_init); - -static void __exit ad7192_exit(void) -{ - spi_unregister_driver(&ad7192_driver); -} -module_exit(ad7192_exit); - -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7190, AD7192, AD7195 ADC"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/adc/ad7192.h b/trunk/drivers/staging/iio/adc/ad7192.h deleted file mode 100644 index a0a5b61a41f1..000000000000 --- a/trunk/drivers/staging/iio/adc/ad7192.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * AD7190 AD7192 AD7195 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ -#ifndef IIO_ADC_AD7192_H_ -#define IIO_ADC_AD7192_H_ - -/* - * TODO: struct ad7192_platform_data needs to go into include/linux/iio - */ - -/** - * struct ad7192_platform_data - platform/board specific information - * @vref_mv: the external reference voltage in millivolt - * @clock_source_sel: [0..3] - * 0 External 4.92 MHz clock connected from MCLK1 to MCLK2 - * 1 External Clock applied to MCLK2 - * 2 Internal 4.92 MHz Clock not available at the MCLK2 pin - * 3 Internal 4.92 MHz Clock available at the MCLK2 pin - * @ext_clk_Hz: the external clock frequency in Hz, if not set - * the driver uses the internal clock (16.776 MHz) - * @refin2_en: REFIN1/REFIN2 Reference Select (AD7190/2 only) - * @rej60_en: 50/60Hz notch filter enable - * @sinc3_en: SINC3 filter enable (default SINC4) - * @chop_en: CHOP mode enable - * @buf_en: buffered input mode enable - * @unipolar_en: unipolar mode enable - * @burnout_curr_en: constant current generators on AIN(+|-) enable - */ - -struct ad7192_platform_data { - u16 vref_mv; - u8 clock_source_sel; - u32 ext_clk_Hz; - bool refin2_en; - bool rej60_en; - bool sinc3_en; - bool chop_en; - bool buf_en; - bool unipolar_en; - bool burnout_curr_en; -}; - -#endif /* IIO_ADC_AD7192_H_ */ diff --git a/trunk/drivers/staging/iio/adc/ad7280a.c b/trunk/drivers/staging/iio/adc/ad7280a.c deleted file mode 100644 index ab6cf9cb5a7f..000000000000 --- a/trunk/drivers/staging/iio/adc/ad7280a.c +++ /dev/null @@ -1,992 +0,0 @@ -/* - * AD7280A Lithium Ion Battery Monitoring System - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../iio.h" -#include "../sysfs.h" - -#include "ad7280a.h" - -/* Registers */ -#define AD7280A_CELL_VOLTAGE_1 0x0 /* D11 to D0, Read only */ -#define AD7280A_CELL_VOLTAGE_2 0x1 /* D11 to D0, Read only */ -#define AD7280A_CELL_VOLTAGE_3 0x2 /* D11 to D0, Read only */ -#define AD7280A_CELL_VOLTAGE_4 0x3 /* D11 to D0, Read only */ -#define AD7280A_CELL_VOLTAGE_5 0x4 /* D11 to D0, Read only */ -#define AD7280A_CELL_VOLTAGE_6 0x5 /* D11 to D0, Read only */ -#define AD7280A_AUX_ADC_1 0x6 /* D11 to D0, Read only */ -#define AD7280A_AUX_ADC_2 0x7 /* D11 to D0, Read only */ -#define AD7280A_AUX_ADC_3 0x8 /* D11 to D0, Read only */ -#define AD7280A_AUX_ADC_4 0x9 /* D11 to D0, Read only */ -#define AD7280A_AUX_ADC_5 0xA /* D11 to D0, Read only */ -#define AD7280A_AUX_ADC_6 0xB /* D11 to D0, Read only */ -#define AD7280A_SELF_TEST 0xC /* D11 to D0, Read only */ -#define AD7280A_CONTROL_HB 0xD /* D15 to D8, Read/write */ -#define AD7280A_CONTROL_LB 0xE /* D7 to D0, Read/write */ -#define AD7280A_CELL_OVERVOLTAGE 0xF /* D7 to D0, Read/write */ -#define AD7280A_CELL_UNDERVOLTAGE 0x10 /* D7 to D0, Read/write */ -#define AD7280A_AUX_ADC_OVERVOLTAGE 0x11 /* D7 to D0, Read/write */ -#define AD7280A_AUX_ADC_UNDERVOLTAGE 0x12 /* D7 to D0, Read/write */ -#define AD7280A_ALERT 0x13 /* D7 to D0, Read/write */ -#define AD7280A_CELL_BALANCE 0x14 /* D7 to D0, Read/write */ -#define AD7280A_CB1_TIMER 0x15 /* D7 to D0, Read/write */ -#define AD7280A_CB2_TIMER 0x16 /* D7 to D0, Read/write */ -#define AD7280A_CB3_TIMER 0x17 /* D7 to D0, Read/write */ -#define AD7280A_CB4_TIMER 0x18 /* D7 to D0, Read/write */ -#define AD7280A_CB5_TIMER 0x19 /* D7 to D0, Read/write */ -#define AD7280A_CB6_TIMER 0x1A /* D7 to D0, Read/write */ -#define AD7280A_PD_TIMER 0x1B /* D7 to D0, Read/write */ -#define AD7280A_READ 0x1C /* D7 to D0, Read/write */ -#define AD7280A_CNVST_CONTROL 0x1D /* D7 to D0, Read/write */ - -/* Bits and Masks */ -#define AD7280A_CTRL_HB_CONV_INPUT_ALL (0 << 6) -#define AD7280A_CTRL_HB_CONV_INPUT_6CELL_AUX1_3_4 (1 << 6) -#define AD7280A_CTRL_HB_CONV_INPUT_6CELL (2 << 6) -#define AD7280A_CTRL_HB_CONV_INPUT_SELF_TEST (3 << 6) -#define AD7280A_CTRL_HB_CONV_RES_READ_ALL (0 << 4) -#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL_AUX1_3_4 (1 << 4) -#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL (2 << 4) -#define AD7280A_CTRL_HB_CONV_RES_READ_NO (3 << 4) -#define AD7280A_CTRL_HB_CONV_START_CNVST (0 << 3) -#define AD7280A_CTRL_HB_CONV_START_CS (1 << 3) -#define AD7280A_CTRL_HB_CONV_AVG_DIS (0 << 1) -#define AD7280A_CTRL_HB_CONV_AVG_2 (1 << 1) -#define AD7280A_CTRL_HB_CONV_AVG_4 (2 << 1) -#define AD7280A_CTRL_HB_CONV_AVG_8 (3 << 1) -#define AD7280A_CTRL_HB_CONV_AVG(x) ((x) << 1) -#define AD7280A_CTRL_HB_PWRDN_SW (1 << 0) - -#define AD7280A_CTRL_LB_SWRST (1 << 7) -#define AD7280A_CTRL_LB_ACQ_TIME_400ns (0 << 5) -#define AD7280A_CTRL_LB_ACQ_TIME_800ns (1 << 5) -#define AD7280A_CTRL_LB_ACQ_TIME_1200ns (2 << 5) -#define AD7280A_CTRL_LB_ACQ_TIME_1600ns (3 << 5) -#define AD7280A_CTRL_LB_ACQ_TIME(x) ((x) << 5) -#define AD7280A_CTRL_LB_MUST_SET (1 << 4) -#define AD7280A_CTRL_LB_THERMISTOR_EN (1 << 3) -#define AD7280A_CTRL_LB_LOCK_DEV_ADDR (1 << 2) -#define AD7280A_CTRL_LB_INC_DEV_ADDR (1 << 1) -#define AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN (1 << 0) - -#define AD7280A_ALERT_GEN_STATIC_HIGH (1 << 6) -#define AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN (3 << 6) - -#define AD7280A_ALL_CELLS (0xAD << 16) - -#define AD7280A_MAX_SPI_CLK_Hz 700000 /* < 1MHz */ -#define AD7280A_MAX_CHAIN 8 -#define AD7280A_CELLS_PER_DEV 6 -#define AD7280A_BITS 12 -#define AD7280A_NUM_CH (AD7280A_AUX_ADC_6 - \ - AD7280A_CELL_VOLTAGE_1 + 1) - -#define AD7280A_DEVADDR_MASTER 0 -#define AD7280A_DEVADDR_ALL 0x1F -/* 5-bit device address is sent LSB first */ -#define AD7280A_DEVADDR(addr) (((addr & 0x1) << 4) | ((addr & 0x2) << 3) | \ - (addr & 0x4) | ((addr & 0x8) >> 3) | \ - ((addr & 0x10) >> 4)) - -/* During a read a valid write is mandatory. - * So writing to the highest available address (Address 0x1F) - * and setting the address all parts bit to 0 is recommended - * So the TXVAL is AD7280A_DEVADDR_ALL + CRC - */ -#define AD7280A_READ_TXVAL 0xF800030A - -/* - * AD7280 CRC - * - * P(x) = x^8 + x^5 + x^3 + x^2 + x^1 + x^0 = 0b100101111 => 0x2F - */ -#define POLYNOM 0x2F -#define POLYNOM_ORDER 8 -#define HIGHBIT 1 << (POLYNOM_ORDER - 1); - -struct ad7280_state { - struct spi_device *spi; - struct iio_chan_spec *channels; - struct iio_dev_attr *iio_attr; - int slave_num; - int scan_cnt; - int readback_delay_us; - unsigned char crc_tab[256]; - unsigned char ctrl_hb; - unsigned char ctrl_lb; - unsigned char cell_threshhigh; - unsigned char cell_threshlow; - unsigned char aux_threshhigh; - unsigned char aux_threshlow; - unsigned char cb_mask[AD7280A_MAX_CHAIN]; -}; - -static void ad7280_crc8_build_table(unsigned char *crc_tab) -{ - unsigned char bit, crc; - int cnt, i; - - for (cnt = 0; cnt < 256; cnt++) { - crc = cnt; - for (i = 0; i < 8; i++) { - bit = crc & HIGHBIT; - crc <<= 1; - if (bit) - crc ^= POLYNOM; - } - crc_tab[cnt] = crc; - } -} - -static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val) -{ - unsigned char crc; - - crc = crc_tab[val >> 16 & 0xFF]; - crc = crc_tab[crc ^ (val >> 8 & 0xFF)]; - - return crc ^ (val & 0xFF); -} - -static int ad7280_check_crc(struct ad7280_state *st, unsigned val) -{ - unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10); - - if (crc != ((val >> 2) & 0xFF)) - return -EIO; - - return 0; -} - -/* After initiating a conversion sequence we need to wait until the - * conversion is done. The delay is typically in the range of 15..30 us - * however depending an the number of devices in the daisy chain and the - * number of averages taken, conversion delays and acquisition time options - * it may take up to 250us, in this case we better sleep instead of busy - * wait. - */ - -static void ad7280_delay(struct ad7280_state *st) -{ - if (st->readback_delay_us < 50) - udelay(st->readback_delay_us); - else - msleep(1); -} - -static int __ad7280_read32(struct spi_device *spi, unsigned *val) -{ - unsigned rx_buf, tx_buf = cpu_to_be32(AD7280A_READ_TXVAL); - int ret; - - struct spi_transfer t = { - .tx_buf = &tx_buf, - .rx_buf = &rx_buf, - .len = 4, - }; - struct spi_message m; - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - - ret = spi_sync(spi, &m); - if (ret) - return ret; - - *val = be32_to_cpu(rx_buf); - - return 0; -} - -static int ad7280_write(struct ad7280_state *st, unsigned devaddr, - unsigned addr, bool all, unsigned val) -{ - unsigned reg = (devaddr << 27 | addr << 21 | - (val & 0xFF) << 13 | all << 12); - - reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2; - reg = cpu_to_be32(reg); - - return spi_write(st->spi, ®, 4); -} - -static int ad7280_read(struct ad7280_state *st, unsigned devaddr, - unsigned addr) -{ - int ret; - unsigned tmp; - - /* turns off the read operation on all parts */ - ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, - AD7280A_CTRL_HB_CONV_INPUT_ALL | - AD7280A_CTRL_HB_CONV_RES_READ_NO | - st->ctrl_hb); - if (ret) - return ret; - - /* turns on the read operation on the addressed part */ - ret = ad7280_write(st, devaddr, AD7280A_CONTROL_HB, 0, - AD7280A_CTRL_HB_CONV_INPUT_ALL | - AD7280A_CTRL_HB_CONV_RES_READ_ALL | - st->ctrl_hb); - if (ret) - return ret; - - /* Set register address on the part to be read from */ - ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2); - if (ret) - return ret; - - __ad7280_read32(st->spi, &tmp); - - if (ad7280_check_crc(st, tmp)) - return -EIO; - - if (((tmp >> 27) != devaddr) || (((tmp >> 21) & 0x3F) != addr)) - return -EFAULT; - - return (tmp >> 13) & 0xFF; -} - -static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr, - unsigned addr) -{ - int ret; - unsigned tmp; - - ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2); - if (ret) - return ret; - - ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, - AD7280A_CTRL_HB_CONV_INPUT_ALL | - AD7280A_CTRL_HB_CONV_RES_READ_NO | - st->ctrl_hb); - if (ret) - return ret; - - ret = ad7280_write(st, devaddr, AD7280A_CONTROL_HB, 0, - AD7280A_CTRL_HB_CONV_INPUT_ALL | - AD7280A_CTRL_HB_CONV_RES_READ_ALL | - AD7280A_CTRL_HB_CONV_START_CS | - st->ctrl_hb); - if (ret) - return ret; - - ad7280_delay(st); - - __ad7280_read32(st->spi, &tmp); - - if (ad7280_check_crc(st, tmp)) - return -EIO; - - if (((tmp >> 27) != devaddr) || (((tmp >> 23) & 0xF) != addr)) - return -EFAULT; - - return (tmp >> 11) & 0xFFF; -} - -static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt, - unsigned *array) -{ - int i, ret; - unsigned tmp, sum = 0; - - ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1, - AD7280A_CELL_VOLTAGE_1 << 2); - if (ret) - return ret; - - ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, - AD7280A_CTRL_HB_CONV_INPUT_ALL | - AD7280A_CTRL_HB_CONV_RES_READ_ALL | - AD7280A_CTRL_HB_CONV_START_CS | - st->ctrl_hb); - if (ret) - return ret; - - ad7280_delay(st); - - for (i = 0; i < cnt; i++) { - __ad7280_read32(st->spi, &tmp); - - if (ad7280_check_crc(st, tmp)) - return -EIO; - - if (array) - array[i] = tmp; - /* only sum cell voltages */ - if (((tmp >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6) - sum += ((tmp >> 11) & 0xFFF); - } - - return sum; -} - -static int ad7280_chain_setup(struct ad7280_state *st) -{ - unsigned val, n; - int ret; - - ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1, - AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN | - AD7280A_CTRL_LB_LOCK_DEV_ADDR | - AD7280A_CTRL_LB_MUST_SET | - AD7280A_CTRL_LB_SWRST | - st->ctrl_lb); - if (ret) - return ret; - - ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1, - AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN | - AD7280A_CTRL_LB_LOCK_DEV_ADDR | - AD7280A_CTRL_LB_MUST_SET | - st->ctrl_lb); - if (ret) - return ret; - - ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1, - AD7280A_CONTROL_LB << 2); - if (ret) - return ret; - - for (n = 0; n <= AD7280A_MAX_CHAIN; n++) { - __ad7280_read32(st->spi, &val); - if (val == 0) - return n - 1; - - if (ad7280_check_crc(st, val)) - return -EIO; - - if (n != AD7280A_DEVADDR(val >> 27)) - return -EIO; - } - - return -EFAULT; -} - -static ssize_t ad7280_show_balance_sw(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7280_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - return sprintf(buf, "%d\n", - !!(st->cb_mask[this_attr->address >> 8] & - (1 << ((this_attr->address & 0xFF) + 2)))); -} - -static ssize_t ad7280_store_balance_sw(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7280_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - bool readin; - int ret; - unsigned devaddr, ch; - - ret = strtobool(buf, &readin); - if (ret) - return ret; - - devaddr = this_attr->address >> 8; - ch = this_attr->address & 0xFF; - - mutex_lock(&dev_info->mlock); - if (readin) - st->cb_mask[devaddr] |= 1 << (ch + 2); - else - st->cb_mask[devaddr] &= ~(1 << (ch + 2)); - - ret = ad7280_write(st, devaddr, AD7280A_CELL_BALANCE, - 0, st->cb_mask[devaddr]); - mutex_unlock(&dev_info->mlock); - - return ret ? ret : len; -} - -static ssize_t ad7280_show_balance_timer(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7280_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - unsigned msecs; - - mutex_lock(&dev_info->mlock); - ret = ad7280_read(st, this_attr->address >> 8, - this_attr->address & 0xFF); - mutex_unlock(&dev_info->mlock); - - if (ret < 0) - return ret; - - msecs = (ret >> 3) * 71500; - - return sprintf(buf, "%d\n", msecs); -} - -static ssize_t ad7280_store_balance_timer(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7280_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - long val; - int ret; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - return ret; - - val /= 71500; - - if (val > 31) - return -EINVAL; - - mutex_lock(&dev_info->mlock); - ret = ad7280_write(st, this_attr->address >> 8, - this_attr->address & 0xFF, - 0, (val & 0x1F) << 3); - mutex_unlock(&dev_info->mlock); - - return ret ? ret : len; -} - -static struct attribute *ad7280_attributes[AD7280A_MAX_CHAIN * - AD7280A_CELLS_PER_DEV * 2 + 1]; - -static struct attribute_group ad7280_attrs_group = { - .attrs = ad7280_attributes, -}; - -static int ad7280_channel_init(struct ad7280_state *st) -{ - int dev, ch, cnt; - - st->channels = kzalloc(sizeof(*st->channels) * - ((st->slave_num + 1) * 12 + 2), GFP_KERNEL); - if (st->channels == NULL) - return -ENOMEM; - - for (dev = 0, cnt = 0; dev <= st->slave_num; dev++) - for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6; ch++, - cnt++) { - if (ch < AD7280A_AUX_ADC_1) { - st->channels[cnt].type = IIO_IN_DIFF; - st->channels[cnt].channel = (dev * 6) + ch; - st->channels[cnt].channel2 = - st->channels[cnt].channel + 1; - } else { - st->channels[cnt].type = IIO_TEMP; - st->channels[cnt].channel = (dev * 6) + ch - 6; - } - st->channels[cnt].indexed = 1; - st->channels[cnt].info_mask = - (1 << IIO_CHAN_INFO_SCALE_SHARED); - st->channels[cnt].address = - AD7280A_DEVADDR(dev) << 8 | ch; - st->channels[cnt].scan_index = cnt; - st->channels[cnt].scan_type.sign = 'u'; - st->channels[cnt].scan_type.realbits = 12; - st->channels[cnt].scan_type.storagebits = 32; - st->channels[cnt].scan_type.shift = 0; - } - - st->channels[cnt].type = IIO_IN_DIFF; - st->channels[cnt].channel = 0; - st->channels[cnt].channel2 = dev * 6; - st->channels[cnt].address = AD7280A_ALL_CELLS; - st->channels[cnt].indexed = 1; - st->channels[cnt].info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED); - st->channels[cnt].scan_index = cnt; - st->channels[cnt].scan_type.sign = 'u'; - st->channels[cnt].scan_type.realbits = 32; - st->channels[cnt].scan_type.storagebits = 32; - st->channels[cnt].scan_type.shift = 0; - cnt++; - st->channels[cnt].type = IIO_TIMESTAMP; - st->channels[cnt].channel = -1; - st->channels[cnt].scan_index = cnt; - st->channels[cnt].scan_type.sign = 's'; - st->channels[cnt].scan_type.realbits = 64; - st->channels[cnt].scan_type.storagebits = 64; - st->channels[cnt].scan_type.shift = 0; - - return cnt + 1; -} - -static int ad7280_attr_init(struct ad7280_state *st) -{ - int dev, ch, cnt; - - st->iio_attr = kzalloc(sizeof(*st->iio_attr) * (st->slave_num + 1) * - AD7280A_CELLS_PER_DEV * 2, GFP_KERNEL); - if (st->iio_attr == NULL) - return -ENOMEM; - - for (dev = 0, cnt = 0; dev <= st->slave_num; dev++) - for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6; - ch++, cnt++) { - st->iio_attr[cnt].address = - AD7280A_DEVADDR(dev) << 8 | ch; - st->iio_attr[cnt].dev_attr.attr.mode = - S_IWUSR | S_IRUGO; - st->iio_attr[cnt].dev_attr.show = - ad7280_show_balance_sw; - st->iio_attr[cnt].dev_attr.store = - ad7280_store_balance_sw; - st->iio_attr[cnt].dev_attr.attr.name = - kasprintf(GFP_KERNEL, - "in%d-in%d_balance_switch_en", - (dev * AD7280A_CELLS_PER_DEV) + ch, - (dev * AD7280A_CELLS_PER_DEV) + ch + 1); - ad7280_attributes[cnt] = - &st->iio_attr[cnt].dev_attr.attr; - cnt++; - st->iio_attr[cnt].address = - AD7280A_DEVADDR(dev) << 8 | - (AD7280A_CB1_TIMER + ch); - st->iio_attr[cnt].dev_attr.attr.mode = - S_IWUSR | S_IRUGO; - st->iio_attr[cnt].dev_attr.show = - ad7280_show_balance_timer; - st->iio_attr[cnt].dev_attr.store = - ad7280_store_balance_timer; - st->iio_attr[cnt].dev_attr.attr.name = - kasprintf(GFP_KERNEL, "in%d-in%d_balance_timer", - (dev * AD7280A_CELLS_PER_DEV) + ch, - (dev * AD7280A_CELLS_PER_DEV) + ch + 1); - ad7280_attributes[cnt] = - &st->iio_attr[cnt].dev_attr.attr; - } - - ad7280_attributes[cnt] = NULL; - - return 0; -} - -static ssize_t ad7280_read_channel_config(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7280_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned val; - - switch (this_attr->address) { - case AD7280A_CELL_OVERVOLTAGE: - val = 1000 + (st->cell_threshhigh * 1568) / 100; - break; - case AD7280A_CELL_UNDERVOLTAGE: - val = 1000 + (st->cell_threshlow * 1568) / 100; - break; - case AD7280A_AUX_ADC_OVERVOLTAGE: - val = (st->aux_threshhigh * 196) / 10; - break; - case AD7280A_AUX_ADC_UNDERVOLTAGE: - val = (st->aux_threshlow * 196) / 10; - break; - default: - return -EINVAL; - } - - return sprintf(buf, "%d\n", val); -} - -static ssize_t ad7280_write_channel_config(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad7280_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - long val; - int ret; - - ret = strict_strtol(buf, 10, &val); - if (ret) - return ret; - - switch (this_attr->address) { - case AD7280A_CELL_OVERVOLTAGE: - case AD7280A_CELL_UNDERVOLTAGE: - val = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */ - break; - case AD7280A_AUX_ADC_OVERVOLTAGE: - case AD7280A_AUX_ADC_UNDERVOLTAGE: - val = (val * 10) / 196; /* LSB 19.6mV */ - break; - default: - return -EFAULT; - } - - val = clamp(val, 0L, 0xFFL); - - mutex_lock(&dev_info->mlock); - switch (this_attr->address) { - case AD7280A_CELL_OVERVOLTAGE: - st->cell_threshhigh = val; - break; - case AD7280A_CELL_UNDERVOLTAGE: - st->cell_threshlow = val; - break; - case AD7280A_AUX_ADC_OVERVOLTAGE: - st->aux_threshhigh = val; - break; - case AD7280A_AUX_ADC_UNDERVOLTAGE: - st->aux_threshlow = val; - break; - } - - ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, - this_attr->address, 1, val); - - mutex_unlock(&dev_info->mlock); - - return ret ? ret : len; -} - -static irqreturn_t ad7280_event_handler(int irq, void *private) -{ - struct iio_dev *dev_info = private; - struct ad7280_state *st = iio_priv(dev_info); - unsigned *channels; - int i, ret; - - channels = kzalloc(sizeof(*channels) * st->scan_cnt, GFP_KERNEL); - if (channels == NULL) - return IRQ_HANDLED; - - ret = ad7280_read_all_channels(st, st->scan_cnt, channels); - if (ret < 0) - return IRQ_HANDLED; - - for (i = 0; i < st->scan_cnt; i++) { - if (((channels[i] >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6) { - if (((channels[i] >> 11) & 0xFFF) >= - st->cell_threshhigh) - iio_push_event(dev_info, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN_DIFF, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - iio_get_time_ns()); - else if (((channels[i] >> 11) & 0xFFF) <= - st->cell_threshlow) - iio_push_event(dev_info, 0, - IIO_UNMOD_EVENT_CODE(IIO_IN_DIFF, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - iio_get_time_ns()); - } else { - if (((channels[i] >> 11) & 0xFFF) >= st->aux_threshhigh) - iio_push_event(dev_info, 0, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - iio_get_time_ns()); - else if (((channels[i] >> 11) & 0xFFF) <= - st->aux_threshlow) - iio_push_event(dev_info, 0, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - iio_get_time_ns()); - } - } - - kfree(channels); - - return IRQ_HANDLED; -} - -static IIO_DEVICE_ATTR_NAMED(in_thresh_low_value, - in-in_thresh_low_value, - S_IRUGO | S_IWUSR, - ad7280_read_channel_config, - ad7280_write_channel_config, - AD7280A_CELL_UNDERVOLTAGE); - -static IIO_DEVICE_ATTR_NAMED(in_thresh_high_value, - in-in_thresh_high_value, - S_IRUGO | S_IWUSR, - ad7280_read_channel_config, - ad7280_write_channel_config, - AD7280A_CELL_OVERVOLTAGE); - -static IIO_DEVICE_ATTR(temp_thresh_low_value, - S_IRUGO | S_IWUSR, - ad7280_read_channel_config, - ad7280_write_channel_config, - AD7280A_AUX_ADC_UNDERVOLTAGE); - -static IIO_DEVICE_ATTR(temp_thresh_high_value, - S_IRUGO | S_IWUSR, - ad7280_read_channel_config, - ad7280_write_channel_config, - AD7280A_AUX_ADC_OVERVOLTAGE); - - -static struct attribute *ad7280_event_attributes[] = { - &iio_dev_attr_in_thresh_low_value.dev_attr.attr, - &iio_dev_attr_in_thresh_high_value.dev_attr.attr, - &iio_dev_attr_temp_thresh_low_value.dev_attr.attr, - &iio_dev_attr_temp_thresh_high_value.dev_attr.attr, - NULL, -}; - -static struct attribute_group ad7280_event_attrs_group = { - .attrs = ad7280_event_attributes, -}; - -static int ad7280_read_raw(struct iio_dev *dev_info, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad7280_state *st = iio_priv(dev_info); - unsigned int scale_uv; - int ret; - - switch (m) { - case 0: - mutex_lock(&dev_info->mlock); - if (chan->address == AD7280A_ALL_CELLS) - ret = ad7280_read_all_channels(st, st->scan_cnt, NULL); - else - ret = ad7280_read_channel(st, chan->address >> 8, - chan->address & 0xFF); - mutex_unlock(&dev_info->mlock); - - if (ret < 0) - return ret; - - *val = ret; - - return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): - if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6) - scale_uv = (4000 * 1000) >> AD7280A_BITS; - else - scale_uv = (5000 * 1000) >> AD7280A_BITS; - - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - } - return -EINVAL; -} - -static const struct iio_info ad7280_info = { - .read_raw = &ad7280_read_raw, - .num_interrupt_lines = 1, - .event_attrs = &ad7280_event_attrs_group, - .attrs = &ad7280_attrs_group, - .driver_module = THIS_MODULE, -}; - -static const struct ad7280_platform_data ad7793_default_pdata = { - .acquisition_time = AD7280A_ACQ_TIME_400ns, - .conversion_averaging = AD7280A_CONV_AVG_DIS, - .thermistor_term_en = true, -}; - -static int __devinit ad7280_probe(struct spi_device *spi) -{ - const struct ad7280_platform_data *pdata = spi->dev.platform_data; - struct ad7280_state *st; - int ret, regdone = 0; - const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890}; - const unsigned short nAVG[4] = {1, 2, 4, 8}; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); - - if (indio_dev == NULL) - return -ENOMEM; - - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - st->spi = spi; - - if (!pdata) - pdata = &ad7793_default_pdata; - - ad7280_crc8_build_table(st->crc_tab); - - st->spi->max_speed_hz = AD7280A_MAX_SPI_CLK_Hz; - st->spi->mode = SPI_MODE_1; - spi_setup(st->spi); - - st->ctrl_lb = AD7280A_CTRL_LB_ACQ_TIME(pdata->acquisition_time & 0x3); - st->ctrl_hb = AD7280A_CTRL_HB_CONV_AVG(pdata->conversion_averaging - & 0x3) | (pdata->thermistor_term_en ? - AD7280A_CTRL_LB_THERMISTOR_EN : 0); - - ret = ad7280_chain_setup(st); - if (ret < 0) - goto error_free_device; - - st->slave_num = ret; - st->scan_cnt = (st->slave_num + 1) * AD7280A_NUM_CH; - st->cell_threshhigh = 0xFF; - st->aux_threshhigh = 0xFF; - - /* - * Total Conversion Time = ((tACQ + tCONV) * - * (Number of Conversions per Part)) − - * tACQ + ((N - 1) * tDELAY) - * - * Readback Delay = Total Conversion Time + tWAIT - */ - - st->readback_delay_us = - ((tACQ_ns[pdata->acquisition_time & 0x3] + 695) * - (AD7280A_NUM_CH * nAVG[pdata->conversion_averaging & 0x3])) - - tACQ_ns[pdata->acquisition_time & 0x3] + - st->slave_num * 250; - - /* Convert to usecs */ - st->readback_delay_us = DIV_ROUND_UP(st->readback_delay_us, 1000); - st->readback_delay_us += 5; /* Add tWAIT */ - - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = ad7280_channel_init(st); - if (ret < 0) - goto error_free_device; - - indio_dev->num_channels = ret; - indio_dev->channels = st->channels; - indio_dev->info = &ad7280_info; - - ret = ad7280_attr_init(st); - if (ret < 0) - goto error_free_channels; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_attr; - regdone = 1; - - if (spi->irq > 0) { - ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, - AD7280A_ALERT, 1, - AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN); - if (ret) - goto error_free_attr; - - ret = ad7280_write(st, AD7280A_DEVADDR(st->slave_num), - AD7280A_ALERT, 0, - AD7280A_ALERT_GEN_STATIC_HIGH | - (pdata->chain_last_alert_ignore & 0xF)); - if (ret) - goto error_free_attr; - - ret = request_threaded_irq(spi->irq, - NULL, - ad7280_event_handler, - IRQF_TRIGGER_FALLING | - IRQF_ONESHOT, - indio_dev->name, - indio_dev); - if (ret) - goto error_free_attr; - } - - return 0; - -error_free_attr: - kfree(st->iio_attr); - -error_free_channels: - kfree(st->channels); - -error_free_device: - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); - - return ret; -} - -static int __devexit ad7280_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7280_state *st = iio_priv(indio_dev); - - if (spi->irq > 0) - free_irq(spi->irq, indio_dev); - - ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1, - AD7280A_CTRL_HB_PWRDN_SW | st->ctrl_hb); - - kfree(st->channels); - kfree(st->iio_attr); - iio_device_unregister(indio_dev); - - return 0; -} - -static const struct spi_device_id ad7280_id[] = { - {"ad7280a", 0}, - {} -}; - -static struct spi_driver ad7280_driver = { - .driver = { - .name = "ad7280", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = ad7280_probe, - .remove = __devexit_p(ad7280_remove), - .id_table = ad7280_id, -}; - -static int __init ad7280_init(void) -{ - return spi_register_driver(&ad7280_driver); -} -module_init(ad7280_init); - -static void __exit ad7280_exit(void) -{ - spi_unregister_driver(&ad7280_driver); -} -module_exit(ad7280_exit); - -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7280A"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/adc/ad7280a.h b/trunk/drivers/staging/iio/adc/ad7280a.h deleted file mode 100644 index 20400b0045e5..000000000000 --- a/trunk/drivers/staging/iio/adc/ad7280a.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * AD7280A Lithium Ion Battery Monitoring System - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#ifndef IIO_ADC_AD7280_H_ -#define IIO_ADC_AD7280_H_ - -/* - * TODO: struct ad7280_platform_data needs to go into include/linux/iio - */ - -#define AD7280A_ACQ_TIME_400ns 0 -#define AD7280A_ACQ_TIME_800ns 1 -#define AD7280A_ACQ_TIME_1200ns 2 -#define AD7280A_ACQ_TIME_1600ns 3 - -#define AD7280A_CONV_AVG_DIS 0 -#define AD7280A_CONV_AVG_2 1 -#define AD7280A_CONV_AVG_4 2 -#define AD7280A_CONV_AVG_8 3 - -#define AD7280A_ALERT_REMOVE_VIN5 (1 << 2) -#define AD7280A_ALERT_REMOVE_VIN4_VIN5 (2 << 2) -#define AD7280A_ALERT_REMOVE_AUX5 (1 << 0) -#define AD7280A_ALERT_REMOVE_AUX4_AUX5 (2 << 0) - -struct ad7280_platform_data { - unsigned acquisition_time; - unsigned conversion_averaging; - unsigned chain_last_alert_ignore; - bool thermistor_term_en; -}; - -#endif /* IIO_ADC_AD7280_H_ */ diff --git a/trunk/drivers/staging/iio/adc/ad7298_core.c b/trunk/drivers/staging/iio/adc/ad7298_core.c index 21d1931edb38..b8e4ae29b0b5 100644 --- a/trunk/drivers/staging/iio/adc/ad7298_core.c +++ b/trunk/drivers/staging/iio/adc/ad7298_core.c @@ -18,6 +18,7 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" +#include "adc.h" #include "ad7298.h" diff --git a/trunk/drivers/staging/iio/adc/ad7298_ring.c b/trunk/drivers/staging/iio/adc/ad7298_ring.c index 741818c0b829..a04c03352624 100644 --- a/trunk/drivers/staging/iio/adc/ad7298_ring.c +++ b/trunk/drivers/staging/iio/adc/ad7298_ring.c @@ -7,14 +7,17 @@ */ #include +#include #include #include +#include #include #include "../iio.h" #include "../ring_generic.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "../trigger.h" +#include "../sysfs.h" #include "ad7298.h" @@ -117,7 +120,7 @@ static int ad7298_ring_preenable(struct iio_dev *indio_dev) static irqreturn_t ad7298_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct ad7298_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; s64 time_ns; @@ -189,6 +192,11 @@ int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) void ad7298_ring_cleanup(struct iio_dev *indio_dev) { + if (indio_dev->trig) { + iio_put_trigger(indio_dev->trig); + iio_trigger_dettach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } iio_dealloc_pollfunc(indio_dev->pollfunc); iio_sw_rb_free(indio_dev->ring); } diff --git a/trunk/drivers/staging/iio/adc/ad7476_core.c b/trunk/drivers/staging/iio/adc/ad7476_core.c index f2fdd48303e3..c21089894d28 100644 --- a/trunk/drivers/staging/iio/adc/ad7476_core.c +++ b/trunk/drivers/staging/iio/adc/ad7476_core.c @@ -17,6 +17,7 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" +#include "adc.h" #include "ad7476.h" diff --git a/trunk/drivers/staging/iio/adc/ad7476_ring.c b/trunk/drivers/staging/iio/adc/ad7476_ring.c index b109afb89846..a92fc5a1a604 100644 --- a/trunk/drivers/staging/iio/adc/ad7476_ring.c +++ b/trunk/drivers/staging/iio/adc/ad7476_ring.c @@ -11,12 +11,14 @@ #include #include #include +#include #include #include "../iio.h" #include "../ring_generic.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "../trigger.h" +#include "../sysfs.h" #include "ad7476.h" @@ -76,7 +78,7 @@ static int ad7476_ring_preenable(struct iio_dev *indio_dev) static irqreturn_t ad7476_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct ad7476_state *st = iio_priv(indio_dev); s64 time_ns; __u8 *rxbuf; @@ -152,6 +154,12 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) void ad7476_ring_cleanup(struct iio_dev *indio_dev) { + /* ensure that the trigger has been detached */ + if (indio_dev->trig) { + iio_put_trigger(indio_dev->trig); + iio_trigger_dettach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } iio_dealloc_pollfunc(indio_dev->pollfunc); iio_sw_rb_free(indio_dev->ring); } diff --git a/trunk/drivers/staging/iio/adc/ad7606_core.c b/trunk/drivers/staging/iio/adc/ad7606_core.c index dcdb180d7e75..459371ae4dcc 100644 --- a/trunk/drivers/staging/iio/adc/ad7606_core.c +++ b/trunk/drivers/staging/iio/adc/ad7606_core.c @@ -20,6 +20,7 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" +#include "adc.h" #include "ad7606.h" diff --git a/trunk/drivers/staging/iio/adc/ad7606_ring.c b/trunk/drivers/staging/iio/adc/ad7606_ring.c index e6424300c8e7..a199bf48396c 100644 --- a/trunk/drivers/staging/iio/adc/ad7606_ring.c +++ b/trunk/drivers/staging/iio/adc/ad7606_ring.c @@ -10,11 +10,13 @@ #include #include #include +#include #include "../iio.h" #include "../ring_generic.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "../trigger.h" +#include "../sysfs.h" #include "ad7606.h" @@ -80,7 +82,8 @@ static int ad7606_ring_preenable(struct iio_dev *indio_dev) static irqreturn_t ad7606_trigger_handler_th_bh(int irq, void *p) { struct iio_poll_func *pf = p; - struct ad7606_state *st = iio_priv(pf->indio_dev); + struct iio_dev *indio_dev = pf->private_data; + struct ad7606_state *st = iio_priv(indio_dev); gpio_set_value(st->pdata->gpio_convst, 1); @@ -197,6 +200,11 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) void ad7606_ring_cleanup(struct iio_dev *indio_dev) { + if (indio_dev->trig) { + iio_put_trigger(indio_dev->trig); + iio_trigger_dettach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } iio_dealloc_pollfunc(indio_dev->pollfunc); iio_sw_rb_free(indio_dev->ring); } diff --git a/trunk/drivers/staging/iio/adc/ad7780.c b/trunk/drivers/staging/iio/adc/ad7780.c index f90cdeacadf6..e0c7b6cc05c7 100644 --- a/trunk/drivers/staging/iio/adc/ad7780.c +++ b/trunk/drivers/staging/iio/adc/ad7780.c @@ -20,6 +20,7 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" +#include "adc.h" #include "ad7780.h" diff --git a/trunk/drivers/staging/iio/adc/ad7793.c b/trunk/drivers/staging/iio/adc/ad7793.c index 1bcb3ebb1bc6..90f6c039d6c6 100644 --- a/trunk/drivers/staging/iio/adc/ad7793.c +++ b/trunk/drivers/staging/iio/adc/ad7793.c @@ -22,7 +22,7 @@ #include "../ring_generic.h" #include "../ring_sw.h" #include "../trigger.h" -#include "../trigger_consumer.h" +#include "adc.h" #include "ad7793.h" @@ -402,7 +402,7 @@ static int ad7793_ring_postdisable(struct iio_dev *indio_dev) static irqreturn_t ad7793_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct iio_ring_buffer *ring = indio_dev->ring; struct ad7793_state *st = iio_priv(indio_dev); s64 dat64[2]; @@ -470,6 +470,12 @@ static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) static void ad7793_ring_cleanup(struct iio_dev *indio_dev) { + /* ensure that the trigger has been detached */ + if (indio_dev->trig) { + iio_put_trigger(indio_dev->trig); + iio_trigger_dettach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } iio_dealloc_pollfunc(indio_dev->pollfunc); iio_sw_rb_free(indio_dev->ring); } diff --git a/trunk/drivers/staging/iio/adc/ad7816.c b/trunk/drivers/staging/iio/adc/ad7816.c index 3fa4bb34a432..0c84217bde3d 100644 --- a/trunk/drivers/staging/iio/adc/ad7816.c +++ b/trunk/drivers/staging/iio/adc/ad7816.c @@ -246,7 +246,7 @@ static const struct attribute_group ad7816_attribute_group = { * temperature bound events */ -#define IIO_EVENT_CODE_AD7816_OTI IIO_UNMOD_EVENT_CODE(IIO_TEMP, \ +#define IIO_EVENT_CODE_AD7816_OTI IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, \ 0, \ IIO_EV_TYPE_THRESH, \ IIO_EV_DIR_FALLING) diff --git a/trunk/drivers/staging/iio/adc/ad7887_core.c b/trunk/drivers/staging/iio/adc/ad7887_core.c index a7da9e68ebaa..3d9121e5c37d 100644 --- a/trunk/drivers/staging/iio/adc/ad7887_core.c +++ b/trunk/drivers/staging/iio/adc/ad7887_core.c @@ -17,7 +17,7 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" - +#include "adc.h" #include "ad7887.h" diff --git a/trunk/drivers/staging/iio/adc/ad7887_ring.c b/trunk/drivers/staging/iio/adc/ad7887_ring.c index 6b3daf41e0c6..0ac7c0b9d71d 100644 --- a/trunk/drivers/staging/iio/adc/ad7887_ring.c +++ b/trunk/drivers/staging/iio/adc/ad7887_ring.c @@ -8,14 +8,17 @@ */ #include +#include #include #include +#include #include #include "../iio.h" #include "../ring_generic.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "../trigger.h" +#include "../sysfs.h" #include "ad7887.h" @@ -112,7 +115,7 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev) static irqreturn_t ad7887_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct ad7887_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; s64 time_ns; @@ -188,6 +191,12 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) void ad7887_ring_cleanup(struct iio_dev *indio_dev) { + /* ensure that the trigger has been detached */ + if (indio_dev->trig) { + iio_put_trigger(indio_dev->trig); + iio_trigger_dettach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } iio_dealloc_pollfunc(indio_dev->pollfunc); iio_sw_rb_free(indio_dev->ring); } diff --git a/trunk/drivers/staging/iio/adc/ad799x_core.c b/trunk/drivers/staging/iio/adc/ad799x_core.c index 2438ed597e9f..92cfe2e3ea4a 100644 --- a/trunk/drivers/staging/iio/adc/ad799x_core.c +++ b/trunk/drivers/staging/iio/adc/ad799x_core.c @@ -34,8 +34,9 @@ #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" +#include "../ring_generic.h" +#include "adc.h" #include "ad799x.h" /* @@ -335,14 +336,8 @@ static irqreturn_t ad799x_event_handler(int irq, void *private) if (status & (1 << i)) iio_push_event(indio_dev, 0, i & 0x1 ? - IIO_UNMOD_EVENT_CODE(IIO_IN, - (i >> 1), - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING) : - IIO_UNMOD_EVENT_CODE(IIO_IN, - (i >> 1), - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), + IIO_EVENT_CODE_IN_HIGH_THRESH(i >> 1) : + IIO_EVENT_CODE_IN_LOW_THRESH(i >> 1), iio_get_time_ns()); } diff --git a/trunk/drivers/staging/iio/adc/ad799x_ring.c b/trunk/drivers/staging/iio/adc/ad799x_ring.c index 8f1fc52560f1..0376a826c26c 100644 --- a/trunk/drivers/staging/iio/adc/ad799x_ring.c +++ b/trunk/drivers/staging/iio/adc/ad799x_ring.c @@ -10,8 +10,10 @@ */ #include +#include #include #include +#include #include #include #include @@ -19,7 +21,8 @@ #include "../iio.h" #include "../ring_generic.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "../trigger.h" +#include "../sysfs.h" #include "ad799x.h" @@ -105,7 +108,7 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev) static irqreturn_t ad799x_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct ad799x_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; s64 time_ns; @@ -204,6 +207,12 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev) void ad799x_ring_cleanup(struct iio_dev *indio_dev) { + /* ensure that the trigger has been detached */ + if (indio_dev->trig) { + iio_put_trigger(indio_dev->trig); + iio_trigger_dettach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } iio_dealloc_pollfunc(indio_dev->pollfunc); iio_sw_rb_free(indio_dev->ring); } diff --git a/trunk/drivers/staging/iio/adc/adc.h b/trunk/drivers/staging/iio/adc/adc.h new file mode 100644 index 000000000000..40c5949880b4 --- /dev/null +++ b/trunk/drivers/staging/iio/adc/adc.h @@ -0,0 +1,42 @@ +/* + * adc.h - sysfs attributes associated with ADCs + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Copyright (c) 2008 Jonathan Cameron + * + */ + +/* Deprecated */ +#define IIO_DEV_ATTR_ADC(_num, _show, _addr) \ + IIO_DEVICE_ATTR(adc_##_num, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_IN_RAW(_num, _show, _addr) \ + IIO_DEVICE_ATTR(in##_num##_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_IN_NAMED_RAW(_num, _name, _show, _addr) \ + IIO_DEVICE_ATTR(in##_num##_##_name##_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_IN_DIFF_RAW(_nump, _numn, _show, _addr) \ + IIO_DEVICE_ATTR_NAMED(in##_nump##min##_numn##_raw, \ + in##_nump-in##_numn##_raw, \ + S_IRUGO, \ + _show, \ + NULL, \ + _addr) + + +#define IIO_CONST_ATTR_IN_NAMED_OFFSET(_num, _name, _string) \ + IIO_CONST_ATTR(in##_num##_##_name##_offset, _string) + +#define IIO_CONST_ATTR_IN_NAMED_SCALE(_num, _name, _string) \ + IIO_CONST_ATTR(in##_num##_##_name##_scale, _string) + +#define IIO_EVENT_CODE_IN_HIGH_THRESH(a) \ + IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \ + IIO_EV_DIR_RISING) +#define IIO_EVENT_CODE_IN_LOW_THRESH(a) \ + IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \ + IIO_EV_DIR_FALLING) diff --git a/trunk/drivers/staging/iio/adc/adt75.c b/trunk/drivers/staging/iio/adc/adt75.c index fc31cac7eae2..38f141de6a4b 100644 --- a/trunk/drivers/staging/iio/adc/adt75.c +++ b/trunk/drivers/staging/iio/adc/adt75.c @@ -257,7 +257,7 @@ static const struct attribute_group adt75_attribute_group = { * temperature bound events */ -#define IIO_EVENT_CODE_ADT75_OTI IIO_UNMOD_EVENT_CODE(IIO_TEMP, \ +#define IIO_EVENT_CODE_ADT75_OTI IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, \ 0, \ IIO_EV_TYPE_THRESH, \ IIO_EV_DIR_FALLING) diff --git a/trunk/drivers/staging/iio/adc/max1363_core.c b/trunk/drivers/staging/iio/adc/max1363_core.c index 6896b4cddf3d..72b0917412ee 100644 --- a/trunk/drivers/staging/iio/adc/max1363_core.c +++ b/trunk/drivers/staging/iio/adc/max1363_core.c @@ -33,8 +33,9 @@ #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" +#include "../ring_generic.h" +#include "adc.h" #include "max1363.h" #define MAX1363_MODE_SINGLE(_num, _mask) { \ @@ -254,7 +255,7 @@ static int max1363_read_raw(struct iio_dev *indio_dev, switch (m) { case 0: ret = max1363_read_single_chan(indio_dev, chan, val, m); - if (ret < 0) + if (ret) return ret; return IIO_VAL_INT; case (1 << IIO_CHAN_INFO_SCALE_SHARED): @@ -591,14 +592,10 @@ static int max1363_write_thresh(struct iio_dev *indio_dev, } static const int max1363_event_codes[] = { - IIO_UNMOD_EVENT_CODE(IIO_IN, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - IIO_UNMOD_EVENT_CODE(IIO_IN, 1, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - IIO_UNMOD_EVENT_CODE(IIO_IN, 2, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - IIO_UNMOD_EVENT_CODE(IIO_IN, 3, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - IIO_UNMOD_EVENT_CODE(IIO_IN, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), - IIO_UNMOD_EVENT_CODE(IIO_IN, 1, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), - IIO_UNMOD_EVENT_CODE(IIO_IN, 2, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), - IIO_UNMOD_EVENT_CODE(IIO_IN, 3, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), + IIO_EVENT_CODE_IN_LOW_THRESH(3), IIO_EVENT_CODE_IN_HIGH_THRESH(3), + IIO_EVENT_CODE_IN_LOW_THRESH(2), IIO_EVENT_CODE_IN_HIGH_THRESH(2), + IIO_EVENT_CODE_IN_LOW_THRESH(1), IIO_EVENT_CODE_IN_HIGH_THRESH(1), + IIO_EVENT_CODE_IN_LOW_THRESH(0), IIO_EVENT_CODE_IN_HIGH_THRESH(0) }; static irqreturn_t max1363_event_handler(int irq, void *private) @@ -1298,8 +1295,6 @@ static int __devinit max1363_probe(struct i2c_client *client, indio_dev->info = st->chip_info->info; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = st->chip_info->num_channels; ret = max1363_initial_setup(st); if (ret < 0) goto error_free_available_scan_masks; diff --git a/trunk/drivers/staging/iio/adc/max1363_ring.c b/trunk/drivers/staging/iio/adc/max1363_ring.c index be601e07639d..f43befd1f776 100644 --- a/trunk/drivers/staging/iio/adc/max1363_ring.c +++ b/trunk/drivers/staging/iio/adc/max1363_ring.c @@ -9,15 +9,19 @@ */ #include +#include #include #include +#include +#include #include #include #include "../iio.h" #include "../ring_generic.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "../trigger.h" +#include "../sysfs.h" #include "max1363.h" @@ -104,7 +108,7 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev) static irqreturn_t max1363_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct max1363_state *st = iio_priv(indio_dev); s64 time_ns; __u8 *rxbuf; @@ -195,6 +199,11 @@ int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) void max1363_ring_cleanup(struct iio_dev *indio_dev) { /* ensure that the trigger has been detached */ + if (indio_dev->trig) { + iio_put_trigger(indio_dev->trig); + iio_trigger_dettach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } iio_dealloc_pollfunc(indio_dev->pollfunc); iio_sw_rb_free(indio_dev->ring); } diff --git a/trunk/drivers/staging/iio/addac/adt7316.c b/trunk/drivers/staging/iio/addac/adt7316.c index c828b6f0a281..637316f79f78 100644 --- a/trunk/drivers/staging/iio/addac/adt7316.c +++ b/trunk/drivers/staging/iio/addac/adt7316.c @@ -203,7 +203,7 @@ struct adt7316_chip_info { #define ADT7316_TEMP_INT_MASK 0x1F #define ADT7516_AIN_INT_MASK 0xE0 #define ADT7316_TEMP_AIN_INT_MASK \ - (ADT7316_TEMP_INT_MASK) + (ADT7316_TEMP_INT_MASK | ADT7316_TEMP_INT_MASK) /* * struct adt7316_chip_info - chip specifc information diff --git a/trunk/drivers/staging/iio/dac/ad5504.c b/trunk/drivers/staging/iio/dac/ad5504.c index ba3d9b3154af..1915f459868b 100644 --- a/trunk/drivers/staging/iio/dac/ad5504.c +++ b/trunk/drivers/staging/iio/dac/ad5504.c @@ -251,7 +251,7 @@ static struct attribute_group ad5504_ev_attribute_group = { static irqreturn_t ad5504_event_handler(int irq, void *private) { iio_push_event(private, 0, - IIO_UNMOD_EVENT_CODE(IIO_TEMP, + IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), @@ -338,7 +338,7 @@ static int __devinit ad5504_probe(struct spi_device *spi) iio_free_device(indio_dev); error_disable_reg: if (!IS_ERR(reg)) - regulator_disable(reg); + regulator_disable(st->reg); error_put_reg: if (!IS_ERR(reg)) regulator_put(reg); diff --git a/trunk/drivers/staging/iio/dac/ad5791.c b/trunk/drivers/staging/iio/dac/ad5791.c index 5b00b70b3fef..64770d2a1b4c 100644 --- a/trunk/drivers/staging/iio/dac/ad5791.c +++ b/trunk/drivers/staging/iio/dac/ad5791.c @@ -381,6 +381,7 @@ static int __devinit ad5791_probe(struct spi_device *spi) if (!IS_ERR(reg_vdd)) regulator_put(reg_vdd); +error_ret: return ret; } diff --git a/trunk/drivers/staging/iio/dds/ad9852.c b/trunk/drivers/staging/iio/dds/ad9852.c index 86722657e7c8..0184585425d8 100644 --- a/trunk/drivers/staging/iio/dds/ad9852.c +++ b/trunk/drivers/staging/iio/dds/ad9852.c @@ -217,6 +217,7 @@ static struct attribute *ad9852_attributes[] = { }; static const struct attribute_group ad9852_attribute_group = { + .name = DRV_NAME, .attrs = ad9852_attributes, }; diff --git a/trunk/drivers/staging/iio/dds/ad9910.c b/trunk/drivers/staging/iio/dds/ad9910.c index 33585533a0b0..0fa217f7b901 100644 --- a/trunk/drivers/staging/iio/dds/ad9910.c +++ b/trunk/drivers/staging/iio/dds/ad9910.c @@ -352,6 +352,7 @@ static struct attribute *ad9910_attributes[] = { }; static const struct attribute_group ad9910_attribute_group = { + .name = DRV_NAME, .attrs = ad9910_attributes, }; diff --git a/trunk/drivers/staging/iio/dds/ad9951.c b/trunk/drivers/staging/iio/dds/ad9951.c index 6c18e24d0f66..d361d1f125de 100644 --- a/trunk/drivers/staging/iio/dds/ad9951.c +++ b/trunk/drivers/staging/iio/dds/ad9951.c @@ -161,6 +161,7 @@ static struct attribute *ad9951_attributes[] = { }; static const struct attribute_group ad9951_attribute_group = { + .name = DRV_NAME, .attrs = ad9951_attributes, }; diff --git a/trunk/drivers/staging/iio/gyro/adis16060_core.c b/trunk/drivers/staging/iio/gyro/adis16060_core.c index 0cbe677359bf..afa52d1961a9 100644 --- a/trunk/drivers/staging/iio/gyro/adis16060_core.c +++ b/trunk/drivers/staging/iio/gyro/adis16060_core.c @@ -14,8 +14,11 @@ #include #include + #include "../iio.h" #include "../sysfs.h" +#include "gyro.h" +#include "../adc/adc.h" #define ADIS16060_GYRO 0x20 /* Measure Angular Rate (Gyro) */ #define ADIS16060_TEMP_OUT 0x10 /* Measure Temperature */ @@ -39,9 +42,11 @@ struct adis16060_state { static struct iio_dev *adis16060_iio_dev; -static int adis16060_spi_write(struct iio_dev *indio_dev, u8 val) +static int adis16060_spi_write(struct device *dev, + u8 val) { int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16060_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -52,9 +57,11 @@ static int adis16060_spi_write(struct iio_dev *indio_dev, u8 val) return ret; } -static int adis16060_spi_read(struct iio_dev *indio_dev, u16 *val) +static int adis16060_spi_read(struct device *dev, + u16 *val) { int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16060_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -75,69 +82,58 @@ static int adis16060_spi_read(struct iio_dev *indio_dev, u16 *val) return ret; } -static int adis16060_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) +static ssize_t adis16060_read(struct device *dev, + struct device_attribute *attr, + char *buf) { - u16 tval = 0; - int ret; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + u16 val = 0; + ssize_t ret; - switch (mask) { - case 0: - /* Take the iio_dev status lock */ - mutex_lock(&indio_dev->mlock); - ret = adis16060_spi_write(indio_dev, chan->address); - if (ret < 0) { - mutex_unlock(&indio_dev->mlock); - return ret; - } - ret = adis16060_spi_read(indio_dev, &tval); - mutex_unlock(&indio_dev->mlock); - *val = tval; - return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): - *val = -7; - *val2 = 461117; - return IIO_VAL_INT_PLUS_MICRO; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): - *val = 0; - *val2 = 34000; - return IIO_VAL_INT_PLUS_MICRO; - } + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); - return -EINVAL; + ret = adis16060_spi_write(dev, this_attr->address); + if (ret < 0) + goto error_ret; + ret = adis16060_spi_read(dev, &val); +error_ret: + mutex_unlock(&indio_dev->mlock); + + if (ret == 0) + return sprintf(buf, "%d\n", val); + else + return ret; } -static const struct iio_info adis16060_info = { - .read_raw = &adis16060_read_raw, - .driver_module = THIS_MODULE, +static IIO_DEV_ATTR_GYRO_Z(adis16060_read, ADIS16060_GYRO); +static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16060_read, NULL, + ADIS16060_TEMP_OUT); +static IIO_CONST_ATTR_TEMP_SCALE("34"); /* Milli degrees C */ +static IIO_CONST_ATTR_TEMP_OFFSET("-7461.117"); /* Milli degrees C */ +static IIO_DEV_ATTR_IN_RAW(0, adis16060_read, ADIS16060_AIN1); +static IIO_DEV_ATTR_IN_RAW(1, adis16060_read, ADIS16060_AIN2); +static IIO_CONST_ATTR(name, "adis16060"); + +static struct attribute *adis16060_attributes[] = { + &iio_dev_attr_gyro_z_raw.dev_attr.attr, + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_dev_attr_in0_raw.dev_attr.attr, + &iio_dev_attr_in1_raw.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + NULL }; -static const struct iio_chan_spec adis16060_channels[] = { - { - .type = IIO_GYRO, - .modified = 1, - .channel2 = IIO_MOD_Z, - .address = ADIS16060_GYRO, - }, { - .type = IIO_IN, - .indexed = 1, - .channel = 0, - .address = ADIS16060_AIN1, - }, { - .type = IIO_IN, - .indexed = 1, - .channel = 1, - .address = ADIS16060_AIN2, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - .address = ADIS16060_TEMP_OUT, - } +static const struct attribute_group adis16060_attribute_group = { + .attrs = adis16060_attributes, +}; + +static const struct iio_info adis16060_info = { + .attrs = &adis16060_attribute_group, + .driver_module = THIS_MODULE, }; static int __devinit adis16060_r_probe(struct spi_device *spi) @@ -158,12 +154,9 @@ static int __devinit adis16060_r_probe(struct spi_device *spi) st->us_r = spi; mutex_init(&st->buf_lock); - indio_dev->name = spi->dev.driver->name; indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16060_info; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = adis16060_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16060_channels); ret = iio_device_register(indio_dev); if (ret) diff --git a/trunk/drivers/staging/iio/gyro/adis16080_core.c b/trunk/drivers/staging/iio/gyro/adis16080_core.c index bd3eb1019867..ad2db4d723df 100644 --- a/trunk/drivers/staging/iio/gyro/adis16080_core.c +++ b/trunk/drivers/staging/iio/gyro/adis16080_core.c @@ -16,6 +16,8 @@ #include "../iio.h" #include "../sysfs.h" +#include "gyro.h" +#include "../adc/adc.h" #define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */ #define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */ @@ -42,10 +44,11 @@ struct adis16080_state { u8 buf[2] ____cacheline_aligned; }; -static int adis16080_spi_write(struct iio_dev *indio_dev, +static int adis16080_spi_write(struct device *dev, u16 val) { int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16080_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -58,10 +61,11 @@ static int adis16080_spi_write(struct iio_dev *indio_dev, return ret; } -static int adis16080_spi_read(struct iio_dev *indio_dev, - u16 *val) +static int adis16080_spi_read(struct device *dev, + u16 *val) { int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16080_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); @@ -75,62 +79,50 @@ static int adis16080_spi_read(struct iio_dev *indio_dev, return ret; } -static int adis16080_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) +static ssize_t adis16080_read(struct device *dev, + struct device_attribute *attr, + char *buf) { - int ret = -EINVAL; - u16 ut; - /* Take the iio_dev status lock */ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + u16 val = 0; + ssize_t ret; + /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); - switch (mask) { - case 0: - ret = adis16080_spi_write(indio_dev, - chan->address | - ADIS16080_DIN_WRITE); - if (ret < 0) - break; - ret = adis16080_spi_read(indio_dev, &ut); - if (ret < 0) - break; - *val = ut; - ret = IIO_VAL_INT; - break; - } + ret = adis16080_spi_write(dev, + this_attr->address | ADIS16080_DIN_WRITE); + if (ret < 0) + goto error_ret; + ret = adis16080_spi_read(dev, &val); +error_ret: mutex_unlock(&indio_dev->mlock); - return ret; + if (ret == 0) + return sprintf(buf, "%d\n", val); + else + return ret; } +static IIO_DEV_ATTR_GYRO_Z(adis16080_read, ADIS16080_DIN_GYRO); +static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16080_read, NULL, + ADIS16080_DIN_TEMP); +static IIO_DEV_ATTR_IN_RAW(0, adis16080_read, ADIS16080_DIN_AIN1); +static IIO_DEV_ATTR_IN_RAW(1, adis16080_read, ADIS16080_DIN_AIN2); + +static struct attribute *adis16080_attributes[] = { + &iio_dev_attr_gyro_z_raw.dev_attr.attr, + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_dev_attr_in0_raw.dev_attr.attr, + &iio_dev_attr_in1_raw.dev_attr.attr, + NULL +}; -static const struct iio_chan_spec adis16080_channels[] = { - { - .type = IIO_GYRO, - .modified = 1, - .channel2 = IIO_MOD_Z, - .address = ADIS16080_DIN_GYRO, - }, { - .type = IIO_IN, - .indexed = 1, - .channel = 0, - .address = ADIS16080_DIN_AIN1, - }, { - .type = IIO_IN, - .indexed = 1, - .channel = 1, - .address = ADIS16080_DIN_AIN2, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .address = ADIS16080_DIN_TEMP, - } +static const struct attribute_group adis16080_attribute_group = { + .attrs = adis16080_attributes, }; static const struct iio_info adis16080_info = { - .read_raw = &adis16080_read_raw, + .attrs = &adis16080_attribute_group, .driver_module = THIS_MODULE, }; @@ -155,8 +147,6 @@ static int __devinit adis16080_probe(struct spi_device *spi) mutex_init(&st->buf_lock); indio_dev->name = spi->dev.driver->name; - indio_dev->channels = adis16080_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16080_channels); indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16080_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/trunk/drivers/staging/iio/gyro/adis16130_core.c b/trunk/drivers/staging/iio/gyro/adis16130_core.c index 5ddaefcf94a0..c80e908d8acf 100644 --- a/trunk/drivers/staging/iio/gyro/adis16130_core.c +++ b/trunk/drivers/staging/iio/gyro/adis16130_core.c @@ -17,6 +17,8 @@ #include "../iio.h" #include "../sysfs.h" +#include "gyro.h" +#include "../adc/adc.h" #define ADIS16130_CON 0x0 #define ADIS16130_CON_RD (1 << 6) @@ -39,77 +41,140 @@ /** * struct adis16130_state - device instance specific data * @us: actual spi_device to write data + * @mode: 24 bits (1) or 16 bits (0) * @buf_lock: mutex to protect tx and rx * @buf: unified tx/rx buffer **/ struct adis16130_state { struct spi_device *us; + u32 mode; struct mutex buf_lock; u8 buf[4] ____cacheline_aligned; }; -static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val) +static int adis16130_spi_write(struct device *dev, u8 reg_addr, + u8 val) { int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adis16130_state *st = iio_priv(indio_dev); - struct spi_message msg; - struct spi_transfer xfer = { - .tx_buf = st->buf, - .rx_buf = st->buf, - .len = 4, - }; mutex_lock(&st->buf_lock); + st->buf[0] = reg_addr; + st->buf[1] = val; - st->buf[0] = ADIS16130_CON_RD | reg_addr; - st->buf[1] = st->buf[2] = st->buf[3] = 0; + ret = spi_write(st->us, st->buf, 2); + mutex_unlock(&st->buf_lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->us, &msg); - ret = spi_read(st->us, st->buf, 4); + return ret; +} + +static int adis16130_spi_read(struct device *dev, u8 reg_addr, + u32 *val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16130_state *st = iio_priv(indio_dev); + + mutex_lock(&st->buf_lock); + + st->buf[0] = ADIS16130_CON_RD | reg_addr; + if (st->mode) + ret = spi_read(st->us, st->buf, 4); + else + ret = spi_read(st->us, st->buf, 3); + + if (ret == 0) { + if (st->mode) + *val = (st->buf[1] << 16) | + (st->buf[2] << 8) | + st->buf[3]; + else + *val = (st->buf[1] << 8) | st->buf[2]; + } - if (ret == 0) - *val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3]; mutex_unlock(&st->buf_lock); return ret; } -static int adis16130_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) +static ssize_t adis16130_val_read(struct device *dev, + struct device_attribute *attr, + char *buf) { - int ret; - u32 temp; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + u32 val; + ssize_t ret; /* Take the iio_dev status lock */ mutex_lock(&indio_dev->mlock); - ret = adis16130_spi_read(indio_dev, chan->address, &temp); + ret = adis16130_spi_read(dev, this_attr->address, &val); mutex_unlock(&indio_dev->mlock); - if (ret) + + if (ret == 0) + return sprintf(buf, "%d\n", val); + else return ret; - *val = temp; - return IIO_VAL_INT; } -static const struct iio_chan_spec adis16130_channels[] = { - { - .type = IIO_GYRO, - .modified = 1, - .channel2 = IIO_MOD_Z, - .address = ADIS16130_RATEDATA, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .address = ADIS16130_TEMPDATA, - } +static ssize_t adis16130_bitsmode_read(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16130_state *st = iio_priv(indio_dev); + + if (st->mode == 1) + return sprintf(buf, "s24\n"); + else + return sprintf(buf, "s16\n"); +} + +static ssize_t adis16130_bitsmode_write(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + u8 val; + + if (sysfs_streq(buf, "s16")) + val = 0; + else if (sysfs_streq(buf, "s24")) + val = 1; + else + return -EINVAL; + + ret = adis16130_spi_write(dev, ADIS16130_MODE, val); + + return ret ? ret : len; +} +static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16130_val_read, NULL, + ADIS16130_TEMPDATA); + +static IIO_DEV_ATTR_GYRO_Z(adis16130_val_read, ADIS16130_RATEDATA); + +static IIO_DEVICE_ATTR(gyro_z_type, S_IWUSR | S_IRUGO, adis16130_bitsmode_read, + adis16130_bitsmode_write, + ADIS16130_MODE); + +static IIO_CONST_ATTR(gyro_z_type_available, "s16 s24"); + +static struct attribute *adis16130_attributes[] = { + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_dev_attr_gyro_z_raw.dev_attr.attr, + &iio_dev_attr_gyro_z_type.dev_attr.attr, + &iio_const_attr_gyro_z_type_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16130_attribute_group = { + .attrs = adis16130_attributes, }; static const struct iio_info adis16130_info = { - .read_raw = &adis16130_read_raw, + .attrs = &adis16130_attribute_group, .driver_module = THIS_MODULE, }; @@ -131,11 +196,10 @@ static int __devinit adis16130_probe(struct spi_device *spi) st->us = spi; mutex_init(&st->buf_lock); indio_dev->name = spi->dev.driver->name; - indio_dev->channels = adis16130_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16130_channels); indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16130_info; indio_dev->modes = INDIO_DIRECT_MODE; + st->mode = 1; ret = iio_device_register(indio_dev); if (ret) diff --git a/trunk/drivers/staging/iio/gyro/adis16260_core.c b/trunk/drivers/staging/iio/gyro/adis16260_core.c index bc45228d0709..f2d43cfcc493 100644 --- a/trunk/drivers/staging/iio/gyro/adis16260_core.c +++ b/trunk/drivers/staging/iio/gyro/adis16260_core.c @@ -21,6 +21,8 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" +#include "../adc/adc.h" +#include "gyro.h" #include "adis16260.h" diff --git a/trunk/drivers/staging/iio/gyro/adis16260_ring.c b/trunk/drivers/staging/iio/gyro/adis16260_ring.c index 10f8a666226b..a4df8b32251e 100644 --- a/trunk/drivers/staging/iio/gyro/adis16260_ring.c +++ b/trunk/drivers/staging/iio/gyro/adis16260_ring.c @@ -1,12 +1,20 @@ #include +#include +#include +#include #include +#include #include #include #include +#include +#include #include "../iio.h" +#include "../sysfs.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "../accel/accel.h" +#include "../trigger.h" #include "adis16260.h" /** @@ -60,7 +68,7 @@ static int adis16260_read_ring_data(struct device *dev, u8 *rx) static irqreturn_t adis16260_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct adis16260_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; int i = 0; diff --git a/trunk/drivers/staging/iio/gyro/adis16260_trigger.c b/trunk/drivers/staging/iio/gyro/adis16260_trigger.c index 2f2b2160f44d..01094d0e714a 100644 --- a/trunk/drivers/staging/iio/gyro/adis16260_trigger.c +++ b/trunk/drivers/staging/iio/gyro/adis16260_trigger.c @@ -1,8 +1,14 @@ #include +#include +#include +#include #include +#include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../trigger.h" #include "adis16260.h" @@ -18,11 +24,6 @@ static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16260_set_irq(indio_dev, state); } -static const struct iio_trigger_ops adis16260_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16260_data_rdy_trigger_set_state, -}; - int adis16260_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -45,8 +46,9 @@ int adis16260_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->ops = &adis16260_trigger_ops; + st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; + st->trig->set_trigger_state = &adis16260_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/trunk/drivers/staging/iio/gyro/adxrs450_core.c b/trunk/drivers/staging/iio/gyro/adxrs450_core.c index f65ad4972630..7502a264770b 100644 --- a/trunk/drivers/staging/iio/gyro/adxrs450_core.c +++ b/trunk/drivers/staging/iio/gyro/adxrs450_core.c @@ -20,6 +20,8 @@ #include "../iio.h" #include "../sysfs.h" +#include "gyro.h" +#include "../adc/adc.h" #include "adxrs450.h" @@ -30,12 +32,26 @@ * Second register's address is reg_address + 1. * @val: somewhere to pass back the value read **/ -static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, - u8 reg_address, - u16 *val) +static int adxrs450_spi_read_reg_16(struct device *dev, + u8 reg_address, + u16 *val) { + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adxrs450_state *st = iio_priv(indio_dev); int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 4, + .cs_change = 1, + }, { + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 4, + }, + }; mutex_lock(&st->buf_lock); st->tx[0] = ADXRS450_READ_DATA | (reg_address >> 7); @@ -46,13 +62,10 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1)) st->tx[3] |= ADXRS450_P; - ret = spi_write(st->us, st->tx, 4); - if (ret) { - dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", - reg_address); - goto error_ret; - } - ret = spi_read(st->us, st->rx, 4); + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); if (ret) { dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", reg_address); @@ -73,12 +86,20 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, * Second register's address is reg_address + 1. * @val: value to be written. **/ -static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, - u8 reg_address, - u16 val) +static int adxrs450_spi_write_reg_16(struct device *dev, + u8 reg_address, + u16 val) { + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adxrs450_state *st = iio_priv(indio_dev); int ret; + struct spi_transfer xfers = { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 4, + }; mutex_lock(&st->buf_lock); st->tx[0] = ADXRS450_WRITE_DATA | reg_address >> 7; @@ -87,12 +108,14 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, st->tx[3] = val << 1; if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1)) - st->tx[3] |= ADXRS450_P; + st->tx[3] |= ADXRS450_P; - ret = spi_write(st->us, st->tx, 4); + spi_message_init(&msg); + spi_message_add_tail(&xfers, &msg); + ret = spi_sync(st->us, &msg); if (ret) dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", - reg_address); + reg_address); msleep(1); /* enforce sequential transfer delay 0.1ms */ mutex_unlock(&st->buf_lock); return ret; @@ -103,10 +126,24 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, * @dev: device associated with child of actual iio_dev * @val: somewhere to pass back the value read **/ -static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) +static int adxrs450_spi_sensor_data(struct device *dev, s16 *val) { + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adxrs450_state *st = iio_priv(indio_dev); int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 4, + .cs_change = 1, + }, { + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 4, + }, + }; mutex_lock(&st->buf_lock); st->tx[0] = ADXRS450_SENSOR_DATA; @@ -114,13 +151,10 @@ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) st->tx[2] = 0; st->tx[3] = 0; - ret = spi_write(st->us, st->tx, 4); - if (ret) { - dev_err(&st->us->dev, "Problem while reading sensor data\n"); - goto error_ret; - } - - ret = spi_read(st->us, st->rx, 4); + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); if (ret) { dev_err(&st->us->dev, "Problem while reading sensor data\n"); goto error_ret; @@ -172,12 +206,73 @@ static int adxrs450_spi_initial(struct adxrs450_state *st, return ret; } +static ssize_t adxrs450_read_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 t; + ret = adxrs450_spi_read_reg_16(dev, + ADXRS450_TEMP1, + &t); + if (ret) + return ret; + return sprintf(buf, "%d\n", t >> 7); +} + +static ssize_t adxrs450_read_quad(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + s16 t; + ret = adxrs450_spi_read_reg_16(dev, + ADXRS450_QUAD1, + &t); + if (ret) + return ret; + return sprintf(buf, "%d\n", t); +} + +static ssize_t adxrs450_write_dnc(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = adxrs450_spi_write_reg_16(dev, + ADXRS450_DNC1, + val & 0x3FF); +error_ret: + return ret ? ret : len; +} + +static ssize_t adxrs450_read_sensor_data(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + s16 t; + + ret = adxrs450_spi_sensor_data(dev, &t); + if (ret) + return ret; + + return sprintf(buf, "%d\n", t); +} + /* Recommended Startup Sequence by spec */ static int adxrs450_initial_setup(struct iio_dev *indio_dev) { u32 t; u16 data; int ret; + struct device *dev = &indio_dev->dev; struct adxrs450_state *st = iio_priv(indio_dev); msleep(ADXRS450_STARTUP_DELAY*2); @@ -210,23 +305,23 @@ static int adxrs450_initial_setup(struct iio_dev *indio_dev) return -EIO; } - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data); + ret = adxrs450_spi_read_reg_16(dev, ADXRS450_FAULT1, &data); if (ret) return ret; if (data & 0x0fff) { dev_err(&st->us->dev, "The device is not in normal status!\n"); return -EINVAL; } - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_PID1, &data); + ret = adxrs450_spi_read_reg_16(dev, ADXRS450_PID1, &data); if (ret) return ret; dev_info(&st->us->dev, "The Part ID is 0x%x\n", data); - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNL, &data); + ret = adxrs450_spi_read_reg_16(dev, ADXRS450_SNL, &data); if (ret) return ret; t = data; - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNH, &data); + ret = adxrs450_spi_read_reg_16(dev, ADXRS450_SNH, &data); if (ret) return ret; t |= data << 16; @@ -235,91 +330,29 @@ static int adxrs450_initial_setup(struct iio_dev *indio_dev) return 0; } -static int adxrs450_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - int ret; - switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): - ret = adxrs450_spi_write_reg_16(indio_dev, - ADXRS450_DNC1, - val & 0x3FF); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static int adxrs450_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - int ret; - s16 t; - u16 ut; - switch (mask) { - case 0: - switch (chan->type) { - case IIO_GYRO: - ret = adxrs450_spi_sensor_data(indio_dev, &t); - if (ret) - break; - *val = t; - ret = IIO_VAL_INT; - break; - case IIO_TEMP: - ret = adxrs450_spi_read_reg_16(indio_dev, - ADXRS450_TEMP1, &ut); - if (ret) - break; - *val = ut; - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - break; - case (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE): - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); - if (ret) - break; - *val = t; - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} +static IIO_DEV_ATTR_GYRO_Z(adxrs450_read_sensor_data, 0); +static IIO_DEV_ATTR_TEMP_RAW(adxrs450_read_temp); +static IIO_DEV_ATTR_GYRO_Z_QUADRATURE_CORRECTION(adxrs450_read_quad, 0); +static IIO_DEV_ATTR_GYRO_Z_CALIBBIAS(S_IWUSR, + NULL, adxrs450_write_dnc, 0); +static IIO_CONST_ATTR(name, "adxrs450"); + +static struct attribute *adxrs450_attributes[] = { + &iio_dev_attr_gyro_z_raw.dev_attr.attr, + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_dev_attr_gyro_z_quadrature_correction_raw.dev_attr.attr, + &iio_dev_attr_gyro_z_calibbias.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + NULL +}; -static const struct iio_chan_spec adxrs450_channels[] = { - { - .type = IIO_GYRO, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE) - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - } +static const struct attribute_group adxrs450_attribute_group = { + .attrs = adxrs450_attributes, }; static const struct iio_info adxrs450_info = { + .attrs = &adxrs450_attribute_group, .driver_module = THIS_MODULE, - .read_raw = &adxrs450_read_raw, - .write_raw = &adxrs450_write_raw, }; static int __devinit adxrs450_probe(struct spi_device *spi) @@ -343,9 +376,6 @@ static int __devinit adxrs450_probe(struct spi_device *spi) indio_dev->dev.parent = &spi->dev; indio_dev->info = &adxrs450_info; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = adxrs450_channels; - indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); - indio_dev->name = spi->dev.driver->name; ret = iio_device_register(indio_dev); if (ret) diff --git a/trunk/drivers/staging/iio/gyro/gyro.h b/trunk/drivers/staging/iio/gyro/gyro.h new file mode 100644 index 000000000000..b5495613407b --- /dev/null +++ b/trunk/drivers/staging/iio/gyro/gyro.h @@ -0,0 +1,85 @@ + +#include "../sysfs.h" + +/* Gyroscope types of attribute */ + +#define IIO_CONST_ATTR_GYRO_OFFSET(_string) \ + IIO_CONST_ATTR(gyro_offset, _string) + +#define IIO_DEV_ATTR_GYRO_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_X_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_x_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_Y_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_y_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_Z_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_z_offset, _mode, _show, _store, _addr) + +#define IIO_CONST_ATTR_GYRO_SCALE(_string) \ + IIO_CONST_ATTR(gyro_scale, _string) + +#define IIO_DEV_ATTR_GYRO_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_scale, S_IRUGO, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_X_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_x_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_Y_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_y_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_Z_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_z_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_CALIBBIAS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_calibbias, S_IRUGO, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_X_CALIBBIAS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_x_calibbias, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_Y_CALIBBIAS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_y_calibbias, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_Z_CALIBBIAS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_z_calibbias, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_CALIBSCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_calibscale, S_IRUGO, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_X_CALIBSCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_x_calibscale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_Y_CALIBSCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_y_calibscale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_Z_CALIBSCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(gyro_z_calibscale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_GYRO_Z_QUADRATURE_CORRECTION(_show, _addr) \ + IIO_DEVICE_ATTR(gyro_z_quadrature_correction_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_GYRO(_show, _addr) \ + IIO_DEVICE_ATTR(gyro_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_GYRO_X(_show, _addr) \ + IIO_DEVICE_ATTR(gyro_x_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_GYRO_Y(_show, _addr) \ + IIO_DEVICE_ATTR(gyro_y_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_GYRO_Z(_show, _addr) \ + IIO_DEVICE_ATTR(gyro_z_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ANGL(_show, _addr) \ + IIO_DEVICE_ATTR(angl_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ANGL_X(_show, _addr) \ + IIO_DEVICE_ATTR(angl_x_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ANGL_Y(_show, _addr) \ + IIO_DEVICE_ATTR(angl_y_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ANGL_Z(_show, _addr) \ + IIO_DEVICE_ATTR(angl_z_raw, S_IRUGO, _show, NULL, _addr) diff --git a/trunk/drivers/staging/iio/iio.h b/trunk/drivers/staging/iio/iio.h index 753f769736ef..7a6ce4d0fb7b 100644 --- a/trunk/drivers/staging/iio/iio.h +++ b/trunk/drivers/staging/iio/iio.h @@ -1,4 +1,3 @@ - /* The industrial I/O core * * Copyright (c) 2008 Jonathan Cameron @@ -23,6 +22,11 @@ * Currently assumes nano seconds. */ +/* Event interface flags */ +#define IIO_BUSY_BIT_POS 1 + +/* naughty temporary hack to match these against the event version + - need to flattern these together */ enum iio_chan_type { /* real channel types */ IIO_IN, @@ -71,8 +75,6 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_PEAK_SEPARATE, IIO_CHAN_INFO_PEAK_SCALE_SHARED, IIO_CHAN_INFO_PEAK_SCALE_SEPARATE, - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED, - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE, }; /** @@ -119,14 +121,26 @@ struct iio_chan_spec { u8 storagebits; u8 shift; } scan_type; - long info_mask; - long event_mask; - char *extend_name; + const long info_mask; + const long event_mask; + const char *extend_name; unsigned processed_val:1; unsigned modified:1; unsigned indexed:1; }; - +/* Meant for internal use only */ +void __iio_device_attr_deinit(struct device_attribute *dev_attr); +int __iio_device_attr_init(struct device_attribute *dev_attr, + const char *postfix, + struct iio_chan_spec const *chan, + ssize_t (*readfunc)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*writefunc)(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len), + bool generic); #define IIO_ST(si, rb, sb, sh) \ { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } @@ -149,6 +163,20 @@ struct iio_chan_spec { { .type = IIO_TIMESTAMP, .channel = -1, \ .scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) } +int __iio_add_chan_devattr(const char *postfix, + const char *group, + struct iio_chan_spec const *chan, + ssize_t (*func)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*writefunc)(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len), + int mask, + bool generic, + struct device *dev, + struct list_head *attr_list); /** * iio_get_time_ns() - utility function to get a time stamp for events etc **/ @@ -248,6 +276,7 @@ struct iio_info { /** * struct iio_dev - industrial I/O device * @id: [INTERN] used to identify device internally + * @dev_data: [DRIVER] device specific data * @modes: [DRIVER] operating modes supported by device * @currentmode: [DRIVER] current operating mode * @dev: [DRIVER] device structure, should be assigned a parent @@ -267,7 +296,7 @@ struct iio_info { **/ struct iio_dev { int id; - + void *dev_data; int modes; int currentmode; struct device dev; @@ -313,6 +342,13 @@ int iio_push_event(struct iio_dev *dev_info, int ev_code, s64 timestamp); +/* Used to distinguish between bipolar and unipolar scan elemenents. + * Whilst this may seem obvious, we may well want to change the representation + * in the future!*/ +#define IIO_SIGNED(a) -(a) +#define IIO_UNSIGNED(a) (a) + +extern dev_t iio_devt; extern struct bus_type iio_bus_type; /** @@ -325,6 +361,25 @@ static inline void iio_put_device(struct iio_dev *dev) put_device(&dev->dev); }; +/** + * to_iio_dev() - get iio_dev for which we have the struct device + * @d: the struct device + **/ +static inline struct iio_dev *to_iio_dev(struct device *d) +{ + return container_of(d, struct iio_dev, dev); +}; + +/** + * iio_dev_get_devdata() - helper function gets device specific data + * @d: the iio_dev associated with the device + **/ +static inline void *iio_dev_get_devdata(struct iio_dev *d) +{ + return d->dev_data; +} + + /* Can we make this smaller? */ #define IIO_ALIGN L1_CACHE_BYTES /** @@ -350,6 +405,22 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv) **/ void iio_free_device(struct iio_dev *dev); +/** + * iio_put() - internal module reference count reduce + **/ +void iio_put(void); + +/** + * iio_get() - internal module reference count increase + **/ +void iio_get(void); + +/** + * iio_device_get_chrdev_minor() - get an unused minor number + **/ +int iio_device_get_chrdev_minor(void); +void iio_device_free_chrdev_minor(int val); + /** * iio_ring_enabled() - helper function to test if any form of ring is enabled * @dev_info: IIO device info structure for device @@ -361,4 +432,8 @@ static inline bool iio_ring_enabled(struct iio_dev *dev_info) | INDIO_RING_HARDWARE_BUFFER); }; +struct ida; + +int iio_get_new_ida_val(struct ida *this_ida); +void iio_free_ida_val(struct ida *this_ida, int id); #endif /* _INDUSTRIAL_IO_H_ */ diff --git a/trunk/drivers/staging/iio/iio_core.h b/trunk/drivers/staging/iio/iio_core.h deleted file mode 100644 index 00e894d50e74..000000000000 --- a/trunk/drivers/staging/iio/iio_core.h +++ /dev/null @@ -1,48 +0,0 @@ -/* The industrial I/O core function defs. - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * These definitions are meant for use only within the IIO core, not indvidual - * drivers. - */ - -/** - * iio_device_get_chrdev_minor() - get an unused minor number - **/ -int iio_device_get_chrdev_minor(void); -void iio_device_free_chrdev_minor(int val); - - -/** - * iio_put() - internal module reference count reduce - **/ -void iio_put(void); - -/** - * iio_get() - internal module reference count increase - **/ -void iio_get(void); - -extern dev_t iio_devt; - -int __iio_add_chan_devattr(const char *postfix, - const char *group, - struct iio_chan_spec const *chan, - ssize_t (*func)(struct device *dev, - struct device_attribute *attr, - char *buf), - ssize_t (*writefunc)(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len), - int mask, - bool generic, - struct device *dev, - struct list_head *attr_list); - -/* Event interface flags */ -#define IIO_BUSY_BIT_POS 1 diff --git a/trunk/drivers/staging/iio/iio_core_trigger.h b/trunk/drivers/staging/iio/iio_core_trigger.h deleted file mode 100644 index 3e5195a82bca..000000000000 --- a/trunk/drivers/staging/iio/iio_core_trigger.h +++ /dev/null @@ -1,46 +0,0 @@ - -/* The industrial I/O core, trigger consumer handling functions - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#ifdef CONFIG_IIO_TRIGGER -/** - * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers - * @dev_info: iio_dev associated with the device that will consume the trigger - **/ -int iio_device_register_trigger_consumer(struct iio_dev *dev_info); - -/** - * iio_device_unregister_trigger_consumer() - reverse the registration process - * @dev_info: iio_dev associated with the device that consumed the trigger - **/ -void iio_device_unregister_trigger_consumer(struct iio_dev *dev_info); - -#else - -/** - * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers - * @dev_info: iio_dev associated with the device that will consume the trigger - **/ -static int iio_device_register_trigger_consumer(struct iio_dev *dev_info) -{ - return 0; -}; - -/** - * iio_device_unregister_trigger_consumer() - reverse the registration process - * @dev_info: iio_dev associated with the device that consumed the trigger - **/ -static void iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) -{ -}; - -#endif /* CONFIG_TRIGGER_CONSUMER */ - - - diff --git a/trunk/drivers/staging/iio/impedance-analyzer/Kconfig b/trunk/drivers/staging/iio/impedance-analyzer/Kconfig deleted file mode 100644 index 9e91a9bc8bfe..000000000000 --- a/trunk/drivers/staging/iio/impedance-analyzer/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# -# Impedance Converter, Network Analyzer drivers -# -comment "Network Analyzer, Impedance Converters" - -config AD5933 - tristate "Analog Devices AD5933, AD5934 driver" - depends on I2C - select IIO_RING_BUFFER - select IIO_SW_RING - help - Say yes here to build support for Analog Devices Impedance Converter, - Network Analyzer, AD5933/4, provides direct access via sysfs. - - To compile this driver as a module, choose M here: the - module will be called ad5933. diff --git a/trunk/drivers/staging/iio/impedance-analyzer/Makefile b/trunk/drivers/staging/iio/impedance-analyzer/Makefile deleted file mode 100644 index 7604d786583e..000000000000 --- a/trunk/drivers/staging/iio/impedance-analyzer/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for Impedance Converter, Network Analyzer drivers -# - -obj-$(CONFIG_AD5933) += ad5933.o diff --git a/trunk/drivers/staging/iio/impedance-analyzer/ad5933.c b/trunk/drivers/staging/iio/impedance-analyzer/ad5933.c deleted file mode 100644 index acc0e69cb588..000000000000 --- a/trunk/drivers/staging/iio/impedance-analyzer/ad5933.c +++ /dev/null @@ -1,818 +0,0 @@ -/* - * AD5933 AD5934 Impedance Converter, Network Analyzer - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../iio.h" -#include "../sysfs.h" -#include "../ring_generic.h" -#include "../ring_sw.h" - -#include "ad5933.h" - -/* AD5933/AD5934 Registers */ -#define AD5933_REG_CONTROL_HB 0x80 /* R/W, 2 bytes */ -#define AD5933_REG_CONTROL_LB 0x81 /* R/W, 2 bytes */ -#define AD5933_REG_FREQ_START 0x82 /* R/W, 3 bytes */ -#define AD5933_REG_FREQ_INC 0x85 /* R/W, 3 bytes */ -#define AD5933_REG_INC_NUM 0x88 /* R/W, 2 bytes, 9 bit */ -#define AD5933_REG_SETTLING_CYCLES 0x8A /* R/W, 2 bytes */ -#define AD5933_REG_STATUS 0x8F /* R, 1 byte */ -#define AD5933_REG_TEMP_DATA 0x92 /* R, 2 bytes*/ -#define AD5933_REG_REAL_DATA 0x94 /* R, 2 bytes*/ -#define AD5933_REG_IMAG_DATA 0x96 /* R, 2 bytes*/ - -/* AD5933_REG_CONTROL_HB Bits */ -#define AD5933_CTRL_INIT_START_FREQ (0x1 << 4) -#define AD5933_CTRL_START_SWEEP (0x2 << 4) -#define AD5933_CTRL_INC_FREQ (0x3 << 4) -#define AD5933_CTRL_REPEAT_FREQ (0x4 << 4) -#define AD5933_CTRL_MEASURE_TEMP (0x9 << 4) -#define AD5933_CTRL_POWER_DOWN (0xA << 4) -#define AD5933_CTRL_STANDBY (0xB << 4) - -#define AD5933_CTRL_RANGE_2000mVpp (0x0 << 1) -#define AD5933_CTRL_RANGE_200mVpp (0x1 << 1) -#define AD5933_CTRL_RANGE_400mVpp (0x2 << 1) -#define AD5933_CTRL_RANGE_1000mVpp (0x3 << 1) -#define AD5933_CTRL_RANGE(x) ((x) << 1) - -#define AD5933_CTRL_PGA_GAIN_1 (0x1 << 0) -#define AD5933_CTRL_PGA_GAIN_5 (0x0 << 0) - -/* AD5933_REG_CONTROL_LB Bits */ -#define AD5933_CTRL_RESET (0x1 << 4) -#define AD5933_CTRL_INT_SYSCLK (0x0 << 3) -#define AD5933_CTRL_EXT_SYSCLK (0x1 << 3) - -/* AD5933_REG_STATUS Bits */ -#define AD5933_STAT_TEMP_VALID (0x1 << 0) -#define AD5933_STAT_DATA_VALID (0x1 << 1) -#define AD5933_STAT_SWEEP_DONE (0x1 << 2) - -/* I2C Block Commands */ -#define AD5933_I2C_BLOCK_WRITE 0xA0 -#define AD5933_I2C_BLOCK_READ 0xA1 -#define AD5933_I2C_ADDR_POINTER 0xB0 - -/* Device Specs */ -#define AD5933_INT_OSC_FREQ_Hz 16776000 -#define AD5933_MAX_OUTPUT_FREQ_Hz 100000 -#define AD5933_MAX_RETRIES 100 - -#define AD5933_OUT_RANGE 1 -#define AD5933_OUT_RANGE_AVAIL 2 -#define AD5933_OUT_SETTLING_CYCLES 3 -#define AD5933_IN_PGA_GAIN 4 -#define AD5933_IN_PGA_GAIN_AVAIL 5 -#define AD5933_FREQ_POINTS 6 - -#define AD5933_POLL_TIME_ms 10 -#define AD5933_INIT_EXCITATION_TIME_ms 100 - -struct ad5933_state { - struct i2c_client *client; - struct regulator *reg; - struct ad5933_platform_data *pdata; - struct delayed_work work; - unsigned long mclk_hz; - unsigned char ctrl_hb; - unsigned char ctrl_lb; - unsigned range_avail[4]; - unsigned short vref_mv; - unsigned short settling_cycles; - unsigned short freq_points; - unsigned freq_start; - unsigned freq_inc; - unsigned state; - unsigned poll_time_jiffies; -}; - -static struct ad5933_platform_data ad5933_default_pdata = { - .vref_mv = 3300, -}; - -static struct iio_chan_spec ad5933_channels[] = { - IIO_CHAN(IIO_TEMP, 0, 1, 1, NULL, 0, 0, 0, - 0, AD5933_REG_TEMP_DATA, IIO_ST('s', 14, 16, 0), 0), - /* Ring Channels */ - IIO_CHAN(IIO_IN, 0, 1, 0, "real_raw", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - AD5933_REG_REAL_DATA, 0, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, "imag_raw", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - AD5933_REG_IMAG_DATA, 1, IIO_ST('s', 16, 16, 0), 0), -}; - -static int ad5933_i2c_write(struct i2c_client *client, - u8 reg, u8 len, u8 *data) -{ - int ret; - - while (len--) { - ret = i2c_smbus_write_byte_data(client, reg++, *data++); - if (ret < 0) { - dev_err(&client->dev, "I2C write error\n"); - return ret; - } - } - return 0; -} - -static int ad5933_i2c_read(struct i2c_client *client, - u8 reg, u8 len, u8 *data) -{ - int ret; - - while (len--) { - ret = i2c_smbus_read_byte_data(client, reg++); - if (ret < 0) { - dev_err(&client->dev, "I2C read error\n"); - return ret; - } - *data++ = ret; - } - return 0; -} - -static int ad5933_cmd(struct ad5933_state *st, unsigned char cmd) -{ - unsigned char dat = st->ctrl_hb | cmd; - - return ad5933_i2c_write(st->client, - AD5933_REG_CONTROL_HB, 1, &dat); -} - -static int ad5933_reset(struct ad5933_state *st) -{ - unsigned char dat = st->ctrl_lb | AD5933_CTRL_RESET; - return ad5933_i2c_write(st->client, - AD5933_REG_CONTROL_LB, 1, &dat); -} - -static int ad5933_wait_busy(struct ad5933_state *st, unsigned char event) -{ - unsigned char val, timeout = AD5933_MAX_RETRIES; - int ret; - - while (timeout--) { - ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &val); - if (ret < 0) - return ret; - if (val & event) - return val; - cpu_relax(); - mdelay(1); - } - - return -EAGAIN; -} - -static int ad5933_set_freq(struct ad5933_state *st, - unsigned reg, unsigned long freq) -{ - unsigned long long freqreg; - union { - u32 d32; - u8 d8[4]; - } dat; - - freqreg = (u64) freq * (u64) (1 << 27); - do_div(freqreg, st->mclk_hz / 4); - - switch (reg) { - case AD5933_REG_FREQ_START: - st->freq_start = freq; - break; - case AD5933_REG_FREQ_INC: - st->freq_inc = freq; - break; - default: - return -EINVAL; - } - - dat.d32 = cpu_to_be32(freqreg); - return ad5933_i2c_write(st->client, reg, 3, &dat.d8[1]); -} - -static int ad5933_setup(struct ad5933_state *st) -{ - unsigned short dat; - int ret; - - ret = ad5933_reset(st); - if (ret < 0) - return ret; - - ret = ad5933_set_freq(st, AD5933_REG_FREQ_START, 10000); - if (ret < 0) - return ret; - - ret = ad5933_set_freq(st, AD5933_REG_FREQ_INC, 200); - if (ret < 0) - return ret; - - st->settling_cycles = 10; - dat = cpu_to_be16(st->settling_cycles); - - ret = ad5933_i2c_write(st->client, - AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); - if (ret < 0) - return ret; - - st->freq_points = 100; - dat = cpu_to_be16(st->freq_points); - - return ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2, (u8 *)&dat); -} - -static void ad5933_calc_out_ranges(struct ad5933_state *st) -{ - int i; - unsigned normalized_3v3[4] = {1980, 198, 383, 970}; - - for (i = 0; i < 4; i++) - st->range_avail[i] = normalized_3v3[i] * st->vref_mv / 3300; - -} - -/* - * handles: AD5933_REG_FREQ_START and AD5933_REG_FREQ_INC - */ - -static ssize_t ad5933_show_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5933_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - unsigned long long freqreg; - union { - u32 d32; - u8 d8[4]; - } dat; - - mutex_lock(&dev_info->mlock); - ret = ad5933_i2c_read(st->client, this_attr->address, 3, &dat.d8[1]); - mutex_unlock(&dev_info->mlock); - if (ret < 0) - return ret; - - freqreg = be32_to_cpu(dat.d32) & 0xFFFFFF; - - freqreg = (u64) freqreg * (u64) (st->mclk_hz / 4); - do_div(freqreg, 1 << 27); - - return sprintf(buf, "%d\n", (int) freqreg); -} - -static ssize_t ad5933_store_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5933_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - long val; - int ret; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - return ret; - - if (val > AD5933_MAX_OUTPUT_FREQ_Hz) - return -EINVAL; - - mutex_lock(&dev_info->mlock); - ret = ad5933_set_freq(st, this_attr->address, val); - mutex_unlock(&dev_info->mlock); - - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(out0_freq_start, S_IRUGO | S_IWUSR, - ad5933_show_frequency, - ad5933_store_frequency, - AD5933_REG_FREQ_START); - -static IIO_DEVICE_ATTR(out0_freq_increment, S_IRUGO | S_IWUSR, - ad5933_show_frequency, - ad5933_store_frequency, - AD5933_REG_FREQ_INC); - -static ssize_t ad5933_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5933_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret = 0, len = 0; - - mutex_lock(&dev_info->mlock); - switch (this_attr->address) { - case AD5933_OUT_RANGE: - len = sprintf(buf, "%d\n", - st->range_avail[(st->ctrl_hb >> 1) & 0x3]); - break; - case AD5933_OUT_RANGE_AVAIL: - len = sprintf(buf, "%d %d %d %d\n", st->range_avail[0], - st->range_avail[3], st->range_avail[2], - st->range_avail[1]); - break; - case AD5933_OUT_SETTLING_CYCLES: - len = sprintf(buf, "%d\n", st->settling_cycles); - break; - case AD5933_IN_PGA_GAIN: - len = sprintf(buf, "%s\n", - (st->ctrl_hb & AD5933_CTRL_PGA_GAIN_1) ? - "1" : "0.2"); - break; - case AD5933_IN_PGA_GAIN_AVAIL: - len = sprintf(buf, "1 0.2\n"); - break; - case AD5933_FREQ_POINTS: - len = sprintf(buf, "%d\n", st->freq_points); - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&dev_info->mlock); - return ret ? ret : len; -} - -static ssize_t ad5933_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *dev_info = dev_get_drvdata(dev); - struct ad5933_state *st = iio_priv(dev_info); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - long val; - int i, ret = 0; - unsigned short dat; - - if (this_attr->address != AD5933_IN_PGA_GAIN) { - ret = strict_strtol(buf, 10, &val); - if (ret) - return ret; - } - - mutex_lock(&dev_info->mlock); - switch (this_attr->address) { - case AD5933_OUT_RANGE: - for (i = 0; i < 4; i++) - if (val == st->range_avail[i]) { - st->ctrl_hb &= ~AD5933_CTRL_RANGE(0x3); - st->ctrl_hb |= AD5933_CTRL_RANGE(i); - ret = ad5933_cmd(st, 0); - break; - } - ret = -EINVAL; - break; - case AD5933_IN_PGA_GAIN: - if (sysfs_streq(buf, "1")) { - st->ctrl_hb |= AD5933_CTRL_PGA_GAIN_1; - } else if (sysfs_streq(buf, "0.2")) { - st->ctrl_hb &= ~AD5933_CTRL_PGA_GAIN_1; - } else { - ret = -EINVAL; - break; - } - ret = ad5933_cmd(st, 0); - break; - case AD5933_OUT_SETTLING_CYCLES: - val = clamp(val, 0L, 0x7FFL); - st->settling_cycles = val; - - /* 2x, 4x handling, see datasheet */ - if (val > 511) - val = (val >> 1) | (1 << 9); - else if (val > 1022) - val = (val >> 2) | (3 << 9); - - dat = cpu_to_be16(val); - ret = ad5933_i2c_write(st->client, - AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); - break; - case AD5933_FREQ_POINTS: - val = clamp(val, 0L, 511L); - st->freq_points = val; - - dat = cpu_to_be16(val); - ret = ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2, - (u8 *)&dat); - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&dev_info->mlock); - return ret ? ret : len; -} - -static IIO_DEVICE_ATTR(out0_scale, S_IRUGO | S_IWUSR, - ad5933_show, - ad5933_store, - AD5933_OUT_RANGE); - -static IIO_DEVICE_ATTR(out0_scale_available, S_IRUGO, - ad5933_show, - NULL, - AD5933_OUT_RANGE_AVAIL); - -static IIO_DEVICE_ATTR(in0_scale, S_IRUGO | S_IWUSR, - ad5933_show, - ad5933_store, - AD5933_IN_PGA_GAIN); - -static IIO_DEVICE_ATTR(in0_scale_available, S_IRUGO, - ad5933_show, - NULL, - AD5933_IN_PGA_GAIN_AVAIL); - -static IIO_DEVICE_ATTR(out0_freq_points, S_IRUGO | S_IWUSR, - ad5933_show, - ad5933_store, - AD5933_FREQ_POINTS); - -static IIO_DEVICE_ATTR(out0_settling_cycles, S_IRUGO | S_IWUSR, - ad5933_show, - ad5933_store, - AD5933_OUT_SETTLING_CYCLES); - -/* note: - * ideally we would handle the scale attributes via the iio_info - * (read|write)_raw methods, however this part is a untypical since we - * don't create dedicated sysfs channel attributes for out0 and in0. - */ -static struct attribute *ad5933_attributes[] = { - &iio_dev_attr_out0_scale.dev_attr.attr, - &iio_dev_attr_out0_scale_available.dev_attr.attr, - &iio_dev_attr_out0_freq_start.dev_attr.attr, - &iio_dev_attr_out0_freq_increment.dev_attr.attr, - &iio_dev_attr_out0_freq_points.dev_attr.attr, - &iio_dev_attr_out0_settling_cycles.dev_attr.attr, - &iio_dev_attr_in0_scale.dev_attr.attr, - &iio_dev_attr_in0_scale_available.dev_attr.attr, - NULL -}; - -static const struct attribute_group ad5933_attribute_group = { - .attrs = ad5933_attributes, -}; - -static int ad5933_read_raw(struct iio_dev *dev_info, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - struct ad5933_state *st = iio_priv(dev_info); - unsigned short dat; - int ret = -EINVAL; - - mutex_lock(&dev_info->mlock); - switch (m) { - case 0: - if (iio_ring_enabled(dev_info)) { - ret = -EBUSY; - goto out; - } - ret = ad5933_cmd(st, AD5933_CTRL_MEASURE_TEMP); - if (ret < 0) - goto out; - ret = ad5933_wait_busy(st, AD5933_STAT_TEMP_VALID); - if (ret < 0) - goto out; - - ret = ad5933_i2c_read(st->client, - AD5933_REG_TEMP_DATA, 2, - (u8 *)&dat); - if (ret < 0) - goto out; - mutex_unlock(&dev_info->mlock); - ret = be16_to_cpu(dat); - /* Temp in Milli degrees Celsius */ - if (ret < 8192) - *val = ret * 1000 / 32; - else - *val = (ret - 16384) * 1000 / 32; - - return IIO_VAL_INT; - } - -out: - mutex_unlock(&dev_info->mlock); - return ret; -} - -static const struct iio_info ad5933_info = { - .read_raw = &ad5933_read_raw, - .attrs = &ad5933_attribute_group, - .driver_module = THIS_MODULE, -}; - -static int ad5933_ring_preenable(struct iio_dev *indio_dev) -{ - struct ad5933_state *st = iio_priv(indio_dev); - struct iio_ring_buffer *ring = indio_dev->ring; - size_t d_size; - int ret; - - if (!ring->scan_count) - return -EINVAL; - - d_size = ring->scan_count * - ad5933_channels[1].scan_type.storagebits / 8; - - if (indio_dev->ring->access->set_bytes_per_datum) - indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, - d_size); - - ret = ad5933_reset(st); - if (ret < 0) - return ret; - - ret = ad5933_cmd(st, AD5933_CTRL_STANDBY); - if (ret < 0) - return ret; - - ret = ad5933_cmd(st, AD5933_CTRL_INIT_START_FREQ); - if (ret < 0) - return ret; - - st->state = AD5933_CTRL_INIT_START_FREQ; - - return 0; -} - -static int ad5933_ring_postenable(struct iio_dev *indio_dev) -{ - struct ad5933_state *st = iio_priv(indio_dev); - - /* AD5933_CTRL_INIT_START_FREQ: - * High Q complex circuits require a long time to reach steady state. - * To facilitate the measurement of such impedances, this mode allows - * the user full control of the settling time requirement before - * entering start frequency sweep mode where the impedance measurement - * takes place. In this mode the impedance is excited with the - * programmed start frequency (ad5933_ring_preenable), - * but no measurement takes place. - */ - - schedule_delayed_work(&st->work, - msecs_to_jiffies(AD5933_INIT_EXCITATION_TIME_ms)); - return 0; -} - -static int ad5933_ring_postdisable(struct iio_dev *indio_dev) -{ - struct ad5933_state *st = iio_priv(indio_dev); - - cancel_delayed_work_sync(&st->work); - return ad5933_cmd(st, AD5933_CTRL_POWER_DOWN); -} - -static const struct iio_ring_setup_ops ad5933_ring_setup_ops = { - .preenable = &ad5933_ring_preenable, - .postenable = &ad5933_ring_postenable, - .postdisable = &ad5933_ring_postdisable, -}; - -static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - indio_dev->ring = iio_sw_rb_allocate(indio_dev); - if (!indio_dev->ring) - return -ENOMEM; - - /* Effectively select the ring buffer implementation */ - indio_dev->ring->access = &ring_sw_access_funcs; - - /* Ring buffer functions - here trigger setup related */ - indio_dev->ring->setup_ops = &ad5933_ring_setup_ops; - - indio_dev->modes |= INDIO_RING_HARDWARE_BUFFER; - - return 0; -} - -static void ad5933_work(struct work_struct *work) -{ - struct ad5933_state *st = container_of(work, - struct ad5933_state, work.work); - struct iio_dev *indio_dev = i2c_get_clientdata(st->client); - struct iio_ring_buffer *ring = indio_dev->ring; - signed short buf[2]; - unsigned char status; - - mutex_lock(&indio_dev->mlock); - if (st->state == AD5933_CTRL_INIT_START_FREQ) { - /* start sweep */ - ad5933_cmd(st, AD5933_CTRL_START_SWEEP); - st->state = AD5933_CTRL_START_SWEEP; - schedule_delayed_work(&st->work, st->poll_time_jiffies); - mutex_unlock(&indio_dev->mlock); - return; - } - - ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); - - if (status & AD5933_STAT_DATA_VALID) { - ad5933_i2c_read(st->client, - (ring->scan_mask & (1 << 0)) ? - AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA, - ring->scan_count * 2, (u8 *)buf); - - if (ring->scan_count == 2) { - buf[0] = be16_to_cpu(buf[0]); - buf[1] = be16_to_cpu(buf[1]); - } else { - buf[0] = be16_to_cpu(buf[0]); - } - /* save datum to the ring */ - ring->access->store_to(ring, (u8 *)buf, iio_get_time_ns()); - } else { - /* no data available - try again later */ - schedule_delayed_work(&st->work, st->poll_time_jiffies); - mutex_unlock(&indio_dev->mlock); - return; - } - - if (status & AD5933_STAT_SWEEP_DONE) { - /* last sample received - power down do nothing until - * the ring enable is toggled */ - ad5933_cmd(st, AD5933_CTRL_POWER_DOWN); - } else { - /* we just received a valid datum, move on to the next */ - ad5933_cmd(st, AD5933_CTRL_INC_FREQ); - schedule_delayed_work(&st->work, st->poll_time_jiffies); - } - - mutex_unlock(&indio_dev->mlock); -} - -static int __devinit ad5933_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret, regdone = 0, voltage_uv = 0; - struct ad5933_platform_data *pdata = client->dev.platform_data; - struct ad5933_state *st; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); - if (indio_dev == NULL) - return -ENOMEM; - - st = iio_priv(indio_dev); - i2c_set_clientdata(client, indio_dev); - st->client = client; - - if (!pdata) - st->pdata = &ad5933_default_pdata; - else - st->pdata = pdata; - - st->reg = regulator_get(&client->dev, "vcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - goto error_put_reg; - voltage_uv = regulator_get_voltage(st->reg); - } - - if (voltage_uv) - st->vref_mv = voltage_uv / 1000; - else - st->vref_mv = st->pdata->vref_mv; - - if (st->pdata->ext_clk_Hz) { - st->mclk_hz = st->pdata->ext_clk_Hz; - st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK; - } else { - st->mclk_hz = AD5933_INT_OSC_FREQ_Hz; - st->ctrl_lb = AD5933_CTRL_INT_SYSCLK; - } - - ad5933_calc_out_ranges(st); - INIT_DELAYED_WORK(&st->work, ad5933_work); - st->poll_time_jiffies = msecs_to_jiffies(AD5933_POLL_TIME_ms); - - indio_dev->dev.parent = &client->dev; - indio_dev->info = &ad5933_info; - indio_dev->name = id->name; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = ad5933_channels; - indio_dev->num_channels = 1; /* only register temp0_input */ - - ret = ad5933_register_ring_funcs_and_init(indio_dev); - if (ret) - goto error_disable_reg; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_unreg_ring; - regdone = 1; - - /* skip temp0_input, register in0_(real|imag)_raw */ - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - &ad5933_channels[1], - 2); - if (ret) - goto error_unreg_ring; - - /* enable both REAL and IMAG channels by default */ - iio_scan_mask_set(indio_dev->ring, 0); - iio_scan_mask_set(indio_dev->ring, 1); - - ret = ad5933_setup(st); - if (ret) - goto error_uninitialize_ring; - - return 0; - -error_uninitialize_ring: - iio_ring_buffer_unregister(indio_dev->ring); -error_unreg_ring: - iio_sw_rb_free(indio_dev->ring); -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); -error_put_reg: - if (!IS_ERR(st->reg)) - regulator_put(st->reg); - - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); - - return ret; -} - -static __devexit int ad5933_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ad5933_state *st = iio_priv(indio_dev); - - iio_ring_buffer_unregister(indio_dev->ring); - iio_sw_rb_free(indio_dev->ring); - if (!IS_ERR(st->reg)) { - regulator_disable(st->reg); - regulator_put(st->reg); - } - iio_device_unregister(indio_dev); - - return 0; -} - -static const struct i2c_device_id ad5933_id[] = { - { "ad5933", 0 }, - { "ad5934", 0 }, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ad5933_id); - -static struct i2c_driver ad5933_driver = { - .driver = { - .name = "ad5933", - }, - .probe = ad5933_probe, - .remove = __devexit_p(ad5933_remove), - .id_table = ad5933_id, -}; - -static __init int ad5933_init(void) -{ - return i2c_add_driver(&ad5933_driver); -} -module_init(ad5933_init); - -static __exit void ad5933_exit(void) -{ - i2c_del_driver(&ad5933_driver); -} -module_exit(ad5933_exit); - -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD5933 Impedance Conv. Network Analyzer"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/impedance-analyzer/ad5933.h b/trunk/drivers/staging/iio/impedance-analyzer/ad5933.h deleted file mode 100644 index b140e42d67cf..000000000000 --- a/trunk/drivers/staging/iio/impedance-analyzer/ad5933.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * AD5933 AD5934 Impedance Converter, Network Analyzer - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#ifndef IIO_ADC_AD5933_H_ -#define IIO_ADC_AD5933_H_ - -/* - * TODO: struct ad5933_platform_data needs to go into include/linux/iio - */ - -/** - * struct ad5933_platform_data - platform specific data - * @ext_clk_Hz: the external clock frequency in Hz, if not set - * the driver uses the internal clock (16.776 MHz) - * @vref_mv: the external reference voltage in millivolt - */ - -struct ad5933_platform_data { - unsigned long ext_clk_Hz; - unsigned short vref_mv; -}; - -#endif /* IIO_ADC_AD5933_H_ */ diff --git a/trunk/drivers/staging/iio/imu/adis16400_core.c b/trunk/drivers/staging/iio/imu/adis16400_core.c index 371eb0104b40..a2c3b67dcbdf 100644 --- a/trunk/drivers/staging/iio/imu/adis16400_core.c +++ b/trunk/drivers/staging/iio/imu/adis16400_core.c @@ -29,13 +29,17 @@ #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" +#include "../accel/accel.h" +#include "../adc/adc.h" +#include "../gyro/gyro.h" +#include "../magnetometer/magnet.h" + #include "adis16400.h" #define DRIVER_NAME "adis16400" enum adis16400_chip_variant { ADIS16300, - ADIS16344, ADIS16350, ADIS16360, ADIS16362, @@ -146,6 +150,8 @@ static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev, mutex_lock(&st->buf_lock); st->tx[0] = ADIS16400_READ_REG(lower_reg_address); st->tx[1] = 0; + st->tx[2] = 0; + st->tx[3] = 0; spi_message_init(&msg); spi_message_add_tail(&xfers[0], &msg); @@ -234,18 +240,17 @@ static ssize_t adis16400_write_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - bool val; - int ret; - - ret = strtobool(buf, &val); - if (ret < 0) - return ret; - if (val) - ret = adis16400_reset(dev_get_drvdata(dev)); - if (ret < 0) - return ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); - return len; + if (len < 1) + return -1; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return adis16400_reset(indio_dev); + } + return -1; } int adis16400_set_irq(struct iio_dev *indio_dev, bool enable) @@ -690,38 +695,6 @@ static struct iio_chan_spec adis16300_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(14) }; -static const struct iio_chan_spec adis16344_channels[] = { - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_x, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_y, ADIS16400_SCAN_GYRO_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Z, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - gyro_z, ADIS16400_SCAN_GYRO_Z, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_x, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_y, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), - accel_z, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0), - IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), - temp0, ADIS16350_SCAN_TEMP_X, IIO_ST('s', 12, 16, 0), 0), - IIO_CHAN_SOFT_TIMESTAMP(12) -}; - static struct attribute *adis16400_attributes[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, @@ -746,16 +719,6 @@ static struct adis16400_chip_info adis16400_chips[] = { (1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) | (1 << 14), }, - [ADIS16344] = { - .channels = adis16344_channels, - .num_channels = ARRAY_SIZE(adis16344_channels), - .gyro_scale_micro = 873, - .accel_scale_micro = 981, - .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) | - (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) | - (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | - (1 << ADIS16400_SCAN_ACC_Z), - }, [ADIS16350] = { .channels = adis16350_channels, .num_channels = ARRAY_SIZE(adis16350_channels), @@ -911,7 +874,6 @@ static int adis16400_remove(struct spi_device *spi) static const struct spi_device_id adis16400_id[] = { {"adis16300", ADIS16300}, - {"adis16344", ADIS16344}, {"adis16350", ADIS16350}, {"adis16354", ADIS16350}, {"adis16355", ADIS16350}, diff --git a/trunk/drivers/staging/iio/imu/adis16400_ring.c b/trunk/drivers/staging/iio/imu/adis16400_ring.c index 3fc24037db29..3612373ddede 100644 --- a/trunk/drivers/staging/iio/imu/adis16400_ring.c +++ b/trunk/drivers/staging/iio/imu/adis16400_ring.c @@ -1,13 +1,21 @@ #include +#include +#include +#include #include +#include #include #include #include +#include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "../accel/accel.h" +#include "../trigger.h" #include "adis16400.h" /** @@ -111,7 +119,7 @@ static int adis16350_spi_read_all(struct device *dev, u8 *rx) static irqreturn_t adis16400_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct adis16400_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; int i = 0, j, ret = 0; diff --git a/trunk/drivers/staging/iio/imu/adis16400_trigger.c b/trunk/drivers/staging/iio/imu/adis16400_trigger.c index 3860d92f1ae7..c6ec41a02a69 100644 --- a/trunk/drivers/staging/iio/imu/adis16400_trigger.c +++ b/trunk/drivers/staging/iio/imu/adis16400_trigger.c @@ -1,8 +1,14 @@ #include +#include +#include +#include #include +#include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../trigger.h" #include "adis16400.h" @@ -18,11 +24,6 @@ static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig, return adis16400_set_irq(indio_dev, state); } -static const struct iio_trigger_ops adis16400_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &adis16400_data_rdy_trigger_set_state, -}; - int adis16400_probe_trigger(struct iio_dev *indio_dev) { int ret; @@ -44,8 +45,9 @@ int adis16400_probe_trigger(struct iio_dev *indio_dev) if (ret) goto error_free_trig; st->trig->dev.parent = &st->us->dev; + st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; - st->trig->ops = &adis16400_trigger_ops; + st->trig->set_trigger_state = &adis16400_data_rdy_trigger_set_state; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/trunk/drivers/staging/iio/industrialio-core.c b/trunk/drivers/staging/iio/industrialio-core.c index ed8a6df5bf42..19819e7578c6 100644 --- a/trunk/drivers/staging/iio/industrialio-core.c +++ b/trunk/drivers/staging/iio/industrialio-core.c @@ -22,8 +22,7 @@ #include #include #include "iio.h" -#include "iio_core.h" -#include "iio_core_trigger.h" +#include "trigger_consumer.h" #define IIO_ID_PREFIX "device" #define IIO_ID_FORMAT IIO_ID_PREFIX "%d" @@ -36,6 +35,7 @@ static DEFINE_IDA(iio_chrdev_ida); static DEFINE_SPINLOCK(iio_ida_lock); dev_t iio_devt; +EXPORT_SYMBOL(iio_devt); #define IIO_DEV_MAX 256 struct bus_type iio_bus_type = { @@ -85,38 +85,8 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias", [IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw", [IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale", - [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED/2] - = "quadrature_correction_raw", }; -/* Return a negative errno on failure */ -static int iio_get_new_ida_val(struct ida *this_ida) -{ - int ret; - int val; - -ida_again: - if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0)) - return -ENOMEM; - - spin_lock(&iio_ida_lock); - ret = ida_get_new(this_ida, &val); - spin_unlock(&iio_ida_lock); - if (unlikely(ret == -EAGAIN)) - goto ida_again; - else if (unlikely(ret)) - return ret; - - return val; -} - -static void iio_free_ida_val(struct ida *this_ida, int id) -{ - spin_lock(&iio_ida_lock); - ida_remove(this_ida, id); - spin_unlock(&iio_ida_lock); -} - int iio_push_event(struct iio_dev *dev_info, int ev_line, int ev_code, @@ -276,18 +246,28 @@ static struct device_type iio_event_type = { int iio_device_get_chrdev_minor(void) { - int ret; + int ret, val; - ret = iio_get_new_ida_val(&iio_chrdev_ida); - if (ret < IIO_DEV_MAX) /* both errors and valid */ +ida_again: + if (unlikely(ida_pre_get(&iio_chrdev_ida, GFP_KERNEL) == 0)) + return -ENOMEM; + spin_lock(&iio_ida_lock); + ret = ida_get_new(&iio_chrdev_ida, &val); + spin_unlock(&iio_ida_lock); + if (unlikely(ret == -EAGAIN)) + goto ida_again; + else if (unlikely(ret)) return ret; - else + if (val > IIO_DEV_MAX) return -ENOMEM; + return val; } void iio_device_free_chrdev_minor(int val) { - iio_free_ida_val(&iio_chrdev_ida, val); + spin_lock(&iio_ida_lock); + ida_remove(&iio_chrdev_ida, val); + spin_unlock(&iio_ida_lock); } static int iio_setup_ev_int(struct iio_event_interface *ev_int, @@ -349,6 +329,24 @@ static void iio_free_ev_int(struct iio_event_interface *ev_int) put_device(&ev_int->dev); } +static int __init iio_dev_init(void) +{ + int err; + + err = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); + if (err < 0) + printk(KERN_ERR "%s: failed to allocate char dev region\n", + __FILE__); + + return err; +} + +static void __exit iio_dev_exit(void) +{ + if (iio_devt) + unregister_chrdev_region(iio_devt, IIO_DEV_MAX); +} + static int __init iio_init(void) { int ret; @@ -362,12 +360,9 @@ static int __init iio_init(void) goto error_nothing; } - ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); - if (ret < 0) { - printk(KERN_ERR "%s: failed to allocate char dev region\n", - __FILE__); + ret = iio_dev_init(); + if (ret < 0) goto error_unregister_bus_type; - } return 0; @@ -379,8 +374,7 @@ static int __init iio_init(void) static void __exit iio_exit(void) { - if (iio_devt) - unregister_chrdev_region(iio_devt, IIO_DEV_MAX); + iio_dev_exit(); bus_unregister(&iio_bus_type); } @@ -530,7 +524,6 @@ static int __iio_build_postfix(struct iio_chan_spec const *chan, return 0; } -static int __iio_device_attr_init(struct device_attribute *dev_attr, const char *postfix, struct iio_chan_spec const *chan, @@ -603,7 +596,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, return ret; } -static void __iio_device_attr_deinit(struct device_attribute *dev_attr) +void __iio_device_attr_deinit(struct device_attribute *dev_attr) { kfree(dev_attr->attr.name); } @@ -732,29 +725,19 @@ static ssize_t iio_show_dev_name(struct device *dev, static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); -static struct attribute *iio_base_dummy_attrs[] = { - NULL -}; -static struct attribute_group iio_base_dummy_group = { - .attrs = iio_base_dummy_attrs, -}; - static int iio_device_register_sysfs(struct iio_dev *dev_info) { int i, ret = 0; struct iio_dev_attr *p, *n; - if (dev_info->info->attrs) + if (dev_info->info->attrs) { ret = sysfs_create_group(&dev_info->dev.kobj, dev_info->info->attrs); - else - ret = sysfs_create_group(&dev_info->dev.kobj, - &iio_base_dummy_group); - - if (ret) { - dev_err(dev_info->dev.parent, - "Failed to register sysfs hooks\n"); - goto error_ret; + if (ret) { + dev_err(dev_info->dev.parent, + "Failed to register sysfs hooks\n"); + goto error_ret; + } } /* @@ -770,7 +753,7 @@ static int iio_device_register_sysfs(struct iio_dev *dev_info) if (ret < 0) goto error_clear_attrs; } - if (dev_info->name) { + if (dev_info->name) { ret = sysfs_add_file_to_group(&dev_info->dev.kobj, &dev_attr_name.attr, NULL); @@ -787,8 +770,6 @@ static int iio_device_register_sysfs(struct iio_dev *dev_info) } if (dev_info->info->attrs) sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs); - else - sysfs_remove_group(&dev_info->dev.kobj, &iio_base_dummy_group); error_ret: return ret; @@ -809,10 +790,38 @@ static void iio_device_unregister_sysfs(struct iio_dev *dev_info) if (dev_info->info->attrs) sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs); - else - sysfs_remove_group(&dev_info->dev.kobj, &iio_base_dummy_group); } +/* Return a negative errno on failure */ +int iio_get_new_ida_val(struct ida *this_ida) +{ + int ret; + int val; + +ida_again: + if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0)) + return -ENOMEM; + + spin_lock(&iio_ida_lock); + ret = ida_get_new(this_ida, &val); + spin_unlock(&iio_ida_lock); + if (unlikely(ret == -EAGAIN)) + goto ida_again; + else if (unlikely(ret)) + return ret; + + return val; +} +EXPORT_SYMBOL(iio_get_new_ida_val); + +void iio_free_ida_val(struct ida *this_ida, int id) +{ + spin_lock(&iio_ida_lock); + ida_remove(this_ida, id); + spin_unlock(&iio_ida_lock); +} +EXPORT_SYMBOL(iio_free_ida_val); + static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_THRESH] = "thresh", [IIO_EV_TYPE_MAG] = "mag", @@ -902,7 +911,7 @@ static int iio_device_add_event_sysfs(struct iio_dev *dev_info, struct iio_chan_spec const *chan) { - int ret = 0, i, mask = 0; + int ret = 0, i, mask; char *postfix; if (!chan->event_mask) return 0; @@ -935,7 +944,6 @@ static int iio_device_add_event_sysfs(struct iio_dev *dev_info, break; default: printk(KERN_INFO "currently unhandled type of event\n"); - continue; } ret = __iio_add_chan_devattr(postfix, NULL, @@ -981,17 +989,18 @@ static int iio_device_add_event_sysfs(struct iio_dev *dev_info, return ret; } -static inline void __iio_remove_event_config_attrs(struct iio_dev *dev_info, - int i) +static inline void __iio_remove_all_event_sysfs(struct iio_dev *dev_info, + const char *groupname, + int num) { struct iio_dev_attr *p, *n; list_for_each_entry_safe(p, n, - &dev_info->event_interfaces[i]. + &dev_info->event_interfaces[num]. dev_attr_list, l) { sysfs_remove_file_from_group(&dev_info - ->event_interfaces[i].dev.kobj, + ->event_interfaces[num].dev.kobj, &p->dev_attr.attr, - NULL); + groupname); kfree(p->dev_attr.attr.name); kfree(p); } @@ -1001,7 +1010,7 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i) { int j; int ret; - INIT_LIST_HEAD(&dev_info->event_interfaces[i].dev_attr_list); + INIT_LIST_HEAD(&dev_info->event_interfaces[0].dev_attr_list); /* Dynically created from the channels array */ if (dev_info->channels) { for (j = 0; j < dev_info->num_channels; j++) { @@ -1015,11 +1024,18 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i) return 0; error_clear_attrs: - __iio_remove_event_config_attrs(dev_info, i); + __iio_remove_all_event_sysfs(dev_info, NULL, i); return ret; } +static inline int __iio_remove_event_config_attrs(struct iio_dev *dev_info, + int i) +{ + __iio_remove_all_event_sysfs(dev_info, NULL, i); + return 0; +} + static int iio_device_register_eventset(struct iio_dev *dev_info) { int ret = 0, i, j; @@ -1045,7 +1061,7 @@ static int iio_device_register_eventset(struct iio_dev *dev_info) if (ret) { dev_err(&dev_info->dev, "Could not get chrdev interface\n"); - goto error_free_setup_event_lines; + goto error_free_setup_ev_ints; } dev_set_drvdata(&dev_info->event_interfaces[i].dev, @@ -1061,33 +1077,31 @@ static int iio_device_register_eventset(struct iio_dev *dev_info) if (ret) { dev_err(&dev_info->dev, "Failed to register sysfs for event attrs"); - iio_free_ev_int(&dev_info->event_interfaces[i]); - goto error_free_setup_event_lines; + goto error_remove_sysfs_interfaces; } + } + + for (i = 0; i < dev_info->info->num_interrupt_lines; i++) { ret = __iio_add_event_config_attrs(dev_info, i); - if (ret) { - if (dev_info->info->event_attrs != NULL) - sysfs_remove_group(&dev_info - ->event_interfaces[i] - .dev.kobj, - &dev_info->info - ->event_attrs[i]); - iio_free_ev_int(&dev_info->event_interfaces[i]); - goto error_free_setup_event_lines; - } + if (ret) + goto error_unregister_config_attrs; } return 0; -error_free_setup_event_lines: - for (j = 0; j < i; j++) { - __iio_remove_event_config_attrs(dev_info, j); +error_unregister_config_attrs: + for (j = 0; j < i; j++) + __iio_remove_event_config_attrs(dev_info, i); + i = dev_info->info->num_interrupt_lines - 1; +error_remove_sysfs_interfaces: + for (j = 0; j < i; j++) if (dev_info->info->event_attrs != NULL) sysfs_remove_group(&dev_info - ->event_interfaces[j].dev.kobj, - &dev_info->info->event_attrs[j]); + ->event_interfaces[j].dev.kobj, + &dev_info->info->event_attrs[j]); +error_free_setup_ev_ints: + for (j = 0; j < i; j++) iio_free_ev_int(&dev_info->event_interfaces[j]); - } kfree(dev_info->event_interfaces); error_ret: @@ -1106,16 +1120,17 @@ static void iio_device_unregister_eventset(struct iio_dev *dev_info) sysfs_remove_group(&dev_info ->event_interfaces[i].dev.kobj, &dev_info->info->event_attrs[i]); - iio_free_ev_int(&dev_info->event_interfaces[i]); } + + for (i = 0; i < dev_info->info->num_interrupt_lines; i++) + iio_free_ev_int(&dev_info->event_interfaces[i]); kfree(dev_info->event_interfaces); } static void iio_dev_release(struct device *device) { - struct iio_dev *dev_info = container_of(device, struct iio_dev, dev); iio_put(); - kfree(dev_info); + kfree(to_iio_dev(device)); } static struct device_type iio_dev_type = { diff --git a/trunk/drivers/staging/iio/industrialio-ring.c b/trunk/drivers/staging/iio/industrialio-ring.c index dce50b1a4ee9..843eb82a69ba 100644 --- a/trunk/drivers/staging/iio/industrialio-ring.c +++ b/trunk/drivers/staging/iio/industrialio-ring.c @@ -21,7 +21,6 @@ #include #include "iio.h" -#include "iio_core.h" #include "ring_generic.h" /** diff --git a/trunk/drivers/staging/iio/industrialio-trigger.c b/trunk/drivers/staging/iio/industrialio-trigger.c index f1ece8619e8d..90ca2df23eab 100644 --- a/trunk/drivers/staging/iio/industrialio-trigger.c +++ b/trunk/drivers/staging/iio/industrialio-trigger.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -17,8 +18,6 @@ #include "iio.h" #include "trigger.h" -#include "iio_core.h" -#include "iio_core_trigger.h" #include "trigger_consumer.h" /* RFC - Question of approach @@ -174,12 +173,13 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name, void iio_trigger_poll(struct iio_trigger *trig, s64 time) { int i; - if (!trig->use_count) + if (!trig->use_count) { for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) if (trig->subirqs[i].enabled) { trig->use_count++; generic_handle_irq(trig->subirq_base + i); } + } } EXPORT_SYMBOL(iio_trigger_poll); @@ -206,8 +206,8 @@ EXPORT_SYMBOL(iio_trigger_poll_chained); void iio_trigger_notify_done(struct iio_trigger *trig) { trig->use_count--; - if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) - if (trig->ops->try_reenable(trig)) { + if (trig->use_count == 0 && trig->try_reenable) + if (trig->try_reenable(trig)) { /* Missed and interrupt so launch new poll now */ iio_trigger_poll(trig, 0); } @@ -215,26 +215,6 @@ void iio_trigger_notify_done(struct iio_trigger *trig) EXPORT_SYMBOL(iio_trigger_notify_done); /* Trigger Consumer related functions */ -static int iio_trigger_get_irq(struct iio_trigger *trig) -{ - int ret; - mutex_lock(&trig->pool_lock); - ret = bitmap_find_free_region(trig->pool, - CONFIG_IIO_CONSUMERS_PER_TRIGGER, - ilog2(1)); - mutex_unlock(&trig->pool_lock); - if (ret >= 0) - ret += trig->subirq_base; - - return ret; -} - -static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) -{ - mutex_lock(&trig->pool_lock); - clear_bit(irq - trig->subirq_base, trig->pool); - mutex_unlock(&trig->pool_lock); -} /* Complexity in here. With certain triggers (datardy) an acknowledgement * may be needed if the pollfuncs do not include the data read for the @@ -243,45 +223,44 @@ static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) * the relevant function is in there may be the best option. */ /* Worth protecting against double additions?*/ -static int iio_trigger_attach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) +int iio_trigger_attach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) { int ret = 0; bool notinuse = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); - /* Prevent the module being removed whilst attached to a trigger */ - __module_get(pf->indio_dev->info->driver_module); pf->irq = iio_trigger_get_irq(trig); ret = request_threaded_irq(pf->irq, pf->h, pf->thread, pf->type, pf->name, pf); - if (trig->ops && trig->ops->set_trigger_state && notinuse) - ret = trig->ops->set_trigger_state(trig, true); + if (trig->set_trigger_state && notinuse) + ret = trig->set_trigger_state(trig, true); return ret; } +EXPORT_SYMBOL(iio_trigger_attach_poll_func); -static int iio_trigger_dettach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) +int iio_trigger_dettach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) { int ret = 0; bool no_other_users = (bitmap_weight(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER) == 1); - if (trig->ops && trig->ops->set_trigger_state && no_other_users) { - ret = trig->ops->set_trigger_state(trig, false); + if (trig->set_trigger_state && no_other_users) { + ret = trig->set_trigger_state(trig, false); if (ret) goto error_ret; } iio_trigger_put_irq(trig, pf->irq); free_irq(pf->irq, pf); - module_put(pf->indio_dev->info->driver_module); error_ret: return ret; } +EXPORT_SYMBOL(iio_trigger_dettach_poll_func); irqreturn_t iio_pollfunc_store_time(int irq, void *p) { @@ -295,7 +274,7 @@ struct iio_poll_func *iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), irqreturn_t (*thread)(int irq, void *p), int type, - struct iio_dev *indio_dev, + void *private, const char *fmt, ...) { @@ -315,7 +294,7 @@ struct iio_poll_func pf->h = h; pf->thread = thread; pf->type = type; - pf->indio_dev = indio_dev; + pf->private_data = private; return pf; } @@ -339,10 +318,12 @@ static ssize_t iio_trigger_read_current(struct device *dev, char *buf) { struct iio_dev *dev_info = dev_get_drvdata(dev); - + int len = 0; if (dev_info->trig) - return sprintf(buf, "%s\n", dev_info->trig->name); - return 0; + len = sprintf(buf, + "%s\n", + dev_info->trig->name); + return len; } /** @@ -377,8 +358,8 @@ static ssize_t iio_trigger_write_current(struct device *dev, return ret; } - if (trig && trig->ops && trig->ops->validate_device) { - ret = trig->ops->validate_device(trig, dev_info); + if (trig && trig->validate_device) { + ret = trig->validate_device(trig, dev_info); if (ret) return ret; } @@ -496,7 +477,6 @@ struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) IRQ_NOPROBE); } iio_get(); - get_device(&trig->dev); } return trig; } @@ -511,18 +491,20 @@ EXPORT_SYMBOL(iio_free_trigger); int iio_device_register_trigger_consumer(struct iio_dev *dev_info) { - return sysfs_create_group(&dev_info->dev.kobj, - &iio_trigger_consumer_attr_group); + int ret; + ret = sysfs_create_group(&dev_info->dev.kobj, + &iio_trigger_consumer_attr_group); + return ret; } +EXPORT_SYMBOL(iio_device_register_trigger_consumer); -void iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) +int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) { - /* Clean up and associated but not attached triggers references */ - if (dev_info->trig) - iio_put_trigger(dev_info->trig); sysfs_remove_group(&dev_info->dev.kobj, &iio_trigger_consumer_attr_group); + return 0; } +EXPORT_SYMBOL(iio_device_unregister_trigger_consumer); int iio_triggered_ring_postenable(struct iio_dev *indio_dev) { diff --git a/trunk/drivers/staging/iio/light/isl29018.c b/trunk/drivers/staging/iio/light/isl29018.c index da5bb33a66c1..426b6af70807 100644 --- a/trunk/drivers/staging/iio/light/isl29018.c +++ b/trunk/drivers/staging/iio/light/isl29018.c @@ -53,10 +53,6 @@ #define ISL29018_REG_ADD_DATA_MSB 0x03 #define ISL29018_MAX_REGS ISL29018_REG_ADD_DATA_MSB -#define ISL29018_REG_TEST 0x08 -#define ISL29018_TEST_SHIFT 0 -#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT) - struct isl29018_chip { struct i2c_client *client; struct mutex lock; @@ -461,48 +457,6 @@ static int isl29018_chip_init(struct i2c_client *client) memset(chip->reg_cache, 0, sizeof(chip->reg_cache)); - /* Code added per Intersil Application Note 1534: - * When VDD sinks to approximately 1.8V or below, some of - * the part's registers may change their state. When VDD - * recovers to 2.25V (or greater), the part may thus be in an - * unknown mode of operation. The user can return the part to - * a known mode of operation either by (a) setting VDD = 0V for - * 1 second or more and then powering back up with a slew rate - * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX - * conversions, clear the test registers, and then rewrite all - * registers to the desired values. - * ... - * FOR ISL29011, ISL29018, ISL29021, ISL29023 - * 1. Write 0x00 to register 0x08 (TEST) - * 2. Write 0x00 to register 0x00 (CMD1) - * 3. Rewrite all registers to the desired values - * - * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says - * the same thing EXCEPT the data sheet asks for a 1ms delay after - * writing the CMD1 register. - */ - status = isl29018_write_data(client, ISL29018_REG_TEST, 0, - ISL29018_TEST_MASK, ISL29018_TEST_SHIFT); - if (status < 0) { - dev_err(&client->dev, "Failed to clear isl29018 TEST reg." - "(%d)\n", status); - return status; - } - - /* See Intersil AN1534 comments above. - * "Operating Mode" (COMMAND1) register is reprogrammed when - * data is read from the device. - */ - status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1, 0, - 0xff, 0); - if (status < 0) { - dev_err(&client->dev, "Failed to clear isl29018 CMD1 reg." - "(%d)\n", status); - return status; - } - - msleep(1); /* per data sheet, page 10 */ - /* set defaults */ status = isl29018_set_range(client, chip->range, &new_range); if (status < 0) { diff --git a/trunk/drivers/staging/iio/light/tsl2563.c b/trunk/drivers/staging/iio/light/tsl2563.c index 665a7441b2ee..f25243b08472 100644 --- a/trunk/drivers/staging/iio/light/tsl2563.c +++ b/trunk/drivers/staging/iio/light/tsl2563.c @@ -596,7 +596,7 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private) struct tsl2563_chip *chip = iio_priv(dev_info); iio_push_event(dev_info, 0, - IIO_UNMOD_EVENT_CODE(IIO_LIGHT, + IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_LIGHT, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), @@ -697,7 +697,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client, struct tsl2563_platform_data *pdata = client->dev.platform_data; int err = 0; int ret; - u8 id = 0; + u8 id; indio_dev = iio_allocate_device(sizeof(*chip)); if (!indio_dev) diff --git a/trunk/drivers/staging/iio/light/tsl2583.c b/trunk/drivers/staging/iio/light/tsl2583.c index f75fe8563899..5694610da1ca 100644 --- a/trunk/drivers/staging/iio/light/tsl2583.c +++ b/trunk/drivers/staging/iio/light/tsl2583.c @@ -68,7 +68,7 @@ enum { TSL258X_CHIP_UNKNOWN = 0, TSL258X_CHIP_WORKING = 1, TSL258X_CHIP_SUSPENDED = 2 -}; +} TSL258X_CHIP_WORKING_STATUS; /* Per-device data */ struct taos_als_info { @@ -87,6 +87,7 @@ struct taos_settings { struct tsl2583_chip { struct mutex als_mutex; struct i2c_client *client; + struct iio_dev *iio_dev; struct taos_als_info als_cur_info; struct taos_settings taos_settings; int als_time_scale; @@ -113,7 +114,7 @@ struct taos_lux { /* This structure is intentionally large to accommodate updates via sysfs. */ /* Sized to 11 = max 10 segments + 1 termination segment */ /* Assumption is is one and only one type of glass used */ -static struct taos_lux taos_device_lux[11] = { +struct taos_lux taos_device_lux[11] = { { 9830, 8520, 15729 }, { 12452, 10807, 23344 }, { 14746, 6383, 11705 }, @@ -158,7 +159,8 @@ static void taos_defaults(struct tsl2583_chip *chip) static int taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len) { - int i, ret; + int ret; + int i; for (i = 0; i < len; i++) { /* select register to write */ @@ -189,47 +191,47 @@ taos_i2c_read(struct i2c_client *client, u8 reg, u8 *val, unsigned int len) * the array are then used along with the time scale factor array values, to * calculate the lux. */ -static int taos_get_lux(struct iio_dev *indio_dev) +static int taos_get_lux(struct i2c_client *client) { u16 ch0, ch1; /* separated ch0/ch1 data from device */ u32 lux; /* raw lux calculated from device data */ u32 ratio; u8 buf[5]; struct taos_lux *p; - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = i2c_get_clientdata(client); int i, ret; u32 ch0lux = 0; u32 ch1lux = 0; if (mutex_trylock(&chip->als_mutex) == 0) { - dev_info(&chip->client->dev, "taos_get_lux device is busy\n"); + dev_info(&client->dev, "taos_get_lux device is busy\n"); return chip->als_cur_info.lux; /* busy, so return LAST VALUE */ } if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { /* device is not enabled */ - dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n"); + dev_err(&client->dev, "taos_get_lux device is not enabled\n"); ret = -EBUSY ; goto out_unlock; } - ret = taos_i2c_read(chip->client, (TSL258X_CMD_REG), &buf[0], 1); + ret = taos_i2c_read(client, (TSL258X_CMD_REG), &buf[0], 1); if (ret < 0) { - dev_err(&chip->client->dev, "taos_get_lux failed to read CMD_REG\n"); + dev_err(&client->dev, "taos_get_lux failed to read CMD_REG\n"); goto out_unlock; } /* is data new & valid */ if (!(buf[0] & TSL258X_STA_ADC_INTR)) { - dev_err(&chip->client->dev, "taos_get_lux data not valid\n"); + dev_err(&client->dev, "taos_get_lux data not valid\n"); ret = chip->als_cur_info.lux; /* return LAST VALUE */ goto out_unlock; } for (i = 0; i < 4; i++) { int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i); - ret = taos_i2c_read(chip->client, reg, &buf[i], 1); + ret = taos_i2c_read(client, reg, &buf[i], 1); if (ret < 0) { - dev_err(&chip->client->dev, "taos_get_lux failed to read" + dev_err(&client->dev, "taos_get_lux failed to read" " register %x\n", reg); goto out_unlock; } @@ -237,12 +239,11 @@ static int taos_get_lux(struct iio_dev *indio_dev) /* clear status, really interrupt status (interrupts are off), but * we use the bit anyway - don't forget 0x80 - this is a command*/ - ret = i2c_smbus_write_byte(chip->client, - (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN | - TSL258X_CMD_ALS_INT_CLR)); + ret = i2c_smbus_write_byte(client, + (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN | TSL258X_CMD_ALS_INT_CLR)); if (ret < 0) { - dev_err(&chip->client->dev, + dev_err(&client->dev, "taos_i2c_write_command failed in taos_get_lux, err = %d\n", ret); goto out_unlock; /* have no data, so return failure */ @@ -284,7 +285,7 @@ static int taos_get_lux(struct iio_dev *indio_dev) /* note: lux is 31 bit max at this point */ if (ch1lux > ch0lux) { - dev_dbg(&chip->client->dev, "No Data - Return last value\n"); + dev_dbg(&client->dev, "No Data - Return last value\n"); ret = chip->als_cur_info.lux = 0; goto out_unlock; } @@ -318,56 +319,54 @@ static int taos_get_lux(struct iio_dev *indio_dev) * to derive actual lux). * Return updated gain_trim value. */ -static int taos_als_calibrate(struct iio_dev *indio_dev) +int taos_als_calibrate(struct i2c_client *client) { - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = i2c_get_clientdata(client); u8 reg_val; unsigned int gain_trim_val; int ret; int lux_val; - ret = i2c_smbus_write_byte(chip->client, - (TSL258X_CMD_REG | TSL258X_CNTRL)); + ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { - dev_err(&chip->client->dev, + dev_err(&client->dev, "taos_als_calibrate failed to reach the CNTRL register, ret=%d\n", ret); return ret; } - reg_val = i2c_smbus_read_byte(chip->client); + reg_val = i2c_smbus_read_byte(client); if ((reg_val & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) != (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) { - dev_err(&chip->client->dev, + dev_err(&client->dev, "taos_als_calibrate failed: device not powered on with ADC enabled\n"); return -1; } - ret = i2c_smbus_write_byte(chip->client, - (TSL258X_CMD_REG | TSL258X_CNTRL)); + ret = i2c_smbus_write_byte(client, (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { - dev_err(&chip->client->dev, + dev_err(&client->dev, "taos_als_calibrate failed to reach the STATUS register, ret=%d\n", ret); return ret; } - reg_val = i2c_smbus_read_byte(chip->client); + reg_val = i2c_smbus_read_byte(client); if ((reg_val & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) { - dev_err(&chip->client->dev, + dev_err(&client->dev, "taos_als_calibrate failed: STATUS - ADC not valid.\n"); return -ENODATA; } - lux_val = taos_get_lux(indio_dev); + lux_val = taos_get_lux(client); if (lux_val < 0) { - dev_err(&chip->client->dev, "taos_als_calibrate failed to get lux\n"); + dev_err(&client->dev, "taos_als_calibrate failed to get lux\n"); return lux_val; } gain_trim_val = (unsigned int) (((chip->taos_settings.als_cal_target) * chip->taos_settings.als_gain_trim) / lux_val); if ((gain_trim_val < 250) || (gain_trim_val > 4000)) { - dev_err(&chip->client->dev, + dev_err(&client->dev, "taos_als_calibrate failed: trim_val of %d is out of range\n", gain_trim_val); return -ENODATA; @@ -381,21 +380,21 @@ static int taos_als_calibrate(struct iio_dev *indio_dev) * Turn the device on. * Configuration must be set before calling this function. */ -static int taos_chip_on(struct iio_dev *indio_dev) +static int taos_chip_on(struct i2c_client *client) { int i; - int ret; + int ret = 0; u8 *uP; u8 utmp; int als_count; int als_time; - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = i2c_get_clientdata(client); /* and make sure we're not already on */ if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { /* if forcing a register update - turn off, then on */ - dev_info(&chip->client->dev, "device is already enabled\n"); - return -EINVAL; + dev_info(&client->dev, "device is already enabled\n"); + return -EINVAL; } /* determine als integration regster */ @@ -417,21 +416,20 @@ static int taos_chip_on(struct iio_dev *indio_dev) /* TSL258x Specific power-on / adc enable sequence * Power on the device 1st. */ utmp = TSL258X_CNTL_PWR_ON; - ret = i2c_smbus_write_byte_data(chip->client, - TSL258X_CMD_REG | TSL258X_CNTRL, utmp); + ret = i2c_smbus_write_byte_data(client, + TSL258X_CMD_REG | TSL258X_CNTRL, utmp); if (ret < 0) { - dev_err(&chip->client->dev, "taos_chip_on failed on CNTRL reg.\n"); + dev_err(&client->dev, "taos_chip_on failed on CNTRL reg.\n"); return -1; } /* Use the following shadow copy for our delay before enabling ADC. * Write all the registers. */ for (i = 0, uP = chip->taos_config; i < TSL258X_REG_MAX; i++) { - ret = i2c_smbus_write_byte_data(chip->client, - TSL258X_CMD_REG + i, + ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG + i, *uP++); if (ret < 0) { - dev_err(&chip->client->dev, + dev_err(&client->dev, "taos_chip_on failed on reg %d.\n", i); return -1; } @@ -441,11 +439,10 @@ static int taos_chip_on(struct iio_dev *indio_dev) /* NOW enable the ADC * initialize the desired mode of operation */ utmp = TSL258X_CNTL_PWR_ON | TSL258X_CNTL_ADC_ENBL; - ret = i2c_smbus_write_byte_data(chip->client, - TSL258X_CMD_REG | TSL258X_CNTRL, + ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL, utmp); if (ret < 0) { - dev_err(&chip->client->dev, "taos_chip_on failed on 2nd CTRL reg.\n"); + dev_err(&client->dev, "taos_chip_on failed on 2nd CTRL reg.\n"); return -1; } chip->taos_chip_status = TSL258X_CHIP_WORKING; @@ -453,26 +450,33 @@ static int taos_chip_on(struct iio_dev *indio_dev) return ret; } -static int taos_chip_off(struct iio_dev *indio_dev) +static int taos_chip_off(struct i2c_client *client) { - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = i2c_get_clientdata(client); int ret; /* turn device off */ chip->taos_chip_status = TSL258X_CHIP_SUSPENDED; - ret = i2c_smbus_write_byte_data(chip->client, - TSL258X_CMD_REG | TSL258X_CNTRL, + ret = i2c_smbus_write_byte_data(client, TSL258X_CMD_REG | TSL258X_CNTRL, 0x00); return ret; } /* Sysfs Interface Functions */ +static ssize_t taos_device_id(struct device *dev, +struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2583_chip *chip = indio_dev->dev_data; + + return sprintf(buf, "%s\n", chip->client->name); +} static ssize_t taos_power_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = indio_dev->dev_data; return sprintf(buf, "%d\n", chip->taos_chip_status); } @@ -481,15 +485,16 @@ static ssize_t taos_power_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) return -EINVAL; if (value == 0) - taos_chip_off(indio_dev); + taos_chip_off(chip->client); else - taos_chip_on(indio_dev); + taos_chip_on(chip->client); return len; } @@ -498,7 +503,7 @@ static ssize_t taos_gain_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = indio_dev->dev_data; char gain[4] = {0}; switch (chip->taos_settings.als_gain) { @@ -523,7 +528,7 @@ static ssize_t taos_gain_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -560,7 +565,7 @@ static ssize_t taos_als_time_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = indio_dev->dev_data; return sprintf(buf, "%d\n", chip->taos_settings.als_time); } @@ -569,7 +574,7 @@ static ssize_t taos_als_time_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -581,7 +586,7 @@ static ssize_t taos_als_time_store(struct device *dev, if (value % 50) return -EINVAL; - chip->taos_settings.als_time = value; + chip->taos_settings.als_time = value; return len; } @@ -597,7 +602,7 @@ static ssize_t taos_als_trim_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = indio_dev->dev_data; return sprintf(buf, "%d\n", chip->taos_settings.als_gain_trim); } @@ -606,7 +611,7 @@ static ssize_t taos_als_trim_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -622,7 +627,7 @@ static ssize_t taos_als_cal_target_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = indio_dev->dev_data; return sprintf(buf, "%d\n", chip->taos_settings.als_cal_target); } @@ -631,7 +636,7 @@ static ssize_t taos_als_cal_target_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) @@ -646,26 +651,27 @@ static ssize_t taos_als_cal_target_store(struct device *dev, static ssize_t taos_lux_show(struct device *dev, struct device_attribute *attr, char *buf) { - int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2583_chip *chip = indio_dev->dev_data; + int lux; - ret = taos_get_lux(dev_get_drvdata(dev)); - if (ret < 0) - return ret; + lux = taos_get_lux(chip->client); - return sprintf(buf, "%d\n", ret); + return sprintf(buf, "%d\n", lux); } static ssize_t taos_do_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2583_chip *chip = indio_dev->dev_data; unsigned long value; if (strict_strtoul(buf, 0, &value)) return -EINVAL; if (value == 1) - taos_als_calibrate(indio_dev); + taos_als_calibrate(chip->client); return len; } @@ -697,8 +703,8 @@ static ssize_t taos_luxtable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2583_chip *chip = iio_priv(indio_dev); - int value[ARRAY_SIZE(taos_device_lux)*3 + 1]; + struct tsl2583_chip *chip = indio_dev->dev_data; + int value[ARRAY_SIZE(taos_device_lux)]; int n; get_options(buf, ARRAY_SIZE(value), value); @@ -719,17 +725,18 @@ static ssize_t taos_luxtable_store(struct device *dev, } if (chip->taos_chip_status == TSL258X_CHIP_WORKING) - taos_chip_off(indio_dev); + taos_chip_off(chip->client); /* Zero out the table */ memset(taos_device_lux, 0, sizeof(taos_device_lux)); memcpy(taos_device_lux, &value[1], (value[0] * 4)); - taos_chip_on(indio_dev); + taos_chip_on(chip->client); return len; } +static DEVICE_ATTR(name, S_IRUGO, taos_device_id, NULL); static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, taos_power_state_show, taos_power_state_store); @@ -755,6 +762,7 @@ static DEVICE_ATTR(illuminance0_lux_table, S_IRUGO | S_IWUSR, taos_luxtable_show, taos_luxtable_store); static struct attribute *sysfs_attrs_ctrl[] = { + &dev_attr_name.attr, &dev_attr_power_state.attr, &dev_attr_illuminance0_calibscale.attr, /* Gain */ &dev_attr_illuminance0_calibscale_available.attr, @@ -790,10 +798,9 @@ static const struct iio_info tsl2583_info = { static int __devinit taos_probe(struct i2c_client *clientp, const struct i2c_device_id *idp) { - int i, ret; + int i, ret = 0; unsigned char buf[TSL258X_MAX_DEVICE_REGS]; - struct tsl2583_chip *chip; - struct iio_dev *indio_dev; + static struct tsl2583_chip *chip; if (!i2c_check_functionality(clientp->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { @@ -803,15 +810,12 @@ static int __devinit taos_probe(struct i2c_client *clientp, return -EOPNOTSUPP; } - indio_dev = iio_allocate_device(sizeof(*chip)); - if (indio_dev == NULL) { - ret = -ENOMEM; - dev_err(&clientp->dev, "iio allocation failed\n"); - goto fail1; - } - chip = iio_priv(indio_dev); + chip = kzalloc(sizeof(struct tsl2583_chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + chip->client = clientp; - i2c_set_clientdata(clientp, indio_dev); + i2c_set_clientdata(clientp, chip); mutex_init(&chip->als_mutex); chip->taos_chip_status = TSL258X_CHIP_UNKNOWN; @@ -823,14 +827,14 @@ static int __devinit taos_probe(struct i2c_client *clientp, if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd " "reg failed in taos_probe(), err = %d\n", ret); - goto fail2; + goto fail1; } ret = i2c_smbus_read_byte(clientp); if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_read_byte from " "reg failed in taos_probe(), err = %d\n", ret); - goto fail2; + goto fail1; } buf[i] = ret; } @@ -838,50 +842,58 @@ static int __devinit taos_probe(struct i2c_client *clientp, if (!taos_tsl258x_device(buf)) { dev_info(&clientp->dev, "i2c device found but does not match " "expected id in taos_probe()\n"); - goto fail2; + goto fail1; } ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL)); if (ret < 0) { dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg " "failed in taos_probe(), err = %d\n", ret); - goto fail2; + goto fail1; + } + + chip->iio_dev = iio_allocate_device(0); + if (!chip->iio_dev) { + ret = -ENOMEM; + dev_err(&clientp->dev, "iio allocation failed\n"); + goto fail1; } - indio_dev->info = &tsl2583_info; - indio_dev->dev.parent = &clientp->dev; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->name = chip->client->name; - ret = iio_device_register(indio_dev); + chip->iio_dev->info = &tsl2583_info; + chip->iio_dev->dev.parent = &clientp->dev; + chip->iio_dev->dev_data = (void *)(chip); + chip->iio_dev->modes = INDIO_DIRECT_MODE; + ret = iio_device_register(chip->iio_dev); if (ret) { dev_err(&clientp->dev, "iio registration failed\n"); - goto fail2; + goto fail1; } /* Load up the V2 defaults (these are hard coded defaults for now) */ taos_defaults(chip); /* Make sure the chip is on */ - taos_chip_on(indio_dev); + taos_chip_on(clientp); dev_info(&clientp->dev, "Light sensor found.\n"); + return 0; + fail1: - iio_free_device(indio_dev); -fail2: + kfree(chip); + return ret; } static int taos_suspend(struct i2c_client *client, pm_message_t state) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = i2c_get_clientdata(client); int ret = 0; mutex_lock(&chip->als_mutex); if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { - ret = taos_chip_off(indio_dev); + ret = taos_chip_off(client); chip->taos_chip_status = TSL258X_CHIP_SUSPENDED; } @@ -891,14 +903,13 @@ static int taos_suspend(struct i2c_client *client, pm_message_t state) static int taos_resume(struct i2c_client *client) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct tsl2583_chip *chip = iio_priv(indio_dev); + struct tsl2583_chip *chip = i2c_get_clientdata(client); int ret = 0; mutex_lock(&chip->als_mutex); if (chip->taos_chip_status == TSL258X_CHIP_SUSPENDED) - ret = taos_chip_on(indio_dev); + ret = taos_chip_on(client); mutex_unlock(&chip->als_mutex); return ret; @@ -907,8 +918,11 @@ static int taos_resume(struct i2c_client *client) static int __devexit taos_remove(struct i2c_client *client) { - iio_device_unregister(i2c_get_clientdata(client)); + struct tsl2583_chip *chip = i2c_get_clientdata(client); + + iio_device_unregister(chip->iio_dev); + kfree(chip); return 0; } diff --git a/trunk/drivers/staging/iio/magnetometer/ak8975.c b/trunk/drivers/staging/iio/magnetometer/ak8975.c index a17fa9f6a30e..33919e87e7ce 100644 --- a/trunk/drivers/staging/iio/magnetometer/ak8975.c +++ b/trunk/drivers/staging/iio/magnetometer/ak8975.c @@ -31,6 +31,7 @@ #include #include "../iio.h" +#include "magnet.h" /* * Register definitions, as well as various shifts and masks to get at the @@ -92,28 +93,38 @@ struct ak8975_data { struct mutex lock; u8 asa[3]; long raw_to_gauss[3]; - bool mode; + unsigned long mode; u8 reg_cache[AK8975_MAX_REGS]; int eoc_gpio; int eoc_irq; }; -static const int ak8975_index_to_reg[] = { - AK8975_REG_HXL, AK8975_REG_HYL, AK8975_REG_HZL, -}; - /* * Helper function to write to the I2C device's registers. */ static int ak8975_write_data(struct i2c_client *client, u8 reg, u8 val, u8 mask, u8 shift) { - struct ak8975_data *data = i2c_get_clientdata(client); u8 regval; - int ret; + struct i2c_msg msg; + u8 w_data[2]; + int ret = 0; + + struct ak8975_data *data = i2c_get_clientdata(client); + + regval = data->reg_cache[reg]; + regval &= ~mask; + regval |= val << shift; - regval = (data->reg_cache[reg] & ~mask) | (val << shift); - ret = i2c_smbus_write_byte_data(client, reg, regval); + w_data[0] = reg; + w_data[1] = regval; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + msg.buf = w_data; + + ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) { dev_err(&client->dev, "Write to device fails status %x\n", ret); return ret; @@ -129,20 +140,21 @@ static int ak8975_write_data(struct i2c_client *client, static int ak8975_read_data(struct i2c_client *client, u8 reg, u8 length, u8 *buffer) { + struct i2c_msg msg[2]; + u8 w_data[2]; int ret; - struct i2c_msg msg[2] = { - { - .addr = client->addr, - .flags = I2C_M_NOSTART, - .len = 1, - .buf = ®, - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = length, - .buf = buffer, - } - }; + + w_data[0] = reg; + + msg[0].addr = client->addr; + msg[0].flags = I2C_M_NOSTART; /* set repeated start and write */ + msg[0].len = 1; + msg[0].buf = w_data; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = length; + msg[1].buf = buffer; ret = i2c_transfer(client->adapter, msg, 2); if (ret < 0) { @@ -192,41 +204,8 @@ static int ak8975_setup(struct i2c_client *client) return ret; } -/* - * Precalculate scale factor (in Gauss units) for each axis and - * store in the device data. - * - * This scale factor is axis-dependent, and is derived from 3 calibration - * factors ASA(x), ASA(y), and ASA(z). - * - * These ASA values are read from the sensor device at start of day, and - * cached in the device context struct. - * - * Adjusting the flux value with the sensitivity adjustment value should be - * done via the following formula: - * - * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 ) - * - * where H is the raw value, ASA is the sensitivity adjustment, and Hadj - * is the resultant adjusted value. - * - * We reduce the formula to: - * - * Hadj = H * (ASA + 128) / 256 - * - * H is in the range of -4096 to 4095. The magnetometer has a range of - * +-1229uT. To go from the raw value to uT is: - * - * HuT = H * 1229/4096, or roughly, 3/10. - * - * Since 1uT = 100 gauss, our final scale factor becomes: - * - * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100 - * Hadj = H * ((ASA + 128) * 30 / 256 - * - * Since ASA doesn't change, we cache the resultant scale factor into the - * device context in ak8975_setup(). - */ + /* Precalculate scale factor for each axis and + store in the device data. */ data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8; data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8; data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8; @@ -243,7 +222,7 @@ static ssize_t show_mode(struct device *dev, struct device_attribute *devattr, struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ak8975_data *data = iio_priv(indio_dev); - return sprintf(buf, "%u\n", data->mode); + return sprintf(buf, "%lu\n", data->mode); } /* @@ -256,22 +235,26 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr, struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ak8975_data *data = iio_priv(indio_dev); struct i2c_client *client = data->client; - bool value; + unsigned long oval; int ret; /* Convert mode string and do some basic sanity checking on it. only 0 or 1 are valid. */ - ret = strtobool(buf, &value); - if (ret < 0) - return ret; + if (strict_strtoul(buf, 10, &oval)) + return -EINVAL; + + if (oval > 1) { + dev_err(dev, "mode value is not supported\n"); + return -EINVAL; + } mutex_lock(&data->lock); /* Write the mode to the device. */ - if (data->mode != value) { + if (data->mode != oval) { ret = ak8975_write_data(client, AK8975_REG_CNTL, - (u8)value, + (u8)oval, AK8975_REG_CNTL_MODE_MASK, AK8975_REG_CNTL_MODE_SHIFT); @@ -280,7 +263,7 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr, mutex_unlock(&data->lock); return ret; } - data->mode = value; + data->mode = oval; } mutex_unlock(&data->lock); @@ -288,6 +271,50 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr, return count; } +/* + * Emits the scale factor to bring the raw value into Gauss units. + * + * This scale factor is axis-dependent, and is derived from 3 calibration + * factors ASA(x), ASA(y), and ASA(z). + * + * These ASA values are read from the sensor device at start of day, and + * cached in the device context struct. + * + * Adjusting the flux value with the sensitivity adjustment value should be + * done via the following formula: + * + * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 ) + * + * where H is the raw value, ASA is the sensitivity adjustment, and Hadj + * is the resultant adjusted value. + * + * We reduce the formula to: + * + * Hadj = H * (ASA + 128) / 256 + * + * H is in the range of -4096 to 4095. The magnetometer has a range of + * +-1229uT. To go from the raw value to uT is: + * + * HuT = H * 1229/4096, or roughly, 3/10. + * + * Since 1uT = 100 gauss, our final scale factor becomes: + * + * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100 + * Hadj = H * ((ASA + 128) * 30 / 256 + * + * Since ASA doesn't change, we cache the resultant scale factor into the + * device context in ak8975_setup(). + */ +static ssize_t show_scale(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ak8975_data *data = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr); + + return sprintf(buf, "%ld\n", data->raw_to_gauss[this_attr->address]); +} + static int wait_conversion_complete_gpio(struct ak8975_data *data) { struct i2c_client *client = data->client; @@ -344,10 +371,13 @@ static int wait_conversion_complete_polled(struct ak8975_data *data) /* * Emits the raw flux value for the x, y, or z axis. */ -static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) +static ssize_t show_raw(struct device *dev, struct device_attribute *devattr, + char *buf) { + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ak8975_data *data = iio_priv(indio_dev); struct i2c_client *client = data->client; + struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr); u16 meas_reg; s16 raw; u8 read_status; @@ -399,8 +429,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) /* Read the flux value from the appropriate register (the register is specified in the iio device attributes). */ - ret = ak8975_read_data(client, ak8975_index_to_reg[index], - 2, (u8 *)&meas_reg); + ret = ak8975_read_data(client, this_attr->address, 2, (u8 *)&meas_reg); if (ret < 0) { dev_err(&client->dev, "Read axis data fails\n"); goto exit; @@ -413,48 +442,30 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) /* Clamp to valid range. */ raw = clamp_t(s16, raw, -4096, 4095); - *val = raw; - return IIO_VAL_INT; + + return sprintf(buf, "%d\n", raw); exit: mutex_unlock(&data->lock); return ret; } -static int ak8975_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct ak8975_data *data = iio_priv(indio_dev); - - switch (mask) { - case 0: - return ak8975_read_axis(indio_dev, chan->address, val); - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): - *val = data->raw_to_gauss[chan->address]; - return IIO_VAL_INT; - } - return -EINVAL; -} - -#define AK8975_CHANNEL(axis, index) \ - { \ - .type = IIO_MAGN, \ - .modified = 1, \ - .channel2 = IIO_MOD_##axis, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ - .address = index, \ - } - -static const struct iio_chan_spec ak8975_channels[] = { - AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2), -}; - static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode, 0); +static IIO_DEV_ATTR_MAGN_X_SCALE(S_IRUGO, show_scale, NULL, 0); +static IIO_DEV_ATTR_MAGN_Y_SCALE(S_IRUGO, show_scale, NULL, 1); +static IIO_DEV_ATTR_MAGN_Z_SCALE(S_IRUGO, show_scale, NULL, 2); +static IIO_DEV_ATTR_MAGN_X(show_raw, AK8975_REG_HXL); +static IIO_DEV_ATTR_MAGN_Y(show_raw, AK8975_REG_HYL); +static IIO_DEV_ATTR_MAGN_Z(show_raw, AK8975_REG_HZL); static struct attribute *ak8975_attr[] = { &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_magn_x_scale.dev_attr.attr, + &iio_dev_attr_magn_y_scale.dev_attr.attr, + &iio_dev_attr_magn_z_scale.dev_attr.attr, + &iio_dev_attr_magn_x_raw.dev_attr.attr, + &iio_dev_attr_magn_y_raw.dev_attr.attr, + &iio_dev_attr_magn_z_raw.dev_attr.attr, NULL }; @@ -464,7 +475,6 @@ static struct attribute_group ak8975_attr_group = { static const struct iio_info ak8975_info = { .attrs = &ak8975_attr_group, - .read_raw = &ak8975_read_raw, .driver_module = THIS_MODULE, }; @@ -520,8 +530,6 @@ static int ak8975_probe(struct i2c_client *client, data->eoc_irq = client->irq; data->eoc_gpio = eoc_gpio; indio_dev->dev.parent = &client->dev; - indio_dev->channels = ak8975_channels; - indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); indio_dev->info = &ak8975_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/trunk/drivers/staging/iio/magnetometer/hmc5843.c b/trunk/drivers/staging/iio/magnetometer/hmc5843.c index 1bb71864d586..b44c273a91a8 100644 --- a/trunk/drivers/staging/iio/magnetometer/hmc5843.c +++ b/trunk/drivers/staging/iio/magnetometer/hmc5843.c @@ -24,6 +24,7 @@ #include #include "../iio.h" #include "../sysfs.h" +#include "magnet.h" #define HMC5843_I2C_ADDRESS 0x1E @@ -61,9 +62,9 @@ /* * Device status */ -#define DATA_READY 0x01 -#define DATA_OUTPUT_LOCK 0x02 -#define VOLTAGE_REGULATOR_ENABLED 0x04 +#define DATA_READY 0x01 +#define DATA_OUTPUT_LOCK 0x02 +#define VOLTAGE_REGULATOR_ENABLED 0x04 /* * Mode register configuration @@ -88,16 +89,22 @@ /* * Device Configutration */ -#define CONF_NORMAL 0x00 +#define CONF_NORMAL 0x00 #define CONF_POSITIVE_BIAS 0x01 #define CONF_NEGATIVE_BIAS 0x02 #define CONF_NOT_USED 0x03 #define MEAS_CONF_MASK 0x03 -static int hmc5843_regval_to_nanoscale[] = { - 6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714 +static const char *regval_to_scale[] = { + "0.0000006173", + "0.0000007692", + "0.0000010309", + "0.0000012821", + "0.0000018868", + "0.0000021739", + "0.0000025641", + "0.0000035714", }; - static const int regval_to_input_field_mg[] = { 700, 1000, @@ -108,7 +115,7 @@ static const int regval_to_input_field_mg[] = { 4500, 6500 }; -static const char * const regval_to_samp_freq[] = { +static const char *regval_to_samp_freq[] = { "0.5", "1", "2", @@ -143,28 +150,37 @@ static s32 hmc5843_configure(struct i2c_client *client, } /* Return the measurement value from the specified channel */ -static int hmc5843_read_measurement(struct iio_dev *indio_dev, - int address, - int *val) +static ssize_t hmc5843_read_measurement(struct device *dev, + struct device_attribute *attr, + char *buf) { + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); + s16 coordinate_val; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct hmc5843_data *data = iio_priv(indio_dev); s32 result; mutex_lock(&data->lock); + result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG); while (!(result & DATA_READY)) result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG); - result = i2c_smbus_read_word_data(client, address); + result = i2c_smbus_read_word_data(client, this_attr->address); mutex_unlock(&data->lock); if (result < 0) return -EINVAL; - *val = (s16)swab16((u16)result); - return IIO_VAL_INT; + coordinate_val = (s16)swab16((u16)result); + return sprintf(buf, "%d\n", coordinate_val); } - +static IIO_DEV_ATTR_MAGN_X(hmc5843_read_measurement, + HMC5843_DATA_OUT_X_MSB_REG); +static IIO_DEV_ATTR_MAGN_Y(hmc5843_read_measurement, + HMC5843_DATA_OUT_Y_MSB_REG); +static IIO_DEV_ATTR_MAGN_Z(hmc5843_read_measurement, + HMC5843_DATA_OUT_Z_MSB_REG); /* * From the datasheet @@ -320,7 +336,7 @@ static s32 hmc5843_set_rate(struct i2c_client *client, reg_val = (data->meas_conf) | (rate << RATE_OFFSET); if (rate >= RATE_NOT_USED) { dev_err(&client->dev, - "This data output rate is not supported\n"); + "This data output rate is not supported \n"); return -EINVAL; } return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val); @@ -451,46 +467,28 @@ static IIO_DEVICE_ATTR(magn_range, set_range, HMC5843_CONFIG_REG_B); -static int hmc5843_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) +static ssize_t show_scale(struct device *dev, + struct device_attribute *attr, + char *buf) { + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct hmc5843_data *data = iio_priv(indio_dev); - - switch (mask) { - case 0: - return hmc5843_read_measurement(indio_dev, - chan->address, - val); - case (1 << IIO_CHAN_INFO_SCALE_SHARED): - *val = 0; - *val2 = hmc5843_regval_to_nanoscale[data->range]; - return IIO_VAL_INT_PLUS_NANO; - }; - return -EINVAL; + return strlen(strcpy(buf, regval_to_scale[data->range])); } - -#define HMC5843_CHANNEL(axis, add) \ - { \ - .type = IIO_MAGN, \ - .modified = 1, \ - .channel2 = IIO_MOD_##axis, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ - .address = add \ - } - -static const struct iio_chan_spec hmc5843_channels[] = { - HMC5843_CHANNEL(X, HMC5843_DATA_OUT_X_MSB_REG), - HMC5843_CHANNEL(Y, HMC5843_DATA_OUT_Y_MSB_REG), - HMC5843_CHANNEL(Z, HMC5843_DATA_OUT_Z_MSB_REG), -}; +static IIO_DEVICE_ATTR(magn_scale, + S_IRUGO, + show_scale, + NULL , 0); static struct attribute *hmc5843_attributes[] = { &iio_dev_attr_meas_conf.dev_attr.attr, &iio_dev_attr_operating_mode.dev_attr.attr, &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_magn_range.dev_attr.attr, + &iio_dev_attr_magn_scale.dev_attr.attr, + &iio_dev_attr_magn_x_raw.dev_attr.attr, + &iio_dev_attr_magn_y_raw.dev_attr.attr, + &iio_dev_attr_magn_z_raw.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, NULL }; @@ -532,7 +530,6 @@ static void hmc5843_init_client(struct i2c_client *client) static const struct iio_info hmc5843_info = { .attrs = &hmc5843_group, - .read_raw = &hmc5843_read_raw, .driver_module = THIS_MODULE, }; @@ -561,9 +558,6 @@ static int hmc5843_probe(struct i2c_client *client, hmc5843_init_client(client); indio_dev->info = &hmc5843_info; - indio_dev->name = id->name; - indio_dev->channels = hmc5843_channels; - indio_dev->num_channels = ARRAY_SIZE(hmc5843_channels); indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; err = iio_device_register(indio_dev); diff --git a/trunk/drivers/staging/iio/magnetometer/magnet.h b/trunk/drivers/staging/iio/magnetometer/magnet.h new file mode 100644 index 000000000000..1260eb7bd41e --- /dev/null +++ b/trunk/drivers/staging/iio/magnetometer/magnet.h @@ -0,0 +1,31 @@ + +#include "../sysfs.h" + +/* Magnetometer types of attribute */ + +#define IIO_DEV_ATTR_MAGN_X_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(magn_x_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_MAGN_Y_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(magn_y_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_MAGN_Z_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(magn_z_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_MAGN_X_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(magn_x_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_MAGN_Y_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(magn_y_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_MAGN_Z_SCALE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(magn_z_scale, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_MAGN_X(_show, _addr) \ + IIO_DEVICE_ATTR(magn_x_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_MAGN_Y(_show, _addr) \ + IIO_DEVICE_ATTR(magn_y_raw, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_MAGN_Z(_show, _addr) \ + IIO_DEVICE_ATTR(magn_z_raw, S_IRUGO, _show, NULL, _addr) diff --git a/trunk/drivers/staging/iio/meter/ade7758_ring.c b/trunk/drivers/staging/iio/meter/ade7758_ring.c index 1e2a09643a35..b89b7f882e84 100644 --- a/trunk/drivers/staging/iio/meter/ade7758_ring.c +++ b/trunk/drivers/staging/iio/meter/ade7758_ring.c @@ -6,14 +6,23 @@ * Licensed under the GPL-2. */ #include +#include +#include +#include +#include +#include #include #include #include +#include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include "../accel/accel.h" +#include "../trigger.h" #include "ade7758.h" /** @@ -60,7 +69,7 @@ static int ade7758_write_waveform_type(struct device *dev, unsigned type) static irqreturn_t ade7758_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; + struct iio_dev *indio_dev = pf->private_data; struct iio_ring_buffer *ring = indio_dev->ring; struct ade7758_state *st = iio_priv(indio_dev); s64 dat64[2]; @@ -127,6 +136,12 @@ static const struct iio_ring_setup_ops ade7758_ring_setup_ops = { void ade7758_unconfigure_ring(struct iio_dev *indio_dev) { + /* ensure that the trigger has been detached */ + if (indio_dev->trig) { + iio_put_trigger(indio_dev->trig); + iio_trigger_dettach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } iio_dealloc_pollfunc(indio_dev->pollfunc); iio_sw_rb_free(indio_dev->ring); } diff --git a/trunk/drivers/staging/iio/meter/ade7758_trigger.c b/trunk/drivers/staging/iio/meter/ade7758_trigger.c index 392dfe302443..a5c3248151ed 100644 --- a/trunk/drivers/staging/iio/meter/ade7758_trigger.c +++ b/trunk/drivers/staging/iio/meter/ade7758_trigger.c @@ -7,10 +7,16 @@ */ #include +#include +#include +#include #include +#include +#include #include #include "../iio.h" +#include "../sysfs.h" #include "../trigger.h" #include "ade7758.h" @@ -51,12 +57,6 @@ static int ade7758_trig_try_reen(struct iio_trigger *trig) return 0; } -static const struct iio_trigger_ops ade7758_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &ade7758_data_rdy_trigger_set_state, - .try_reenable = &ade7758_trig_try_reen, -}; - int ade7758_probe_trigger(struct iio_dev *indio_dev) { struct ade7758_state *st = iio_priv(indio_dev); @@ -79,8 +79,10 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev) goto error_free_trig; st->trig->dev.parent = &st->us->dev; - st->trig->ops = &ade7758_trigger_ops; + st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; + st->trig->set_trigger_state = &ade7758_data_rdy_trigger_set_state; + st->trig->try_reenable = &ade7758_trig_try_reen; ret = iio_trigger_register(st->trig); /* select default trigger */ diff --git a/trunk/drivers/staging/iio/meter/ade7854.c b/trunk/drivers/staging/iio/meter/ade7854.c index 9b240ed858ff..b82659f43bc6 100644 --- a/trunk/drivers/staging/iio/meter/ade7854.c +++ b/trunk/drivers/staging/iio/meter/ade7854.c @@ -582,7 +582,7 @@ int ade7854_probe(struct iio_dev *indio_dev, struct device *dev) iio_device_unregister(indio_dev); error_free_dev: iio_free_device(indio_dev); - +error_ret: return ret; } EXPORT_SYMBOL(ade7854_probe); diff --git a/trunk/drivers/staging/iio/resolver/ad2s1210.c b/trunk/drivers/staging/iio/resolver/ad2s1210.c index 53cb031b04dc..ecaf7bb790fe 100644 --- a/trunk/drivers/staging/iio/resolver/ad2s1210.c +++ b/trunk/drivers/staging/iio/resolver/ad2s1210.c @@ -639,6 +639,7 @@ static struct attribute *ad2s1210_attributes[] = { }; static const struct attribute_group ad2s1210_attribute_group = { + .name = DRV_NAME, .attrs = ad2s1210_attributes, }; diff --git a/trunk/drivers/staging/iio/resolver/ad2s90.c b/trunk/drivers/staging/iio/resolver/ad2s90.c index 43a66d46d00c..166e2414ac85 100644 --- a/trunk/drivers/staging/iio/resolver/ad2s90.c +++ b/trunk/drivers/staging/iio/resolver/ad2s90.c @@ -58,6 +58,7 @@ static struct attribute *ad2s90_attributes[] = { }; static const struct attribute_group ad2s90_attribute_group = { + .name = DRV_NAME, .attrs = ad2s90_attributes, }; diff --git a/trunk/drivers/staging/iio/sysfs.h b/trunk/drivers/staging/iio/sysfs.h index 0b75823fbe1b..dd79b5844212 100644 --- a/trunk/drivers/staging/iio/sysfs.h +++ b/trunk/drivers/staging/iio/sysfs.h @@ -12,17 +12,19 @@ #ifndef _INDUSTRIAL_IO_SYSFS_H_ #define _INDUSTRIAL_IO_SYSFS_H_ -struct iio_chan_spec; +#include "iio.h" /** * struct iio_dev_attr - iio specific device attribute * @dev_attr: underlying device attribute * @address: associated register address + * @val2: secondary attribute value * @l: list head for maintaining list of dynamically created attrs. */ struct iio_dev_attr { struct device_attribute dev_attr; int address; + int val2; struct list_head l; struct iio_chan_spec const *c; }; @@ -62,6 +64,10 @@ struct iio_const_attr { struct iio_dev_attr iio_dev_attr_##_vname \ = IIO_ATTR(_name, _mode, _show, _store, _addr) +#define IIO_DEVICE_ATTR_2(_name, _mode, _show, _store, _addr, _val2) \ + struct iio_dev_attr iio_dev_attr_##_name \ + = IIO_ATTR_2(_name, _mode, _show, _store, _addr, _val2) + #define IIO_CONST_ATTR(_name, _string) \ struct iio_const_attr iio_const_attr_##_name \ = { .string = _string, \ @@ -71,14 +77,30 @@ struct iio_const_attr { struct iio_const_attr iio_const_attr_##_vname \ = { .string = _string, \ .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} - /* Generic attributes of onetype or another */ + +/** + * IIO_DEV_ATTR_REV - revision number for the device + * @_show: output method for the attribute + * + * Very much device dependent. + **/ +#define IIO_DEV_ATTR_REV(_show) \ + IIO_DEVICE_ATTR(revision, S_IRUGO, _show, NULL, 0) + /** * IIO_DEV_ATTR_RESET: resets the device **/ #define IIO_DEV_ATTR_RESET(_store) \ IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, _store, 0) +/** + * IIO_CONST_ATTR_NAME - constant identifier + * @_string: the name + **/ +#define IIO_CONST_ATTR_NAME(_string) \ + IIO_CONST_ATTR(name, _string) + /** * IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency * @_mode: sysfs file mode/permissions @@ -89,11 +111,15 @@ struct iio_const_attr { IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0) /** - * IIO_DEV_ATTR_SAMP_FREQ_AVAIL - list available sampling frequencies + * IIO_DEV_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies * @_show: output method for the attribute * * May be mode dependent on some devices **/ +/* Deprecated */ +#define IIO_DEV_ATTR_AVAIL_SAMP_FREQ(_show) \ + IIO_DEVICE_ATTR(available_sampling_frequency, S_IRUGO, _show, NULL, 0) + #define IIO_DEV_ATTR_SAMP_FREQ_AVAIL(_show) \ IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, _show, NULL, 0) /** @@ -105,6 +131,27 @@ struct iio_const_attr { #define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \ IIO_CONST_ATTR(sampling_frequency_available, _string) +/** + * IIO_DEV_ATTR_SW_RING_ENABLE - enable software ring buffer + * @_show: output method for the attribute + * @_store: input method for the attribute + * + * Success may be dependent on attachment of trigger previously. + **/ +#define IIO_DEV_ATTR_SW_RING_ENABLE(_show, _store) \ + IIO_DEVICE_ATTR(sw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) + +/** + * IIO_DEV_ATTR_HW_RING_ENABLE - enable hardware ring buffer + * @_show: output method for the attribute + * @_store: input method for the attribute + * + * This is a different attribute from the software one as one can envision + * schemes where a combination of the two may be used. + **/ +#define IIO_DEV_ATTR_HW_RING_ENABLE(_show, _store) \ + IIO_DEVICE_ATTR(hw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) + #define IIO_DEV_ATTR_TEMP_RAW(_show) \ IIO_DEVICE_ATTR(temp_raw, S_IRUGO, _show, NULL, 0) @@ -114,6 +161,28 @@ struct iio_const_attr { #define IIO_CONST_ATTR_TEMP_SCALE(_string) \ IIO_CONST_ATTR(temp_scale, _string) +/* must match our channel defs */ +#define IIO_EV_CLASS_IN IIO_IN +#define IIO_EV_CLASS_IN_DIFF IIO_IN_DIFF +#define IIO_EV_CLASS_ACCEL IIO_ACCEL +#define IIO_EV_CLASS_GYRO IIO_GYRO +#define IIO_EV_CLASS_MAGN IIO_MAGN +#define IIO_EV_CLASS_LIGHT IIO_LIGHT +#define IIO_EV_CLASS_PROXIMITY IIO_PROXIMITY +#define IIO_EV_CLASS_TEMP IIO_TEMP + +#define IIO_EV_MOD_X IIO_MOD_X +#define IIO_EV_MOD_Y IIO_MOD_Y +#define IIO_EV_MOD_Z IIO_MOD_Z +#define IIO_EV_MOD_X_AND_Y IIO_MOD_X_AND_Y +#define IIO_EV_MOD_X_ANX_Z IIO_MOD_X_AND_Z +#define IIO_EV_MOD_Y_AND_Z IIO_MOD_Y_AND_Z +#define IIO_EV_MOD_X_AND_Y_AND_Z IIO_MOD_X_AND_Y_AND_Z +#define IIO_EV_MOD_X_OR_Y IIO_MOD_X_OR_Y +#define IIO_EV_MOD_X_OR_Z IIO_MOD_X_OR_Z +#define IIO_EV_MOD_Y_OR_Z IIO_MOD_Y_OR_Z +#define IIO_EV_MOD_X_OR_Y_OR_Z IIO_MOD_X_OR_Y_OR_Z + #define IIO_EV_TYPE_THRESH 0 #define IIO_EV_TYPE_MAG 1 #define IIO_EV_TYPE_ROC 2 @@ -138,6 +207,10 @@ struct iio_const_attr { #define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction) \ IIO_EVENT_CODE(channelclass, 0, number, 0, type, direction) + +#define IIO_BUFFER_EVENT_CODE(code) \ + (IIO_EV_CLASS_BUFFER | (code << 8)) + #define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 24) & 0xf) /* Event code number extraction depends on which type of event we have. diff --git a/trunk/drivers/staging/iio/trigger.h b/trunk/drivers/staging/iio/trigger.h index 722fc338f366..e0b58ed749b8 100644 --- a/trunk/drivers/staging/iio/trigger.h +++ b/trunk/drivers/staging/iio/trigger.h @@ -15,27 +15,6 @@ struct iio_subirq { bool enabled; }; -/** - * struct iio_trigger_ops - operations structure for an iio_trigger. - * @owner: used to monitor usage count of the trigger. - * @set_trigger_state: switch on/off the trigger on demand - * @try_reenable: function to reenable the trigger when the - * use count is zero (may be NULL) - * @validate_device: function to validate the device when the - * current trigger gets changed. - * - * This is typically static const within a driver and shared by - * instances of a given device. - **/ -struct iio_trigger_ops { - struct module *owner; - int (*set_trigger_state)(struct iio_trigger *trig, bool state); - int (*try_reenable)(struct iio_trigger *trig); - int (*validate_device)(struct iio_trigger *trig, - struct iio_dev *indio_dev); -}; - - /** * struct iio_trigger - industrial I/O trigger device * @@ -47,6 +26,11 @@ struct iio_trigger_ops { * @alloc_list: [DRIVER] used for driver specific trigger list * @owner: [DRIVER] used to monitor usage count of the trigger. * @use_count: use count for the trigger + * @set_trigger_state: [DRIVER] switch on/off the trigger on demand + * @try_reenable: function to reenable the trigger when the + * use count is zero (may be NULL) + * @validate_device: function to validate the device when the + * current trigger gets changed. * @subirq_chip: [INTERN] associate 'virtual' irq chip. * @subirq_base: [INTERN] base number for irqs provided by trigger. * @subirqs: [INTERN] information about the 'child' irqs. @@ -54,7 +38,6 @@ struct iio_trigger_ops { * @pool_lock: [INTERN] protection of the irq pool. **/ struct iio_trigger { - const struct iio_trigger_ops *ops; int id; const char *name; struct device dev; @@ -65,6 +48,11 @@ struct iio_trigger { struct module *owner; int use_count; + int (*set_trigger_state)(struct iio_trigger *trig, bool state); + int (*try_reenable)(struct iio_trigger *trig); + int (*validate_device)(struct iio_trigger *trig, + struct iio_dev *indio_dev); + struct irq_chip subirq_chip; int subirq_base; @@ -73,6 +61,29 @@ struct iio_trigger { struct mutex pool_lock; }; +/** + * struct iio_poll_func - poll function pair + * + * @private_data: data specific to device (passed into poll func) + * @h: the function that is actually run on trigger + * @thread: threaded interrupt part + * @type: the type of interrupt (basically if oneshot) + * @name: name used to identify the trigger consumer. + * @irq: the corresponding irq as allocated from the + * trigger pool + * @timestamp: some devices need a timestamp grabbed as soon + * as possible after the trigger - hence handler + * passes it via here. + **/ +struct iio_poll_func { + void *private_data; + irqreturn_t (*h)(int irq, void *p); + irqreturn_t (*thread)(int irq, void *p); + int type; + char *name; + int irq; + s64 timestamp; +}; static inline struct iio_trigger *to_iio_trigger(struct device *d) { @@ -81,14 +92,14 @@ static inline struct iio_trigger *to_iio_trigger(struct device *d) static inline void iio_put_trigger(struct iio_trigger *trig) { - module_put(trig->ops->owner); put_device(&trig->dev); + module_put(trig->owner); }; static inline void iio_get_trigger(struct iio_trigger *trig) { + __module_get(trig->owner); get_device(&trig->dev); - __module_get(trig->ops->owner); }; /** @@ -103,6 +114,23 @@ int iio_trigger_register(struct iio_trigger *trig_info); **/ void iio_trigger_unregister(struct iio_trigger *trig_info); +/** + * iio_trigger_attach_poll_func() - add a function pair to be run on trigger + * @trig: trigger to which the function pair are being added + * @pf: poll function pair + **/ +int iio_trigger_attach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf); + +/** + * iio_trigger_dettach_poll_func() - remove function pair from those to be + * run on trigger + * @trig: trigger from which the function is being removed + * @pf: poll function pair + **/ +int iio_trigger_dettach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf); + /** * iio_trigger_poll() - called on a trigger occurring * @trig: trigger which occurred @@ -111,9 +139,48 @@ void iio_trigger_unregister(struct iio_trigger *trig_info); **/ void iio_trigger_poll(struct iio_trigger *trig, s64 time); void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time); +void iio_trigger_notify_done(struct iio_trigger *trig); irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); +static inline int iio_trigger_get_irq(struct iio_trigger *trig) +{ + int ret; + mutex_lock(&trig->pool_lock); + ret = bitmap_find_free_region(trig->pool, + CONFIG_IIO_CONSUMERS_PER_TRIGGER, + ilog2(1)); + mutex_unlock(&trig->pool_lock); + if (ret >= 0) + ret += trig->subirq_base; + + return ret; +}; + +static inline void iio_trigger_put_irq(struct iio_trigger *trig, int irq) +{ + mutex_lock(&trig->pool_lock); + clear_bit(irq - trig->subirq_base, trig->pool); + mutex_unlock(&trig->pool_lock); +}; + +struct iio_poll_func +*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + int type, + void *private, + const char *fmt, + ...); +void iio_dealloc_pollfunc(struct iio_poll_func *pf); +irqreturn_t iio_pollfunc_store_time(int irq, void *p); + +/* + * Two functions for common case where all that happens is a pollfunc + * is attached and detached from a trigger + */ +int iio_triggered_ring_postenable(struct iio_dev *indio_dev); +int iio_triggered_ring_predisable(struct iio_dev *indio_dev); + struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void iio_free_trigger(struct iio_trigger *trig); diff --git a/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 243f38f80de1..4f1729565582 100644 --- a/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/trunk/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -143,10 +143,6 @@ static int iio_bfin_tmr_get_number(int irq) return -ENODEV; } -static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = { - owner = THIS_MODULE, -}; - static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) { struct bfin_tmr_state *st; @@ -179,7 +175,7 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) } st->trig->private_data = st; - st->trig->ops = &iio_bfin_tmr_trigger_ops; + st->trig->owner = THIS_MODULE; st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups; ret = iio_trigger_register(st->trig); if (ret) diff --git a/trunk/drivers/staging/iio/trigger/iio-trig-gpio.c b/trunk/drivers/staging/iio/trigger/iio-trig-gpio.c index f2a655981622..f1fb795e6410 100644 --- a/trunk/drivers/staging/iio/trigger/iio-trig-gpio.c +++ b/trunk/drivers/staging/iio/trigger/iio-trig-gpio.c @@ -47,10 +47,6 @@ static irqreturn_t iio_gpio_trigger_poll(int irq, void *private) return IRQ_HANDLED; } -static const struct iio_trigger_ops iio_gpio_trigger_ops = { - .owner = THIS_MODULE, -}; - static int iio_gpio_trigger_probe(struct platform_device *pdev) { struct iio_gpio_trigger_info *trig_info; @@ -85,7 +81,7 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev) } trig->private_data = trig_info; trig_info->irq = irq; - trig->ops = &iio_gpio_trigger_ops; + trig->owner = THIS_MODULE; ret = request_irq(irq, iio_gpio_trigger_poll, irqflags, trig->name, trig); if (ret) { diff --git a/trunk/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/trunk/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c index d35d085da949..01cf7e20b515 100644 --- a/trunk/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c +++ b/trunk/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c @@ -96,11 +96,6 @@ static void iio_prtc_trigger_poll(void *private_data) iio_trigger_poll(private_data, 0); } -static const struct iio_trigger_ops iio_prtc_trigger_ops = { - .owner = THIS_MODULE, - .set_trigger_state = &iio_trig_periodic_rtc_set_state, -}; - static int iio_trig_periodic_rtc_probe(struct platform_device *dev) { char **pdata = dev->dev.platform_data; @@ -126,7 +121,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev) } trig->private_data = trig_info; trig->owner = THIS_MODULE; - trig->ops = &iio_prtc_trigger_ops; + trig->set_trigger_state = &iio_trig_periodic_rtc_set_state; /* RTC access */ trig_info->rtc = rtc_class_open(pdata[i]); diff --git a/trunk/drivers/staging/iio/trigger/iio-trig-sysfs.c b/trunk/drivers/staging/iio/trigger/iio-trig-sysfs.c index 174dc65709d5..47248cd1fa0d 100644 --- a/trunk/drivers/staging/iio/trigger/iio-trig-sysfs.c +++ b/trunk/drivers/staging/iio/trigger/iio-trig-sysfs.c @@ -77,16 +77,9 @@ static const struct attribute_group *iio_sysfs_trig_groups[] = { NULL }; - -/* Nothing to actually do upon release */ -static void iio_trigger_sysfs_release(struct device *dev) -{ -} - static struct device iio_sysfs_trig_dev = { .bus = &iio_bus_type, .groups = iio_sysfs_trig_groups, - .release = &iio_trigger_sysfs_release, }; static ssize_t iio_sysfs_trigger_poll(struct device *dev, @@ -114,10 +107,6 @@ static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = { NULL }; -static const struct iio_trigger_ops iio_sysfs_trigger_ops = { - .owner = THIS_MODULE, -}; - static int iio_sysfs_trigger_probe(int id) { struct iio_sysfs_trig *t; @@ -146,7 +135,7 @@ static int iio_sysfs_trigger_probe(int id) } t->trig->dev.groups = iio_sysfs_trigger_attr_groups; - t->trig->ops = &iio_sysfs_trigger_ops; + t->trig->owner = THIS_MODULE; t->trig->dev.parent = &iio_sysfs_trig_dev; ret = iio_trigger_register(t->trig); diff --git a/trunk/drivers/staging/iio/trigger_consumer.h b/trunk/drivers/staging/iio/trigger_consumer.h index 418e0bd5f4ce..9d52d9637777 100644 --- a/trunk/drivers/staging/iio/trigger_consumer.h +++ b/trunk/drivers/staging/iio/trigger_consumer.h @@ -1,52 +1,47 @@ -/* The industrial I/O core, trigger consumer functions + +/* The industrial I/O core, trigger consumer handling functions * - * Copyright (c) 2008-2011 Jonathan Cameron + * Copyright (c) 2008 Jonathan Cameron * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. */ +#ifdef CONFIG_IIO_TRIGGER /** - * struct iio_poll_func - poll function pair - * - * @indio_dev: data specific to device (passed into poll func) - * @h: the function that is actually run on trigger - * @thread: threaded interrupt part - * @type: the type of interrupt (basically if oneshot) - * @name: name used to identify the trigger consumer. - * @irq: the corresponding irq as allocated from the - * trigger pool - * @timestamp: some devices need a timestamp grabbed as soon - * as possible after the trigger - hence handler - * passes it via here. + * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers + * @dev_info: iio_dev associated with the device that will consume the trigger + **/ +int iio_device_register_trigger_consumer(struct iio_dev *dev_info); + +/** + * iio_device_unregister_trigger_consumer() - reverse the registration process + * @dev_info: iio_dev associated with the device that consumed the trigger + **/ +int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info); + +#else + +/** + * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers + * @dev_info: iio_dev associated with the device that will consume the trigger **/ -struct iio_poll_func { - struct iio_dev *indio_dev; - irqreturn_t (*h)(int irq, void *p); - irqreturn_t (*thread)(int irq, void *p); - int type; - char *name; - int irq; - s64 timestamp; +static int iio_device_register_trigger_consumer(struct iio_dev *dev_info) +{ + return 0; }; +/** + * iio_device_unregister_trigger_consumer() - reverse the registration process + * @dev_info: iio_dev associated with the device that consumed the trigger + **/ +static int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) +{ + return 0; +}; + +#endif /* CONFIG_TRIGGER_CONSUMER */ -struct iio_poll_func -*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), - irqreturn_t (*thread)(int irq, void *p), - int type, - struct iio_dev *indio_dev, - const char *fmt, - ...); -void iio_dealloc_pollfunc(struct iio_poll_func *pf); -irqreturn_t iio_pollfunc_store_time(int irq, void *p); -void iio_trigger_notify_done(struct iio_trigger *trig); -/* - * Two functions for common case where all that happens is a pollfunc - * is attached and detached from a trigger - */ -int iio_triggered_ring_postenable(struct iio_dev *indio_dev); -int iio_triggered_ring_predisable(struct iio_dev *indio_dev); diff --git a/trunk/drivers/staging/keucr/scsiglue.c b/trunk/drivers/staging/keucr/scsiglue.c index e1f3931d41e0..135f7f21dfde 100644 --- a/trunk/drivers/staging/keucr/scsiglue.c +++ b/trunk/drivers/staging/keucr/scsiglue.c @@ -144,7 +144,7 @@ static int command_abort(struct scsi_cmnd *srb) scsi_lock(us_to_host(us)); if (us->srb != srb) { scsi_unlock(us_to_host(us)); - printk("-- nothing to abort\n"); + printk ("-- nothing to abort\n"); return FAILED; } @@ -279,8 +279,7 @@ static int proc_info(struct Scsi_Host *host, char *buffer, char **start, pos += sprintf(pos, " Quirks:"); #define US_FLAG(name, value) \ - if (us->fflags & value)\ - pos += sprintf(pos, " " #name); + if (us->fflags & value) pos += sprintf(pos, " " #name); US_DO_ALL_FLAGS #undef US_FLAG diff --git a/trunk/drivers/staging/keucr/smil.h b/trunk/drivers/staging/keucr/smil.h index 24a636a4aa1c..b5a8fa7c7989 100644 --- a/trunk/drivers/staging/keucr/smil.h +++ b/trunk/drivers/staging/keucr/smil.h @@ -177,7 +177,8 @@ struct SSFDCTYPE { WORD MaxLogBlocks; }; -typedef struct SSFDCTYPE_T { +typedef struct SSFDCTYPE_T +{ BYTE Model; BYTE Attribute; BYTE MaxZones; @@ -193,7 +194,8 @@ struct ADDRESS { WORD LogBlock; /* Logical Block Number of Zone */ }; -typedef struct ADDRESS_T { +typedef struct ADDRESS_T +{ BYTE Zone; /* Zone Number */ BYTE Sector; /* Sector(512byte) Number on Block */ WORD PhyBlock; /* Physical Block Number on Zone */ diff --git a/trunk/drivers/staging/keucr/smilsub.c b/trunk/drivers/staging/keucr/smilsub.c index d4dd5ed516ce..b315d5f8e197 100644 --- a/trunk/drivers/staging/keucr/smilsub.c +++ b/trunk/drivers/staging/keucr/smilsub.c @@ -2,37 +2,42 @@ #include "usb.h" #include "scsiglue.h" #include "transport.h" +//#include "init.h" +//#include "stdlib.h" +//#include "EUCR6SK.h" #include "smcommon.h" #include "smil.h" -void _Set_D_SsfdcRdCmd(BYTE); -void _Set_D_SsfdcRdAddr(BYTE); -void _Set_D_SsfdcRdChip(void); -void _Set_D_SsfdcRdStandby(void); -void _Start_D_SsfdcRdHwECC(void); -void _Stop_D_SsfdcRdHwECC(void); -void _Load_D_SsfdcRdHwECC(BYTE); -void _Set_D_SsfdcWrCmd(BYTE); -void _Set_D_SsfdcWrAddr(BYTE); -void _Set_D_SsfdcWrBlock(void); -void _Set_D_SsfdcWrStandby(void); -void _Start_D_SsfdcWrHwECC(void); -void _Load_D_SsfdcWrHwECC(BYTE); -int _Check_D_SsfdcBusy(WORD); -int _Check_D_SsfdcStatus(void); -void _Reset_D_SsfdcErr(void); -void _Read_D_SsfdcBuf(BYTE *); -void _Write_D_SsfdcBuf(BYTE *); -void _Read_D_SsfdcByte(BYTE *); -void _ReadRedt_D_SsfdcBuf(BYTE *); -void _WriteRedt_D_SsfdcBuf(BYTE *); -BYTE _Check_D_DevCode(BYTE); - -void _Set_D_ECCdata(BYTE, BYTE *); -void _Calc_D_ECCdata(BYTE *); - - +void _Set_D_SsfdcRdCmd (BYTE); +void _Set_D_SsfdcRdAddr (BYTE); +void _Set_D_SsfdcRdChip (void); +void _Set_D_SsfdcRdStandby (void); +void _Start_D_SsfdcRdHwECC (void); +void _Stop_D_SsfdcRdHwECC (void); +void _Load_D_SsfdcRdHwECC (BYTE); +void _Set_D_SsfdcWrCmd (BYTE); +void _Set_D_SsfdcWrAddr (BYTE); +void _Set_D_SsfdcWrBlock (void); +void _Set_D_SsfdcWrStandby (void); +void _Start_D_SsfdcWrHwECC (void); +void _Load_D_SsfdcWrHwECC (BYTE); +int _Check_D_SsfdcBusy (WORD); +int _Check_D_SsfdcStatus (void); +void _Reset_D_SsfdcErr (void); +void _Read_D_SsfdcBuf (BYTE *); +void _Write_D_SsfdcBuf (BYTE *); +void _Read_D_SsfdcByte (BYTE *); +void _ReadRedt_D_SsfdcBuf (BYTE *); +void _WriteRedt_D_SsfdcBuf (BYTE *); +BYTE _Check_D_DevCode (BYTE); + +void _Set_D_ECCdata (BYTE,BYTE *); +void _Calc_D_ECCdata (BYTE *); + +//void SM_ReadDataWithDMA (PFDO_DEVICE_EXTENSION, BYTE *, WORD); +//void SM_WriteDataWithDMA (PFDO_DEVICE_EXTENSION, BYTE *, WORD); +// struct SSFDCTYPE Ssfdc; struct ADDRESS Media; struct CIS_AREA CisArea; @@ -44,179 +49,221 @@ extern DWORD ErrXDCode; extern WORD ReadBlock; extern WORD WriteBlock; +//KEVENT SM_DMADoneEvent; +#define EVEN 0 // Even Page for 256byte/page +#define ODD 1 // Odd Page for 256byte/page -#define EVEN 0 /* Even Page for 256byte/page */ -#define ODD 1 /* Odd Page for 256byte/page */ - -/* SmartMedia Redundant buffer data Control Subroutine - *----- Check_D_DataBlank() -------------------------------------------- - */ +//SmartMedia Redundant buffer data Control Subroutine +//----- Check_D_DataBlank() -------------------------------------------- int Check_D_DataBlank(BYTE *redundant) { char i; - for (i = 0; i < REDTSIZE; i++) - if (*redundant++ != 0xFF) - return ERROR; + for(i=0; ipBulkCbw; + //BYTE buf[0x200]; + + //printk("Ssfdc_D_Reset --- But do nothing !!\n"); return; +/* RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW)); + pBulkCbw->dCBWSignature = CBW_SIGNTURE; + pBulkCbw->bCBWLun = CBW_LUN; + //pBulkCbw->dCBWDataTransferLength = 0x200; + pBulkCbw->bmCBWFlags = 0x80; + pBulkCbw->CBWCb[0] = 0xF2; + pBulkCbw->CBWCb[1] = 0x07; + + ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_READ, NULL); + + if (!NT_SUCCESS(ntStatus)) + { + ENE_Print("Ssfdc_D_Reset Fail !!\n"); + //return ntStatus; + }*/ } -/* ----- Ssfdc_D_ReadCisSect() ------------------------------------------ */ -int Ssfdc_D_ReadCisSect(struct us_data *us, BYTE *buf, BYTE *redundant) +//----- Ssfdc_D_ReadCisSect() ------------------------------------------ +int Ssfdc_D_ReadCisSect(struct us_data *us, BYTE *buf,BYTE *redundant) { - BYTE zone, sector; + BYTE zone,sector; WORD block; - - zone = Media.Zone; block = Media.PhyBlock; sector = Media.Sector; - Media.Zone = 0; - Media.PhyBlock = CisArea.PhyBlock; - Media.Sector = CisArea.Sector; - - if (Ssfdc_D_ReadSect(us, buf, redundant)) { - Media.Zone = zone; Media.PhyBlock = block; Media.Sector = sector; - return ERROR; + //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc; + //ADDRESS_T bb = (ADDRESS_T) &Media; + + zone=Media.Zone; block=Media.PhyBlock; sector=Media.Sector; + Media.Zone=0; + Media.PhyBlock=CisArea.PhyBlock; + Media.Sector=CisArea.Sector; + + if (Ssfdc_D_ReadSect(us,buf,redundant)) + { + Media.Zone=zone; Media.PhyBlock=block; Media.Sector=sector; + return(ERROR); } - Media.Zone = zone; Media.PhyBlock = block; Media.Sector = sector; - return SMSUCCESS; + Media.Zone=zone; Media.PhyBlock=block; Media.Sector=sector; + return(SMSUCCESS); } - -/* 6250 CMD 1 */ -/* ----- Ssfdc_D_ReadSect() --------------------------------------------- */ -int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf, BYTE *redundant) +/* +////----- Ssfdc_D_WriteRedtMode() ---------------------------------------- +//void Ssfdc_D_WriteRedtMode(void) +//{ +// _Set_D_SsfdcRdCmd (RST_CHIP); +// _Check_D_SsfdcBusy (BUSY_RESET); +// _Set_D_SsfdcRdCmd (READ_REDT); +// _Check_D_SsfdcBusy (BUSY_READ); +// _Set_D_SsfdcRdStandby (); +//} +// +////----- Ssfdc_D_ReadID() ----------------------------------------------- +//void Ssfdc_D_ReadID(BYTE *buf, BYTE ReadID) +//{ +// _Set_D_SsfdcRdCmd (ReadID); +// _Set_D_SsfdcRdChip (); +// _Read_D_SsfdcByte (buf++); +// _Read_D_SsfdcByte (buf++); +// _Read_D_SsfdcByte (buf++); +// _Read_D_SsfdcByte (buf); +// _Set_D_SsfdcRdStandby (); +//} +*/ +// 6250 CMD 1 +//----- Ssfdc_D_ReadSect() --------------------------------------------- +int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf,BYTE *redundant) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; WORD addr; result = ENE_LoadBinCode(us, SM_RW_PATTERN); - if (result != USB_STOR_XFER_GOOD) { + if (result != USB_STOR_XFER_GOOD) + { printk("Load SM RW Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock; - addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector; + addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; + addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; - /* Read sect data */ + // Read sect data memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; @@ -224,14 +271,14 @@ int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf, BYTE *redundant) bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x02; bcb->CDB[4] = (BYTE)addr; - bcb->CDB[3] = (BYTE)(addr / 0x0100); - bcb->CDB[2] = Media.Zone / 2; + bcb->CDB[3] = (BYTE)(addr/0x0100); + bcb->CDB[2] = Media.Zone/2; result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - /* Read redundant */ + // Read redundant memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x10; @@ -239,8 +286,8 @@ int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf, BYTE *redundant) bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x03; bcb->CDB[4] = (BYTE)addr; - bcb->CDB[3] = (BYTE)(addr / 0x0100); - bcb->CDB[2] = Media.Zone / 2; + bcb->CDB[3] = (BYTE)(addr/0x0100); + bcb->CDB[2] = Media.Zone/2; bcb->CDB[8] = 0; bcb->CDB[9] = 1; @@ -251,23 +298,25 @@ int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf, BYTE *redundant) return USB_STOR_TRANSPORT_GOOD; } -/* ----- Ssfdc_D_ReadBlock() --------------------------------------------- */ -int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant) +//----- Ssfdc_D_ReadBlock() --------------------------------------------- +int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf,BYTE *redundant) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; WORD addr; + //printk("Ssfdc_D_ReadBlock\n"); result = ENE_LoadBinCode(us, SM_RW_PATTERN); - if (result != USB_STOR_XFER_GOOD) { + if (result != USB_STOR_XFER_GOOD) + { printk("Load SM RW Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock; - addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector; + addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; + addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; - /* Read sect data */ + // Read sect data memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200*count; @@ -275,14 +324,14 @@ int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x02; bcb->CDB[4] = (BYTE)addr; - bcb->CDB[3] = (BYTE)(addr / 0x0100); - bcb->CDB[2] = Media.Zone / 2; + bcb->CDB[3] = (BYTE)(addr/0x0100); + bcb->CDB[2] = Media.Zone/2; result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - /* Read redundant */ + // Read redundant memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x10; @@ -290,8 +339,8 @@ int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x03; bcb->CDB[4] = (BYTE)addr; - bcb->CDB[3] = (BYTE)(addr / 0x0100); - bcb->CDB[2] = Media.Zone / 2; + bcb->CDB[3] = (BYTE)(addr/0x0100); + bcb->CDB[2] = Media.Zone/2; bcb->CDB[8] = 0; bcb->CDB[9] = 1; @@ -301,27 +350,190 @@ int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant return USB_STOR_TRANSPORT_GOOD; } - - -/* ----- Ssfdc_D_CopyBlock() -------------------------------------------- */ -int Ssfdc_D_CopyBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant) +/* +////----- Ssfdc_D_ReadSect_DMA() --------------------------------------------- +//int Ssfdc_D_ReadSect_DMA(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant) +//{ +// WORD SectByteCount, addr; +// DWORD Buffer[4]; +// WORD len; +// +// if (!_Hw_D_ChkCardIn()) +// return(ERROR); +// addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; +// addr=addr*(WORD)Ssfdc.MaxSectors+Media.Sector; +// // cycle starting address +// SM_STARTADDR_LSB = 0x00; +// SM_STARTADDR_IISB = (BYTE)addr; +// SM_STARTADDR_IIISB = (BYTE)(addr/0x0100); +// SM_STARTADDR_MSB = Media.Zone/2; +// +// //Sector byte count = 0x200(DMA) +// SectByteCount = 0x20f; +// SM_BYTECNT_LO = (BYTE)SectByteCount; +// SM_CMD_CTRL3 = (SM_CMD_CTRL3 & 0xFC) | (BYTE)(SectByteCount/0x0100); +// if ( ((fdoExt->ChipID==READER_CB712)&&(fdoExt->RevID==CHIP_A)) || fdoExt->IsHibernate ) +// SM_FIFO_CTRL = (SM_APB08_MASK | SM_DMAEN_MASK | SM_DMA_UPSTREAM_MASK | SM_FIFOSHLDVLU_8_MASK); +// else +// SM_FIFO_CTRL = (SM_APB32_MASK | SM_DMAEN_MASK | SM_DMA_UPSTREAM_MASK | SM_FIFOSHLDVLU_8_MASK); +// +// _Hw_D_EccRdReset(); +// _Hw_D_EccRdStart(); +// +// SM_CMD_CTRL1 = (SM_CMD_READ_1); +// SM_CMD_CTRL1 = (SM_CMD_READ_1 | SM_CMD_START_BIT); +// +// SectByteCount = 0x1ff; +// //SM_ReadDataWithDMA(fdoExt, buf, SectByteCount); +// //_ReadRedt_D_SsfdcBuf(redundant); +// len = 0x1000 - ((WORD)(buf) & 0x0FFF); +// if (len < 0x200) +// { +// SM_ReadDataWithDMA(fdoExt, buf, len-1); +// SM_ReadDataWithDMA(fdoExt, buf+len, SectByteCount-len); +// //ENE_Print("Read DMA !!! buf1 = %p, len = %x, buf2 = %p\n", buf, len, buf+len); +// } +// else +// SM_ReadDataWithDMA(fdoExt, buf, SectByteCount); +// +// if ( ((fdoExt->ChipID==READER_CB712)&&(fdoExt->RevID==CHIP_A)) || fdoExt->IsHibernate ) +// { +// _ReadRedt_D_SsfdcBuf(redundant); +// } +// else +// { +// Buffer[0] = READ_PORT_DWORD(SM_REG_DATA); +// Buffer[1] = READ_PORT_DWORD(SM_REG_DATA); +// Buffer[2] = READ_PORT_DWORD(SM_REG_DATA); +// Buffer[3] = READ_PORT_DWORD(SM_REG_DATA); +// memcpy(redundant, Buffer, 0x10); +// } +// +// while ( _Hw_D_ChkCardIn() ) +// { +// if((READ_PORT_BYTE(SM_REG_INT_STATUS) & 0x10)) +// { +// WRITE_PORT_BYTE(SM_REG_INT_STATUS, 0x10); +// break; +// } +// } +// _Hw_D_EccRdStop(); +// _Hw_D_SetRdStandby(); +// _Load_D_SsfdcRdHwECC(EVEN); +// +// _Calc_D_ECCdata(buf); +// _Set_D_SsfdcRdStandby(); +// +// if (!_Hw_D_ChkCardIn()) +// return(ERROR); +// return(SMSUCCESS); +//} +// +////----- Ssfdc_D_ReadSect_PIO() --------------------------------------------- +//int Ssfdc_D_ReadSect_PIO(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant) +//{ +// _Set_D_SsfdcRdCmd(READ); +// _Set_D_SsfdcRdAddr(EVEN); +// +// if (_Check_D_SsfdcBusy(BUSY_READ)) +// { _Reset_D_SsfdcErr(); return(ERROR); } +// +// _Start_D_SsfdcRdHwECC(); +// _Read_D_SsfdcBuf(buf); +// _Stop_D_SsfdcRdHwECC(); +// _ReadRedt_D_SsfdcBuf(redundant); +// _Load_D_SsfdcRdHwECC(EVEN); +// +// if (_Check_D_SsfdcBusy(BUSY_READ)) +// { _Reset_D_SsfdcErr(); return(ERROR); } +// +// _Calc_D_ECCdata(buf); +// _Set_D_SsfdcRdStandby(); +// return(SMSUCCESS); +//} + +// 6250 CMD 3 +//----- Ssfdc_D_WriteSect() -------------------------------------------- +int Ssfdc_D_WriteSect(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant) +{ + PBULK_CBW pBulkCbw = fdoExt->pBulkCbw; + NTSTATUS ntStatus; + WORD addr; + + //ENE_Print("SMILSUB --- Ssfdc_D_WriteSect\n"); + ENE_LoadBinCode(fdoExt, SM_RW_PATTERN); + + addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; + addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; + + // Write sect data + RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW)); + pBulkCbw->dCBWSignature = CBW_SIGNTURE; + pBulkCbw->bCBWLun = CBW_LUN; + pBulkCbw->dCBWDataTransferLength = 0x200; + pBulkCbw->bmCBWFlags = 0x00; + pBulkCbw->CBWCb[0] = 0xF0; + pBulkCbw->CBWCb[1] = 0x04; + //pBulkCbw->CBWCb[4] = (BYTE)addr; + //pBulkCbw->CBWCb[3] = (BYTE)(addr/0x0100); + //pBulkCbw->CBWCb[2] = Media.Zone/2; + //pBulkCbw->CBWCb[5] = *(redundant+REDT_ADDR1H); + //pBulkCbw->CBWCb[6] = *(redundant+REDT_ADDR1L); + pBulkCbw->CBWCb[7] = (BYTE)addr; + pBulkCbw->CBWCb[6] = (BYTE)(addr/0x0100); + pBulkCbw->CBWCb[5] = Media.Zone/2; + pBulkCbw->CBWCb[8] = *(redundant+REDT_ADDR1H); + pBulkCbw->CBWCb[9] = *(redundant+REDT_ADDR1L); + + ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_WRITE, buf); + + if (!NT_SUCCESS(ntStatus)) + return(ERROR); + +// // For Test +// { +// BYTE bf[0x200], rdd[0x10]; +// ULONG i; +// +// RtlZeroMemory(bf, 0x200); +// RtlZeroMemory(rdd, 0x10); +// ntStatus = SM_ReadBlock(fdoExt, bf, rdd); +// for (i=0; i<0x200; i++) +// { +// if (buf[i] != bf[i]) +// ENE_Print("buf[%x] = %x, bf[%x] = %x\n", buf, bf); +// } +// if (!NT_SUCCESS(ntStatus)) +// ENE_Print("Error\n"); +// } + + return(SMSUCCESS); +} +*/ +//----- Ssfdc_D_CopyBlock() -------------------------------------------- +int Ssfdc_D_CopyBlock(struct us_data *us, WORD count, BYTE *buf,BYTE *redundant) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; + //PBULK_CBW pBulkCbw = fdoExt->pBulkCbw; + //NTSTATUS ntStatus; WORD ReadAddr, WriteAddr; + //printk("Ssfdc_D_WriteSect --- ZONE = %x, ReadBlock = %x, WriteBlock = %x\n", Media.Zone, ReadBlock, WriteBlock); + result = ENE_LoadBinCode(us, SM_RW_PATTERN); - if (result != USB_STOR_XFER_GOOD) { + if (result != USB_STOR_XFER_GOOD) + { printk("Load SM RW Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - ReadAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks + ReadBlock; + ReadAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks+ReadBlock; ReadAddr = ReadAddr*(WORD)Ssfdc.MaxSectors; - WriteAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks + WriteBlock; + WriteAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks+WriteBlock; WriteAddr = WriteAddr*(WORD)Ssfdc.MaxSectors; - /* Write sect data */ + // Write sect data memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200*count; @@ -329,17 +541,19 @@ int Ssfdc_D_CopyBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant bcb->CDB[0] = 0xF0; bcb->CDB[1] = 0x08; bcb->CDB[7] = (BYTE)WriteAddr; - bcb->CDB[6] = (BYTE)(WriteAddr / 0x0100); - bcb->CDB[5] = Media.Zone / 2; - bcb->CDB[8] = *(redundant + REDT_ADDR1H); - bcb->CDB[9] = *(redundant + REDT_ADDR1L); + bcb->CDB[6] = (BYTE)(WriteAddr/0x0100); + bcb->CDB[5] = Media.Zone/2; + bcb->CDB[8] = *(redundant+REDT_ADDR1H); + bcb->CDB[9] = *(redundant+REDT_ADDR1L); bcb->CDB[10] = Media.Sector; - if (ReadBlock != NO_ASSIGN) { + if (ReadBlock != NO_ASSIGN) + { bcb->CDB[4] = (BYTE)ReadAddr; - bcb->CDB[3] = (BYTE)(ReadAddr / 0x0100); - bcb->CDB[2] = Media.Zone / 2; - } else + bcb->CDB[3] = (BYTE)(ReadAddr/0x0100); + bcb->CDB[2] = Media.Zone/2; + } + else bcb->CDB[11] = 1; result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0); @@ -348,25 +562,196 @@ int Ssfdc_D_CopyBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant return USB_STOR_TRANSPORT_GOOD; } - -/* ----- Ssfdc_D_WriteSectForCopy() ------------------------------------- */ +/* +//----- Ssfdc_D_WriteBlock() -------------------------------------------- +int Ssfdc_D_WriteBlock(PFDO_DEVICE_EXTENSION fdoExt, WORD count, BYTE *buf,BYTE *redundant) +{ + PBULK_CBW pBulkCbw = fdoExt->pBulkCbw; + NTSTATUS ntStatus; + WORD addr; + + //ENE_Print("SMILSUB --- Ssfdc_D_WriteSect\n"); + ENE_LoadBinCode(fdoExt, SM_RW_PATTERN); + + addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; + addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; + + // Write sect data + RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW)); + pBulkCbw->dCBWSignature = CBW_SIGNTURE; + pBulkCbw->bCBWLun = CBW_LUN; + pBulkCbw->dCBWDataTransferLength = 0x200*count; + pBulkCbw->bmCBWFlags = 0x00; + pBulkCbw->CBWCb[0] = 0xF0; + pBulkCbw->CBWCb[1] = 0x04; + pBulkCbw->CBWCb[7] = (BYTE)addr; + pBulkCbw->CBWCb[6] = (BYTE)(addr/0x0100); + pBulkCbw->CBWCb[5] = Media.Zone/2; + pBulkCbw->CBWCb[8] = *(redundant+REDT_ADDR1H); + pBulkCbw->CBWCb[9] = *(redundant+REDT_ADDR1L); + + ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_WRITE, buf); + + if (!NT_SUCCESS(ntStatus)) + return(ERROR); + +// // For Test +// { +// BYTE bf[0x200], rdd[0x10]; +// ULONG i; +// +// RtlZeroMemory(bf, 0x200); +// RtlZeroMemory(rdd, 0x10); +// ntStatus = SM_ReadBlock(fdoExt, bf, rdd); +// for (i=0; i<0x200; i++) +// { +// if (buf[i] != bf[i]) +// ENE_Print("buf[%x] = %x, bf[%x] = %x\n", buf, bf); +// } +// if (!NT_SUCCESS(ntStatus)) +// ENE_Print("Error\n"); +// } + + return(SMSUCCESS); +} +// +////----- Ssfdc_D_WriteSect_DMA() -------------------------------------------- +//int Ssfdc_D_WriteSect_DMA(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant) +//{ +// WORD SectByteCount, addr; +// DWORD Buffer[4]; +// WORD len; +// +// if (!_Hw_D_ChkCardIn()) +// return(ERROR); +// addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; +// addr=addr*(WORD)Ssfdc.MaxSectors+Media.Sector; +// // cycle starting address +// SM_STARTADDR_LSB = 0x00; +// SM_STARTADDR_IISB = (BYTE)addr; +// SM_STARTADDR_IIISB = (BYTE)(addr/0x0100); +// SM_STARTADDR_MSB = Media.Zone/2; +// +// //Sector byte count (DMA) +// SectByteCount = 0x20f; +// SM_BYTECNT_LO = (BYTE)SectByteCount; +// SM_CMD_CTRL3 = (SM_CMD_CTRL3 & 0xFC) | 0x20 | (BYTE)(SectByteCount/0x0100); +// if ( ((fdoExt->ChipID==READER_CB712)&&(fdoExt->RevID==CHIP_A)) || fdoExt->IsHibernate ) +// SM_FIFO_CTRL = (SM_APB08_MASK | SM_DMAEN_MASK | SM_DMA_DOWNSTREAM_MASK | SM_FIFOSHLDVLU_8_MASK); +// else +// SM_FIFO_CTRL = (SM_APB32_MASK | SM_DMAEN_MASK | SM_DMA_DOWNSTREAM_MASK | SM_FIFOSHLDVLU_8_MASK); +// +// _Hw_D_EccRdReset(); +// _Hw_D_EccRdStart(); +// +// SM_CMD_CTRL1 = SM_CMD_PAGPRGM_TRUE; +// SM_CMD_CTRL1 = (SM_CMD_PAGPRGM_TRUE | SM_CMD_START_BIT); +// +// SectByteCount = 0x1ff; +// //SM_WriteDataWithDMA(fdoExt, buf, SectByteCount); +// //_WriteRedt_D_SsfdcBuf(redundant); +// len = 0x1000 - ((WORD)(buf) & 0x0FFF); +// if (len < 0x200) +// { +// SM_WriteDataWithDMA(fdoExt, buf, len-1); +// SM_WriteDataWithDMA(fdoExt, buf+len, SectByteCount-len); +// //ENE_Print("Read DMA !!! buf1 = %p, len = %x, buf2 = %p\n", buf, len, buf+len); +// } +// else +// SM_WriteDataWithDMA(fdoExt, buf, SectByteCount); +// +// //T1 = (ULONGLONG)buf & 0xFFFFFFFFFFFFF000; +// //T2 = ((ULONGLONG)buf + 0x1FF) & 0xFFFFFFFFFFFFF000; +// //if (T1 != T2) +// // ENE_Print("Ssfdc_D_WriteSect_DMA !!! buf = %p, T1 = %p, T2 = %p\n", buf, T1, T2); +// //if (T2-T1) +// //{ +// // l1 = (WORD)(T2 - (ULONGLONG)buf); +// // SM_WriteDataWithDMA(fdoExt, buf, l1-1); +// // SM_WriteDataWithDMA(fdoExt, (PBYTE)T2, SectByteCount-l1); +// //} +// //else +// // SM_WriteDataWithDMA(fdoExt, buf, SectByteCount); +// +// if ( ((fdoExt->ChipID==READER_CB712)&&(fdoExt->RevID==CHIP_A)) || fdoExt->IsHibernate ) +// { +// _WriteRedt_D_SsfdcBuf(redundant); +// } +// else +// { +// memcpy(Buffer, redundant, 0x10); +// WRITE_PORT_DWORD(SM_REG_DATA, Buffer[0]); +// WRITE_PORT_DWORD(SM_REG_DATA, Buffer[1]); +// WRITE_PORT_DWORD(SM_REG_DATA, Buffer[2]); +// WRITE_PORT_DWORD(SM_REG_DATA, Buffer[3]); +// } +// +// while ( _Hw_D_ChkCardIn() ) +// { +// if ((READ_PORT_BYTE(SM_REG_INT_STATUS) & 0x10)) +// { +// WRITE_PORT_BYTE(SM_REG_INT_STATUS, 0x10); +// break; +// } +// } +// _Hw_D_EccRdStop(); +// _Hw_D_SetRdStandby(); +// +// _Set_D_SsfdcWrStandby(); +// _Set_D_SsfdcRdStandby(); +// if (!_Hw_D_ChkCardIn()) +// return(ERROR); +// +// return(SMSUCCESS); +//} +// +////----- Ssfdc_D_WriteSect_PIO() -------------------------------------------- +//int Ssfdc_D_WriteSect_PIO(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant) +//{ +// _Calc_D_ECCdata(buf); +// _Set_D_SsfdcWrCmd(WRDATA); +// _Set_D_SsfdcWrAddr(EVEN); +// _Start_D_SsfdcWrHwECC(); +// +// _Write_D_SsfdcBuf(buf); +// +// _Load_D_SsfdcWrHwECC(EVEN); +// _Set_D_ECCdata(EVEN,redundant); +// +// _WriteRedt_D_SsfdcBuf(redundant); +// +// _Set_D_SsfdcWrCmd(WRITE); +// +// if (_Check_D_SsfdcBusy(BUSY_PROG)) +// { _Reset_D_SsfdcErr(); return(ERROR); } +// +// _Set_D_SsfdcWrStandby(); +// _Set_D_SsfdcRdStandby(); +// return(SMSUCCESS); +//} +*/ +//----- Ssfdc_D_WriteSectForCopy() ------------------------------------- int Ssfdc_D_WriteSectForCopy(struct us_data *us, BYTE *buf, BYTE *redundant) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; - WORD addr; + //PBULK_CBW pBulkCbw = fdoExt->pBulkCbw; + //NTSTATUS ntStatus; + WORD addr; + //printk("SMILSUB --- Ssfdc_D_WriteSectForCopy\n"); result = ENE_LoadBinCode(us, SM_RW_PATTERN); - if (result != USB_STOR_XFER_GOOD) { + if (result != USB_STOR_XFER_GOOD) + { printk("Load SM RW Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock; - addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector; + addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; + addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; - /* Write sect data */ + // Write sect data memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; @@ -374,10 +759,10 @@ int Ssfdc_D_WriteSectForCopy(struct us_data *us, BYTE *buf, BYTE *redundant) bcb->CDB[0] = 0xF0; bcb->CDB[1] = 0x04; bcb->CDB[7] = (BYTE)addr; - bcb->CDB[6] = (BYTE)(addr / 0x0100); - bcb->CDB[5] = Media.Zone / 2; - bcb->CDB[8] = *(redundant + REDT_ADDR1H); - bcb->CDB[9] = *(redundant + REDT_ADDR1L); + bcb->CDB[6] = (BYTE)(addr/0x0100); + bcb->CDB[5] = Media.Zone/2; + bcb->CDB[8] = *(redundant+REDT_ADDR1H); + bcb->CDB[9] = *(redundant+REDT_ADDR1L); result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0); if (result != USB_STOR_XFER_GOOD) @@ -386,8 +771,8 @@ int Ssfdc_D_WriteSectForCopy(struct us_data *us, BYTE *buf, BYTE *redundant) return USB_STOR_TRANSPORT_GOOD; } -/* 6250 CMD 5 */ -/* ----- Ssfdc_D_EraseBlock() ------------------------------------------- */ +// 6250 CMD 5 +//----- Ssfdc_D_EraseBlock() ------------------------------------------- int Ssfdc_D_EraseBlock(struct us_data *us) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; @@ -395,13 +780,14 @@ int Ssfdc_D_EraseBlock(struct us_data *us) WORD addr; result = ENE_LoadBinCode(us, SM_RW_PATTERN); - if (result != USB_STOR_XFER_GOOD) { + if (result != USB_STOR_XFER_GOOD) + { printk("Load SM RW Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock; - addr = addr*(WORD)Ssfdc.MaxSectors; + addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; + addr=addr*(WORD)Ssfdc.MaxSectors; memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); @@ -410,8 +796,8 @@ int Ssfdc_D_EraseBlock(struct us_data *us) bcb->CDB[0] = 0xF2; bcb->CDB[1] = 0x06; bcb->CDB[7] = (BYTE)addr; - bcb->CDB[6] = (BYTE)(addr / 0x0100); - bcb->CDB[5] = Media.Zone / 2; + bcb->CDB[6] = (BYTE)(addr/0x0100); + bcb->CDB[5] = Media.Zone/2; result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0); if (result != USB_STOR_XFER_GOOD) @@ -420,23 +806,24 @@ int Ssfdc_D_EraseBlock(struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -/* 6250 CMD 2 */ -/*----- Ssfdc_D_ReadRedtData() ----------------------------------------- */ +// 6250 CMD 2 +//----- Ssfdc_D_ReadRedtData() ----------------------------------------- int Ssfdc_D_ReadRedtData(struct us_data *us, BYTE *redundant) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; WORD addr; - BYTE *buf; + BYTE *buf; result = ENE_LoadBinCode(us, SM_RW_PATTERN); - if (result != USB_STOR_XFER_GOOD) { + if (result != USB_STOR_XFER_GOOD) + { printk("Load SM RW Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock; - addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector; + addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; + addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); @@ -445,12 +832,13 @@ int Ssfdc_D_ReadRedtData(struct us_data *us, BYTE *redundant) bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x03; bcb->CDB[4] = (BYTE)addr; - bcb->CDB[3] = (BYTE)(addr / 0x0100); - bcb->CDB[2] = Media.Zone / 2; + bcb->CDB[3] = (BYTE)(addr/0x0100); + bcb->CDB[2] = Media.Zone/2; bcb->CDB[8] = 0; bcb->CDB[9] = 1; buf = kmalloc(0x10, GFP_KERNEL); + //result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0); result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0); memcpy(redundant, buf, 0x10); kfree(buf); @@ -460,22 +848,25 @@ int Ssfdc_D_ReadRedtData(struct us_data *us, BYTE *redundant) return USB_STOR_TRANSPORT_GOOD; } -/* 6250 CMD 4 */ -/* ----- Ssfdc_D_WriteRedtData() ---------------------------------------- */ +// 6250 CMD 4 +//----- Ssfdc_D_WriteRedtData() ---------------------------------------- int Ssfdc_D_WriteRedtData(struct us_data *us, BYTE *redundant) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; + //PBULK_CBW pBulkCbw = fdoExt->pBulkCbw; + //NTSTATUS ntStatus; WORD addr; result = ENE_LoadBinCode(us, SM_RW_PATTERN); - if (result != USB_STOR_XFER_GOOD) { + if (result != USB_STOR_XFER_GOOD) + { printk("Load SM RW Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock; - addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector; + addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; + addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); @@ -484,10 +875,10 @@ int Ssfdc_D_WriteRedtData(struct us_data *us, BYTE *redundant) bcb->CDB[0] = 0xF2; bcb->CDB[1] = 0x05; bcb->CDB[7] = (BYTE)addr; - bcb->CDB[6] = (BYTE)(addr / 0x0100); - bcb->CDB[5] = Media.Zone / 2; - bcb->CDB[8] = *(redundant + REDT_ADDR1H); - bcb->CDB[9] = *(redundant + REDT_ADDR1L); + bcb->CDB[6] = (BYTE)(addr/0x0100); + bcb->CDB[5] = Media.Zone/2; + bcb->CDB[8] = *(redundant+REDT_ADDR1H); + bcb->CDB[9] = *(redundant+REDT_ADDR1L); result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0); if (result != USB_STOR_XFER_GOOD) @@ -496,167 +887,609 @@ int Ssfdc_D_WriteRedtData(struct us_data *us, BYTE *redundant) return USB_STOR_TRANSPORT_GOOD; } -/* ----- Ssfdc_D_CheckStatus() ------------------------------------------ */ +//----- Ssfdc_D_CheckStatus() ------------------------------------------ int Ssfdc_D_CheckStatus(void) { - return SMSUCCESS; + // Driver ¤£°µ + return(SMSUCCESS); + //_Set_D_SsfdcRdCmd(RDSTATUS); + // + //if (_Check_D_SsfdcStatus()) + //{ _Set_D_SsfdcRdStandby(); return(ERROR); } + // + //_Set_D_SsfdcRdStandby(); + //return(SMSUCCESS); } - - - -/* SmartMedia ID Code Check & Mode Set Subroutine - * ----- Set_D_SsfdcModel() --------------------------------------------- - */ +/* +////NAND Memory (SmartMedia) Control Subroutine for Read Data +////----- _Set_D_SsfdcRdCmd() -------------------------------------------- +//void _Set_D_SsfdcRdCmd(BYTE cmd) +//{ +// _Hw_D_SetRdCmd(); +// _Hw_D_OutData(cmd); +// _Hw_D_SetRdData(); +//} +// +////----- _Set_D_SsfdcRdAddr() ------------------------------------------- +//void _Set_D_SsfdcRdAddr(BYTE add) +//{ +// WORD addr; +// SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc; +// ADDRESS_T bb = (ADDRESS_T) &Media; +// +// addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; +// addr=addr*(WORD)Ssfdc.MaxSectors+Media.Sector; +// +// //if ((Ssfdc.Attribute &MPS)==PS256) // for 256byte/page +// // addr=addr*2+(WORD)add; +// +// _Hw_D_SetRdAddr(); +// _Hw_D_OutData(0x00); +// _Hw_D_OutData((BYTE)addr); +// _Hw_D_OutData((BYTE)(addr/0x0100)); +// +// if ((Ssfdc.Attribute &MADC)==AD4CYC) +// _Hw_D_OutData((BYTE)(Media.Zone/2)); // Patch +// +// _Hw_D_SetRdData(); +//} +// +////----- _Set_D_SsfdcRdChip() ------------------------------------------- +//void _Set_D_SsfdcRdChip(void) +//{ +// _Hw_D_SetRdAddr(); +// _Hw_D_OutData(0x00); +// _Hw_D_SetRdData(); +//} +// +////----- _Set_D_SsfdcRdStandby() ---------------------------------------- +//void _Set_D_SsfdcRdStandby(void) +//{ +// _Hw_D_SetRdStandby(); +//} +// +////----- _Start_D_SsfdcRdHwECC() ---------------------------------------- +//void _Start_D_SsfdcRdHwECC(void) +//{ +//#ifdef HW_ECC_SUPPORTED +// _Hw_D_EccRdReset(); +// _Hw_D_InData(); +// _Hw_D_EccRdStart(); +//#endif +//} +// +////----- _Stop_D_SsfdcRdHwECC() ----------------------------------------- +//void _Stop_D_SsfdcRdHwECC(void) +//{ +//#ifdef HW_ECC_SUPPORTED +// _Hw_D_EccRdStop(); +//#endif +//} +// +////----- _Load_D_SsfdcRdHwECC() ----------------------------------------- +//void _Load_D_SsfdcRdHwECC(BYTE add) +//{ +//#ifdef HW_ECC_SUPPORTED +// _Hw_D_EccRdRead(); +// //if (!(add==ODD && (Ssfdc.Attribute &MPS)==PS256)) +// { +// EccBuf[0]=_Hw_D_InData(); +// EccBuf[1]=_Hw_D_InData(); +// EccBuf[2]=_Hw_D_InData(); +// } +// +// //if (!(add==EVEN && (Ssfdc.Attribute &MPS)==PS256)) +// { +// EccBuf[3]=_Hw_D_InData(); +// EccBuf[4]=_Hw_D_InData(); +// EccBuf[5]=_Hw_D_InData(); +// } +// +// _Hw_D_EccRdStop(); +//#endif +//} +// +////NAND Memory (SmartMedia) Control Subroutine for Write Data +// +////----- _Set_D_SsfdcWrCmd() ----------------------------------------- +//void _Set_D_SsfdcWrCmd(BYTE cmd) +//{ +// _Hw_D_SetWrCmd(); +// _Hw_D_OutData(cmd); +// _Hw_D_SetWrData(); +//} +// +////----- _Set_D_SsfdcWrAddr() ----------------------------------------- +//void _Set_D_SsfdcWrAddr(BYTE add) +//{ +// WORD addr; +// SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc; +// ADDRESS_T bb = (ADDRESS_T) &Media; +// +// addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; +// addr=addr*(WORD)Ssfdc.MaxSectors+Media.Sector; +// +// //if ((Ssfdc.Attribute &MPS)==PS256) // for 256byte/page +// // addr=addr*2+(WORD)add; +// +// _Hw_D_SetWrAddr(); +// _Hw_D_OutData(0x00); +// _Hw_D_OutData((BYTE)addr); +// _Hw_D_OutData((BYTE)(addr/0x0100)); +// +// if ((Ssfdc.Attribute &MADC)==AD4CYC) +// _Hw_D_OutData((BYTE)(Media.Zone/2)); // Patch +// +// _Hw_D_SetWrData(); +//} +// +////----- _Set_D_SsfdcWrBlock() ----------------------------------------- +//void _Set_D_SsfdcWrBlock(void) +//{ +// WORD addr; +// SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc; +// ADDRESS_T bb = (ADDRESS_T) &Media; +// +// addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; +// addr=addr*(WORD)Ssfdc.MaxSectors; +// +// //if ((Ssfdc.Attribute &MPS)==PS256) // for 256byte/page +// // addr=addr*2; +// +// _Hw_D_SetWrAddr(); +// _Hw_D_OutData((BYTE)addr); +// _Hw_D_OutData((BYTE)(addr/0x0100)); +// +// if ((Ssfdc.Attribute &MADC)==AD4CYC) +// _Hw_D_OutData((BYTE)(Media.Zone/2)); // Patch +// +// _Hw_D_SetWrData(); +//} +// +////----- _Set_D_SsfdcWrStandby() ----------------------------------------- +//void _Set_D_SsfdcWrStandby(void) +//{ +// _Hw_D_SetWrStandby(); +//} +// +////----- _Start_D_SsfdcWrHwECC() ----------------------------------------- +//void _Start_D_SsfdcWrHwECC(void) +//{ +//#ifdef HW_ECC_SUPPORTED +// _Hw_D_EccWrReset(); +// _Hw_D_InData(); +// _Hw_D_EccWrStart(); +//#endif +//} +// +////----- _Load_D_SsfdcWrHwECC() ----------------------------------------- +//void _Load_D_SsfdcWrHwECC(BYTE add) +//{ +//#ifdef HW_ECC_SUPPORTED +// _Hw_D_EccWrRead(); +// //if (!(add==ODD && (Ssfdc.Attribute &MPS)==PS256)) +// { +// EccBuf[0]=_Hw_D_InData(); +// EccBuf[1]=_Hw_D_InData(); +// EccBuf[2]=_Hw_D_InData(); +// } +// +// //if (!(add==EVEN && (Ssfdc.Attribute &MPS)==PS256)) +// { +// EccBuf[3]=_Hw_D_InData(); +// EccBuf[4]=_Hw_D_InData(); +// EccBuf[5]=_Hw_D_InData(); +// } +// +// _Hw_D_EccWrStop(); +//#endif +//} +// +////NAND Memory (SmartMedia) Control Subroutine +////----- _Check_D_SsfdcBusy() ------------------------------------------- +//int _Check_D_SsfdcBusy(WORD time) +//{ +// WORD count = 0; +// +// do { +// if (!_Hw_D_ChkBusy()) +// return(SMSUCCESS); +// EDelay(100); +// count++; +// } while (count<=time); +// +// return(ERROR); +//} +// +////----- _Check_D_SsfdcStatus() ----------------------------------------- +//int _Check_D_SsfdcStatus(void) +//{ +// if (_Hw_D_InData() & WR_FAIL) +// return(ERROR); +// +// return(SMSUCCESS); +//} +// +//// For 712 +////----- _Reset_D_SsfdcErr() ----------------------------------------- +//void _Reset_D_SsfdcErr(void) +//{ +// WORD count = 0; +// +// _Hw_D_SetRdCmd(); +// _Hw_D_OutData(RST_CHIP); +// _Hw_D_SetRdData(); +// +// do { +// if (!_Hw_D_ChkBusy()) +// break; +// EDelay(100); +// count++; +// } while (count<=BUSY_RESET); +// +// _Hw_D_SetRdStandby(); +//} +// +////NAND Memory (SmartMedia) Buffer Data Xfer Subroutine +////----- SM_ReadDataWithDMA() ----------------------------------------- +//void SM_ReadDataWithDMA(PFDO_DEVICE_EXTENSION fdoExt, BYTE *databuf, WORD SectByteCount) +//{ +// PHYSICAL_ADDRESS Addr; +// LARGE_INTEGER ptimeout ; +// +// KeClearEvent(&fdoExt->SM_DMADoneEvent); +// +// Addr = MmGetPhysicalAddress(databuf); +// +// WRITE_PORT_DWORD(SM_DMA_ADDR_REG, (DWORD)Addr.LowPart); +// WRITE_PORT_BYTE(SM_DMA_DATA_CTRL, 0); +// WRITE_PORT_WORD(SM_DMA_BYTE_COUNT_REG, SectByteCount); +// +// while ( _Hw_D_ChkCardIn() ) +// { +// if ((READ_PORT_BYTE(SM_REG_FIFO_STATUS) & 0x80)) +// break; +// } +// if (!_Hw_D_ChkCardIn()) return; +// WRITE_PORT_BYTE(SM_DMA_DATA_CTRL, 0x01); +// +// ptimeout.QuadPart = 2000 * (-10000); // 2 sec +// KeWaitForSingleObject(&fdoExt->SM_DMADoneEvent, Executive, KernelMode, FALSE, &ptimeout); +// _Hw_D_SetDMAIntMask(); +//} +// +////----- SM_WriteDataWithDMA() ----------------------------------------- +//void SM_WriteDataWithDMA(PFDO_DEVICE_EXTENSION fdoExt, BYTE *databuf, WORD SectByteCount) +//{ +// PHYSICAL_ADDRESS Addr; +// LARGE_INTEGER ptimeout ; +// +// KeClearEvent(&fdoExt->SM_DMADoneEvent); +// +// Addr = MmGetPhysicalAddress(databuf); +// +// WRITE_PORT_DWORD(SM_DMA_ADDR_REG, (DWORD)Addr.LowPart); +// WRITE_PORT_BYTE(SM_DMA_DATA_CTRL, 2); +// WRITE_PORT_WORD(SM_DMA_BYTE_COUNT_REG, SectByteCount); +// +// while ( _Hw_D_ChkCardIn() ) +// { +// if ((READ_PORT_BYTE(SM_REG_FIFO_STATUS) & 0x40)) +// break; +// } +// if (!_Hw_D_ChkCardIn()) return; +// WRITE_PORT_BYTE(SM_DMA_DATA_CTRL, 0x03); +// +// ptimeout.QuadPart = 2000 * (-10000); // 2 sec +// KeWaitForSingleObject(&fdoExt->SM_DMADoneEvent, Executive, KernelMode, FALSE, &ptimeout); +// _Hw_D_SetDMAIntMask(); +//} +// +////----- _Read_D_SsfdcBuf() ----------------------------------------- +//void _Read_D_SsfdcBuf(BYTE *databuf) +//{ +// int i; +// +// //for(i=0x0000;i<(((Ssfdc.Attribute &MPS)==PS256)?0x0100:0x0200);i++) +// for(i=0; i<0x200; i++) +// *databuf++ =_Hw_D_InData(); +//} +// +////----- _Write_D_SsfdcBuf() ----------------------------------------- +//void _Write_D_SsfdcBuf(BYTE *databuf) +//{ +// int i; +// +// //for(i=0x0000;i<(((Ssfdc.Attribute &MPS)==PS256)?0x0100:0x0200);i++) +// for(i=0; i<0x200; i++) +// _Hw_D_OutData(*databuf++); +//} +// +////----- _Read_D_SsfdcByte() ----------------------------------------- +//void _Read_D_SsfdcByte(BYTE *databuf) +//{ +// *databuf=(BYTE)_Hw_D_InData(); +//} +// +////----- _ReadRedt_D_SsfdcBuf() ----------------------------------------- +//void _ReadRedt_D_SsfdcBuf(BYTE *redundant) +//{ +// char i; +// +// //for(i=0x00;i<(((Ssfdc.Attribute &MPS)==PS256)?0x08:0x10);i++) +// for(i=0; i<0x10; i++) +// redundant[i] =_Hw_D_InData(); +//} +// +////----- _WriteRedt_D_SsfdcBuf() ----------------------------------------- +//void _WriteRedt_D_SsfdcBuf(BYTE *redundant) +//{ +// char i; +// +// //for(i=0x00;i<(((Ssfdc.Attribute &MPS)==PS256)?0x08:0x10);i++) +// for(i=0; i<0x10; i++) +// _Hw_D_OutData(*redundant++); +//} +*/ +//SmartMedia ID Code Check & Mode Set Subroutine +//----- Set_D_SsfdcModel() --------------------------------------------- int Set_D_SsfdcModel(BYTE dcode) { - switch (_Check_D_DevCode(dcode)) { - case SSFDC1MB: - Ssfdc.Model = SSFDC1MB; - Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS256; - Ssfdc.MaxZones = 1; - Ssfdc.MaxBlocks = 256; - Ssfdc.MaxLogBlocks = 250; - Ssfdc.MaxSectors = 8; - break; - case SSFDC2MB: - Ssfdc.Model = SSFDC2MB; - Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS256; - Ssfdc.MaxZones = 1; - Ssfdc.MaxBlocks = 512; - Ssfdc.MaxLogBlocks = 500; - Ssfdc.MaxSectors = 8; - break; - case SSFDC4MB: - Ssfdc.Model = SSFDC4MB; - Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS512; - Ssfdc.MaxZones = 1; - Ssfdc.MaxBlocks = 512; - Ssfdc.MaxLogBlocks = 500; - Ssfdc.MaxSectors = 16; - break; - case SSFDC8MB: - Ssfdc.Model = SSFDC8MB; - Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS512; - Ssfdc.MaxZones = 1; - Ssfdc.MaxBlocks = 1024; - Ssfdc.MaxLogBlocks = 1000; - Ssfdc.MaxSectors = 16; - break; - case SSFDC16MB: - Ssfdc.Model = SSFDC16MB; - Ssfdc.Attribute = FLASH | AD3CYC | BS32 | PS512; - Ssfdc.MaxZones = 1; - Ssfdc.MaxBlocks = 1024; - Ssfdc.MaxLogBlocks = 1000; - Ssfdc.MaxSectors = 32; - break; - case SSFDC32MB: - Ssfdc.Model = SSFDC32MB; - Ssfdc.Attribute = FLASH | AD3CYC | BS32 | PS512; - Ssfdc.MaxZones = 2; - Ssfdc.MaxBlocks = 1024; - Ssfdc.MaxLogBlocks = 1000; - Ssfdc.MaxSectors = 32; - break; - case SSFDC64MB: - Ssfdc.Model = SSFDC64MB; - Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; - Ssfdc.MaxZones = 4; - Ssfdc.MaxBlocks = 1024; - Ssfdc.MaxLogBlocks = 1000; - Ssfdc.MaxSectors = 32; - break; - case SSFDC128MB: - Ssfdc.Model = SSFDC128MB; - Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; - Ssfdc.MaxZones = 8; - Ssfdc.MaxBlocks = 1024; - Ssfdc.MaxLogBlocks = 1000; - Ssfdc.MaxSectors = 32; - break; - case SSFDC256MB: - Ssfdc.Model = SSFDC256MB; - Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; - Ssfdc.MaxZones = 16; - Ssfdc.MaxBlocks = 1024; - Ssfdc.MaxLogBlocks = 1000; - Ssfdc.MaxSectors = 32; - break; - case SSFDC512MB: - Ssfdc.Model = SSFDC512MB; - Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; - Ssfdc.MaxZones = 32; - Ssfdc.MaxBlocks = 1024; - Ssfdc.MaxLogBlocks = 1000; - Ssfdc.MaxSectors = 32; - break; - case SSFDC1GB: - Ssfdc.Model = SSFDC1GB; - Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; - Ssfdc.MaxZones = 64; - Ssfdc.MaxBlocks = 1024; - Ssfdc.MaxLogBlocks = 1000; - Ssfdc.MaxSectors = 32; - break; - case SSFDC2GB: - Ssfdc.Model = SSFDC2GB; - Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; - Ssfdc.MaxZones = 128; - Ssfdc.MaxBlocks = 1024; - Ssfdc.MaxLogBlocks = 1000; - Ssfdc.MaxSectors = 32; - break; - default: - Ssfdc.Model = NOSSFDC; - return ERROR; - } - - return SMSUCCESS; + switch (_Check_D_DevCode(dcode)) { + case SSFDC1MB: + Ssfdc.Model = SSFDC1MB; + Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS256; + Ssfdc.MaxZones = 1; + Ssfdc.MaxBlocks = 256; + Ssfdc.MaxLogBlocks = 250; + Ssfdc.MaxSectors = 8; + break; + case SSFDC2MB: + Ssfdc.Model = SSFDC2MB; + Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS256; + Ssfdc.MaxZones = 1; + Ssfdc.MaxBlocks = 512; + Ssfdc.MaxLogBlocks = 500; + Ssfdc.MaxSectors = 8; + break; + case SSFDC4MB: + Ssfdc.Model = SSFDC4MB; + Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS512; + Ssfdc.MaxZones = 1; + Ssfdc.MaxBlocks = 512; + Ssfdc.MaxLogBlocks = 500; + Ssfdc.MaxSectors = 16; + break; + case SSFDC8MB: + Ssfdc.Model = SSFDC8MB; + Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS512; + Ssfdc.MaxZones = 1; + Ssfdc.MaxBlocks = 1024; + Ssfdc.MaxLogBlocks = 1000; + Ssfdc.MaxSectors = 16; + break; + case SSFDC16MB: + Ssfdc.Model = SSFDC16MB; + Ssfdc.Attribute = FLASH | AD3CYC | BS32 | PS512; + Ssfdc.MaxZones = 1; + Ssfdc.MaxBlocks = 1024; + Ssfdc.MaxLogBlocks = 1000; + Ssfdc.MaxSectors = 32; + break; + case SSFDC32MB: + Ssfdc.Model = SSFDC32MB; + Ssfdc.Attribute = FLASH | AD3CYC | BS32 | PS512; + Ssfdc.MaxZones = 2; + Ssfdc.MaxBlocks = 1024; + Ssfdc.MaxLogBlocks = 1000; + Ssfdc.MaxSectors = 32; + break; + case SSFDC64MB: + Ssfdc.Model = SSFDC64MB; + Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; + Ssfdc.MaxZones = 4; + Ssfdc.MaxBlocks = 1024; + Ssfdc.MaxLogBlocks = 1000; + Ssfdc.MaxSectors = 32; + break; + case SSFDC128MB: + Ssfdc.Model = SSFDC128MB; + Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; + Ssfdc.MaxZones = 8; + Ssfdc.MaxBlocks = 1024; + Ssfdc.MaxLogBlocks = 1000; + Ssfdc.MaxSectors = 32; + break; + case SSFDC256MB: + Ssfdc.Model = SSFDC256MB; + Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; + Ssfdc.MaxZones = 16; + Ssfdc.MaxBlocks = 1024; + Ssfdc.MaxLogBlocks = 1000; + Ssfdc.MaxSectors = 32; + break; + case SSFDC512MB: + Ssfdc.Model = SSFDC512MB; + Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; + Ssfdc.MaxZones = 32; + Ssfdc.MaxBlocks = 1024; + Ssfdc.MaxLogBlocks = 1000; + Ssfdc.MaxSectors = 32; + break; + case SSFDC1GB: + Ssfdc.Model = SSFDC1GB; + Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; + Ssfdc.MaxZones = 64; + Ssfdc.MaxBlocks = 1024; + Ssfdc.MaxLogBlocks = 1000; + Ssfdc.MaxSectors = 32; + break; + case SSFDC2GB: + Ssfdc.Model = SSFDC2GB; + Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512; + Ssfdc.MaxZones = 128; + Ssfdc.MaxBlocks = 1024; + Ssfdc.MaxLogBlocks = 1000; + Ssfdc.MaxSectors = 32; + break; + default: + Ssfdc.Model = NOSSFDC; + return(ERROR); + } + + return(SMSUCCESS); } -/* ----- _Check_D_DevCode() --------------------------------------------- */ +//----- _Check_D_DevCode() --------------------------------------------- BYTE _Check_D_DevCode(BYTE dcode) { - switch (dcode) { - case 0x6E: - case 0xE8: - case 0xEC: return SSFDC1MB; /* 8Mbit (1M) NAND */ - case 0x64: - case 0xEA: return SSFDC2MB; /* 16Mbit (2M) NAND */ - case 0x6B: - case 0xE3: - case 0xE5: return SSFDC4MB; /* 32Mbit (4M) NAND */ - case 0xE6: return SSFDC8MB; /* 64Mbit (8M) NAND */ - case 0x73: return SSFDC16MB; /* 128Mbit (16M)NAND */ - case 0x75: return SSFDC32MB; /* 256Mbit (32M)NAND */ - case 0x76: return SSFDC64MB; /* 512Mbit (64M)NAND */ - case 0x79: return SSFDC128MB; /* 1Gbit(128M)NAND */ - case 0x71: return SSFDC256MB; - case 0xDC: return SSFDC512MB; - case 0xD3: return SSFDC1GB; - case 0xD5: return SSFDC2GB; - default: return NOSSFDC; - } + switch(dcode){ + case 0x6E: + case 0xE8: + case 0xEC: return(SSFDC1MB); // 8Mbit (1M) NAND + case 0x64: + case 0xEA: return(SSFDC2MB); // 16Mbit (2M) NAND + case 0x6B: + case 0xE3: + case 0xE5: return(SSFDC4MB); // 32Mbit (4M) NAND + case 0xE6: return(SSFDC8MB); // 64Mbit (8M) NAND + case 0x73: return(SSFDC16MB); // 128Mbit (16M)NAND + case 0x75: return(SSFDC32MB); // 256Mbit (32M)NAND + case 0x76: return(SSFDC64MB); // 512Mbit (64M)NAND + case 0x79: return(SSFDC128MB); // 1Gbit(128M)NAND + case 0x71: return(SSFDC256MB); + case 0xDC: return(SSFDC512MB); + case 0xD3: return(SSFDC1GB); + case 0xD5: return(SSFDC2GB); + default: return(NOSSFDC); + } } - - - - -/* SmartMedia ECC Control Subroutine - * ----- Check_D_ReadError() ---------------------------------------------- - */ +/* +////SmartMedia Power Control Subroutine +////----- Cnt_D_Reset() ---------------------------------------------- +//void Cnt_D_Reset(void) +//{ +// _Hw_D_LedOff(); +// _Hw_D_SetRdStandby(); +// _Hw_D_VccOff(); +//} +// +////----- Cnt_D_PowerOn() ---------------------------------------------- +//int Cnt_D_PowerOn(void) +//{ +// // No support 5V. +// _Hw_D_EnableVcc3VOn(); // Set SM_REG_CTRL_5 Reg. to 3V +// _Hw_D_VccOn(); +// _Hw_D_SetRdStandby(); +// _Wait_D_Timer(TIME_PON); +// +// if (_Hw_D_ChkPower()) +// { +// _Hw_D_EnableOB(); // Set SM_REG_CTRL_5 Reg. to 0x83 +// return(SMSUCCESS); +// } +// +// _Hw_D_SetVccOff(); +// return(ERROR); +//} +// +////----- Cnt_D_PowerOff() ---------------------------------------------- +//void Cnt_D_PowerOff(void) +//{ +// _Hw_D_SetRdStandby(); +// _Hw_D_SetVccOff(); +// _Hw_D_VccOff(); +//} +// +////----- Cnt_D_LedOn() ---------------------------------------------- +//void Cnt_D_LedOn(void) +//{ +// _Hw_D_LedOn(); +//} +// +////----- Cnt_D_LedOff() ---------------------------------------------- +//void Cnt_D_LedOff(void) +//{ +// _Hw_D_LedOff(); +//} +// +////----- Check_D_CntPower() ---------------------------------------------- +//int Check_D_CntPower(void) +//{ +// if (_Hw_D_ChkPower()) +// return(SMSUCCESS); // Power On +// +// return(ERROR); // Power Off +//} +// +////----- Check_D_CardExist() ---------------------------------------------- +//int Check_D_CardExist(void) +//{ +// char i,j,k; +// +// if (!_Hw_D_ChkStatus()) // Not Status Change +// if (_Hw_D_ChkCardIn()) +// return(SMSUCCESS); // Card exist in Slot +// +// for(i=0,j=0,k=0; i<16; i++) { +// if (_Hw_D_ChkCardIn()) // Status Change +// { +// j++; k=0; +// } +// else +// { +// j=0; k++; +// } +// +// if (j>3) +// return(SMSUCCESS); // Card exist in Slot +// if (k>3) +// return(ERROR); // NO Card exist in Slot +// +// _Wait_D_Timer(TIME_CDCHK); +// } +// +// return(ERROR); +//} +// +////----- Check_D_CardStsChg() ---------------------------------------------- +//int Check_D_CardStsChg(void) +//{ +// if (_Hw_D_ChkStatus()) +// return(ERROR); // Status Change +// +// return(SMSUCCESS); // Not Status Change +//} +// +////----- Check_D_SsfdcWP() ---------------------------------------------- +//int Check_D_SsfdcWP(void) +//{ // ERROR: WP, SMSUCCESS: Not WP +// char i; +// +// for(i=0; i<8; i++) { +// if (_Hw_D_ChkWP()) +// return(ERROR); +// _Wait_D_Timer(TIME_WPCHK); +// } +// +// return(SMSUCCESS); +//} +// +*/ +//SmartMedia ECC Control Subroutine +//----- Check_D_ReadError() ---------------------------------------------- int Check_D_ReadError(BYTE *redundant) { return SMSUCCESS; } -/* ----- Check_D_Correct() ---------------------------------------------- */ -int Check_D_Correct(BYTE *buf, BYTE *redundant) +//----- Check_D_Correct() ---------------------------------------------- +int Check_D_Correct(BYTE *buf,BYTE *redundant) { return SMSUCCESS; } -/* ----- Check_D_CISdata() ---------------------------------------------- */ +//----- Check_D_CISdata() ---------------------------------------------- int Check_D_CISdata(BYTE *buf, BYTE *redundant) { BYTE cis[] = {0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, @@ -683,11 +1516,86 @@ int Check_D_CISdata(BYTE *buf, BYTE *redundant) return ERROR; } -/* ----- Set_D_RightECC() ---------------------------------------------- */ +//----- Set_D_RightECC() ---------------------------------------------- void Set_D_RightECC(BYTE *redundant) { - /* Driver ECC Check */ + // Driver ¤£°µ ECC Check return; + //StringCopy((char *)(redundant+0x0D),(char *)EccBuf,3); + //StringCopy((char *)(redundant+0x08),(char *)(EccBuf+0x03),3); } - - +/* +////----- _Calc_D_ECCdata() ---------------------------------------------- +//void _Calc_D_ECCdata(BYTE *buf) +//{ +//#ifdef HW_ECC_SUPPORTED +//#else +// _Calculate_D_SwECC(buf,EccBuf); +// buf+=0x0100; +// _Calculate_D_SwECC(buf,EccBuf+0x03); +//#endif +//} +// +////----- _Set_D_ECCdata() ---------------------------------------------- +//void _Set_D_ECCdata(BYTE add,BYTE *redundant) +//{ +// //if (add==EVEN && (Ssfdc.Attribute &MPS)==PS256) +// // return; +// +// // for 256byte/page +// StringCopy((char *)(redundant+0x0D),(char *)EccBuf,3); +// StringCopy((char *)(redundant+0x08),(char *)(EccBuf+0x03),3); +//} +*/ + +/* +//----- SM_ReadBlock() --------------------------------------------- +int SM_ReadBlock(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant) +{ + PBULK_CBW pBulkCbw = fdoExt->pBulkCbw; + NTSTATUS ntStatus; + WORD addr; + + ENE_LoadBinCode(fdoExt, SM_RW_PATTERN); + + addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; + addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; + + // Read sect data + RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW)); + pBulkCbw->dCBWSignature = CBW_SIGNTURE; + pBulkCbw->bCBWLun = CBW_LUN; + pBulkCbw->dCBWDataTransferLength = 0x200; + pBulkCbw->bmCBWFlags = 0x80; + pBulkCbw->CBWCb[0] = 0xF1; + pBulkCbw->CBWCb[1] = 0x02; + pBulkCbw->CBWCb[4] = (BYTE)addr; + pBulkCbw->CBWCb[3] = (BYTE)(addr/0x0100); + pBulkCbw->CBWCb[2] = Media.Zone/2; + + ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_READ, buf); + + if (!NT_SUCCESS(ntStatus)) + return(ERROR); + + // Read redundant + RtlZeroMemory(pBulkCbw, sizeof(struct _BULK_CBW)); + pBulkCbw->dCBWSignature = CBW_SIGNTURE; + pBulkCbw->bCBWLun = CBW_LUN; + pBulkCbw->dCBWDataTransferLength = 0x10; + pBulkCbw->bmCBWFlags = 0x80; + pBulkCbw->CBWCb[0] = 0xF1; + pBulkCbw->CBWCb[1] = 0x03; + pBulkCbw->CBWCb[4] = (BYTE)addr; + pBulkCbw->CBWCb[3] = (BYTE)(addr/0x0100); + pBulkCbw->CBWCb[2] = Media.Zone/2; + pBulkCbw->CBWCb[5] = 0; + pBulkCbw->CBWCb[6] = 1; + + ntStatus = ENE_SendScsiCmd(fdoExt, FDIR_READ, redundant); + + if (!NT_SUCCESS(ntStatus)) + return(ERROR); + + return(SMSUCCESS); +}*/ diff --git a/trunk/drivers/staging/keucr/smscsi.c b/trunk/drivers/staging/keucr/smscsi.c index 58b555571185..a6fa77f9c48e 100644 --- a/trunk/drivers/staging/keucr/smscsi.c +++ b/trunk/drivers/staging/keucr/smscsi.c @@ -9,46 +9,36 @@ #include "usb.h" #include "scsiglue.h" #include "transport.h" +//#include "smcommon.h" #include "smil.h" -int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Start_Stop(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb); -int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb); +int SM_SCSI_Test_Unit_Ready (struct us_data *us, struct scsi_cmnd *srb); +int SM_SCSI_Inquiry (struct us_data *us, struct scsi_cmnd *srb); +int SM_SCSI_Mode_Sense (struct us_data *us, struct scsi_cmnd *srb); +int SM_SCSI_Start_Stop (struct us_data *us, struct scsi_cmnd *srb); +int SM_SCSI_Read_Capacity (struct us_data *us, struct scsi_cmnd *srb); +int SM_SCSI_Read (struct us_data *us, struct scsi_cmnd *srb); +int SM_SCSI_Write (struct us_data *us, struct scsi_cmnd *srb); extern PBYTE SMHostAddr; extern DWORD ErrXDCode; -/* ----- SM_SCSIIrp() -------------------------------------------------- */ +//----- SM_SCSIIrp() -------------------------------------------------- int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb) { int result; us->SrbStatus = SS_SUCCESS; - switch (srb->cmnd[0]) { - case TEST_UNIT_READY: - result = SM_SCSI_Test_Unit_Ready(us, srb); - break; /* 0x00 */ - case INQUIRY: - result = SM_SCSI_Inquiry(us, srb); - break; /* 0x12 */ - case MODE_SENSE: - result = SM_SCSI_Mode_Sense(us, srb); - break; /* 0x1A */ - case READ_CAPACITY: - result = SM_SCSI_Read_Capacity(us, srb); - break; /* 0x25 */ - case READ_10: - result = SM_SCSI_Read(us, srb); - break; /* 0x28 */ - case WRITE_10: - result = SM_SCSI_Write(us, srb); - break; /* 0x2A */ - - default: + switch (srb->cmnd[0]) + { + case TEST_UNIT_READY : result = SM_SCSI_Test_Unit_Ready (us, srb); break; //0x00 + case INQUIRY : result = SM_SCSI_Inquiry (us, srb); break; //0x12 + case MODE_SENSE : result = SM_SCSI_Mode_Sense (us, srb); break; //0x1A + case READ_CAPACITY : result = SM_SCSI_Read_Capacity (us, srb); break; //0x25 + case READ_10 : result = SM_SCSI_Read (us, srb); break; //0x28 + case WRITE_10 : result = SM_SCSI_Write (us, srb); break; //0x2A + + default: us->SrbStatus = SS_ILLEGAL_REQUEST; result = USB_STOR_TRANSPORT_FAILED; break; @@ -56,22 +46,25 @@ int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb) return result; } -/* ----- SM_SCSI_Test_Unit_Ready() -------------------------------------------------- */ +//----- SM_SCSI_Test_Unit_Ready() -------------------------------------------------- int SM_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb) { + //printk("SM_SCSI_Test_Unit_Ready\n"); if (us->SM_Status.Insert && us->SM_Status.Ready) return USB_STOR_TRANSPORT_GOOD; - else { + else + { ENE_SMInit(us); return USB_STOR_TRANSPORT_GOOD; } - + return USB_STOR_TRANSPORT_GOOD; } -/* ----- SM_SCSI_Inquiry() -------------------------------------------------- */ +//----- SM_SCSI_Inquiry() -------------------------------------------------- int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb) { + //printk("SM_SCSI_Inquiry\n"); BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30}; usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF); @@ -79,11 +72,11 @@ int SM_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb) } -/* ----- SM_SCSI_Mode_Sense() -------------------------------------------------- */ +//----- SM_SCSI_Mode_Sense() -------------------------------------------------- int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb) { - BYTE mediaNoWP[12] = {0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00}; - BYTE mediaWP[12] = {0x0b, 0x00, 0x80, 0x08, 0x00, 0x00, 0x71, 0xc0, 0x00, 0x00, 0x02, 0x00}; + BYTE mediaNoWP[12] = {0x0b,0x00,0x00,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00}; + BYTE mediaWP[12] = {0x0b,0x00,0x80,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00}; if (us->SM_Status.WtP) usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF); @@ -94,7 +87,7 @@ int SM_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb) return USB_STOR_TRANSPORT_GOOD; } -/* ----- SM_SCSI_Read_Capacity() -------------------------------------------------- */ +//----- SM_SCSI_Read_Capacity() -------------------------------------------------- int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb) { unsigned int offset = 0; @@ -107,37 +100,45 @@ int SM_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb) bl_len = 0x200; bl_num = Ssfdc.MaxLogBlocks * Ssfdc.MaxSectors * Ssfdc.MaxZones - 1; + //printk("MaxLogBlocks = %x\n", Ssfdc.MaxLogBlocks); + //printk("MaxSectors = %x\n", Ssfdc.MaxSectors); + //printk("MaxZones = %x\n", Ssfdc.MaxZones); + //printk("bl_num = %x\n", bl_num); us->bl_num = bl_num; printk("bl_len = %x\n", bl_len); printk("bl_num = %x\n", bl_num); - buf[0] = (bl_num >> 24) & 0xff; - buf[1] = (bl_num >> 16) & 0xff; - buf[2] = (bl_num >> 8) & 0xff; - buf[3] = (bl_num >> 0) & 0xff; - buf[4] = (bl_len >> 24) & 0xff; - buf[5] = (bl_len >> 16) & 0xff; - buf[6] = (bl_len >> 8) & 0xff; - buf[7] = (bl_len >> 0) & 0xff; - + //srb->request_bufflen = 8; + buf[0] = (bl_num>>24) & 0xff; + buf[1] = (bl_num>>16) & 0xff; + buf[2] = (bl_num>> 8) & 0xff; + buf[3] = (bl_num>> 0) & 0xff; + buf[4] = (bl_len>>24) & 0xff; + buf[5] = (bl_len>>16) & 0xff; + buf[6] = (bl_len>> 8) & 0xff; + buf[7] = (bl_len>> 0) & 0xff; + usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF); + //usb_stor_set_xfer_buf(us, buf, srb->request_bufflen, srb, TO_XFER_BUF); return USB_STOR_TRANSPORT_GOOD; } -/* ----- SM_SCSI_Read() -------------------------------------------------- */ +//----- SM_SCSI_Read() -------------------------------------------------- int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb) { - int result = 0; + //struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; + int result=0; PBYTE Cdb = srb->cmnd; - DWORD bn = ((Cdb[2] << 24) & 0xff000000) | ((Cdb[3] << 16) & 0x00ff0000) | - ((Cdb[4] << 8) & 0x0000ff00) | ((Cdb[5] << 0) & 0x000000ff); - WORD blen = ((Cdb[7] << 8) & 0xff00) | ((Cdb[8] << 0) & 0x00ff); + DWORD bn = ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) | + ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff); + WORD blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff); DWORD blenByte = blen * 0x200; void *buf; - + //printk("SCSIOP_READ --- bn = %X, blen = %X, srb->use_sg = %X\n", bn, blen, srb->use_sg); + if (bn > us->bl_num) return USB_STOR_TRANSPORT_ERROR; @@ -156,17 +157,19 @@ int SM_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb) return USB_STOR_TRANSPORT_GOOD; } -/* ----- SM_SCSI_Write() -------------------------------------------------- */ +//----- SM_SCSI_Write() -------------------------------------------------- int SM_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb) { - int result = 0; + //struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; + int result=0; PBYTE Cdb = srb->cmnd; - DWORD bn = ((Cdb[2] << 24) & 0xff000000) | ((Cdb[3] << 16) & 0x00ff0000) | - ((Cdb[4] << 8) & 0x0000ff00) | ((Cdb[5] << 0) & 0x000000ff); - WORD blen = ((Cdb[7] << 8) & 0xff00) | ((Cdb[8] << 0) & 0x00ff); + DWORD bn = ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) | + ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff); + WORD blen = ((Cdb[7]<< 8) & 0xff00) | ((Cdb[8]<< 0) & 0x00ff); DWORD blenByte = blen * 0x200; void *buf; + //printk("SCSIOP_Write --- bn = %X, blen = %X, srb->use_sg = %X\n", bn, blen, srb->use_sg); if (bn > us->bl_num) return USB_STOR_TRANSPORT_ERROR; diff --git a/trunk/drivers/staging/mei/interrupt.c b/trunk/drivers/staging/mei/interrupt.c index ca1e0c90a941..9cb186bf1874 100644 --- a/trunk/drivers/staging/mei/interrupt.c +++ b/trunk/drivers/staging/mei/interrupt.c @@ -1540,12 +1540,6 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) mutex_lock(&dev->device_lock); mei_io_list_init(&complete_list); dev->host_hw_state = mei_hcsr_read(dev); - - /* Ack the interrupt here - * In case of MSI we don't go throuhg the quick handler */ - if (pci_dev_msi_enabled(dev->pdev)) - mei_reg_write(dev, H_CSR, dev->host_hw_state); - dev->me_hw_state = mei_mecsr_read(dev); /* check if ME wants a reset */ diff --git a/trunk/drivers/staging/mei/main.c b/trunk/drivers/staging/mei/main.c index 8d7678569e71..de8825fcd8ce 100644 --- a/trunk/drivers/staging/mei/main.c +++ b/trunk/drivers/staging/mei/main.c @@ -151,20 +151,11 @@ static int __devinit mei_probe(struct pci_dev *pdev, err = -ENOMEM; goto free_device; } - pci_enable_msi(pdev); - - /* request and enable interrupt */ - if (pci_dev_msi_enabled(pdev)) - err = request_threaded_irq(pdev->irq, - NULL, - mei_interrupt_thread_handler, - 0, mei_driver_name, dev); - else - err = request_threaded_irq(pdev->irq, + /* request and enable interrupt */ + err = request_threaded_irq(pdev->irq, mei_interrupt_quick_handler, mei_interrupt_thread_handler, IRQF_SHARED, mei_driver_name, dev); - if (err) { printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n", pdev->irq); @@ -192,7 +183,6 @@ static int __devinit mei_probe(struct pci_dev *pdev, mei_disable_interrupts(dev); flush_scheduled_work(); free_irq(pdev->irq, dev); - pci_disable_msi(pdev); unmap_memory: pci_iounmap(pdev, dev->mem_addr); free_device: @@ -257,7 +247,6 @@ static void __devexit mei_remove(struct pci_dev *pdev) mei_disable_interrupts(dev); free_irq(pdev->irq, dev); - pci_disable_msi(pdev); pci_set_drvdata(pdev, NULL); if (dev->mem_addr) @@ -1107,7 +1096,7 @@ static int mei_pci_suspend(struct device *device) mutex_unlock(&dev->device_lock); free_irq(pdev->irq, dev); - pci_disable_msi(pdev); + return err; } @@ -1122,20 +1111,11 @@ static int mei_pci_resume(struct device *device) if (!dev) return -ENODEV; - pci_enable_msi(pdev); - - /* request and enable interrupt */ - if (pci_dev_msi_enabled(pdev)) - err = request_threaded_irq(pdev->irq, - NULL, - mei_interrupt_thread_handler, - 0, mei_driver_name, dev); - else - err = request_threaded_irq(pdev->irq, + /* request and enable interrupt */ + err = request_threaded_irq(pdev->irq, mei_interrupt_quick_handler, mei_interrupt_thread_handler, IRQF_SHARED, mei_driver_name, dev); - if (err) { printk(KERN_ERR "mei: Request_irq failure. irq = %d\n", pdev->irq); diff --git a/trunk/drivers/staging/nvec/nvec.c b/trunk/drivers/staging/nvec/nvec.c index efdc8dbbac66..72258e8c64ca 100644 --- a/trunk/drivers/staging/nvec/nvec.c +++ b/trunk/drivers/staging/nvec/nvec.c @@ -22,7 +22,6 @@ #include #include #include -#include #include "nvec.h" static unsigned char EC_DISABLE_EVENT_REPORTING[] = {'\x04','\x00','\x00'}; @@ -31,25 +30,6 @@ static unsigned char EC_GET_FIRMWARE_VERSION[] = {'\x07','\x15'}; static struct nvec_chip *nvec_power_handle; -static struct mfd_cell nvec_devices[] = { - { - .name = "nvec-kbd", - .id = 1, - }, - { - .name = "nvec-mouse", - .id = 1, - }, - { - .name = "nvec-power", - .id = 1, - }, - { - .name = "nvec-power", - .id = 2, - }, -}; - int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb, unsigned int events) { @@ -159,7 +139,7 @@ static void nvec_dispatch(struct work_struct *work) } else { parse_msg(nvec, msg); if((!msg) || (!msg->data)) - dev_warn(nvec->dev, "attempt access zero pointer\n"); + dev_warn(nvec->dev, "attempt access zero pointer"); else { kfree(msg->data); kfree(msg); @@ -168,16 +148,16 @@ static void nvec_dispatch(struct work_struct *work) } } -static irqreturn_t nvec_interrupt(int irq, void *dev) +static irqreturn_t i2c_interrupt(int irq, void *dev) { unsigned long status; unsigned long received; unsigned char to_send; struct nvec_msg *msg; struct nvec_chip *nvec = (struct nvec_chip *)dev; - void __iomem *base = nvec->base; + unsigned char *i2c_regs = nvec->i2c_regs; - status = readl(base + I2C_SL_STATUS); + status = readl(i2c_regs + I2C_SL_STATUS); if(!(status & I2C_SL_IRQ)) { @@ -242,7 +222,7 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) nvec->state = NVEC_WAIT; } } - writel(to_send, base + I2C_SL_RCVD); + writel(to_send, i2c_regs + I2C_SL_RCVD); gpio_set_value(nvec->gpio, 1); @@ -250,10 +230,10 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) goto handled; } else { - received = readl(base + I2C_SL_RCVD); + received = readl(i2c_regs + I2C_SL_RCVD); //Workaround? if(status & RCVD) { - writel(0, base + I2C_SL_RCVD); + writel(0, i2c_regs + I2C_SL_RCVD); goto handled; } @@ -278,26 +258,37 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) return IRQ_HANDLED; } -static void tegra_init_i2c_slave(struct nvec_chip *nvec) +static int __devinit nvec_add_subdev(struct nvec_chip *nvec, struct nvec_subdev *subdev) { - u32 val; + struct platform_device *pdev; + + pdev = platform_device_alloc(subdev->name, subdev->id); + pdev->dev.parent = nvec->dev; + pdev->dev.platform_data = subdev->platform_data; - clk_enable(nvec->i2c_clk); + return platform_device_add(pdev); +} - tegra_periph_reset_assert(nvec->i2c_clk); +static void tegra_init_i2c_slave(struct nvec_platform_data *pdata, unsigned char *i2c_regs, + struct clk *i2c_clk) +{ + u32 val; + + clk_enable(i2c_clk); + tegra_periph_reset_assert(i2c_clk); udelay(2); - tegra_periph_reset_deassert(nvec->i2c_clk); + tegra_periph_reset_deassert(i2c_clk); - writel(nvec->i2c_addr>>1, nvec->base + I2C_SL_ADDR1); - writel(0, nvec->base + I2C_SL_ADDR2); + writel(pdata->i2c_addr>>1, i2c_regs + I2C_SL_ADDR1); + writel(0, i2c_regs + I2C_SL_ADDR2); - writel(0x1E, nvec->base + I2C_SL_DELAY_COUNT); + writel(0x1E, i2c_regs + I2C_SL_DELAY_COUNT); val = I2C_CNFG_NEW_MASTER_SFM | I2C_CNFG_PACKET_MODE_EN | (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT); - writel(val, nvec->base + I2C_CNFG); - writel(I2C_SL_NEWL, nvec->base + I2C_SL_CNFG); + writel(val, i2c_regs + I2C_CNFG); + writel(I2C_SL_NEWL, i2c_regs + I2C_SL_CNFG); - clk_disable(nvec->i2c_clk); + clk_disable(i2c_clk); } static void nvec_power_off(void) @@ -308,14 +299,12 @@ static void nvec_power_off(void) static int __devinit tegra_nvec_probe(struct platform_device *pdev) { - int err, ret; + int err, i, ret; struct clk *i2c_clk; struct nvec_platform_data *pdata = pdev->dev.platform_data; struct nvec_chip *nvec; struct nvec_msg *msg; - struct resource *res; - struct resource *iomem; - void __iomem *base; + unsigned char *i2c_regs; nvec = kzalloc(sizeof(struct nvec_chip), GFP_KERNEL); if(nvec == NULL) { @@ -325,51 +314,49 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nvec); nvec->dev = &pdev->dev; nvec->gpio = pdata->gpio; - nvec->i2c_addr = pdata->i2c_addr; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; + nvec->irq = pdata->irq; + +/* + i2c_clk=clk_get_sys(NULL, "i2c"); + if(IS_ERR_OR_NULL(i2c_clk)) + printk(KERN_ERR"No such clock tegra-i2c.2\n"); + else + clk_enable(i2c_clk); +*/ + i2c_regs = ioremap(pdata->base, pdata->size); + if(!i2c_regs) { + dev_err(nvec->dev, "failed to ioremap registers\n"); + goto failed; } - iomem = request_mem_region(res->start, resource_size(res), pdev->name); - if (!iomem) { - dev_err(&pdev->dev, "I2C region already claimed\n"); - return -EBUSY; - } + nvec->i2c_regs = i2c_regs; - base = ioremap(iomem->start, resource_size(iomem)); - if (!base) { - dev_err(&pdev->dev, "Can't ioremap I2C region\n"); - return -ENOMEM; + i2c_clk = clk_get_sys(pdata->clock, NULL); + if(IS_ERR_OR_NULL(i2c_clk)) { + dev_err(nvec->dev, "failed to get clock tegra-i2c.2\n"); + goto failed; } - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(&pdev->dev, "no irq resource?\n"); - ret = -ENODEV; - goto err_iounmap; - } + tegra_init_i2c_slave(pdata, i2c_regs, i2c_clk); - i2c_clk = clk_get_sys("tegra-i2c.2", NULL); - if (IS_ERR(i2c_clk)) { - dev_err(nvec->dev, "failed to get controller clock\n"); - goto err_iounmap; + err = request_irq(nvec->irq, i2c_interrupt, IRQF_DISABLED, "nvec", nvec); + if(err) { + dev_err(nvec->dev, "couldn't request irq"); + goto failed; } clk_enable(i2c_clk); clk_set_rate(i2c_clk, 8*80000); - nvec->base = base; - nvec->irq = res->start; - nvec->i2c_clk = i2c_clk; - /* Set the gpio to low when we've got something to say */ err = gpio_request(nvec->gpio, "nvec gpio"); if(err < 0) dev_err(nvec->dev, "couldn't request gpio\n"); + tegra_gpio_enable(nvec->gpio); + gpio_direction_output(nvec->gpio, 1); + gpio_set_value(nvec->gpio, 1); + ATOMIC_INIT_NOTIFIER_HEAD(&nvec->notifier_list); init_completion(&nvec->sync_write); @@ -379,21 +366,20 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) INIT_WORK(&nvec->rx_work, nvec_dispatch); INIT_WORK(&nvec->tx_work, nvec_request_master); - err = request_irq(nvec->irq, nvec_interrupt, 0, "nvec", nvec); - if (err) { - dev_err(nvec->dev, "couldn't request irq\n"); - goto failed; - } - - tegra_init_i2c_slave(nvec); - - gpio_direction_output(nvec->gpio, 1); - gpio_set_value(nvec->gpio, 1); - /* enable event reporting */ nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING, sizeof(EC_ENABLE_EVENT_REPORTING)); + nvec_kbd_init(nvec); +#ifdef CONFIG_SERIO_NVEC_PS2 + nvec_ps2(nvec); +#endif + + /* setup subdevs */ + for (i = 0; i < pdata->num_subdevs; i++) { + ret = nvec_add_subdev(nvec, &pdata->subdevs[i]); + } + nvec->nvec_status_notifier.notifier_call = nvec_status_notifier; nvec_register_notifier(nvec, &nvec->nvec_status_notifier, 0); @@ -410,11 +396,6 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) kfree(msg->data); kfree(msg); - ret = mfd_add_devices(nvec->dev, -1, nvec_devices, - ARRAY_SIZE(nvec_devices), base, 0); - if(ret) - dev_err(nvec->dev, "error adding subdevices\n"); - /* unmute speakers? */ nvec_write_async(nvec, "\x0d\x10\x59\x94", 4); @@ -426,8 +407,6 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) return 0; -err_iounmap: - iounmap(base); failed: kfree(nvec); return -ENOMEM; @@ -435,15 +414,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) static int __devexit tegra_nvec_remove(struct platform_device *pdev) { - struct nvec_chip *nvec = platform_get_drvdata(pdev); - - nvec_write_async(nvec, EC_DISABLE_EVENT_REPORTING, 3); - mfd_remove_devices(nvec->dev); - free_irq(nvec->irq, &nvec_interrupt); - iounmap(nvec->base); - gpio_free(nvec->gpio); - kfree(nvec); - + // TODO: unregister return 0; } @@ -465,7 +436,6 @@ static int tegra_nvec_resume(struct platform_device *pdev) { struct nvec_chip *nvec = platform_get_drvdata(pdev); dev_dbg(nvec->dev, "resuming\n"); - tegra_init_i2c_slave(nvec); nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING, 3); return 0; diff --git a/trunk/drivers/staging/nvec/nvec.h b/trunk/drivers/staging/nvec/nvec.h index d9ff721d1d8d..a2d82dce62d7 100644 --- a/trunk/drivers/staging/nvec/nvec.h +++ b/trunk/drivers/staging/nvec/nvec.h @@ -45,17 +45,21 @@ struct nvec_subdev { }; struct nvec_platform_data { + int num_subdevs; int i2c_addr; int gpio; + int irq; + int base; + int size; + char clock[16]; + struct nvec_subdev *subdevs; }; struct nvec_chip { struct device *dev; int gpio; int irq; - int i2c_addr; - void __iomem *base; - struct clk *i2c_clk; + unsigned char *i2c_regs; nvec_state state; struct atomic_notifier_head notifier_list; struct list_head rx_data, tx_data; @@ -80,6 +84,9 @@ extern int nvec_unregister_notifier(struct device *dev, const char *nvec_send_msg(unsigned char *src, unsigned char *dst_size, how_care care_resp, void (*rt_handler)(unsigned char *data)); +extern int nvec_ps2(struct nvec_chip *nvec); +extern int nvec_kbd_init(struct nvec_chip *nvec); + #define I2C_CNFG 0x00 #define I2C_CNFG_PACKET_MODE_EN (1<<10) #define I2C_CNFG_NEW_MASTER_SFM (1<<11) diff --git a/trunk/drivers/staging/nvec/nvec_kbd.c b/trunk/drivers/staging/nvec/nvec_kbd.c index 347a38c46874..9a9850725b5b 100644 --- a/trunk/drivers/staging/nvec/nvec_kbd.c +++ b/trunk/drivers/staging/nvec/nvec_kbd.c @@ -1,11 +1,10 @@ #include #include #include -#include #include "nvec-keytable.h" #include "nvec.h" -#define ACK_KBD_EVENT {'\x05', '\xed', '\x01'} +#define ACK_KBD_EVENT {'\x05','\xed','\x01'} static unsigned char keycodes[ARRAY_SIZE(code_tab_102us) + ARRAY_SIZE(extcode_tab_us102)]; @@ -28,10 +27,10 @@ static int nvec_keys_notifier(struct notifier_block *nb, nvec_size _size = (msg[0] & (3 << 5)) >> 5; /* power on/off button */ - if (_size == NVEC_VAR_SIZE) + if(_size == NVEC_VAR_SIZE) return NOTIFY_STOP; - if (_size == NVEC_3BYTES) + if(_size == NVEC_3BYTES) msg++; code = msg[1] & 0x7f; @@ -52,13 +51,13 @@ static int nvec_kbd_event(struct input_dev *dev, unsigned int type, unsigned char buf[] = ACK_KBD_EVENT; struct nvec_chip *nvec = keys_dev.nvec; - if (type == EV_REP) + if(type==EV_REP) return 0; - if (type != EV_LED) + if(type!=EV_LED) return -1; - if (code != LED_CAPSL) + if(code!=LED_CAPSL) return -1; buf[2] = !!value; @@ -67,19 +66,18 @@ static int nvec_kbd_event(struct input_dev *dev, unsigned int type, return 0; } -static int __devinit nvec_kbd_probe(struct platform_device *pdev) +int __init nvec_kbd_init(struct nvec_chip *nvec) { - struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); int i, j, err; struct input_dev *idev; j = 0; - for (i = 0; i < ARRAY_SIZE(code_tab_102us); ++i) + for(i = 0; i < ARRAY_SIZE(code_tab_102us); ++i) keycodes[j++] = code_tab_102us[i]; - for (i = 0; i < ARRAY_SIZE(extcode_tab_us102); ++i) - keycodes[j++] = extcode_tab_us102[i]; + for(i = 0; i < ARRAY_SIZE(extcode_tab_us102); ++i) + keycodes[j++]=extcode_tab_us102[i]; idev = input_allocate_device(); idev->name = "Tegra nvec keyboard"; @@ -91,12 +89,12 @@ static int __devinit nvec_kbd_probe(struct platform_device *pdev) idev->keycodesize = sizeof(unsigned char); idev->keycodemax = ARRAY_SIZE(keycodes); - for (i = 0; i < ARRAY_SIZE(keycodes); ++i) + for( i = 0; i < ARRAY_SIZE(keycodes); ++i) set_bit(keycodes[i], idev->keybit); clear_bit(0, idev->keybit); err = input_register_device(idev); - if (err) + if(err) goto fail; keys_dev.input = idev; @@ -122,18 +120,3 @@ static int __devinit nvec_kbd_probe(struct platform_device *pdev) input_free_device(idev); return err; } - -static struct platform_driver nvec_kbd_driver = { - .probe = nvec_kbd_probe, - .driver = { - .name = "nvec-kbd", - .owner = THIS_MODULE, - }, -}; - -static int __init nvec_kbd_init(void) -{ - return platform_driver_register(&nvec_kbd_driver); -} - -module_init(nvec_kbd_init); diff --git a/trunk/drivers/staging/nvec/nvec_ps2.c b/trunk/drivers/staging/nvec/nvec_ps2.c index 0d3149b3e856..6bb9430f3521 100644 --- a/trunk/drivers/staging/nvec/nvec_ps2.c +++ b/trunk/drivers/staging/nvec/nvec_ps2.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "nvec.h" #define START_STREAMING {'\x06','\x03','\x01'} @@ -78,9 +77,8 @@ static int nvec_ps2_notifier(struct notifier_block *nb, } -static int __devinit nvec_mouse_probe(struct platform_device *pdev) +int __init nvec_ps2(struct nvec_chip *nvec) { - struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); struct serio *ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL); ser_dev->id.type=SERIO_8042; @@ -103,18 +101,3 @@ static int __devinit nvec_mouse_probe(struct platform_device *pdev) return 0; } - -static struct platform_driver nvec_mouse_driver = { - .probe = nvec_mouse_probe, - .driver = { - .name = "nvec-mouse", - .owner = THIS_MODULE, - }, -}; - -static int __init nvec_mouse_init(void) -{ - return platform_driver_register(&nvec_mouse_driver); -} - -module_init(nvec_mouse_init); diff --git a/trunk/drivers/staging/olpc_dcon/olpc_dcon.c b/trunk/drivers/staging/olpc_dcon/olpc_dcon.c index 87268059eb45..750fe5045efa 100644 --- a/trunk/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/trunk/drivers/staging/olpc_dcon/olpc_dcon.c @@ -36,6 +36,9 @@ static int resumeline = 898; module_param(resumeline, int, 0444); +static int noinit; +module_param(noinit, int, 0444); + /* Default off since it doesn't work on DCON ASIC in B-test OLPC board */ static int useaa = 1; module_param(useaa, int, 0444); @@ -65,10 +68,11 @@ static s32 dcon_read(struct dcon_priv *dcon, u8 reg) static int dcon_hw_init(struct dcon_priv *dcon, int is_init) { + struct i2c_client *client = dcon->client; uint16_t ver; int rc = 0; - ver = dcon_read(dcon, DCON_REG_ID); + ver = i2c_smbus_read_word_data(client, DCON_REG_ID); if ((ver >> 8) != 0xDC) { printk(KERN_ERR "olpc-dcon: DCON ID not 0xDCxx: 0x%04x " "instead.\n", ver); @@ -86,19 +90,30 @@ static int dcon_hw_init(struct dcon_priv *dcon, int is_init) } } - if (ver < 0xdc02) { - dev_err(&dcon->client->dev, - "DCON v1 is unsupported, giving up..\n"); - rc = -ENODEV; - goto err; + if (ver < 0xdc02 && !noinit) { + /* Initialize the DCON registers */ + + /* Start with work-arounds for DCON ASIC */ + i2c_smbus_write_word_data(client, 0x4b, 0x00cc); + i2c_smbus_write_word_data(client, 0x4b, 0x00cc); + i2c_smbus_write_word_data(client, 0x4b, 0x00cc); + i2c_smbus_write_word_data(client, 0x0b, 0x007a); + i2c_smbus_write_word_data(client, 0x36, 0x025c); + i2c_smbus_write_word_data(client, 0x37, 0x025e); + + /* Initialise SDRAM */ + + i2c_smbus_write_word_data(client, 0x3b, 0x002b); + i2c_smbus_write_word_data(client, 0x41, 0x0101); + i2c_smbus_write_word_data(client, 0x42, 0x0101); + } else if (!noinit) { + /* SDRAM setup/hold time */ + i2c_smbus_write_word_data(client, 0x3a, 0xc040); + i2c_smbus_write_word_data(client, 0x41, 0x0000); + i2c_smbus_write_word_data(client, 0x41, 0x0101); + i2c_smbus_write_word_data(client, 0x42, 0x0101); } - /* SDRAM setup/hold time */ - dcon_write(dcon, 0x3a, 0xc040); - dcon_write(dcon, 0x41, 0x0000); - dcon_write(dcon, 0x41, 0x0101); - dcon_write(dcon, 0x42, 0x0101); - /* Colour swizzle, AA, no passthrough, backlight */ if (is_init) { dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE | @@ -106,11 +121,11 @@ static int dcon_hw_init(struct dcon_priv *dcon, int is_init) if (useaa) dcon->disp_mode |= MODE_COL_AA; } - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); + i2c_smbus_write_word_data(client, DCON_REG_MODE, dcon->disp_mode); /* Set the scanline to interrupt on during resume */ - dcon_write(dcon, DCON_REG_SCAN_INT, resumeline); + i2c_smbus_write_word_data(client, DCON_REG_SCAN_INT, resumeline); err: return rc; diff --git a/trunk/drivers/staging/pohmelfs/trans.c b/trunk/drivers/staging/pohmelfs/trans.c index 06c1a7451b1b..36a253582565 100644 --- a/trunk/drivers/staging/pohmelfs/trans.c +++ b/trunk/drivers/staging/pohmelfs/trans.c @@ -50,7 +50,7 @@ static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st) int err = 0; unsigned int i, attached_pages = t->attached_pages, ci; struct msghdr msg; - struct page **pages = (t->eng) ? t->eng->pages : t->pages; + struct page **pages = (t->eng)?t->eng->pages:t->pages; struct page *p; unsigned int size; @@ -61,7 +61,7 @@ static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st) msg.msg_flags = MSG_WAITALL | MSG_MORE; ci = 0; - for (i = 0; i < t->page_num; ++i) { + for (i=0; ipage_num; ++i) { struct page *page = pages[ci]; struct netfs_cmd cmd; struct iovec io; @@ -169,7 +169,7 @@ int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st) } dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n", - __func__, (t->page_num) ? "partial" : "full", + __func__, (t->page_num)?"partial":"full", t, t->gen, t->iovec.iov_len, t->page_num); err = 0; diff --git a/trunk/drivers/staging/rtl8187se/Makefile b/trunk/drivers/staging/rtl8187se/Makefile index 72db504b23b4..11a92262c666 100644 --- a/trunk/drivers/staging/rtl8187se/Makefile +++ b/trunk/drivers/staging/rtl8187se/Makefile @@ -1,7 +1,7 @@ -#ccflags-y += -DCONFIG_IEEE80211_NOWEP=y -#ccflags-y += -std=gnu89 -#ccflags-y += -O2 +#EXTRA_CFLAGS += -DCONFIG_IEEE80211_NOWEP=y +#EXTRA_CFLAGS += -std=gnu89 +#EXTRA_CFLAGS += -O2 #CC = gcc ccflags-y := -DSW_ANTE diff --git a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h index 40dd715d9df7..e79a7e212979 100644 --- a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211.h @@ -1339,8 +1339,8 @@ int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len); /* ieee80211_softmac.c */ -extern short ieee80211_is_54g(const struct ieee80211_network *net); -extern short ieee80211_is_shortslot(const struct ieee80211_network *net); +extern short ieee80211_is_54g(struct ieee80211_network net); +extern short ieee80211_is_shortslot(struct ieee80211_network net); extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, u16 type, u16 stype); diff --git a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 26bacb96d247..38e67f0bf624 100644 --- a/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/trunk/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -32,14 +32,14 @@ u8 rsn_authen_cipher_suite[16][4] = { {0x00,0x0F,0xAC,0x05}, //WEP-104 }; -short ieee80211_is_54g(const struct ieee80211_network *net) +short ieee80211_is_54g(struct ieee80211_network net) { - return (net->rates_ex_len > 0) || (net->rates_len > 4); + return ((net.rates_ex_len > 0) || (net.rates_len > 4)); } -short ieee80211_is_shortslot(const struct ieee80211_network *net) +short ieee80211_is_shortslot(struct ieee80211_network net) { - return net->capability & WLAN_CAPABILITY_SHORT_SLOT; + return (net.capability & WLAN_CAPABILITY_SHORT_SLOT); } /* returns the total length needed for pleacing the RATE MFIE @@ -789,7 +789,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d else atim_len = 0; - if(ieee80211_is_54g(&ieee->current_network)) + if(ieee80211_is_54g(ieee->current_network)) erp_len = 3; else erp_len = 0; @@ -1258,7 +1258,7 @@ void ieee80211_associate_complete_wq(struct work_struct *work) struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq); printk(KERN_INFO "Associated successfully\n"); - if(ieee80211_is_54g(&ieee->current_network) && + if(ieee80211_is_54g(ieee->current_network) && (ieee->modulation & IEEE80211_OFDM_MODULATION)){ ieee->rate = 540; @@ -1379,7 +1379,7 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee ieee->beinretry = false; queue_work(ieee->wq, &ieee->associate_procedure_wq); }else{ - if(ieee80211_is_54g(&ieee->current_network) && + if(ieee80211_is_54g(ieee->current_network) && (ieee->modulation & IEEE80211_OFDM_MODULATION)){ ieee->rate = 540; printk(KERN_INFO"Using G rates\n"); diff --git a/trunk/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/trunk/drivers/staging/rtl8187se/r8180_rtl8225z2.c index ee5b867fd0d4..3f09f76080af 100644 --- a/trunk/drivers/staging/rtl8187se/r8180_rtl8225z2.c +++ b/trunk/drivers/staging/rtl8187se/r8180_rtl8225z2.c @@ -596,7 +596,7 @@ static void rtl8225_rf_set_chan(struct net_device *dev, short ch) { struct r8180_priv *priv = ieee80211_priv(dev); short gset = (priv->ieee80211->state == IEEE80211_LINKED && - ieee80211_is_54g(&priv->ieee80211->current_network)) || + ieee80211_is_54g(priv->ieee80211->current_network)) || priv->ieee80211->iw_mode == IW_MODE_MONITOR; rtl8225_SetTXPowerLevel(dev, ch); @@ -615,7 +615,7 @@ static void rtl8225_rf_set_chan(struct net_device *dev, short ch) } if (priv->ieee80211->state == IEEE80211_LINKED && - ieee80211_is_shortslot(&priv->ieee80211->current_network)) + ieee80211_is_shortslot(priv->ieee80211->current_network)) write_nic_byte(dev, SLOT, 0x9); else write_nic_byte(dev, SLOT, 0x14); diff --git a/trunk/drivers/staging/rtl8192e/rtl819x_Qos.h b/trunk/drivers/staging/rtl8192e/rtl819x_Qos.h index 8f5e0fdd2f31..49e49cb9df7c 100644 --- a/trunk/drivers/staging/rtl8192e/rtl819x_Qos.h +++ b/trunk/drivers/staging/rtl8192e/rtl819x_Qos.h @@ -352,7 +352,7 @@ typedef struct _STA_QOS{ #define GET_QBSS_LOAD_AVAILABLE_CAPACITY(__pStart) ReadEF2Byte((u8*)(__pStart) + 3) #define SET_QBSS_LOAD_AVAILABLE_CAPACITY(__pStart, __Value) WriteEF2Byte((u8*)(__pStart) + 3, __Value) -typedef struct _BSS_QOS{ +struct bss_qos { QOS_MODE bdQoSMode; u8 bdWMMIEBuf[MAX_WMMELE_LENGTH]; @@ -365,7 +365,7 @@ typedef struct _BSS_QOS{ u8 QBssLoad[QBSS_LOAD_SIZE]; bool bQBssLoadValid; -}BSS_QOS, *PBSS_QOS; +};//, *struct bss_qos *; #define sQoSCtlLng 2 #define QOS_CTRL_LEN(_QosMode) ( (_QosMode > QOS_DISABLE)? sQoSCtlLng : 0 ) diff --git a/trunk/drivers/staging/rtl8192u/ieee80211/compress.c b/trunk/drivers/staging/rtl8192u/ieee80211/compress.c index 5416ab63a738..86c23c9223f2 100644 --- a/trunk/drivers/staging/rtl8192u/ieee80211/compress.c +++ b/trunk/drivers/staging/rtl8192u/ieee80211/compress.c @@ -12,10 +12,10 @@ * */ #include -/*#include */ +//#include #include "rtl_crypto.h" #include -#include +#include #include #include "internal.h" diff --git a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 1c0a1db6420f..463cc2618904 100644 --- a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -2416,8 +2416,8 @@ extern int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, extern int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len); /* ieee80211_softmac.c */ -extern short ieee80211_is_54g(const struct ieee80211_network *net); -extern short ieee80211_is_shortslot(const struct ieee80211_network *net); +extern short ieee80211_is_54g(struct ieee80211_network net); +extern short ieee80211_is_shortslot(struct ieee80211_network net); extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, u16 type, u16 stype); diff --git a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index c2ab5fa15465..b00eb0e65f33 100644 --- a/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/trunk/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -31,14 +31,14 @@ u8 rsn_authen_cipher_suite[16][4] = { {0x00,0x0F,0xAC,0x05}, //WEP-104 }; -short ieee80211_is_54g(const struct ieee80211_network *net) +short ieee80211_is_54g(struct ieee80211_network net) { - return (net->rates_ex_len > 0) || (net->rates_len > 4); + return ((net.rates_ex_len > 0) || (net.rates_len > 4)); } -short ieee80211_is_shortslot(const struct ieee80211_network *net) +short ieee80211_is_shortslot(struct ieee80211_network net) { - return net->capability & WLAN_CAPABILITY_SHORT_SLOT; + return (net.capability & WLAN_CAPABILITY_SHORT_SLOT); } /* returns the total length needed for pleacing the RATE MFIE @@ -718,7 +718,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d else atim_len = 0; - if(ieee80211_is_54g(&ieee->current_network)) + if(ieee80211_is_54g(ieee->current_network)) erp_len = 3; else erp_len = 0; @@ -1333,7 +1333,7 @@ void ieee80211_associate_complete_wq(struct work_struct *work) { struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq); printk(KERN_INFO "Associated successfully\n"); - if(ieee80211_is_54g(&ieee->current_network) && + if(ieee80211_is_54g(ieee->current_network) && (ieee->modulation & IEEE80211_OFDM_MODULATION)){ ieee->rate = 108; @@ -1489,7 +1489,7 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee ieee->state = IEEE80211_ASSOCIATING; queue_work(ieee->wq, &ieee->associate_procedure_wq); }else{ - if(ieee80211_is_54g(&ieee->current_network) && + if(ieee80211_is_54g(ieee->current_network) && (ieee->modulation & IEEE80211_OFDM_MODULATION)){ ieee->rate = 108; ieee->SetWirelessMode(ieee->dev, IEEE_G); diff --git a/trunk/drivers/staging/rtl8712/big_endian.h b/trunk/drivers/staging/rtl8712/big_endian.h index b16f8ecf99c6..8512d1b5919d 100644 --- a/trunk/drivers/staging/rtl8712/big_endian.h +++ b/trunk/drivers/staging/rtl8712/big_endian.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef _LINUX_BYTEORDER_BIG_ENDIAN_H #define _LINUX_BYTEORDER_BIG_ENDIAN_H diff --git a/trunk/drivers/staging/rtl8712/drv_types.h b/trunk/drivers/staging/rtl8712/drv_types.h index c5303c3fda14..4f380a64aa85 100644 --- a/trunk/drivers/staging/rtl8712/drv_types.h +++ b/trunk/drivers/staging/rtl8712/drv_types.h @@ -117,11 +117,6 @@ struct dvobj_priv { struct usb_device *pusbdev; }; -/** - * struct _adapter - the main adapter structure for this device. - * - * bup: True indicates that the interface is Up. - */ struct _adapter { struct dvobj_priv dvobjpriv; struct mlme_priv mlmepriv; diff --git a/trunk/drivers/staging/rtl8712/ethernet.h b/trunk/drivers/staging/rtl8712/ethernet.h index 882d61b2e959..ba8d777d8e10 100644 --- a/trunk/drivers/staging/rtl8712/ethernet.h +++ b/trunk/drivers/staging/rtl8712/ethernet.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __INC_ETHERNET_H #define __INC_ETHERNET_H diff --git a/trunk/drivers/staging/rtl8712/generic.h b/trunk/drivers/staging/rtl8712/generic.h index 8868c9f4adf8..742424bdf16b 100644 --- a/trunk/drivers/staging/rtl8712/generic.h +++ b/trunk/drivers/staging/rtl8712/generic.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef _LINUX_BYTEORDER_GENERIC_H #define _LINUX_BYTEORDER_GENERIC_H diff --git a/trunk/drivers/staging/rtl8712/if_ether.h b/trunk/drivers/staging/rtl8712/if_ether.h index 2bbe527bcd5c..0e9753b9ed37 100644 --- a/trunk/drivers/staging/rtl8712/if_ether.h +++ b/trunk/drivers/staging/rtl8712/if_ether.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ /* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket diff --git a/trunk/drivers/staging/rtl8712/little_endian.h b/trunk/drivers/staging/rtl8712/little_endian.h index cd57d6c2850f..0248c143c6df 100644 --- a/trunk/drivers/staging/rtl8712/little_endian.h +++ b/trunk/drivers/staging/rtl8712/little_endian.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef _LINUX_BYTEORDER_LITTLE_ENDIAN_H #define _LINUX_BYTEORDER_LITTLE_ENDIAN_H diff --git a/trunk/drivers/staging/rtl8712/mlme_osdep.h b/trunk/drivers/staging/rtl8712/mlme_osdep.h index a20fe81f921f..968e78765a3b 100644 --- a/trunk/drivers/staging/rtl8712/mlme_osdep.h +++ b/trunk/drivers/staging/rtl8712/mlme_osdep.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __MLME_OSDEP_H_ #define __MLME_OSDEP_H_ diff --git a/trunk/drivers/staging/rtl8712/mp_custom_oid.h b/trunk/drivers/staging/rtl8712/mp_custom_oid.h index 40510089b781..a9e0b3483e3c 100644 --- a/trunk/drivers/staging/rtl8712/mp_custom_oid.h +++ b/trunk/drivers/staging/rtl8712/mp_custom_oid.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __CUSTOM_OID_H #define __CUSTOM_OID_H diff --git a/trunk/drivers/staging/rtl8712/os_intfs.c b/trunk/drivers/staging/rtl8712/os_intfs.c index 6697941e2321..3f38e8eca3f1 100644 --- a/trunk/drivers/staging/rtl8712/os_intfs.c +++ b/trunk/drivers/staging/rtl8712/os_intfs.c @@ -375,12 +375,6 @@ static void enable_video_mode(struct _adapter *padapter, int cbw40_value) r8712_fw_cmd(padapter, intcmd); } -/** - * - * This function intends to handle the activation of an interface - * i.e. when it is brought Up/Active from a Down state. - * - */ static int netdev_open(struct net_device *pnetdev) { struct _adapter *padapter = (struct _adapter *)_netdev_priv(pnetdev); @@ -440,12 +434,6 @@ static int netdev_open(struct net_device *pnetdev) return -1; } -/** - * - * This function intends to handle the shutdown of an interface - * i.e. when it is brought Down from an Up/Active state. - * - */ static int netdev_close(struct net_device *pnetdev) { struct _adapter *padapter = (struct _adapter *) _netdev_priv(pnetdev); @@ -470,8 +458,6 @@ static int netdev_close(struct net_device *pnetdev) r8712_free_network_queue(padapter); /*Stop driver mlme relation timer*/ stop_drv_timers(padapter); - /* The interface is no longer Up: */ - padapter->bup = false; return 0; } diff --git a/trunk/drivers/staging/rtl8712/osdep_service.h b/trunk/drivers/staging/rtl8712/osdep_service.h index aac97bb8b803..c683d7609e6c 100644 --- a/trunk/drivers/staging/rtl8712/osdep_service.h +++ b/trunk/drivers/staging/rtl8712/osdep_service.h @@ -203,6 +203,7 @@ static inline unsigned char _cancel_timer_ex(struct timer_list *ptimer) static inline void thread_enter(void *context) { + daemonize("%s", "RTKTHREAD"); allow_signal(SIGTERM); } diff --git a/trunk/drivers/staging/rtl8712/recv_osdep.h b/trunk/drivers/staging/rtl8712/recv_osdep.h index f4384ef00868..60a54dd90ff1 100644 --- a/trunk/drivers/staging/rtl8712/recv_osdep.h +++ b/trunk/drivers/staging/rtl8712/recv_osdep.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RECV_OSDEP_H_ #define __RECV_OSDEP_H_ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_bitdef.h index bff57a8eef3c..356184fa0606 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_bitdef.h @@ -1,24 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ - - #ifndef __RTL8712_BITDEF_H__ #define __RTL8712_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h index 8dffe101becf..6c49903a42f2 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_CMDCTRL_BITDEF_H__ #define __RTL8712_CMDCTRL_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h index 9374f1c48853..5d9a3f20ea6e 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_CMDCTRL_REGDEF_H__ #define __RTL8712_CMDCTRL_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h index 8bd483795ca4..7b34d4025e3e 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_DEBUGCTRL_BITDEF_H__ #define __RTL8712_DEBUGCTRL_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h index 43630bb068f5..27cad716868c 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_DEBUGCTRL_REGDEF_H__ #define __RTL8712_DEBUGCTRL_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h index 32dab81f1767..c69b1b72c28c 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_EDCASETTING_BITDEF_H__ #define __RTL8712_EDCASETTING_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h index d992cb8b1c73..de3d3e23ba95 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_EDCASETTING_REGDEF_H__ #define __RTL8712_EDCASETTING_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h index c564dc862d9d..e5df19f4b02b 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_FIFOCTRL_BITDEF_H__ #define __RTL8712_FIFOCTRL_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h index 29b89c45c70c..c2e3af2c79f6 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_FIFOCTRL_REGDEF_H__ #define __RTL8712_FIFOCTRL_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_gp_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_gp_bitdef.h index 884a8212176d..35ca809e1799 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_gp_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_gp_bitdef.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_GP_BITDEF_H__ #define __RTL8712_GP_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_gp_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_gp_regdef.h index 8fc68f6a2c79..17e72bda617e 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_gp_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_gp_regdef.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_GP_REGDEF_H__ #define __RTL8712_GP_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_hal.h b/trunk/drivers/staging/rtl8712/rtl8712_hal.h index 665e71838172..c696dd8a2ea4 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_hal.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_hal.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_HAL_H__ #define __RTL8712_HAL_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h index 49598c314f09..02f24809814d 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_INTERRUPT_BITDEF_H__ #define __RTL8712_INTERRUPT_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h index 28e0a7ebcad7..74800cd2340d 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_MACSETTING_BITDEF_H__ #define __RTL8712_MACSETTING_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h index ced0da9332d5..00b003bd6900 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_MACSETTING_REGDEF_H__ #define __RTL8712_MACSETTING_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h index 8fc689416519..0922a8dc1322 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_POWERSAVE_BITDEF_H__ #define __RTL8712_POWERSAVE_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_powersave_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_powersave_regdef.h index 4632ddd5d1f7..72927df3db24 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_powersave_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_powersave_regdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_POWERSAVE_REGDEF_H__ #define __RTL8712_POWERSAVE_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h index 6d3d6e8522fb..87048b3fe04f 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_RATECTRL_BITDEF_H__ #define __RTL8712_RATECTRL_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h index 73dfc3610154..31c8363e5bc6 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_RATECTRL_REGDEF_H__ #define __RTL8712_RATECTRL_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_regdef.h index e7bca55b59d0..5b0de2ab6b61 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_regdef.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_REGDEF_H__ #define __RTL8712_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_security_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_security_bitdef.h index 05dafa0c3333..8df4bf4a0699 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_security_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_security_bitdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_SECURITY_BITDEF_H__ #define __RTL8712_SECURITY_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_spec.h b/trunk/drivers/staging/rtl8712/rtl8712_spec.h index af11b44b1140..3f181eed4ee9 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_spec.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_spec.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_SPEC_H__ #define __RTL8712_SPEC_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h index eed09c872fc9..dce15c2ff503 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_SYSCFG_BITDEF_H__ #define __RTL8712_SYSCFG_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h index 767dfdf8d83f..687e1b7a03f5 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_SYSCFG_REGDEF_H__ #define __RTL8712_SYSCFG_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h index 724421582421..32ce9fab5dbe 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_TIMECTRL_BITDEF_H__ #define __RTL8712_TIMECTRL_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h index 106916c7e310..8a3dd562ba89 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL8712_TIMECTRL_REGDEF_H__ #define __RTL8712_TIMECTRL_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h b/trunk/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h index 61a3603aa587..6d3be2a24226 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_WMAC_BITDEF_H__ #define __RTL8712_WMAC_BITDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl8712_wmac_regdef.h b/trunk/drivers/staging/rtl8712/rtl8712_wmac_regdef.h index d9f8347ab461..ac80dfb317cb 100644 --- a/trunk/drivers/staging/rtl8712/rtl8712_wmac_regdef.h +++ b/trunk/drivers/staging/rtl8712/rtl8712_wmac_regdef.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL8712_WMAC_REGDEF_H__ #define __RTL8712_WMAC_REGDEF_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl871x_byteorder.h b/trunk/drivers/staging/rtl8712/rtl871x_byteorder.h index bd3703b98bce..07707e23dbed 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_byteorder.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_byteorder.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef _RTL871X_BYTEORDER_H_ #define _RTL871X_BYTEORDER_H_ diff --git a/trunk/drivers/staging/rtl8712/rtl871x_eeprom.h b/trunk/drivers/staging/rtl8712/rtl871x_eeprom.h index 497276e53bbe..fb15f5bde426 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_eeprom.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_eeprom.h @@ -1,22 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ #ifndef __RTL871X_EEPROM_H__ #define __RTL871X_EEPROM_H__ diff --git a/trunk/drivers/staging/rtl8712/rtl871x_event.h b/trunk/drivers/staging/rtl8712/rtl871x_event.h index e03ee90d2870..6ce06767130d 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_event.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_event.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef _RTL871x_EVENT_H_ #define _RTL871x_EVENT_H_ diff --git a/trunk/drivers/staging/rtl8712/rtl871x_ht.h b/trunk/drivers/staging/rtl8712/rtl871x_ht.h index 41872d937408..612203deea73 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_ht.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_ht.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef _RTL871X_HT_H_ #define _RTL871X_HT_H_ diff --git a/trunk/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/trunk/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index d310a6174b97..40e6b5cc412d 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/trunk/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -975,13 +975,6 @@ static int r871x_wx_set_priv(struct net_device *dev, * s2. set_802_11_authentication_mode() * s3. set_802_11_encryption_mode() * s4. set_802_11_bssid() - * - * This function intends to handle the Set AP command, which specifies the - * MAC# of a preferred Access Point. - * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl. - * - * For this operation to succeed, there is no need for the interface to be Up. - * */ static int r8711_wx_set_wap(struct net_device *dev, struct iw_request_info *info, @@ -999,6 +992,8 @@ static int r8711_wx_set_wap(struct net_device *dev, struct wlan_network *pnetwork = NULL; enum NDIS_802_11_AUTHENTICATION_MODE authmode; + if (padapter->bup == false) + return -1; if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) return -1; if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) @@ -1079,14 +1074,6 @@ static int r871x_wx_set_mlme(struct net_device *dev, return ret; } -/** - * - * This function intends to handle the Set Scan command. - * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl. - * - * For this operation to succeed, the interface is brought Up beforehand. - * - */ static int r8711_wx_set_scan(struct net_device *dev, struct iw_request_info *a, union iwreq_data *wrqu, char *extra) @@ -1182,12 +1169,6 @@ static int r8711_wx_get_scan(struct net_device *dev, * s2. set_802_11_authenticaion_mode() * s3. set_802_11_encryption_mode() * s4. set_802_11_ssid() - * - * This function intends to handle the Set ESSID command. - * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl. - * - * For this operation to succeed, there is no need for the interface to be Up. - * */ static int r8711_wx_set_essid(struct net_device *dev, struct iw_request_info *a, @@ -1203,6 +1184,8 @@ static int r8711_wx_set_essid(struct net_device *dev, struct list_head *phead; u32 len; + if (padapter->bup == false) + return -1; if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) return -1; if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) @@ -2089,10 +2072,9 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) param = (struct ieee_param *)_malloc(p->length); if (param == NULL) return -ENOMEM; - if (copy_from_user(param, p->pointer, p->length)) { + if (copy_from_user(param, p->pointer, p->length)) kfree((u8 *)param); return -EFAULT; - } switch (param->cmd) { case IEEE_CMD_SET_WPA_PARAM: ret = wpa_set_param(dev, param->u.wpa_param.name, diff --git a/trunk/drivers/staging/rtl8712/rtl871x_ioctl_set.h b/trunk/drivers/staging/rtl8712/rtl871x_ioctl_set.h index de0a8482c988..8dff2b196ff2 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_ioctl_set.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_ioctl_set.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __IOCTL_SET_H #define __IOCTL_SET_H diff --git a/trunk/drivers/staging/rtl8712/rtl871x_mp.h b/trunk/drivers/staging/rtl8712/rtl871x_mp.h index a42d4f40d149..805aba07159e 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_mp.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_mp.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL871X_MP_H_ #define __RTL871X_MP_H_ diff --git a/trunk/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/trunk/drivers/staging/rtl8712/rtl871x_pwrctrl.h index b41ca2892be5..34f074aebd69 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL871X_PWRCTRL_H_ #define __RTL871X_PWRCTRL_H_ diff --git a/trunk/drivers/staging/rtl8712/rtl871x_rf.h b/trunk/drivers/staging/rtl8712/rtl871x_rf.h index 133ed6462928..6c54966f13f7 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_rf.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_rf.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL871X_RF_H_ #define __RTL871X_RF_H_ diff --git a/trunk/drivers/staging/rtl8712/rtl871x_security.h b/trunk/drivers/staging/rtl8712/rtl871x_security.h index a13395fe21d7..bff71d2aae98 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_security.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_security.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __RTL871X_SECURITY_H_ #define __RTL871X_SECURITY_H_ diff --git a/trunk/drivers/staging/rtl8712/rtl871x_wlan_sme.h b/trunk/drivers/staging/rtl8712/rtl871x_wlan_sme.h index 44924d5de217..d9733ac6a43a 100644 --- a/trunk/drivers/staging/rtl8712/rtl871x_wlan_sme.h +++ b/trunk/drivers/staging/rtl8712/rtl871x_wlan_sme.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef _RTL871X_WLAN_SME_H_ #define _RTL871X_WLAN_SME_H_ diff --git a/trunk/drivers/staging/rtl8712/swab.h b/trunk/drivers/staging/rtl8712/swab.h index f12781829c1b..44709a91bafc 100644 --- a/trunk/drivers/staging/rtl8712/swab.h +++ b/trunk/drivers/staging/rtl8712/swab.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef _LINUX_BYTEORDER_SWAB_H #define _LINUX_BYTEORDER_SWAB_H diff --git a/trunk/drivers/staging/rtl8712/usb_ops.h b/trunk/drivers/staging/rtl8712/usb_ops.h index 78e775a46364..dc0611a2a0df 100644 --- a/trunk/drivers/staging/rtl8712/usb_ops.h +++ b/trunk/drivers/staging/rtl8712/usb_ops.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __USB_OPS_H_ #define __USB_OPS_H_ diff --git a/trunk/drivers/staging/rtl8712/usb_osintf.h b/trunk/drivers/staging/rtl8712/usb_osintf.h index d397a82986d2..0da6c1db048e 100644 --- a/trunk/drivers/staging/rtl8712/usb_osintf.h +++ b/trunk/drivers/staging/rtl8712/usb_osintf.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef __USB_OSINTF_H #define __USB_OSINTF_H diff --git a/trunk/drivers/staging/rtl8712/usb_vendor_req.h b/trunk/drivers/staging/rtl8712/usb_vendor_req.h index 82335a83d0d2..d35c538c47a1 100644 --- a/trunk/drivers/staging/rtl8712/usb_vendor_req.h +++ b/trunk/drivers/staging/rtl8712/usb_vendor_req.h @@ -1,28 +1,3 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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 for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE - * Larry Finger - * - ******************************************************************************/ #ifndef _USB_VENDOR_REQUEST_H_ #define _USB_VENDOR_REQUEST_H_ diff --git a/trunk/drivers/staging/rts5139/Kconfig b/trunk/drivers/staging/rts5139/Kconfig deleted file mode 100644 index f940e516945a..000000000000 --- a/trunk/drivers/staging/rts5139/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -config RTS5139 - tristate "Realtek RTS5139 USB card reader support" - depends on USB_SUPPORT && SCSI - help - Say Y here to include driver code to support the Realtek - RTS5139 USB card readers. - - If this driver is compiled as a module, it will be named rts5139. - -config RTS5139_DEBUG - bool "Realtek RTS5139 Card Reader verbose debug" - depends on RTS5139 - help - Say Y here in order to have the rts5139 code generate - verbose debugging messages. - diff --git a/trunk/drivers/staging/rts5139/Makefile b/trunk/drivers/staging/rts5139/Makefile deleted file mode 100644 index 82b8958e8d31..000000000000 --- a/trunk/drivers/staging/rts5139/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# Driver for Realtek RTS51xx USB card reader -# -# Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2, or (at your option) any -# later version. -# -# 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 for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, see . -# -# Author: -# wwang (wei_wang@realsil.com.cn) -# No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China -# Maintainer: -# Edwin Rong (edwin_rong@realsil.com.cn) -# No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China -# -# Makefile for the RTS51xx USB Card Reader drivers. -# - -TARGET_MODULE := rts5139 - -EXTRA_CFLAGS := -Idrivers/scsi -I$(PWD) - -obj-m += $(TARGET_MODULE).o - -common-obj := rts51x_transport.o rts51x_scsi.o rts51x_fop.o - -$(TARGET_MODULE)-objs := $(common-obj) rts51x.o rts51x_chip.o rts51x_card.o \ - xd.o sd.o ms.o sd_cprm.o ms_mg.o diff --git a/trunk/drivers/staging/rts5139/TODO b/trunk/drivers/staging/rts5139/TODO deleted file mode 100644 index 4bde726ea5fa..000000000000 --- a/trunk/drivers/staging/rts5139/TODO +++ /dev/null @@ -1,5 +0,0 @@ -TODO: -- support more USB card reader of Realtek family -- use kernel coding style -- checkpatch.pl fixes - diff --git a/trunk/drivers/staging/rts5139/debug.h b/trunk/drivers/staging/rts5139/debug.h deleted file mode 100644 index 73dec133a1bf..000000000000 --- a/trunk/drivers/staging/rts5139/debug.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_DEBUG_H -#define __RTS51X_DEBUG_H - -#include - -#define RTS51X_TIP "rts51x: " - -#ifdef CONFIG_RTS5139_DEBUG -#define RTS51X_DEBUGP(x...) printk(KERN_DEBUG RTS51X_TIP x) -#define RTS51X_DEBUGPN(x...) printk(KERN_DEBUG x) -#define RTS51X_DEBUGPX(x...) printk(x) -#define RTS51X_DEBUG(x) x -#else -#define RTS51X_DEBUGP(x...) -#define RTS51X_DEBUGPN(x...) -#define RTS51X_DEBUGPX(x...) -#define RTS51X_DEBUG(x) -#endif - -#endif /* __RTS51X_DEBUG_H */ diff --git a/trunk/drivers/staging/rts5139/ms.c b/trunk/drivers/staging/rts5139/ms.c deleted file mode 100644 index b0e9071c8e52..000000000000 --- a/trunk/drivers/staging/rts5139/ms.c +++ /dev/null @@ -1,4191 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include -#include -#include - -#include "debug.h" -#include "trace.h" -#include "rts51x.h" -#include "rts51x_transport.h" -#include "rts51x_scsi.h" -#include "rts51x_card.h" -#include "ms.h" - -static inline void ms_set_err_code(struct rts51x_chip *chip, u8 err_code) -{ - struct ms_info *ms_card = &(chip->ms_card); - - ms_card->err_code = err_code; -} - -static inline int ms_check_err_code(struct rts51x_chip *chip, u8 err_code) -{ - struct ms_info *ms_card = &(chip->ms_card); - - return (ms_card->err_code == err_code); -} - -static int ms_parse_err_code(struct rts51x_chip *chip) -{ - TRACE_RET(chip, STATUS_FAIL); -} - -static int ms_transfer_tpc(struct rts51x_chip *chip, u8 trans_mode, u8 tpc, - u8 cnt, u8 cfg) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - - RTS51X_DEBUGP("ms_transfer_tpc: tpc = 0x%x\n", tpc); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | trans_mode); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, - MS_TRANSFER_END); - - rts51x_add_cmd(chip, READ_REG_CMD, MS_TRANS_CFG, 0, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 2, 5000); - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - rts51x_clear_ms_error(chip); - ms_set_err_code(chip, MS_TO_ERROR); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - - if (!(tpc & 0x08)) { /* Read Packet */ - /* Check CRC16 & Ready Timeout */ - if (chip->rsp_buf[1] & MS_CRC16_ERR) { - ms_set_err_code(chip, MS_CRC16_ERROR); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - } else { /* Write Packet */ - if (CHK_MSPRO(ms_card) && !(chip->rsp_buf[1] & 0x80)) { - if (chip->rsp_buf[1] & (MS_INT_ERR | MS_INT_CMDNK)) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - } - } - - /* Check Timeout of Ready Signal */ - if (chip->rsp_buf[1] & MS_RDY_TIMEOUT) { - rts51x_clear_ms_error(chip); - ms_set_err_code(chip, MS_TO_ERROR); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - - return STATUS_SUCCESS; -} - -int ms_transfer_data(struct rts51x_chip *chip, u8 trans_mode, u8 tpc, - u16 sec_cnt, u8 cfg, int mode_2k, int use_sg, void *buf, - int buf_len) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - u8 val, err_code = 0, flag = 0; - enum dma_data_direction dir; - unsigned int pipe; - - if (!buf || !buf_len) - TRACE_RET(chip, STATUS_FAIL); - - if (trans_mode == MS_TM_AUTO_READ) { - pipe = RCV_BULK_PIPE(chip); - dir = DMA_FROM_DEVICE; - flag = MODE_CDIR; - err_code = MS_FLASH_READ_ERROR; - } else if (trans_mode == MS_TM_AUTO_WRITE) { - pipe = SND_BULK_PIPE(chip); - dir = DMA_TO_DEVICE; - flag = MODE_CDOR; - err_code = MS_FLASH_WRITE_ERROR; - } else { - TRACE_RET(chip, STATUS_FAIL); - } - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_H, 0xFF, - (u8) (sec_cnt >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, - (u8) sec_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - RING_BUFFER); - - if (mode_2k) - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE, - MS_2K_SECTOR_MODE); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE, - 0); - - trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | trans_mode); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, - MS_TRANSFER_END); - - retval = rts51x_send_cmd(chip, flag | STAGE_MS_STATUS, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - rts51x_transfer_data_rcc(chip, pipe, buf, buf_len, use_sg, NULL, - 15000, flag); - if (retval != STATUS_SUCCESS) { - ms_set_err_code(chip, err_code); - rts51x_clear_ms_error(chip); - TRACE_RET(chip, retval); - } - - retval = rts51x_get_rsp(chip, 3, 15000); - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - ms_set_err_code(chip, err_code); - rts51x_clear_ms_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - ms_card->last_rw_int = val = chip->rsp_buf[1]; - if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -int ms_write_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *data, - int data_len) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - - if (!data || (data_len < cnt)) - TRACE_RET(chip, STATUS_ERROR); - - rts51x_init_cmd(chip); - - for (i = 0; i < cnt; i++) { - rts51x_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, - data[i]); - } - if (cnt % 2) - rts51x_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, - 0xFF, 0xFF); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_WRITE_BYTES); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, - MS_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 1, 5000); - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - u8 val = 0; - - rts51x_ep0_read_register(chip, MS_TRANS_CFG, &val); - RTS51X_DEBUGP("MS_TRANS_CFG: 0x%02x\n", val); - - rts51x_clear_ms_error(chip); - - if (!(tpc & 0x08)) { /* Read Packet */ - /* Check CRC16 & Ready Timeout */ - if (val & MS_CRC16_ERR) { - ms_set_err_code(chip, MS_CRC16_ERROR); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - } else { /* Write Packet */ - if (CHK_MSPRO(ms_card) && !(val & 0x80)) { - if (val & (MS_INT_ERR | MS_INT_CMDNK)) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, - ms_parse_err_code(chip)); - } - } - } - - /* Check Timeout of Ready Signal */ - if (val & MS_RDY_TIMEOUT) { - ms_set_err_code(chip, MS_TO_ERROR); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - - ms_set_err_code(chip, MS_TO_ERROR); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - - return STATUS_SUCCESS; -} - -int ms_read_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *data, - int data_len) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - - if (!data) - TRACE_RET(chip, STATUS_ERROR); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_READ_BYTES); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, - MS_TRANSFER_END); - - for (i = 0; i < data_len - 1; i++) - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0); - - if (data_len % 2) - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, - 0); - else - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1, - 0, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, data_len + 1, 5000); - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - u8 val = 0; - - rts51x_ep0_read_register(chip, MS_TRANS_CFG, &val); - RTS51X_DEBUGP("MS_TRANS_CFG: 0x%02x\n", val); - - rts51x_clear_ms_error(chip); - - if (!(tpc & 0x08)) { /* Read Packet */ - /* Check CRC16 & Ready Timeout */ - if (val & MS_CRC16_ERR) { - ms_set_err_code(chip, MS_CRC16_ERROR); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - } else { /* Write Packet */ - if (CHK_MSPRO(ms_card) && !(val & 0x80)) { - if (val & (MS_INT_ERR | MS_INT_CMDNK)) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, - ms_parse_err_code(chip)); - } - } - } - - /* Check Timeout of Ready Signal */ - if (val & MS_RDY_TIMEOUT) { - ms_set_err_code(chip, MS_TO_ERROR); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - - ms_set_err_code(chip, MS_TO_ERROR); - TRACE_RET(chip, ms_parse_err_code(chip)); - } - - rts51x_read_rsp_buf(chip, 1, data, data_len); - - return STATUS_SUCCESS; -} - -int ms_set_rw_reg_addr(struct rts51x_chip *chip, - u8 read_start, u8 read_cnt, u8 write_start, u8 write_cnt) -{ - int retval, i; - u8 data[4]; - - data[0] = read_start; - data[1] = read_cnt; - data[2] = write_start; - data[3] = write_cnt; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, SET_RW_REG_ADRS, 4, NO_WAIT_INT, data, - 4); - if (retval == STATUS_SUCCESS) - return STATUS_SUCCESS; - rts51x_clear_ms_error(chip); - } - - TRACE_RET(chip, STATUS_FAIL); -} - -static int ms_send_cmd(struct rts51x_chip *chip, u8 cmd, u8 cfg) -{ - u8 data[2]; - - data[0] = cmd; - data[1] = 0; - - return ms_write_bytes(chip, PRO_SET_CMD, 1, cfg, data, 1); -} - -static int ms_set_cmd(struct rts51x_chip *chip, - u8 read_start, u8 read_count, - u8 write_start, u8 write_count, - u8 cmd, u8 cfg, u8 *data, int data_len, u8 *int_stat) -{ - int retval, i; - u8 val; - - if (!data || (data_len <= 0) || (data_len > 128)) { - RTS51X_DEBUGP("ms_set_cmd (data_len = %d)\n", data_len); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = - ms_set_rw_reg_addr(chip, read_start, read_count, write_start, - write_count); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, WRITE_REG, write_count, NO_WAIT_INT, - data, data_len); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - - ms_set_err_code(chip, MS_NO_ERROR); - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_send_cmd(chip, cmd, WAIT_INT); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - /* GET_INT Register */ - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (int_stat) - *int_stat = val; - - return STATUS_SUCCESS; -} - -#ifdef MS_SPEEDUP -static int ms_auto_set_cmd(struct rts51x_chip *chip, - u8 read_start, u8 read_count, - u8 write_start, u8 write_count, - u8 cmd, u8 cfg, u8 *data, int data_len, - u8 *int_stat) -{ - int retval; - int i; - - if (!data || (data_len <= 0) || (data_len > 128)) { - RTS51X_DEBUGP("ms_auto_set_cmd (data_len = %d)\n", data_len); - TRACE_RET(chip, STATUS_FAIL); - } - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_READ_START, 0xFF, read_start); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_READ_COUNT, 0xFF, read_count); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_WRITE_START, 0xFF, write_start); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_WRITE_COUNT, 0xFF, write_count); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_COMMAND, 0xFF, cmd); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - - for (i = 0; i < data_len; i++) { - rts51x_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, - data[i]); - } - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_SET_CMD); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, - MS_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR | STAGE_MS_STATUS, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 3, 5000); - - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - rts51x_clear_ms_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - if (int_stat) - *int_stat = chip->rsp_buf[2]; - - return STATUS_SUCCESS; -} -#endif - -static int ms_set_init_para(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - - if (CHK_HG8BIT(ms_card)) { - if (chip->asic_code) - ms_card->ms_clock = chip->option.asic_ms_hg_clk; - else - ms_card->ms_clock = chip->option.fpga_ms_hg_clk; - } else if (CHK_MSPRO(ms_card) || CHK_MS4BIT(ms_card)) { - if (chip->asic_code) - ms_card->ms_clock = chip->option.asic_ms_4bit_clk; - else - ms_card->ms_clock = chip->option.fpga_ms_4bit_clk; - } else { - if (chip->asic_code) - ms_card->ms_clock = 38; - else - ms_card->ms_clock = CLK_40; - } - - retval = switch_clock(chip, ms_card->ms_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_select_card(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -int ms_switch_clock(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - - retval = rts51x_select_card(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = switch_clock(chip, ms_card->ms_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static void ms_pull_ctl_disable(struct rts51x_chip *chip) -{ - if (CHECK_PKG(chip, LQFP48)) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); - } -} - -static void ms_pull_ctl_enable(struct rts51x_chip *chip) -{ - if (CHECK_PKG(chip, LQFP48)) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); - } -} - -static int ms_prepare_reset(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - - ms_card->ms_type = 0; - ms_card->check_ms_flow = 0; - ms_card->switch_8bit_fail = 0; - ms_card->delay_write.delay_write_flag = 0; - - ms_card->pro_under_formatting = 0; - - rts51x_init_cmd(chip); - - if (chip->asic_code) { - ms_pull_ctl_enable(chip); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, - FPGA_MS_PULL_CTL_BIT | 0x20, 0); - } - /* Tri-state MS output */ - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0); - - if (!chip->option.FT2_fast_mode) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, - POWER_OFF); - } - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (!chip->option.FT2_fast_mode) { - wait_timeout(250); - - card_power_on(chip, MS_CARD); - wait_timeout(150); - -#ifdef SUPPORT_OCP - rts51x_get_card_status(chip, &(chip->card_status)); - /* get OCP status */ - chip->ocp_stat = (chip->card_status >> 4) & 0x03; - - if (chip->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) { - RTS51X_DEBUGP("Over current, OCPSTAT is 0x%x\n", - chip->ocp_stat); - TRACE_RET(chip, STATUS_FAIL); - } -#endif - } - - rts51x_init_cmd(chip); - - /* Enable MS Output */ - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, - MS_OUTPUT_EN); - - /* Reset Registers */ - if (chip->asic_code) - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_CFG, 0xFF, - SAMPLE_TIME_RISING | PUSH_TIME_DEFAULT | - NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_CFG, 0xFF, - SAMPLE_TIME_FALLING | PUSH_TIME_DEFAULT | - NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, - NO_WAIT_INT | NO_AUTO_READ_INT_REG); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return ms_set_init_para(chip); -} - -static int ms_identify_media_type(struct rts51x_chip *chip, int switch_8bit_bus) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - u8 val; - - retval = ms_set_rw_reg_addr(chip, Pro_StatusReg, 6, SystemParm, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - /* Get Register form MS-PRO card */ - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG, 6, - NO_WAIT_INT); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - - RTS51X_READ_REG(chip, PPBUF_BASE2 + 2, &val); - RTS51X_DEBUGP("Type register: 0x%x\n", val); - if (val != 0x01) { - if (val != 0x02) - ms_card->check_ms_flow = 1; - TRACE_RET(chip, STATUS_FAIL); - } - /* Category Register */ - RTS51X_READ_REG(chip, PPBUF_BASE2 + 4, &val); - RTS51X_DEBUGP("Category register: 0x%x\n", val); - if (val != 0) { - ms_card->check_ms_flow = 1; - TRACE_RET(chip, STATUS_FAIL); - } - /* Class Register */ - RTS51X_READ_REG(chip, PPBUF_BASE2 + 5, &val); - RTS51X_DEBUGP("Class register: 0x%x\n", val); - if (val == 0) { - RTS51X_READ_REG(chip, PPBUF_BASE2, &val); - if (val & WRT_PRTCT) - chip->card_wp |= MS_CARD; - else - chip->card_wp &= ~MS_CARD; - } else if ((val == 0x01) || (val == 0x02) || (val == 0x03)) { - chip->card_wp |= MS_CARD; - } else { - ms_card->check_ms_flow = 1; - TRACE_RET(chip, STATUS_FAIL); - } - - ms_card->ms_type |= TYPE_MSPRO; - - /* Check MSPro-HG Card, use IF Mode Register to distinguish */ - RTS51X_READ_REG(chip, PPBUF_BASE2 + 3, &val); - RTS51X_DEBUGP("IF Mode register: 0x%x\n", val); - if (val == 0) { - ms_card->ms_type &= 0x0F; - } else if (val == 7) { - if (switch_8bit_bus) - ms_card->ms_type |= MS_HG; - else - ms_card->ms_type &= 0x0F; - } else { - TRACE_RET(chip, STATUS_FAIL); - } - - /* end Procedure to identify Media Type */ - return STATUS_SUCCESS; -} - -static int ms_confirm_cpu_startup(struct rts51x_chip *chip) -{ - int retval, i, k; - u8 val; - - /* Confirm CPU StartUp */ - k = 0; - do { - if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) - TRACE_RET(chip, STATUS_FAIL); - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, - 1); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - - if (k > 100) - TRACE_RET(chip, STATUS_FAIL); - k++; - wait_timeout(100); - } while (!(val & INT_REG_CED)); - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - - if (val & INT_REG_ERR) { - if (val & INT_REG_CMDNK) { /* CMDNK = 1 */ - chip->card_wp |= (MS_CARD); - } else { /* CMDNK = 0 */ - TRACE_RET(chip, STATUS_FAIL); - } - } - /*-- end confirm CPU startup */ - - return STATUS_SUCCESS; -} - -static int ms_switch_parallel_bus(struct rts51x_chip *chip) -{ - int retval, i; - u8 data[2]; - - data[0] = PARALLEL_4BIT_IF; - data[1] = 0; - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT, data, 2); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static int ms_switch_8bit_bus(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - u8 data[2]; - - data[0] = PARALLEL_8BIT_IF; - data[1] = 0; - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT, data, 2); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTS51X_WRITE_REG(chip, MS_CFG, 0x98, - MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING); - ms_card->ms_type |= MS_8BIT; - - retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, - NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -static int ms_pro_reset_flow(struct rts51x_chip *chip, int switch_8bit_bus) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - - for (i = 0; i < 3; i++) { - retval = ms_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_identify_media_type(chip, switch_8bit_bus); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_confirm_cpu_startup(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_switch_parallel_bus(chip); - if (retval != STATUS_SUCCESS) { - if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) - TRACE_RET(chip, STATUS_FAIL); - continue; - } else { - break; - } - } - - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_WRITE_REG(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4); - - RTS51X_WRITE_REG(chip, MS_CFG, PUSH_TIME_ODD, PUSH_TIME_ODD); - - retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (CHK_MSHG(ms_card) && switch_8bit_bus) { - retval = ms_switch_8bit_bus(chip); - if (retval != STATUS_SUCCESS) { - ms_card->switch_8bit_fail = 1; - TRACE_RET(chip, retval); - } - } - - return STATUS_SUCCESS; -} - -#ifdef XC_POWERCLASS -static int msxc_change_power(struct rts51x_chip *chip, u8 mode) -{ - int retval; - u8 buf[6]; - - ms_cleanup_work(chip); - - /* Set Parameter Register */ - retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - buf[0] = 0; - buf[1] = mode; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - - retval = ms_write_bytes(chip, PRO_WRITE_REG, 6, NO_WAIT_INT, buf, 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_send_cmd(chip, XC_CHG_POWER, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_READ_REG(chip, MS_TRANS_CFG, buf); - if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR)) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} -#endif - -static int ms_read_attribute_info(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - u8 val, *buf, class_code, device_type, sub_class, data[16]; - u16 total_blk = 0, blk_size = 0; -#ifdef SUPPORT_MSXC - u32 xc_total_blk = 0, xc_blk_size = 0; -#endif - u32 sys_info_addr = 0, sys_info_size; -#ifdef SUPPORT_PCGL_1P18 - u32 model_name_addr = 0, model_name_size; - int found_sys_info = 0, found_model_name = 0; -#endif - - retval = ms_set_rw_reg_addr(chip, Pro_IntReg, 2, Pro_SystemParm, 7); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (CHK_MS8BIT(ms_card)) - data[0] = PARALLEL_8BIT_IF; - else - data[0] = PARALLEL_4BIT_IF; - data[1] = 0; - - data[2] = 0x40; - data[3] = 0; - data[4] = 0; - data[5] = 0; - /* Start address 0 */ - data[6] = 0; - data[7] = 0; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, PRO_WRITE_REG, 7, NO_WAIT_INT, data, - 8); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - buf = kmalloc(64 * 512, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, STATUS_NOMEM); - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_send_cmd(chip, PRO_READ_ATRB, WAIT_INT); - if (retval != STATUS_SUCCESS) - continue; - - retval = rts51x_read_register(chip, MS_TRANS_CFG, &val); - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - if (!(val & MS_INT_BREQ)) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = - ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, - 0x40, WAIT_INT, 0, 0, buf, 64 * 512); - if (retval == STATUS_SUCCESS) - break; - else - rts51x_clear_ms_error(chip); - } - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_RET(chip, retval); - } - - i = 0; - do { - retval = rts51x_read_register(chip, MS_TRANS_CFG, &val); - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_RET(chip, retval); - } - - if ((val & MS_INT_CED) || !(val & MS_INT_BREQ)) - break; - - retval = - ms_transfer_tpc(chip, MS_TM_NORMAL_READ, PRO_READ_LONG_DATA, - 0, WAIT_INT); - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_RET(chip, retval); - } - - i++; - } while (i < 1024); - - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_RET(chip, retval); - } - - if ((buf[0] != 0xa5) && (buf[1] != 0xc3)) { - /* Signature code is wrong */ - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - - if ((buf[4] < 1) || (buf[4] > 12)) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - - for (i = 0; i < buf[4]; i++) { - int cur_addr_off = 16 + i * 12; - -#ifdef SUPPORT_MSXC - if ((buf[cur_addr_off + 8] == 0x10) - || (buf[cur_addr_off + 8] == 0x13)) { -#else - if (buf[cur_addr_off + 8] == 0x10) { -#endif - sys_info_addr = ((u32) buf[cur_addr_off + 0] << 24) | - ((u32) buf[cur_addr_off + 1] << 16) | - ((u32) buf[cur_addr_off + 2] << 8) | - buf[cur_addr_off + 3]; - sys_info_size = - ((u32) buf[cur_addr_off + 4] << 24) | - ((u32) buf[cur_addr_off + 5] << 16) | - ((u32) buf[cur_addr_off + 6] << 8) | - buf[cur_addr_off + 7]; - RTS51X_DEBUGP("sys_info_addr = 0x%x," - "sys_info_size = 0x%x\n", - sys_info_addr, sys_info_size); - if (sys_info_size != 96) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - if (sys_info_addr < 0x1A0) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - if ((sys_info_size + sys_info_addr) > 0x8000) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } -#ifdef SUPPORT_MSXC - if (buf[cur_addr_off + 8] == 0x13) - ms_card->ms_type |= MS_XC; -#endif -#ifdef SUPPORT_PCGL_1P18 - found_sys_info = 1; -#else - break; -#endif - } -#ifdef SUPPORT_PCGL_1P18 - if (buf[cur_addr_off + 8] == 0x15) { - model_name_addr = ((u32) buf[cur_addr_off + 0] << 24) | - ((u32) buf[cur_addr_off + 1] << 16) | - ((u32) buf[cur_addr_off + 2] << 8) | - buf[cur_addr_off + 3]; - model_name_size = - ((u32) buf[cur_addr_off + 4] << 24) | - ((u32) buf[cur_addr_off + 5] << 16) | - ((u32) buf[cur_addr_off + 6] << 8) | - buf[cur_addr_off + 7]; - RTS51X_DEBUGP("model_name_addr = 0x%x," - "model_name_size = 0x%x\n", - model_name_addr, model_name_size); - if (model_name_size != 48) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - if (model_name_addr < 0x1A0) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - if ((model_name_size + model_name_addr) > 0x8000) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - - found_model_name = 1; - } - - if (found_sys_info && found_model_name) - break; -#endif - } - - if (i == buf[4]) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - - class_code = buf[sys_info_addr + 0]; - device_type = buf[sys_info_addr + 56]; - sub_class = buf[sys_info_addr + 46]; -#ifdef SUPPORT_MSXC - if (CHK_MSXC(ms_card)) { - xc_total_blk = ((u32) buf[sys_info_addr + 6] << 24) | - ((u32) buf[sys_info_addr + 7] << 16) | - ((u32) buf[sys_info_addr + 8] << 8) | - buf[sys_info_addr + 9]; - xc_blk_size = ((u32) buf[sys_info_addr + 32] << 24) | - ((u32) buf[sys_info_addr + 33] << 16) | - ((u32) buf[sys_info_addr + 34] << 8) | - buf[sys_info_addr + 35]; - RTS51X_DEBUGP("xc_total_blk = 0x%x, xc_blk_size = 0x%x\n", - xc_total_blk, xc_blk_size); - } else { - total_blk = - ((u16) buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + - 7]; - blk_size = - ((u16) buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + - 3]; - RTS51X_DEBUGP("total_blk = 0x%x, blk_size = 0x%x\n", total_blk, - blk_size); - } -#else - total_blk = - ((u16) buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + 7]; - blk_size = ((u16) buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + 3]; - RTS51X_DEBUGP("total_blk = 0x%x, blk_size = 0x%x\n", total_blk, - blk_size); -#endif - - RTS51X_DEBUGP("class_code = 0x%x, device_type = 0x%x," - "sub_class = 0x%x\n", - class_code, device_type, sub_class); - - memcpy(ms_card->raw_sys_info, buf + sys_info_addr, 96); -#ifdef SUPPORT_PCGL_1P18 - memcpy(ms_card->raw_model_name, buf + model_name_addr, 48); -#endif - - kfree(buf); - - /* Confirm System Information */ -#ifdef SUPPORT_MSXC - if (CHK_MSXC(ms_card)) { - if (class_code != 0x03) - TRACE_RET(chip, STATUS_FAIL); - } else { - if (class_code != 0x02) - TRACE_RET(chip, STATUS_FAIL); - } -#else - if (class_code != 0x02) - TRACE_RET(chip, STATUS_FAIL); -#endif - - if (device_type != 0x00) { - if ((device_type == 0x01) || (device_type == 0x02) - || (device_type == 0x03)) - chip->card_wp |= MS_CARD; - else - TRACE_RET(chip, STATUS_FAIL); - } - if (sub_class & 0xC0) - TRACE_RET(chip, STATUS_FAIL); - - RTS51X_DEBUGP("class_code: 0x%x, device_type: 0x%x, sub_class: 0x%x\n", - class_code, device_type, sub_class); - -#ifdef SUPPORT_MSXC - if (CHK_MSXC(ms_card)) { - chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity = - xc_total_blk * xc_blk_size; - } else { - chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity = - total_blk * blk_size; - } -#else - chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity = - total_blk * blk_size; -#endif - - return STATUS_SUCCESS; -} - -#ifdef SUPPORT_MAGIC_GATE -int mg_set_tpc_para_sub(struct rts51x_chip *chip, int type, u8 mg_entry_num); -#endif - -static int reset_ms_pro(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; -#ifdef XC_POWERCLASS - u8 change_power_class = 2; -#endif - -#ifdef XC_POWERCLASS -Retry: -#endif - retval = ms_pro_reset_flow(chip, 1); - if (retval != STATUS_SUCCESS) { - if (ms_card->switch_8bit_fail) { - retval = ms_pro_reset_flow(chip, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - TRACE_RET(chip, retval); - } - } - - retval = ms_read_attribute_info(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#ifdef XC_POWERCLASS - if (CHK_HG8BIT(ms_card)) - change_power_class = 0; - - if (change_power_class && CHK_MSXC(ms_card)) { - u8 power_class_mode = (ms_card->raw_sys_info[46] & 0x18) >> 3; - RTS51X_DEBUGP("power_class_mode = 0x%x", power_class_mode); - if (change_power_class > power_class_mode) - change_power_class = power_class_mode; - if (change_power_class) { - retval = msxc_change_power(chip, change_power_class); - if (retval != STATUS_SUCCESS) { - change_power_class--; - goto Retry; - } - } - } -#endif - -#ifdef SUPPORT_MAGIC_GATE - retval = mg_set_tpc_para_sub(chip, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#endif - - if (CHK_HG8BIT(ms_card)) - chip->card_bus_width[chip->card2lun[MS_CARD]] = 8; - else - chip->card_bus_width[chip->card2lun[MS_CARD]] = 4; - - return STATUS_SUCCESS; -} - -static int ms_read_status_reg(struct rts51x_chip *chip) -{ - int retval; - u8 val[2]; - - retval = ms_set_rw_reg_addr(chip, StatusReg0, 2, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_read_bytes(chip, READ_REG, 2, NO_WAIT_INT, val, 2); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (val[1] & (STS_UCDT | STS_UCEX | STS_UCFG)) { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int ms_check_boot_block(struct rts51x_chip *chip, u16 block_addr) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - u8 extra[MS_EXTRA_SIZE], data[10], val = 0; - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (block_addr >> 8); - data[3] = (u8) block_addr; - /* Page Number - * Extra data access mode */ - data[4] = 0x40; - data[5] = 0; - - retval = ms_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6, - BLOCK_READ, WAIT_INT, data, 6, &val); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - retval = - ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - } - - retval = - ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT, extra, - MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (!(extra[0] & BLOCK_OK) || (extra[1] & NOT_BOOT_BLOCK)) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int ms_read_extra_data(struct rts51x_chip *chip, - u16 block_addr, u8 page_num, u8 *buf, - int buf_len) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - u8 val = 0, data[10]; - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (block_addr >> 8); - data[3] = (u8) block_addr; - /* Page Number - * Extra data access mode */ - data[4] = 0x40; - data[5] = page_num; - -#ifdef MS_SPEEDUP - retval = - ms_auto_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6, - BLOCK_READ, WAIT_INT, data, 6, &val); -#else - retval = ms_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6, - BLOCK_READ, WAIT_INT, data, 6, &val); -#endif - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - retval = - ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - } - - retval = - ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT, data, - MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (buf && buf_len) { - if (buf_len > MS_EXTRA_SIZE) - buf_len = MS_EXTRA_SIZE; - memcpy(buf, data, buf_len); - } - - return STATUS_SUCCESS; -} - -static int ms_write_extra_data(struct rts51x_chip *chip, - u16 block_addr, u8 page_num, u8 *buf, - int buf_len) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - u8 val = 0, data[16]; - - if (!buf || (buf_len < MS_EXTRA_SIZE)) - TRACE_RET(chip, STATUS_FAIL); - /* Write REG */ - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (block_addr >> 8); - data[3] = (u8) block_addr; - /* Page Number - * Extra data access mode */ - data[4] = 0x40; - data[5] = page_num; - - for (i = 6; i < MS_EXTRA_SIZE + 6; i++) - data[i] = buf[i - 6]; - -#ifdef MS_SPEEDUP - retval = - ms_auto_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, - 6 + MS_EXTRA_SIZE, BLOCK_WRITE, WAIT_INT, data, 16, - &val); -#else - retval = - ms_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, - 6 + MS_EXTRA_SIZE, BLOCK_WRITE, WAIT_INT, data, 16, - &val); -#endif - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - return STATUS_SUCCESS; -} - -static int ms_read_page(struct rts51x_chip *chip, u16 block_addr, u8 page_num) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - u8 val = 0, data[6]; - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (block_addr >> 8); - data[3] = (u8) block_addr; - /* Page Number - * Single page access mode */ - data[4] = 0x20; - data[5] = page_num; - - retval = ms_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6, - BLOCK_READ, WAIT_INT, data, 6, &val); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - } else { - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - retval = - ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, 0, - NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int ms_set_bad_block(struct rts51x_chip *chip, u16 phy_blk) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - u8 val = 0, data[8], extra[MS_EXTRA_SIZE]; - - retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (phy_blk >> 8); - data[3] = (u8) phy_blk; - data[4] = 0x80; - data[5] = 0; - data[6] = extra[0] & 0x7F; - data[7] = 0xFF; - -#ifdef MS_SPEEDUP - retval = ms_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7, - BLOCK_WRITE, WAIT_INT, data, 7, &val); -#else - retval = ms_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7, - BLOCK_WRITE, WAIT_INT, data, 7, &val); -#endif - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - return STATUS_SUCCESS; -} - -static int ms_erase_block(struct rts51x_chip *chip, u16 phy_blk) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i = 0; - u8 val = 0, data[6]; - - retval = - ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, - 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (phy_blk >> 8); - data[3] = (u8) phy_blk; - data[4] = 0; - data[5] = 0; - -ERASE_RTY: -#ifdef MS_SPEEDUP - retval = - ms_auto_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6, - BLOCK_ERASE, WAIT_INT, data, 6, &val); -#else - retval = ms_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6, - BLOCK_ERASE, WAIT_INT, data, 6, &val); -#endif - - if (val & INT_REG_CMDNK) { - if (i < 3) { - i++; - goto ERASE_RTY; - } - ms_set_err_code(chip, MS_CMD_NK); - ms_set_bad_block(chip, phy_blk); - TRACE_RET(chip, STATUS_FAIL); - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - return STATUS_SUCCESS; -} - -static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len) -{ - if (!extra || (extra_len < MS_EXTRA_SIZE)) - return; - - memset(extra, 0xFF, MS_EXTRA_SIZE); - - if (type == setPS_NG) - extra[0] = 0xB8; - else - extra[0] = 0x98; - - extra[2] = (u8) (log_blk >> 8); - extra[3] = (u8) log_blk; -} - -static int ms_init_page(struct rts51x_chip *chip, u16 phy_blk, u16 log_blk, - u8 start_page, u8 end_page) -{ - int retval; - u8 extra[MS_EXTRA_SIZE], i; - - memset(extra, 0xff, MS_EXTRA_SIZE); - - extra[0] = 0xf8; /* Block, page OK, data erased */ - extra[1] = 0xff; - extra[2] = (u8) (log_blk >> 8); - extra[3] = (u8) log_blk; - - for (i = start_page; i < end_page; i++) { - if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) - TRACE_RET(chip, STATUS_FAIL); - - retval = - ms_write_extra_data(chip, phy_blk, i, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -static int ms_copy_page(struct rts51x_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 start_page, u8 end_page) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, rty_cnt, uncorrect_flag = 0; - u8 extra[MS_EXTRA_SIZE], val, i, j, data[16]; - - RTS51X_DEBUGP("Copy page from 0x%x to 0x%x, logical block is 0x%x\n", - old_blk, new_blk, log_blk); - RTS51X_DEBUGP("start_page = %d, end_page = %d\n", start_page, - end_page); - - retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_READ_REG(chip, PPBUF_BASE2, &val); - - if (val & BUF_FULL) { - /* Clear Buffer */ - retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* GET_INT Register */ - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (!(val & INT_REG_CED)) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - for (i = start_page; i < end_page; i++) { - if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) - TRACE_RET(chip, STATUS_FAIL); - - ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE); - - retval = - ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* Write REG */ - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (old_blk >> 8); - data[3] = (u8) old_blk; - data[4] = 0x20; - data[5] = i; - - retval = - ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) { - uncorrect_flag = 1; - RTS51X_DEBUGP("Uncorrectable" - "error\n"); - } else { - uncorrect_flag = 0; - } - - retval = - ms_transfer_tpc(chip, MS_TM_NORMAL_READ, - READ_PAGE_DATA, 0, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (uncorrect_flag) { - ms_set_page_status(log_blk, setPS_NG, - extra, MS_EXTRA_SIZE); - if (i == 0) - extra[0] &= 0xEF; - ms_write_extra_data(chip, old_blk, i, - extra, - MS_EXTRA_SIZE); - RTS51X_DEBUGP("page %d :" - "extra[0] = 0x%x\n", - i, extra[0]); - MS_SET_BAD_BLOCK_FLG(ms_card); - - ms_set_page_status(log_blk, setPS_Error, - extra, MS_EXTRA_SIZE); - ms_write_extra_data(chip, new_blk, i, - extra, MS_EXTRA_SIZE); - continue; - } - - for (rty_cnt = 0; rty_cnt < MS_MAX_RETRY_COUNT; - rty_cnt++) { - retval = - ms_transfer_tpc(chip, - MS_TM_NORMAL_WRITE, - WRITE_PAGE_DATA, 0, - NO_WAIT_INT); - if (retval == STATUS_SUCCESS) - break; - } - if (rty_cnt == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - } - - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - retval = ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, - (6 + MS_EXTRA_SIZE)); - - /* Write REG */ - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (new_blk >> 8); - data[3] = (u8) new_blk; - data[4] = 0x20; - data[5] = i; - - /* for MS check procedure */ - if ((extra[0] & 0x60) != 0x60) - data[6] = extra[0]; - else - data[6] = 0xF8; - - data[6 + 1] = 0xFF; - data[6 + 2] = (u8) (log_blk >> 8); - data[6 + 3] = (u8) log_blk; - - for (j = 4; j <= MS_EXTRA_SIZE; j++) - data[6 + j] = 0xFF; - - retval = - ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE), - NO_WAIT_INT, data, 16); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* GET_INT Register */ - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - if (i == 0) { - retval = - ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, 7); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (old_blk >> 8); - data[3] = (u8) old_blk; - data[4] = 0x80; - data[5] = 0; - data[6] = 0xEF; - data[7] = 0xFF; - - retval = - ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, - data, 8); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ms_set_err_code(chip, MS_NO_ERROR); - retval = - ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, - 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, - MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - } - } - - return STATUS_SUCCESS; -} - -#ifdef MS_SPEEDUP -static int ms_auto_copy_page(struct rts51x_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 start_page, u8 end_page) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - u8 page_len, bus_width, val = 0; - u8 extra[MS_EXTRA_SIZE]; - - RTS51X_DEBUGP("Auto copy page from 0x%x to 0x%x," - "logical block is 0x%x\n", - old_blk, new_blk, log_blk); - RTS51X_DEBUGP("start_page = %d, end_page = %d\n", start_page, - end_page); - - page_len = end_page - start_page; - - retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_READ_REG(chip, PPBUF_BASE2, &val); - - if (val & BUF_FULL) { - retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (!(val & INT_REG_CED)) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - bus_width = 0x88; - } else { - /* Serial interface */ - bus_width = 0x80; - } - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_OLD_BLOCK_0, 0xFF, (u8) old_blk); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_OLD_BLOCK_1, 0xFF, - (u8) (old_blk >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_NEW_BLOCK_0, 0xFF, (u8) new_blk); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_NEW_BLOCK_1, 0xFF, - (u8) (new_blk >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_LOG_BLOCK_0, 0xFF, (u8) log_blk); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_LOG_BLOCK_1, 0xFF, - (u8) (log_blk >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_PAGE_START, 0xFF, start_page); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_PAGE_LENGTH, 0xFF, page_len); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_BUS_WIDTH, 0xFF, bus_width); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_COPY_PAGE); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, - MS_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) { - rts51x_clear_ms_error(chip); - TRACE_RET(chip, retval); - } - - retval = rts51x_get_rsp(chip, 1, 5000); - - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - rts51x_clear_ms_error(chip); - if (retval == STATUS_TIMEDOUT) - TRACE_RET(chip, retval); - TRACE_GOTO(chip, Fail); - } - - return STATUS_SUCCESS; - -Fail: - retval = ms_erase_block(chip, new_blk); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - ms_copy_page(chip, old_blk, new_blk, log_blk, start_page, end_page); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} -#endif - -static int reset_ms(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - u16 i, reg_addr, block_size; - u8 val, j, *ptr; -#ifndef SUPPORT_MAGIC_GATE - u16 eblock_cnt; -#endif - - retval = ms_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ms_card->ms_type |= TYPE_MS; - - retval = ms_send_cmd(chip, MS_RESET, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_READ_REG(chip, PPBUF_BASE2, &val); - if (val & WRT_PRTCT) - chip->card_wp |= MS_CARD; - else - chip->card_wp &= ~MS_CARD; - - i = 0; - -RE_SEARCH: - /* Search For Boot Block */ - while (i < (MAX_DEFECTIVE_BLOCK + 2)) { - if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) - TRACE_RET(chip, STATUS_FAIL); - - retval = ms_check_boot_block(chip, i); - if (retval != STATUS_SUCCESS) { - i++; - continue; - } - - ms_card->boot_block = i; - break; - } - - if (i == (MAX_DEFECTIVE_BLOCK + 2)) { - RTS51X_DEBUGP("No boot block found!"); - TRACE_RET(chip, STATUS_FAIL); - } - for (j = 0; j < 3; j++) { - retval = ms_read_page(chip, ms_card->boot_block, j); - if (retval != STATUS_SUCCESS) { - if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) { - i = ms_card->boot_block + 1; - ms_set_err_code(chip, MS_NO_ERROR); - goto RE_SEARCH; - } - } - } - - /* Read boot block contents */ - retval = ms_read_page(chip, ms_card->boot_block, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* Read MS system information as sys_info */ - retval = - rts51x_seq_read_register(chip, PPBUF_BASE2 + 0x1A0, 96, - ms_card->raw_sys_info); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* Read useful block contents */ - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, READ_REG_CMD, HEADER_ID0, 0, 0); - rts51x_add_cmd(chip, READ_REG_CMD, HEADER_ID1, 0, 0); - - for (reg_addr = DISABLED_BLOCK0; reg_addr <= DISABLED_BLOCK3; - reg_addr++) { - rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - } - - for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++) - rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - rts51x_add_cmd(chip, READ_REG_CMD, MS_Device_Type, 0, 0); - rts51x_add_cmd(chip, READ_REG_CMD, MS_4bit_Support, 0, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 16, 100); - - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ptr = rts51x_get_rsp_data(chip); - - RTS51X_DEBUGP("Boot block data:\n"); - RTS51X_DUMP(ptr, 16); - - if (ptr[0] != 0x00 || ptr[1] != 0x01) { - i = ms_card->boot_block + 1; - goto RE_SEARCH; - } - if (ptr[12] != 0x02 || ptr[13] != 0x00) { - i = ms_card->boot_block + 1; - goto RE_SEARCH; - } - if ((ptr[14] == 1) || (ptr[14] == 3)) - chip->card_wp |= MS_CARD; - block_size = ((u16) ptr[6] << 8) | ptr[7]; - if (block_size == 0x0010) { - ms_card->block_shift = 5; - ms_card->page_off = 0x1F; - } else if (block_size == 0x0008) { - ms_card->block_shift = 4; - ms_card->page_off = 0x0F; - } - ms_card->total_block = ((u16) ptr[8] << 8) | ptr[9]; - -#ifdef SUPPORT_MAGIC_GATE - j = ptr[10]; - - if (ms_card->block_shift == 4) { - if (j < 2) - ms_card->capacity = 0x1EE0; - else - ms_card->capacity = 0x3DE0; - } else { - if (j < 5) - ms_card->capacity = 0x7BC0; - else if (j < 0xA) - ms_card->capacity = 0xF7C0; - else if (j < 0x11) - ms_card->capacity = 0x1EF80; - else - ms_card->capacity = 0x3DF00; - } -#else - eblock_cnt = ((u16) ptr[10] << 8) | ptr[11]; - - ms_card->capacity = ((u32) eblock_cnt - 2) << ms_card->block_shift; -#endif - - chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity; - - if (ptr[15]) { - retval = ms_set_rw_reg_addr(chip, 0, 0, SystemParm, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - RTS51X_WRITE_REG(chip, PPBUF_BASE2, 0xFF, 0x88); - RTS51X_WRITE_REG(chip, PPBUF_BASE2 + 1, 0xFF, 0); - - retval = - ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG, 1, - NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - RTS51X_WRITE_REG(chip, MS_CFG, 0x58 | MS_NO_CHECK_INT, - MS_BUS_WIDTH_4 | PUSH_TIME_ODD | - MS_NO_CHECK_INT); - - ms_card->ms_type |= MS_4BIT; - } - - if (CHK_MS4BIT(ms_card)) - chip->card_bus_width[chip->card2lun[MS_CARD]] = 4; - else - chip->card_bus_width[chip->card2lun[MS_CARD]] = 1; - - return STATUS_SUCCESS; -} - -static int ms_init_l2p_tbl(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int size, i, seg_no, retval; - u16 defect_block, reg_addr; - u8 val1, val2; - - ms_card->segment_cnt = ms_card->total_block >> 9; - RTS51X_DEBUGP("ms_card->segment_cnt = %d\n", ms_card->segment_cnt); - - size = ms_card->segment_cnt * sizeof(struct zone_entry); - ms_card->segment = vmalloc(size); - if (ms_card->segment == NULL) - TRACE_RET(chip, STATUS_FAIL); - memset(ms_card->segment, 0, size); - - retval = ms_read_page(chip, ms_card->boot_block, 1); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, INIT_FAIL); - - reg_addr = PPBUF_BASE2; - for (i = 0; i < (((ms_card->total_block >> 9) * 10) + 1); i++) { - retval = rts51x_read_register(chip, reg_addr++, &val1); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, INIT_FAIL); - retval = rts51x_read_register(chip, reg_addr++, &val2); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, INIT_FAIL); - - defect_block = ((u16) val1 << 8) | val2; - if (defect_block == 0xFFFF) - break; - seg_no = defect_block / 512; - ms_card->segment[seg_no].defect_list[ms_card->segment[seg_no]. - disable_count++] = - defect_block; - } - - for (i = 0; i < ms_card->segment_cnt; i++) { - ms_card->segment[i].build_flag = 0; - ms_card->segment[i].l2p_table = NULL; - ms_card->segment[i].free_table = NULL; - ms_card->segment[i].get_index = 0; - ms_card->segment[i].set_index = 0; - ms_card->segment[i].unused_blk_cnt = 0; - - RTS51X_DEBUGP("defective block count of segment %d is %d\n", - i, ms_card->segment[i].disable_count); - } - - return STATUS_SUCCESS; - -INIT_FAIL: - if (ms_card->segment) { - vfree(ms_card->segment); - ms_card->segment = NULL; - } - - return STATUS_FAIL; -} - -static u16 ms_get_l2p_tbl(struct rts51x_chip *chip, int seg_no, u16 log_off) -{ - struct ms_info *ms_card = &(chip->ms_card); - struct zone_entry *segment; - - if (ms_card->segment == NULL) - return 0xFFFF; - - segment = &(ms_card->segment[seg_no]); - - if (segment->l2p_table) - return segment->l2p_table[log_off]; - - return 0xFFFF; -} - -static void ms_set_l2p_tbl(struct rts51x_chip *chip, int seg_no, u16 log_off, - u16 phy_blk) -{ - struct ms_info *ms_card = &(chip->ms_card); - struct zone_entry *segment; - - if (ms_card->segment == NULL) - return; - - segment = &(ms_card->segment[seg_no]); - if (segment->l2p_table) - segment->l2p_table[log_off] = phy_blk; -} - -static void ms_set_unused_block(struct rts51x_chip *chip, u16 phy_blk) -{ - struct ms_info *ms_card = &(chip->ms_card); - struct zone_entry *segment; - int seg_no; - - seg_no = (int)phy_blk >> 9; - segment = &(ms_card->segment[seg_no]); - - segment->free_table[segment->set_index++] = phy_blk; - if (segment->set_index >= MS_FREE_TABLE_CNT) - segment->set_index = 0; - segment->unused_blk_cnt++; -} - -static u16 ms_get_unused_block(struct rts51x_chip *chip, int seg_no) -{ - struct ms_info *ms_card = &(chip->ms_card); - struct zone_entry *segment; - u16 phy_blk; - - segment = &(ms_card->segment[seg_no]); - - if (segment->unused_blk_cnt <= 0) - return 0xFFFF; - - phy_blk = segment->free_table[segment->get_index]; - segment->free_table[segment->get_index++] = 0xFFFF; - if (segment->get_index >= MS_FREE_TABLE_CNT) - segment->get_index = 0; - segment->unused_blk_cnt--; - - return phy_blk; -} - -static const unsigned short ms_start_idx[] = { - 0, 494, 990, 1486, 1982, 2478, 2974, 3470, - 3966, 4462, 4958, 5454, 5950, 6446, 6942, 7438, 7934 -}; - -static int ms_arbitrate_l2p(struct rts51x_chip *chip, u16 phy_blk, u16 log_off, - u8 us1, u8 us2) -{ - struct ms_info *ms_card = &(chip->ms_card); - struct zone_entry *segment; - int seg_no; - u16 tmp_blk; - - seg_no = (int)phy_blk >> 9; - segment = &(ms_card->segment[seg_no]); - tmp_blk = segment->l2p_table[log_off]; - - if (us1 != us2) { - if (us1 == 0) { - if (!(chip->card_wp & MS_CARD)) - ms_erase_block(chip, tmp_blk); - ms_set_unused_block(chip, tmp_blk); - segment->l2p_table[log_off] = phy_blk; - } else { - if (!(chip->card_wp & MS_CARD)) - ms_erase_block(chip, phy_blk); - ms_set_unused_block(chip, phy_blk); - } - } else { - if (phy_blk < tmp_blk) { - if (!(chip->card_wp & MS_CARD)) - ms_erase_block(chip, phy_blk); - ms_set_unused_block(chip, phy_blk); - } else { - if (!(chip->card_wp & MS_CARD)) - ms_erase_block(chip, tmp_blk); - ms_set_unused_block(chip, tmp_blk); - segment->l2p_table[log_off] = phy_blk; - } - } - - return STATUS_SUCCESS; -} - -static int ms_build_l2p_tbl(struct rts51x_chip *chip, int seg_no) -{ - struct ms_info *ms_card = &(chip->ms_card); - struct zone_entry *segment; - int retval, table_size, disable_cnt, defect_flag, i; - u16 start, end, phy_blk, log_blk, tmp_blk; - u8 extra[MS_EXTRA_SIZE], us1, us2; - - RTS51X_DEBUGP("ms_build_l2p_tbl: %d\n", seg_no); - - if (ms_card->segment == NULL) { - retval = ms_init_l2p_tbl(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - if (ms_card->segment[seg_no].build_flag) { - RTS51X_DEBUGP("l2p table of segment %d has been built\n", - seg_no); - return STATUS_SUCCESS; - } - - if (seg_no == 0) - table_size = 494; - else - table_size = 496; - - segment = &(ms_card->segment[seg_no]); - - if (segment->l2p_table == NULL) { - segment->l2p_table = vmalloc(table_size * 2); - if (segment->l2p_table == NULL) - TRACE_GOTO(chip, BUILD_FAIL); - } - memset((u8 *) (segment->l2p_table), 0xff, table_size * 2); - - if (segment->free_table == NULL) { - segment->free_table = vmalloc(MS_FREE_TABLE_CNT * 2); - if (segment->free_table == NULL) - TRACE_GOTO(chip, BUILD_FAIL); - } - memset((u8 *) (segment->free_table), 0xff, MS_FREE_TABLE_CNT * 2); - - start = (u16) seg_no << 9; - end = (u16) (seg_no + 1) << 9; - - disable_cnt = segment->disable_count; - - segment->get_index = segment->set_index = 0; - segment->unused_blk_cnt = 0; - - for (phy_blk = start; phy_blk < end; phy_blk++) { - if (disable_cnt) { - defect_flag = 0; - for (i = 0; i < segment->disable_count; i++) { - if (phy_blk == segment->defect_list[i]) { - defect_flag = 1; - break; - } - } - if (defect_flag) { - disable_cnt--; - continue; - } - } - - retval = - ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) { - RTS51X_DEBUGP("read extra data fail\n"); - ms_set_bad_block(chip, phy_blk); - continue; - } - - if (seg_no == ms_card->segment_cnt - 1) { - if (!(extra[1] & NOT_TRANSLATION_TABLE)) { - if (!(chip->card_wp & MS_CARD)) { - retval = ms_erase_block(chip, phy_blk); - if (retval != STATUS_SUCCESS) - continue; - extra[2] = 0xff; - extra[3] = 0xff; - } - } - } - - if (!(extra[0] & BLOCK_OK)) - continue; - if (!(extra[1] & NOT_BOOT_BLOCK)) - continue; - if ((extra[0] & PAGE_OK) != PAGE_OK) - continue; - - log_blk = ((u16) extra[2] << 8) | extra[3]; - - if (log_blk == 0xFFFF) { - if (!(chip->card_wp & MS_CARD)) { - retval = ms_erase_block(chip, phy_blk); - if (retval != STATUS_SUCCESS) - continue; - } - ms_set_unused_block(chip, phy_blk); - continue; - } - - if ((log_blk < ms_start_idx[seg_no]) || - (log_blk >= ms_start_idx[seg_no + 1])) { - if (!(chip->card_wp & MS_CARD)) { - retval = ms_erase_block(chip, phy_blk); - if (retval != STATUS_SUCCESS) - continue; - } - ms_set_unused_block(chip, phy_blk); - continue; - } - - if (segment->l2p_table[log_blk - ms_start_idx[seg_no]] == - 0xFFFF) { - segment->l2p_table[log_blk - ms_start_idx[seg_no]] = - phy_blk; - continue; - } - - us1 = extra[0] & 0x10; - tmp_blk = segment->l2p_table[log_blk - ms_start_idx[seg_no]]; - retval = - ms_read_extra_data(chip, tmp_blk, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - continue; - us2 = extra[0] & 0x10; - - (void)ms_arbitrate_l2p(chip, phy_blk, - log_blk - ms_start_idx[seg_no], us1, - us2); - continue; - } - - segment->build_flag = 1; - - RTS51X_DEBUGP("unused block count: %d\n", segment->unused_blk_cnt); - - if (seg_no == ms_card->segment_cnt - 1) { - if (segment->unused_blk_cnt < 2) - chip->card_wp |= MS_CARD; - } else { - if (segment->unused_blk_cnt < 1) - chip->card_wp |= MS_CARD; - } - - if (chip->card_wp & MS_CARD) - return STATUS_SUCCESS; - - for (log_blk = ms_start_idx[seg_no]; log_blk < ms_start_idx[seg_no + 1]; - log_blk++) { - if (segment->l2p_table[log_blk - ms_start_idx[seg_no]] == - 0xFFFF) { - phy_blk = ms_get_unused_block(chip, seg_no); - if (phy_blk == 0xFFFF) { - chip->card_wp |= MS_CARD; - return STATUS_SUCCESS; - } - retval = ms_init_page(chip, phy_blk, log_blk, 0, 1); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, BUILD_FAIL); - segment->l2p_table[log_blk - ms_start_idx[seg_no]] = - phy_blk; - if (seg_no == ms_card->segment_cnt - 1) { - if (segment->unused_blk_cnt < 2) { - chip->card_wp |= MS_CARD; - return STATUS_SUCCESS; - } - } else { - if (segment->unused_blk_cnt < 1) { - chip->card_wp |= MS_CARD; - return STATUS_SUCCESS; - } - } - } - } - - if (seg_no == 0) { - for (log_blk = 0; log_blk < 494; log_blk++) { - tmp_blk = segment->l2p_table[log_blk]; - if (tmp_blk < ms_card->boot_block) { - RTS51X_DEBUGP("Boot block is not the first" - "normal block.\n"); - - if (chip->card_wp & MS_CARD) - break; - - phy_blk = ms_get_unused_block(chip, 0); -#ifdef MS_SPEEDUP - retval = - ms_auto_copy_page(chip, tmp_blk, phy_blk, - log_blk, 0, - ms_card->page_off + 1); -#else - retval = ms_copy_page(chip, tmp_blk, phy_blk, - log_blk, 0, - ms_card->page_off + 1); -#endif - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - segment->l2p_table[log_blk] = phy_blk; - - retval = ms_set_bad_block(chip, tmp_blk); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - } - } - - return STATUS_SUCCESS; - -BUILD_FAIL: - segment->build_flag = 0; - if (segment->l2p_table) { - vfree(segment->l2p_table); - segment->l2p_table = NULL; - } - if (segment->free_table) { - vfree(segment->free_table); - segment->free_table = NULL; - } - - return STATUS_FAIL; -} - -int reset_ms_card(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - - memset(ms_card, 0, sizeof(struct ms_info)); - - enable_card_clock(chip, MS_CARD); - - retval = rts51x_select_card(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ms_card->ms_type = 0; - ms_card->last_rw_int = 0; - - retval = reset_ms_pro(chip); - if (retval != STATUS_SUCCESS) { - if (ms_card->check_ms_flow) { - retval = reset_ms(chip); - if (retval != STATUS_SUCCESS) { - if (chip->option.reset_or_rw_fail_set_pad_drive) { - rts51x_write_register(chip, - CARD_DRIVE_SEL, SD20_DRIVE_MASK, - DRIVE_8mA); - } - TRACE_RET(chip, retval); - } - } else { - if (chip->option.reset_or_rw_fail_set_pad_drive) { - rts51x_write_register(chip, CARD_DRIVE_SEL, - SD20_DRIVE_MASK, - DRIVE_8mA); - } - TRACE_RET(chip, retval); - } - } - - retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (!CHK_MSPRO(ms_card)) { - retval = ms_build_l2p_tbl(chip, ms_card->total_block / 512 - 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - RTS51X_DEBUGP("ms_card->ms_type = 0x%x\n", ms_card->ms_type); - - return STATUS_SUCCESS; -} - -static int mspro_set_rw_cmd(struct rts51x_chip *chip, u32 start_sec, - u16 sec_cnt, u8 cmd) -{ - int retval, i; - u8 data[8]; - - data[0] = cmd; - data[1] = (u8) (sec_cnt >> 8); - data[2] = (u8) sec_cnt; - data[3] = (u8) (start_sec >> 24); - data[4] = (u8) (start_sec >> 16); - data[5] = (u8) (start_sec >> 8); - data[6] = (u8) start_sec; - data[7] = 0; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, data, 8); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -void mspro_stop_seq_mode(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - - if (ms_card->seq_mode) { - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return; - - ms_card->seq_mode = 0; - ms_card->total_sec_cnt = 0; - ms_card->last_rw_int = 0; - ms_send_cmd(chip, PRO_STOP, WAIT_INT); - - rts51x_ep0_write_register(chip, MC_FIFO_CTL, FIFO_FLUSH, - FIFO_FLUSH); - } -} - -static inline int ms_auto_tune_clock(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - - if (chip->asic_code) { - if (ms_card->ms_clock > 30) - ms_card->ms_clock -= 20; - } else { - if (ms_card->ms_clock == CLK_80) - ms_card->ms_clock = CLK_60; - else if (ms_card->ms_clock == CLK_60) - ms_card->ms_clock = CLK_40; - } - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static int mspro_rw_multi_sector(struct scsi_cmnd *srb, - struct rts51x_chip *chip, u32 start_sector, - u16 sector_cnt) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, mode_2k = 0; - u16 count; - u8 val, trans_mode, rw_tpc, rw_cmd; - - ms_set_err_code(chip, MS_NO_ERROR); - - ms_card->counter = 0; - - if (CHK_MSHG(ms_card)) { - if ((start_sector % 4) || (sector_cnt % 4)) { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - rw_tpc = PRO_READ_LONG_DATA; - rw_cmd = PRO_READ_DATA; - } else { - rw_tpc = PRO_WRITE_LONG_DATA; - rw_cmd = PRO_WRITE_DATA; - } - } else { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - rw_tpc = PRO_READ_QUAD_DATA; - rw_cmd = PRO_READ_2K_DATA; - } else { - rw_tpc = PRO_WRITE_QUAD_DATA; - rw_cmd = PRO_WRITE_2K_DATA; - } - mode_2k = 1; - } - } else { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - rw_tpc = PRO_READ_LONG_DATA; - rw_cmd = PRO_READ_DATA; - } else { - rw_tpc = PRO_WRITE_LONG_DATA; - rw_cmd = PRO_WRITE_DATA; - } - } - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (srb->sc_data_direction == DMA_FROM_DEVICE) - trans_mode = MS_TM_AUTO_READ; - else - trans_mode = MS_TM_AUTO_WRITE; - - val = ms_card->last_rw_int; - - if (ms_card->seq_mode) { - if ((ms_card->pre_dir != srb->sc_data_direction) - || ((ms_card->pre_sec_addr + ms_card->pre_sec_cnt) != - start_sector) - || (mode_2k && (ms_card->seq_mode & MODE_512_SEQ)) - || (!mode_2k && (ms_card->seq_mode & MODE_2K_SEQ)) - || !(val & MS_INT_BREQ) - || ((ms_card->total_sec_cnt + sector_cnt) > 0xFE00)) { - ms_card->seq_mode = 0; - ms_card->total_sec_cnt = 0; - ms_card->last_rw_int = 0; - if (val & MS_INT_BREQ) { - retval = ms_send_cmd(chip, PRO_STOP, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - rts51x_ep0_write_register(chip, MC_FIFO_CTL, - FIFO_FLUSH, FIFO_FLUSH); - } - } - } - - if (!ms_card->seq_mode) { - ms_card->total_sec_cnt = 0; - if (sector_cnt >= 0x80) { - if ((ms_card->capacity - start_sector) > 0xFE00) - count = 0xFE00; - else - count = - (u16) (ms_card->capacity - start_sector); - if (count > sector_cnt) { - if (mode_2k) - ms_card->seq_mode |= MODE_2K_SEQ; - else - ms_card->seq_mode |= MODE_512_SEQ; - } - } else { - count = sector_cnt; - } - retval = mspro_set_rw_cmd(chip, start_sector, count, rw_cmd); - if (retval != STATUS_SUCCESS) { - ms_card->seq_mode = 0; - TRACE_RET(chip, retval); - } - } - - retval = - ms_transfer_data(chip, trans_mode, rw_tpc, sector_cnt, WAIT_INT, - mode_2k, scsi_sg_count(srb), scsi_sglist(srb), - scsi_bufflen(srb)); - if (retval != STATUS_SUCCESS) { - ms_card->seq_mode = 0; - rts51x_ep0_read_register(chip, MS_TRANS_CFG, &val); - rts51x_clear_ms_error(chip); - if (val & MS_INT_BREQ) - ms_send_cmd(chip, PRO_STOP, WAIT_INT); - if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) { - RTS51X_DEBUGP("MSPro CRC error, tune clock!\n"); - ms_auto_tune_clock(chip); - } - - TRACE_RET(chip, retval); - } - - ms_card->pre_sec_addr = start_sector; - ms_card->pre_sec_cnt = sector_cnt; - ms_card->pre_dir = srb->sc_data_direction; - ms_card->total_sec_cnt += sector_cnt; - - return STATUS_SUCCESS; -} - -static int mspro_read_format_progress(struct rts51x_chip *chip, - const int short_data_len) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - u32 total_progress, cur_progress; - u8 cnt, tmp; - u8 data[8]; - - ms_card->format_status = FORMAT_FAIL; - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_READ_REG(chip, MS_TRANS_CFG, &tmp); - - if ((tmp & (MS_INT_CED | MS_INT_CMDNK | MS_INT_ERR)) == MS_INT_CED) { - ms_card->format_status = FORMAT_SUCCESS; - ms_card->pro_under_formatting = 0; - return STATUS_SUCCESS; - } - if (! - ((tmp & (MS_INT_BREQ | MS_INT_CED | MS_INT_CMDNK | MS_INT_ERR)) == - MS_INT_BREQ)) { - ms_card->pro_under_formatting = 0; - TRACE_RET(chip, STATUS_FAIL); - } - - if (short_data_len >= 256) - cnt = 0; - else - cnt = (u8) short_data_len; - - retval = - ms_read_bytes(chip, PRO_READ_SHORT_DATA, cnt, WAIT_INT, data, 8); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - total_progress = - (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; - cur_progress = - (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; - - RTS51X_DEBUGP("total_progress = %d, cur_progress = %d\n", - total_progress, cur_progress); - - if (total_progress == 0) { - ms_card->progress = 0; - } else { - u64 ulltmp = (u64) cur_progress * (u64) 65535; - do_div(ulltmp, total_progress); - ms_card->progress = (u16) ulltmp; - } - RTS51X_DEBUGP("progress = %d\n", ms_card->progress); - - for (i = 0; i < 2500; i++) { - RTS51X_READ_REG(chip, MS_TRANS_CFG, &tmp); - if (tmp & - (MS_INT_CED | MS_INT_CMDNK | MS_INT_BREQ | MS_INT_ERR)) - break; - - wait_timeout(1); - } - - if (i == 2500) - TRACE_RET(chip, STATUS_FAIL); - - RTS51X_DEBUGP("MSPro format tmp:%d\n", tmp); - - if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) - TRACE_RET(chip, STATUS_FAIL); - if (tmp & MS_INT_CED) { - ms_card->format_status = FORMAT_SUCCESS; - ms_card->pro_under_formatting = 0; - } else if (tmp & MS_INT_BREQ) { - ms_card->format_status = FORMAT_IN_PROGRESS; - } else { - ms_card->format_status = FORMAT_FAIL; - ms_card->pro_under_formatting = 0; - TRACE_RET(chip, STATUS_FAIL); - } - - RTS51X_DEBUGP("MSPro format format_status:%d\n", - ms_card->format_status); - - return STATUS_SUCCESS; -} - -void mspro_polling_format_status(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int i; - - if (ms_card->pro_under_formatting) { - for (i = 0; i < 65535; i++) { - mspro_read_format_progress(chip, MS_SHORT_DATA_LEN); - if (ms_card->format_status != FORMAT_IN_PROGRESS) - break; - } - } - - return; -} - -void mspro_format_sense(struct rts51x_chip *chip, unsigned int lun) -{ - struct ms_info *ms_card = &(chip->ms_card); - - if (CHK_FORMAT_STATUS(ms_card, FORMAT_SUCCESS)) { - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - ms_card->pro_under_formatting = 0; - ms_card->progress = 0; - } else if (CHK_FORMAT_STATUS(ms_card, FORMAT_IN_PROGRESS)) { - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, - 0, (u16) (ms_card->progress)); - } else { - set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED); - ms_card->pro_under_formatting = 0; - ms_card->progress = 0; - } -} - -int mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip, - int short_data_len, int quick_format) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - u8 buf[8], tmp; - u16 para; - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, Pro_TPCParm, 0x01); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - memset(buf, 0, 2); - switch (short_data_len) { - case 32: - buf[0] = 0; - break; - case 64: - buf[0] = 1; - break; - case 128: - buf[0] = 2; - break; - case 256: - default: - buf[0] = 3; - break; - } - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, PRO_WRITE_REG, 1, NO_WAIT_INT, buf, 2); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - /* Format command */ - if (quick_format) - para = 0x0000; - else - para = 0x0001; - retval = mspro_set_rw_cmd(chip, 0, para, PRO_FORMAT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* Check INT */ - RTS51X_READ_REG(chip, MS_TRANS_CFG, &tmp); - if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) - TRACE_RET(chip, STATUS_FAIL); - - if ((tmp & (MS_INT_BREQ | MS_INT_CED)) == MS_INT_BREQ) { - ms_card->pro_under_formatting = 1; - ms_card->progress = 0; - ms_card->format_status = FORMAT_IN_PROGRESS; - return STATUS_SUCCESS; - } - - if (tmp & MS_INT_CED) { - ms_card->pro_under_formatting = 0; - ms_card->progress = 0; - ms_card->format_status = FORMAT_SUCCESS; - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE); - return STATUS_SUCCESS; - } - - TRACE_RET(chip, STATUS_FAIL); -} - -#ifdef MS_SPEEDUP -static int ms_read_multiple_pages(struct rts51x_chip *chip, u16 phy_blk, - u16 log_blk, u8 start_page, u8 end_page, - u8 *buf, void **ptr, unsigned int *offset) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - int send_blkend; - u8 extra[MS_EXTRA_SIZE], val1, val2, data[6]; - u8 page_cnt = end_page - start_page, page_addr, sec_cnt; - - if (end_page != (ms_card->page_off + 1)) - send_blkend = 1; - else - send_blkend = 0; - - retval = - ms_read_extra_data(chip, phy_blk, start_page, extra, MS_EXTRA_SIZE); - if (retval == STATUS_SUCCESS) { - if ((extra[1] & 0x30) != 0x30) { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (phy_blk >> 8); - data[3] = (u8) phy_blk; - /* Page Number - * Extra data access mode */ - data[4] = 0; - data[5] = start_page; - - retval = - ms_auto_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6, - BLOCK_READ, WAIT_INT, data, 6, &val1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - rts51x_init_cmd(chip); - - if (send_blkend) - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_BLKEND, SET_BLKEND, - SET_BLKEND); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_BLKEND, SET_BLKEND, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, WAIT_INT, - NO_WAIT_INT); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, - (u8) page_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_H, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA); - - trans_dma_enable(DMA_FROM_DEVICE, chip, 512 * page_cnt, DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_MULTI_READ); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, - MS_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CDIR | STAGE_MS_STATUS, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - rts51x_transfer_data_partial(chip, RCV_BULK_PIPE(chip), (void *)buf, - ptr, offset, 512 * page_cnt, - scsi_sg_count(chip->srb), NULL, 2000); - if (retval != STATUS_SUCCESS) { - rts51x_clear_ms_error(chip); - if (retval == STATUS_TIMEDOUT) - TRACE_RET(chip, retval); - TRACE_GOTO(chip, Fail); - } - retval = rts51x_get_rsp(chip, 3, 200); - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - rts51x_clear_ms_error(chip); - if (retval == STATUS_TIMEDOUT) - TRACE_RET(chip, retval); - TRACE_GOTO(chip, Fail); - } - - return STATUS_SUCCESS; - -Fail: - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, READ_REG_CMD, MS_SECTOR_CNT_L, 0, 0); - - retval = rts51x_send_cmd(chip, MODE_CR | STAGE_MS_STATUS, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 3, 200); - - if (CHECK_MS_TRANS_FAIL(chip, retval)) - TRACE_RET(chip, STATUS_FAIL); - - sec_cnt = chip->rsp_buf[0]; - RTS51X_DEBUGP("%d pages need be trasferred, %d pages remained\n", - (int)page_cnt, (int)sec_cnt); - page_addr = start_page + (page_cnt - sec_cnt); - - if (CHK_MS4BIT(ms_card)) { - val1 = chip->rsp_buf[1]; - RTS51X_DEBUGP("MS_TRANS_CFG: 0x%x\n", val1); - } else { - val1 = 0; - } - - val2 = chip->rsp_buf[2]; - RTS51X_DEBUGP("GET_INT: 0x%x\n", val2); - - if ((val1 & INT_CMDNK) || (val2 & INT_REG_CMDNK)) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - - if ((val1 & INT_ERR) || (val2 & INT_REG_ERR)) { - if ((val1 & INT_BREQ) || (val2 & INT_REG_BREQ)) { - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) { - if (!(chip->card_wp & MS_CARD)) { - reset_ms(chip); - ms_set_page_status(log_blk, setPS_NG, - extra, MS_EXTRA_SIZE); - ms_write_extra_data(chip, phy_blk, - page_addr, extra, - MS_EXTRA_SIZE); - } - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } else { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } else { - if (CHK_MS4BIT(ms_card)) { - if (!(val1 & INT_BREQ) && !(val2 & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } else { - if (!(val2 & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - TRACE_RET(chip, STATUS_FAIL); -} - -static int ms_write_multiple_pages(struct rts51x_chip *chip, u16 old_blk, - u16 new_blk, u16 log_blk, u8 start_page, - u8 end_page, u8 *buf, void **ptr, - unsigned int *offset) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - int send_blkend; - u8 val, data[16]; - u8 page_cnt = end_page - start_page; - - if ((end_page == (ms_card->page_off + 1)) || (page_cnt == 1)) - send_blkend = 0; - else - send_blkend = 1; - - if (!start_page) { - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (old_blk >> 8); - data[3] = (u8) old_blk; - data[4] = 0x80; - data[5] = 0; - data[6] = 0xEF; - data[7] = 0xFF; - - retval = - ms_auto_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 7, BLOCK_WRITE, WAIT_INT, data, - 7, &val); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - retval = - ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, - (6 + MS_EXTRA_SIZE)); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (new_blk >> 8); - data[3] = (u8) new_blk; - /* Page Number - * Extra data access mode */ - if (page_cnt == 1) { - /* Single page access mode */ - data[4] = 0x20; - } else { - /* Block access mode */ - data[4] = 0; - } - data[5] = start_page; - data[6] = 0xF8; - data[7] = 0xFF; - data[8] = (u8) (log_blk >> 8); - data[9] = (u8) log_blk; - - for (i = 0x0A; i < 0x10; i++) { - /* ECC */ - data[i] = 0xFF; - } - - retval = - ms_auto_set_cmd(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, - (6 + MS_EXTRA_SIZE), BLOCK_WRITE, WAIT_INT, data, - 16, &val); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - rts51x_init_cmd(chip); - - if (send_blkend) - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_BLKEND, SET_BLKEND, - SET_BLKEND); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_BLKEND, SET_BLKEND, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, WAIT_INT, - NO_WAIT_INT); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, - (u8) page_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_H, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, WRITE_PAGE_DATA); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - RING_BUFFER); - - trans_dma_enable(DMA_TO_DEVICE, chip, 512 * page_cnt, DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_MULTI_WRITE); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, - MS_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CDOR | STAGE_MS_STATUS, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - rts51x_transfer_data_partial(chip, SND_BULK_PIPE(chip), (void *)buf, - ptr, offset, 512 * page_cnt, - scsi_sg_count(chip->srb), NULL, 2000); - if (retval != STATUS_SUCCESS) { - rts51x_clear_ms_error(chip); - TRACE_RET(chip, retval); - } - - retval = rts51x_get_rsp(chip, 3, 2000); - - - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - rts51x_clear_ms_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -#else - -static int ms_read_multiple_pages(struct rts51x_chip *chip, u16 phy_blk, - u16 log_blk, u8 start_page, u8 end_page, - u8 *buf, void **ptr, unsigned int *offset) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - u8 extra[MS_EXTRA_SIZE], page_addr, val, trans_cfg, data[6]; - - retval = - ms_read_extra_data(chip, phy_blk, start_page, extra, MS_EXTRA_SIZE); - if (retval == STATUS_SUCCESS) { - if ((extra[1] & 0x30) != 0x30) { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - retval = - ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, - 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* Write REG */ - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (phy_blk >> 8); - data[3] = (u8) phy_blk; - /* Page Number - * Extra data access mode */ - data[4] = 0; - data[5] = start_page; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - - ms_set_err_code(chip, MS_NO_ERROR); - - retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - for (page_addr = start_page; page_addr < end_page; page_addr++) { - ms_set_err_code(chip, MS_NO_ERROR); - - if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) { - ms_set_err_code(chip, MS_NO_CARD); - chip->card_exist &= ~MS_CARD; - chip->card_ready &= ~MS_CARD; - TRACE_RET(chip, STATUS_FAIL); - } - /* GET_INT Register */ - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - if (val & INT_REG_ERR) { - if (val & INT_REG_BREQ) { - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) { - if (!(chip->card_wp & MS_CARD)) { - reset_ms(chip); - ms_set_page_status(log_blk, - setPS_NG, extra, - MS_EXTRA_SIZE); - ms_write_extra_data(chip, - phy_blk, page_addr, - extra, MS_EXTRA_SIZE); - } - ms_set_err_code(chip, - MS_FLASH_READ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } else { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } else { - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - if (page_addr == (end_page - 1)) { - if (!(val & INT_REG_CED)) { - retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - retval = - ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, - 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (!(val & INT_REG_CED)) { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - - trans_cfg = NO_WAIT_INT; - } else { - trans_cfg = WAIT_INT; - } - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, - READ_PAGE_DATA); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, - trans_cfg); - - trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_NORMAL_READ); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CDIR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - rts51x_transfer_data_partial(chip, RCV_BULK_PIPE(chip), - (void *)buf, ptr, offset, 512, - scsi_sg_count(chip->srb), NULL, - 2000); - if (retval != STATUS_SUCCESS) { - if (retval == STATUS_TIMEDOUT) { - ms_set_err_code(chip, MS_TO_ERROR); - rts51x_clear_ms_error(chip); - TRACE_RET(chip, retval); - } - - retval = - rts51x_ep0_read_register(chip, MS_TRANS_CFG, &val); - if (retval != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_TO_ERROR); - rts51x_clear_ms_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) { - ms_set_err_code(chip, MS_CRC16_ERROR); - rts51x_clear_ms_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - } - - retval = rts51x_get_rsp(chip, 1, 2000); - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - if (retval == STATUS_TIMEDOUT) { - ms_set_err_code(chip, MS_TO_ERROR); - rts51x_clear_ms_error(chip); - TRACE_RET(chip, retval); - } - - retval = - rts51x_ep0_read_register(chip, MS_TRANS_CFG, &val); - if (retval != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_TO_ERROR); - rts51x_clear_ms_error(chip); - TRACE_RET(chip, retval); - } - if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) { - ms_set_err_code(chip, MS_CRC16_ERROR); - rts51x_clear_ms_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - return STATUS_SUCCESS; -} - -static int ms_write_multiple_pages(struct rts51x_chip *chip, u16 old_blk, - u16 new_blk, u16 log_blk, u8 start_page, - u8 end_page, u8 *buf, void **ptr, - unsigned int *offset) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - u8 page_addr, val, data[16]; - - if (!start_page) { - retval = - ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, - SystemParm, 7); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (old_blk >> 8); - data[3] = (u8) old_blk; - data[4] = 0x80; - data[5] = 0; - data[6] = 0xEF; - data[7] = 0xFF; - - retval = - ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 8); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* GET_INT Register */ - ms_set_err_code(chip, MS_NO_ERROR); - retval = - ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, - NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - retval = - ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, - (6 + MS_EXTRA_SIZE)); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - /* Block Address */ - data[1] = 0; - data[2] = (u8) (new_blk >> 8); - data[3] = (u8) new_blk; - /* Page Number - * Extra data access mode */ - if ((end_page - start_page) == 1) { - /* Single page access mode */ - data[4] = 0x20; - } else { - /* Block access mode */ - data[4] = 0; - } - data[5] = start_page; - data[6] = 0xF8; - data[7] = 0xFF; - data[8] = (u8) (log_blk >> 8); - data[9] = (u8) log_blk; - - for (i = 0x0A; i < 0x10; i++) { - /* ECC */ - data[i] = 0xFF; - } - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, WRITE_REG, 6 + MS_EXTRA_SIZE, - NO_WAIT_INT, data, 16); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - /* GET_INT Register */ - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - for (page_addr = start_page; page_addr < end_page; page_addr++) { - ms_set_err_code(chip, MS_NO_ERROR); - - if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) { - ms_set_err_code(chip, MS_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - TRACE_RET(chip, STATUS_FAIL); - } - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - - udelay(30); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, - WRITE_PAGE_DATA); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, - WAIT_INT); - - trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_NORMAL_WRITE); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CDOR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - rts51x_transfer_data_partial(chip, SND_BULK_PIPE(chip), - (void *)buf, ptr, offset, 512, - scsi_sg_count(chip->srb), NULL, - 2000); - if (retval != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_TO_ERROR); - rts51x_clear_ms_error(chip); - - if (retval == STATUS_TIMEDOUT) - TRACE_RET(chip, STATUS_TIMEDOUT); - else - TRACE_RET(chip, STATUS_FAIL); - } - - retval = rts51x_get_rsp(chip, 1, 2000); - if (CHECK_MS_TRANS_FAIL(chip, retval)) { - ms_set_err_code(chip, MS_TO_ERROR); - rts51x_clear_ms_error(chip); - - if (retval == STATUS_TIMEDOUT) - TRACE_RET(chip, STATUS_TIMEDOUT); - else - TRACE_RET(chip, STATUS_FAIL); - } - /* GET_INT Register */ - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if ((end_page - start_page) == 1) { - if (!(val & INT_REG_CED)) { - /* Command can not be executed */ - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } else { - if (page_addr == (end_page - 1)) { - if (!(val & INT_REG_CED)) { - retval = - ms_send_cmd(chip, BLOCK_END, - WAIT_INT); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - /* GET_INT Register */ - retval = - ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, - &val, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - if ((page_addr == (end_page - 1)) - || (page_addr == ms_card->page_off)) { - if (!(val & INT_REG_CED)) { - ms_set_err_code(chip, - MS_FLASH_WRITE_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - } - } - - return STATUS_SUCCESS; -} -#endif - -static int ms_finish_write(struct rts51x_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 page_off) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, seg_no; - -#ifdef MS_SPEEDUP - retval = ms_auto_copy_page(chip, old_blk, new_blk, log_blk, - page_off, ms_card->page_off + 1); -#else - retval = ms_copy_page(chip, old_blk, new_blk, log_blk, - page_off, ms_card->page_off + 1); -#endif - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - seg_no = old_blk >> 9; - - if (MS_TST_BAD_BLOCK_FLG(ms_card)) { - MS_CLR_BAD_BLOCK_FLG(ms_card); - ms_set_bad_block(chip, old_blk); - } else { - retval = ms_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) - ms_set_unused_block(chip, old_blk); - } - - ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk); - - return STATUS_SUCCESS; -} - -static int ms_prepare_write(struct rts51x_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 start_page) -{ - int retval; - - if (start_page) { -#ifdef MS_SPEEDUP - retval = - ms_auto_copy_page(chip, old_blk, new_blk, log_blk, 0, - start_page); -#else - retval = - ms_copy_page(chip, old_blk, new_blk, log_blk, 0, - start_page); -#endif - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -int ms_delay_write(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - struct ms_delay_write_tag *delay_write = &(ms_card->delay_write); - int retval; - - if (delay_write->delay_write_flag) { - retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - delay_write->delay_write_flag = 0; - retval = ms_finish_write(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - delay_write->logblock, - delay_write->pageoff); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - if (srb->sc_data_direction == DMA_FROM_DEVICE) - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); -} - -static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip, - u32 start_sector, u16 sector_cnt) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - int retval, seg_no; - unsigned int offset = 0; - u16 old_blk = 0, new_blk = 0, log_blk, total_sec_cnt = sector_cnt; - u8 start_page, end_page = 0, page_cnt; - u8 *buf; - void *ptr = NULL; - struct ms_delay_write_tag *delay_write = &(ms_card->delay_write); - - ms_set_err_code(chip, MS_NO_ERROR); - - ms_card->counter = 0; - - buf = (u8 *) scsi_sglist(srb); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) { - ms_rw_fail(srb, chip); - TRACE_RET(chip, retval); - } - - log_blk = (u16) (start_sector >> ms_card->block_shift); - start_page = (u8) (start_sector & ms_card->page_off); - - for (seg_no = 0; seg_no < sizeof(ms_start_idx) / 2; seg_no++) { - if (log_blk < ms_start_idx[seg_no + 1]) - break; - } - - if (ms_card->segment[seg_no].build_flag == 0) { - retval = ms_build_l2p_tbl(chip, seg_no); - if (retval != STATUS_SUCCESS) { - chip->card_fail |= MS_CARD; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, retval); - } - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - if (delay_write->delay_write_flag && - (delay_write->logblock == log_blk) && - (start_page > delay_write->pageoff)) { - delay_write->delay_write_flag = 0; -#ifdef MS_SPEEDUP - retval = ms_auto_copy_page(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - log_blk, - delay_write->pageoff, - start_page); -#else - retval = ms_copy_page(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - log_blk, delay_write->pageoff, - start_page); -#endif - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, retval); - } - old_blk = delay_write->old_phyblock; - new_blk = delay_write->new_phyblock; - } else if (delay_write->delay_write_flag && - (delay_write->logblock == log_blk) && - (start_page == delay_write->pageoff)) { - delay_write->delay_write_flag = 0; - old_blk = delay_write->old_phyblock; - new_blk = delay_write->new_phyblock; - } else { - retval = ms_delay_write(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, retval); - } - old_blk = - ms_get_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no]); - new_blk = ms_get_unused_block(chip, seg_no); - if ((old_blk == 0xFFFF) || (new_blk == 0xFFFF)) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = - ms_prepare_write(chip, old_blk, new_blk, log_blk, - start_page); - if (retval != STATUS_SUCCESS) { - if (monitor_card_cd(chip, MS_CARD) == - CD_NOT_EXIST) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, STATUS_FAIL); - } - - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, retval); - } - } - } else { - retval = ms_delay_write(chip); - if (retval != STATUS_SUCCESS) { - if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, STATUS_FAIL); - } - - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, retval); - } - old_blk = - ms_get_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no]); - if (old_blk == 0xFFFF) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - RTS51X_DEBUGP("seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", seg_no, - old_blk, new_blk); - - while (total_sec_cnt) { - if ((start_page + total_sec_cnt) > (ms_card->page_off + 1)) - end_page = ms_card->page_off + 1; - else - end_page = start_page + (u8) total_sec_cnt; - page_cnt = end_page - start_page; - - RTS51X_DEBUGP("start_page = %d, end_page = %d," - "page_cnt = %d\n", - start_page, end_page, page_cnt); - - if (srb->sc_data_direction == DMA_FROM_DEVICE) - retval = ms_read_multiple_pages(chip, - old_blk, log_blk, - start_page, end_page, - buf, &ptr, &offset); - else - retval = ms_write_multiple_pages(chip, old_blk, - new_blk, log_blk, - start_page, end_page, - buf, &ptr, &offset); - - if (retval != STATUS_SUCCESS) { - if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, STATUS_FAIL); - } - - ms_rw_fail(srb, chip); - TRACE_RET(chip, retval); - } - /* Update L2P table if need */ - if (srb->sc_data_direction == DMA_TO_DEVICE) { - if (end_page == (ms_card->page_off + 1)) { - retval = ms_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) - ms_set_unused_block(chip, old_blk); - ms_set_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no], - new_blk); - } - } - - total_sec_cnt -= page_cnt; - - if (total_sec_cnt == 0) - break; - - log_blk++; - - for (seg_no = 0; seg_no < sizeof(ms_start_idx) / 2; seg_no++) { - if (log_blk < ms_start_idx[seg_no + 1]) - break; - } - - if (ms_card->segment[seg_no].build_flag == 0) { - retval = ms_build_l2p_tbl(chip, seg_no); - if (retval != STATUS_SUCCESS) { - chip->card_fail |= MS_CARD; - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, retval); - } - } - - old_blk = - ms_get_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no]); - if (old_blk == 0xFFFF) { - ms_rw_fail(srb, chip); - TRACE_RET(chip, STATUS_FAIL); - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - new_blk = ms_get_unused_block(chip, seg_no); - if (new_blk == 0xFFFF) { - ms_rw_fail(srb, chip); - TRACE_RET(chip, STATUS_FAIL); - } - } - - RTS51X_DEBUGP("seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", - seg_no, old_blk, new_blk); - - start_page = 0; - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - if (end_page < (ms_card->page_off + 1)) { - delay_write->delay_write_flag = 1; - delay_write->old_phyblock = old_blk; - delay_write->new_phyblock = new_blk; - delay_write->logblock = log_blk; - delay_write->pageoff = end_page; - } - } - - scsi_set_resid(srb, 0); - - return STATUS_SUCCESS; -} - -int ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector, - u16 sector_cnt) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - - if (CHK_MSPRO(ms_card)) - retval = - mspro_rw_multi_sector(srb, chip, start_sector, sector_cnt); - else - retval = - ms_rw_multi_sector(srb, chip, start_sector, sector_cnt); - - return retval; -} - -void ms_free_l2p_tbl(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int i = 0; - - if (ms_card->segment != NULL) { - for (i = 0; i < ms_card->segment_cnt; i++) { - if (ms_card->segment[i].l2p_table != NULL) { - vfree(ms_card->segment[i].l2p_table); - ms_card->segment[i].l2p_table = NULL; - } - if (ms_card->segment[i].free_table != NULL) { - vfree(ms_card->segment[i].free_table); - ms_card->segment[i].free_table = NULL; - } - } - vfree(ms_card->segment); - ms_card->segment = NULL; - } -} - -void ms_cleanup_work(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - - if (CHK_MSPRO(ms_card)) { - if (ms_card->seq_mode) { - RTS51X_DEBUGP("MS Pro: stop transmission\n"); - mspro_stop_seq_mode(chip); - ms_card->counter = 0; - } - if (CHK_MSHG(ms_card)) { - u8 value; - rts51x_read_register(chip, MS_CFG, &value); - if (value & MS_2K_SECTOR_MODE) - rts51x_write_register(chip, MS_CFG, - MS_2K_SECTOR_MODE, 0x00); - } - } else if ((!CHK_MSPRO(ms_card)) - && ms_card->delay_write.delay_write_flag) { - RTS51X_DEBUGP("MS: delay write\n"); - ms_delay_write(chip); - ms_card->counter = 0; - } -} - -int ms_power_off_card3v3(struct rts51x_chip *chip) -{ - int retval; - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0); - if (chip->asic_code) - ms_pull_ctl_disable(chip); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, - FPGA_MS_PULL_CTL_BIT | 0x20, - FPGA_MS_PULL_CTL_BIT); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0); - if (!chip->option.FT2_fast_mode) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, - POWER_OFF); - } - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -int release_ms_card(struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - - RTS51X_DEBUGP("release_ms_card\n"); - - ms_card->delay_write.delay_write_flag = 0; - ms_card->pro_under_formatting = 0; - - chip->card_ready &= ~MS_CARD; - chip->card_fail &= ~MS_CARD; - chip->card_wp &= ~MS_CARD; - - ms_free_l2p_tbl(chip); - - rts51x_write_register(chip, SFSM_ED, HW_CMD_STOP, HW_CMD_STOP); - - memset(ms_card->raw_sys_info, 0, 96); -#ifdef SUPPORT_PCGL_1P18 - memset(ms_card->raw_model_name, 0, 48); -#endif - - retval = ms_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} diff --git a/trunk/drivers/staging/rts5139/ms.h b/trunk/drivers/staging/rts5139/ms.h deleted file mode 100644 index f9d46d210f23..000000000000 --- a/trunk/drivers/staging/rts5139/ms.h +++ /dev/null @@ -1,263 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_MS_H -#define __RTS51X_MS_H - -#include "rts51x_chip.h" - -#define MS_MAX_RETRY_COUNT 3 - -#define MS_EXTRA_SIZE 0x9 - -#define WRT_PRTCT 0x01 - -/* Error Code */ -#define MS_NO_ERROR 0x00 -#define MS_CRC16_ERROR 0x80 -#define MS_TO_ERROR 0x40 -#define MS_NO_CARD 0x20 -#define MS_NO_MEMORY 0x10 -#define MS_CMD_NK 0x08 -#define MS_FLASH_READ_ERROR 0x04 -#define MS_FLASH_WRITE_ERROR 0x02 -#define MS_BREQ_ERROR 0x01 -#define MS_NOT_FOUND 0x03 - -/* Transfer Protocol Command */ -#define READ_PAGE_DATA 0x02 -#define READ_REG 0x04 -#define GET_INT 0x07 -#define WRITE_PAGE_DATA 0x0D -#define WRITE_REG 0x0B -#define SET_RW_REG_ADRS 0x08 -#define SET_CMD 0x0E - -#define PRO_READ_LONG_DATA 0x02 -#define PRO_READ_SHORT_DATA 0x03 -#define PRO_READ_REG 0x04 -#define PRO_READ_QUAD_DATA 0x05 -#define PRO_GET_INT 0x07 -#define PRO_WRITE_LONG_DATA 0x0D -#define PRO_WRITE_SHORT_DATA 0x0C -#define PRO_WRITE_QUAD_DATA 0x0A -#define PRO_WRITE_REG 0x0B -#define PRO_SET_RW_REG_ADRS 0x08 -#define PRO_SET_CMD 0x0E -#define PRO_EX_SET_CMD 0x09 - -#ifdef SUPPORT_MAGIC_GATE -#define MG_GET_ID 0x40 -#define MG_SET_LID 0x41 -#define MG_GET_LEKB 0x42 -#define MG_SET_RD 0x43 -#define MG_MAKE_RMS 0x44 -#define MG_MAKE_KSE 0x45 -#define MG_SET_IBD 0x46 -#define MG_GET_IBD 0x47 -#endif - -#ifdef XC_POWERCLASS -#define XC_CHG_POWER 0x16 -#endif - -/* ++ CMD over Memory Stick */ -/* Flash CMD */ -#define BLOCK_READ 0xAA -#define BLOCK_WRITE 0x55 -#define BLOCK_END 0x33 -#define BLOCK_ERASE 0x99 -#define FLASH_STOP 0xCC - -/* Function CMD */ -#define SLEEP 0x5A -#define CLEAR_BUF 0xC3 -#define MS_RESET 0x3C -/* -- CMD over Memory Stick */ - -/* ++ CMD over Memory Stick Pro */ -/* Flash CMD */ -#define PRO_READ_DATA 0x20 -#define PRO_WRITE_DATA 0x21 -#define PRO_READ_ATRB 0x24 -#define PRO_STOP 0x25 -#define PRO_ERASE 0x26 -#define PRO_READ_2K_DATA 0x27 -#define PRO_WRITE_2K_DATA 0x28 - -/* Function CMD */ -#define PRO_FORMAT 0x10 -#define PRO_SLEEP 0x11 -/* -- CMD over Memory Stick Pro */ - -/* register inside memory stick */ -#define IntReg 0x01 -#define StatusReg0 0x02 -#define StatusReg1 0x03 - -#define SystemParm 0x10 -#define BlockAdrs 0x11 -#define CMDParm 0x14 -#define PageAdrs 0x15 - -#define OverwriteFlag 0x16 -#define ManagemenFlag 0x17 -#define LogicalAdrs 0x18 -#define ReserveArea 0x1A - -/* register inside memory pro */ -#define Pro_IntReg 0x01 -#define Pro_StatusReg 0x02 -#define Pro_TypeReg 0x04 -#define Pro_IFModeReg 0x05 -#define Pro_CatagoryReg 0x06 -#define Pro_ClassReg 0x07 - -#define Pro_SystemParm 0x10 -#define Pro_DataCount1 0x11 -#define Pro_DataCount0 0x12 -#define Pro_DataAddr3 0x13 -#define Pro_DataAddr2 0x14 -#define Pro_DataAddr1 0x15 -#define Pro_DataAddr0 0x16 - -#define Pro_TPCParm 0x17 -#define Pro_CMDParm 0x18 - -/* define for INT Register */ -#define INT_REG_CED 0x80 -#define INT_REG_ERR 0x40 -#define INT_REG_BREQ 0x20 -#define INT_REG_CMDNK 0x01 - -/* INT signal */ -#define INT_CED 0x01 -#define INT_ERR 0x02 -#define INT_BREQ 0x04 -#define INT_CMDNK 0x08 - -/* define for OverwriteFlag Register */ -#define BLOCK_BOOT 0xC0 -#define BLOCK_OK 0x80 -#define PAGE_OK 0x60 -#define DATA_COMPL 0x10 - -/* define for ManagemenFlag Register */ -#define NOT_BOOT_BLOCK 0x4 -#define NOT_TRANSLATION_TABLE 0x8 - -/* Header */ -#define HEADER_ID0 (PPBUF_BASE2) /* 0 */ -#define HEADER_ID1 (PPBUF_BASE2 + 1) /* 1 */ -/* System Entry */ -#define DISABLED_BLOCK0 (PPBUF_BASE2 + 0x170 + 4) /* 2 */ -#define DISABLED_BLOCK1 (PPBUF_BASE2 + 0x170 + 5) /* 3 */ -#define DISABLED_BLOCK2 (PPBUF_BASE2 + 0x170 + 6) /* 4 */ -#define DISABLED_BLOCK3 (PPBUF_BASE2 + 0x170 + 7) /* 5 */ -/* Boot & Attribute Information */ -#define BLOCK_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 2) /* 6 */ -#define BLOCK_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 3) /* 7 */ -#define BLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 4) /* 8 */ -#define BLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 5) /* 9 */ -#define EBLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 6) /* 10 */ -#define EBLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 7) /* 11 */ -#define PAGE_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 8) /* 12 */ -#define PAGE_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 9) /* 13 */ - -/* joey 2004-08-07 for MS check Procedure */ -#define MS_Device_Type (PPBUF_BASE2 + 0x1D8) /* 14 */ -/* end */ - -/* joey 2004-05-03 */ -#define MS_4bit_Support (PPBUF_BASE2 + 0x1D3) /* 15 */ -/* end */ - -#define setPS_NG 1 -#define setPS_Error 0 - -/* define for Pro_SystemParm Register */ -#define PARALLEL_8BIT_IF 0x40 -#define PARALLEL_4BIT_IF 0x00 -#define SERIAL_IF 0x80 - -/* define for StatusReg0 Register */ -#define BUF_FULL 0x10 -#define BUF_EMPTY 0x20 - -/* define for StatusReg1 Register */ -#define MEDIA_BUSY 0x80 -#define FLASH_BUSY 0x40 -#define DATA_ERROR 0x20 -#define STS_UCDT 0x10 -#define EXTRA_ERROR 0x08 -#define STS_UCEX 0x04 -#define FLAG_ERROR 0x02 -#define STS_UCFG 0x01 - -#define MS_SHORT_DATA_LEN 32 - -#define FORMAT_SUCCESS 0 -#define FORMAT_FAIL 1 -#define FORMAT_IN_PROGRESS 2 - -#define MS_SET_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag |= 0x80) -#define MS_CLR_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag &= 0x7F) -#define MS_TST_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag & 0x80) - -#define CHECK_MS_TRANS_FAIL(chip, retval) \ - (((retval) != STATUS_SUCCESS) || \ - (chip->rsp_buf[0] & MS_TRANSFER_ERR)) - -void mspro_polling_format_status(struct rts51x_chip *chip); -void mspro_format_sense(struct rts51x_chip *chip, unsigned int lun); - -void mspro_stop_seq_mode(struct rts51x_chip *chip); -int reset_ms_card(struct rts51x_chip *chip); -int ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector, - u16 sector_cnt); -int mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip, - int short_data_len, int quick_format); -void ms_free_l2p_tbl(struct rts51x_chip *chip); -void ms_cleanup_work(struct rts51x_chip *chip); -int ms_power_off_card3v3(struct rts51x_chip *chip); -int release_ms_card(struct rts51x_chip *chip); -int ms_delay_write(struct rts51x_chip *chip); - -#ifdef SUPPORT_MAGIC_GATE - -int ms_switch_clock(struct rts51x_chip *chip); -int ms_write_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 * data, - int data_len); -int ms_read_bytes(struct rts51x_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 * data, - int data_len); -int ms_set_rw_reg_addr(struct rts51x_chip *chip, u8 read_start, u8 read_cnt, - u8 write_start, u8 write_cnt); -int ms_transfer_data(struct rts51x_chip *chip, u8 trans_mode, u8 tpc, - u16 sec_cnt, u8 cfg, int mode_2k, int use_sg, void *buf, - int buf_len); -#endif - -#endif /* __RTS51X_MS_H */ diff --git a/trunk/drivers/staging/rts5139/ms_mg.c b/trunk/drivers/staging/rts5139/ms_mg.c deleted file mode 100644 index 154b5230aa5e..000000000000 --- a/trunk/drivers/staging/rts5139/ms_mg.c +++ /dev/null @@ -1,642 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include -#include - -#include "debug.h" -#include "trace.h" -#include "rts51x.h" -#include "rts51x_transport.h" -#include "rts51x_scsi.h" -#include "rts51x_card.h" -#include "ms.h" - -#ifdef SUPPORT_MAGIC_GATE - -int mg_check_int_error(struct rts51x_chip *chip) -{ - u8 value; - - rts51x_read_register(chip, MS_TRANS_CFG, &value); - if (value & (INT_ERR | INT_CMDNK)) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int mg_send_ex_cmd(struct rts51x_chip *chip, u8 cmd, u8 entry_num) -{ - int retval, i; - u8 data[8]; - - data[0] = cmd; - data[1] = 0; - data[2] = 0; - data[3] = 0; - data[4] = 0; - data[5] = 0; - data[6] = entry_num; - data[7] = 0; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = - ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, data, 8); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - TRACE_RET(chip, STATUS_FAIL); - retval = mg_check_int_error(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -int mg_set_tpc_para_sub(struct rts51x_chip *chip, int type, u8 mg_entry_num) -{ - int retval; - u8 buf[6]; - - RTS51X_DEBUGP("--%s--\n", __func__); - - if (type == 0) - retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_TPCParm, 1); - else - retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - buf[0] = 0; - buf[1] = 0; - if (type == 1) { - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = mg_entry_num; - } - retval = - ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6, - NO_WAIT_INT, buf, 6); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -/** - * Get MagciGate ID and set Leaf ID to medium. - - * After receiving this SCSI command, adapter shall fulfill 2 tasks - * below in order: - * 1. send GET_ID TPC command to get MagicGate ID and hold it till - * Response&challenge CMD. - * 2. send SET_ID TPC command to medium with Leaf ID released by host - * in this SCSI CMD. - */ -int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval; - int i; - unsigned int lun = SCSI_LUN(srb); - u8 buf1[32], buf2[12]; - - RTS51X_DEBUGP("--%s--\n", __func__); - - if (scsi_bufflen(srb) < 12) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, STATUS_FAIL); - } - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = mg_send_ex_cmd(chip, MG_SET_LID, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - TRACE_RET(chip, retval); - } - - memset(buf1, 0, 32); - rts51x_get_xfer_buf(buf2, min(12, (int)scsi_bufflen(srb)), srb); - for (i = 0; i < 8; i++) - buf1[8 + i] = buf2[4 + i]; - retval = - ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf1, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - TRACE_RET(chip, retval); - } - retval = mg_check_int_error(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -/** - * Send Local EKB to host. - - * After receiving this SCSI command, adapter shall read the divided - * data(1536 bytes totally) from medium by using READ_LONG_DATA TPC - * for 3 times, and report data to host with data-length is 1052 bytes. - */ -int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval = STATUS_FAIL; - int bufflen; - unsigned int lun = SCSI_LUN(srb); - u8 *buf = NULL; - - RTS51X_DEBUGP("--%s--\n", __func__); - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - buf = kmalloc(1540, GFP_KERNEL); - if (!buf) - TRACE_RET(chip, STATUS_NOMEM); - - buf[0] = 0x04; - buf[1] = 0x1A; - buf[2] = 0x00; - buf[3] = 0x00; - - retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - TRACE_GOTO(chip, GetEKBFinish); - } - - retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, - 3, WAIT_INT, 0, 0, buf + 4, 1536); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, - MS_STOP | MS_CLR_ERR); - TRACE_GOTO(chip, GetEKBFinish); - } - retval = mg_check_int_error(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - TRACE_GOTO(chip, GetEKBFinish); - } - - bufflen = min(1052, (int)scsi_bufflen(srb)); - rts51x_set_xfer_buf(buf, bufflen, srb); - -GetEKBFinish: - kfree(buf); - return retval; -} - -/** - * Send challenge(host) to medium. - - * After receiving this SCSI command, adapter shall sequentially issues - * TPC commands to the medium for writing 8-bytes data as challenge - * by host within a short data packet. - */ -int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - int bufflen; - int i; - unsigned int lun = SCSI_LUN(srb); - u8 buf[32], tmp; - - RTS51X_DEBUGP("--%s--\n", __func__); - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = mg_send_ex_cmd(chip, MG_GET_ID, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, retval); - } - - retval = - ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, retval); - } - retval = mg_check_int_error(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, retval); - } - - memcpy(ms_card->magic_gate_id, buf, 16); - - for (i = 0; i < 2500; i++) { - RTS51X_READ_REG(chip, MS_TRANS_CFG, &tmp); - if (tmp & - (MS_INT_CED | MS_INT_CMDNK | MS_INT_BREQ | MS_INT_ERR)) - break; - - wait_timeout(1); - } - - if (i == 2500) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = mg_send_ex_cmd(chip, MG_SET_RD, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, retval); - } - - bufflen = min(12, (int)scsi_bufflen(srb)); - rts51x_get_xfer_buf(buf, bufflen, srb); - - for (i = 0; i < 8; i++) - buf[i] = buf[4 + i]; - for (i = 0; i < 24; i++) - buf[8 + i] = 0; - retval = - ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, retval); - } - retval = mg_check_int_error(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, retval); - } - - ms_card->mg_auth = 0; - - return STATUS_SUCCESS; -} - -/** - * Send Response and Challenge data to host. - - * After receiving this SCSI command, adapter shall communicates with - * the medium, get parameters(HRd, Rms, MagicGateID) by using READ_SHORT_DATA - * TPC and send the data to host according to certain format required by - * MG-R specification. - * The paremeter MagicGateID is the one that adapter has obtained from - * the medium by TPC commands in Set Leaf ID command phase previously. - */ -int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval, i; - int bufflen; - unsigned int lun = SCSI_LUN(srb); - u8 buf1[32], buf2[36], tmp; - - RTS51X_DEBUGP("--%s--\n", __func__); - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - TRACE_RET(chip, retval); - } - - retval = - ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf1, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - TRACE_RET(chip, retval); - } - retval = mg_check_int_error(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - TRACE_RET(chip, retval); - } - - buf2[0] = 0x00; - buf2[1] = 0x22; - buf2[2] = 0x00; - buf2[3] = 0x00; - - memcpy(buf2 + 4, ms_card->magic_gate_id, 16); - memcpy(buf2 + 20, buf1, 16); - - bufflen = min(36, (int)scsi_bufflen(srb)); - rts51x_set_xfer_buf(buf2, bufflen, srb); - - for (i = 0; i < 2500; i++) { - RTS51X_READ_REG(chip, MS_TRANS_CFG, &tmp); - if (tmp & (MS_INT_CED | MS_INT_CMDNK | - MS_INT_BREQ | MS_INT_ERR)) - break; - - wait_timeout(1); - } - - if (i == 2500) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -/** - * Send response(host) to medium. - - * After receiving this SCSI command, adapter shall sequentially - * issues TPC commands to the medium for writing 8-bytes data as - * challenge by host within a short data packet. - */ -int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - int i; - int bufflen; - unsigned int lun = SCSI_LUN(srb); - u8 buf[32]; - - RTS51X_DEBUGP("--%s--\n", __func__); - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - TRACE_RET(chip, retval); - } - - bufflen = min(12, (int)scsi_bufflen(srb)); - rts51x_get_xfer_buf(buf, bufflen, srb); - - for (i = 0; i < 8; i++) - buf[i] = buf[4 + i]; - for (i = 0; i < 24; i++) - buf[8 + i] = 0; - retval = - ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - TRACE_RET(chip, retval); - } - retval = mg_check_int_error(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - TRACE_RET(chip, retval); - } - - ms_card->mg_auth = 1; - - return STATUS_SUCCESS; -} - -/** * Send ICV data to host. - - * After receiving this SCSI command, adapter shall read the divided - * data(1024 bytes totally) from medium by using READ_LONG_DATA TPC - * for 2 times, and report data to host with data-length is 1028 bytes. - * - * Since the extra 4 bytes data is just only a prefix to original data - * that read from medium, so that the 4-byte data pushed into Ring buffer - * precedes data tramsinssion from medium to Ring buffer by DMA mechanisim - * in order to get maximum performance and minimum code size simultaneously. - */ -int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - int bufflen; - unsigned int lun = SCSI_LUN(srb); - u8 *buf = NULL; - - RTS51X_DEBUGP("--%s--\n", __func__); - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - buf = kmalloc(1028, GFP_KERNEL); - if (!buf) - TRACE_RET(chip, STATUS_NOMEM); - - buf[0] = 0x04; - buf[1] = 0x02; - buf[2] = 0x00; - buf[3] = 0x00; - - retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_GOTO(chip, GetICVFinish); - } - - retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, - 2, WAIT_INT, 0, 0, buf + 4, 1024); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, - MS_STOP | MS_CLR_ERR); - TRACE_GOTO(chip, GetICVFinish); - } - retval = mg_check_int_error(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_GOTO(chip, GetICVFinish); - } - - bufflen = min(1028, (int)scsi_bufflen(srb)); - rts51x_set_xfer_buf(buf, bufflen, srb); - -GetICVFinish: - kfree(buf); - return retval; -} - -/** - * Send ICV data to medium. - - * After receiving this SCSI command, adapter shall receive 1028 bytes - * and write the later 1024 bytes to medium by WRITE_LONG_DATA TPC - * consecutively. - * - * Since the first 4-bytes data is just only a prefix to original data - * that sent by host, and it should be skipped by shifting DMA pointer - * before writing 1024 bytes to medium. - */ -int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - int retval; - int bufflen; -#ifdef MG_SET_ICV_SLOW - int i; -#endif - unsigned int lun = SCSI_LUN(srb); - u8 *buf = NULL; - - RTS51X_DEBUGP("--%s--\n", __func__); - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - buf = kmalloc(1028, GFP_KERNEL); - if (!buf) - TRACE_RET(chip, STATUS_NOMEM); - - bufflen = min(1028, (int)scsi_bufflen(srb)); - rts51x_get_xfer_buf(buf, bufflen, srb); - - retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num); - if (retval != STATUS_SUCCESS) { - if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) - set_sense_type(chip, lun, - SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } else { - set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); - } - TRACE_GOTO(chip, SetICVFinish); - } - -#ifdef MG_SET_ICV_SLOW - for (i = 0; i < 2; i++) { - udelay(50); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, - PRO_WRITE_LONG_DATA); - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, - WAIT_INT); - - trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_NORMAL_WRITE); - rts51x_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CDOR, 100); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); - TRACE_GOTO(chip, SetICVFinish); - } - - retval = rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), - buf + 4 + i * 512, 512, 0, - NULL, 3000, STAGE_DO); - if (retval != STATUS_SUCCESS) { - rts51x_clear_ms_error(chip); - if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) - set_sense_type(chip, lun, - SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } - retval = STATUS_FAIL; - TRACE_GOTO(chip, SetICVFinish); - } - - retval = rts51x_get_rsp(chip, 1, 3000); - if (CHECK_MS_TRANS_FAIL(chip, retval) - || mg_check_int_error(chip)) { - rts51x_clear_ms_error(chip); - if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) - set_sense_type(chip, lun, - SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } - retval = STATUS_FAIL; - TRACE_GOTO(chip, SetICVFinish); - } - } -#else - retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA, - 2, WAIT_INT, 0, 0, buf + 4, 1024); - if (retval != STATUS_SUCCESS) { - rts51x_clear_ms_error(chip); - if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) - set_sense_type(chip, lun, - SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } else { - set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); - } - TRACE_GOTO(chip, SetICVFinish); - } -#endif - -SetICVFinish: - kfree(buf); - return retval; -} - -#endif /* SUPPORT_MAGIC_GATE */ diff --git a/trunk/drivers/staging/rts5139/ms_mg.h b/trunk/drivers/staging/rts5139/ms_mg.h deleted file mode 100644 index e2ca55085f97..000000000000 --- a/trunk/drivers/staging/rts5139/ms_mg.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_MS_MG_H -#define __RTS51X_MS_MG_H - -#include "rts51x_chip.h" -#include "ms.h" - -int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip); - -#endif /* __RTS51X_MS_MG_H */ diff --git a/trunk/drivers/staging/rts5139/rts51x.c b/trunk/drivers/staging/rts5139/rts51x.c deleted file mode 100644 index d9cee6d0b124..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x.c +++ /dev/null @@ -1,967 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "ms.h" -#include "rts51x.h" -#include "rts51x_chip.h" -#include "rts51x_card.h" -#include "rts51x_scsi.h" -#include "rts51x_transport.h" -#include "rts51x_fop.h" - -MODULE_DESCRIPTION(RTS51X_DESC); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRIVER_VERSION); - -#ifdef SCSI_SCAN_DELAY -static unsigned int delay_use = 5; -module_param(delay_use, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); -#endif - -static int auto_delink_en; -module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); - -static int ss_en; -module_param(ss_en, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ss_en, "enable selective suspend"); - -static int ss_delay = 50; -module_param(ss_delay, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ss_delay, - "seconds to delay before entering selective suspend"); - -static int needs_remote_wakeup; -module_param(needs_remote_wakeup, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(needs_remote_wakeup, "ss state needs remote wakeup supported"); - -#ifdef SUPPORT_FILE_OP -static const struct file_operations rts51x_fops = { - .owner = THIS_MODULE, - .read = rts51x_read, - .write = rts51x_write, - .unlocked_ioctl = rts51x_ioctl, - .open = rts51x_open, - .release = rts51x_release, -}; - -/* - * usb class driver info in order to get a minor number from the usb core, - * and to have the device registered with the driver core - */ -static struct usb_class_driver rts51x_class = { - .name = "rts51x%d", - .fops = &rts51x_fops, - .minor_base = 192, -}; -#endif - -#ifdef CONFIG_PM /* Minimal support for suspend and resume */ - -static inline void usb_autopm_enable(struct usb_interface *intf) -{ - atomic_set(&intf->pm_usage_cnt, 1); - usb_autopm_put_interface(intf); -} - -static inline void usb_autopm_disable(struct usb_interface *intf) -{ - atomic_set(&intf->pm_usage_cnt, 0); - usb_autopm_get_interface(intf); -} - -void rts51x_try_to_enter_ss(struct rts51x_chip *chip) -{ - RTS51X_DEBUGP("Ready to enter SS state\n"); - usb_autopm_enable(chip->usb->pusb_intf); -} - -void rts51x_try_to_exit_ss(struct rts51x_chip *chip) -{ - RTS51X_DEBUGP("Exit from SS state\n"); - usb_autopm_disable(chip->usb->pusb_intf); -} - -int rts51x_suspend(struct usb_interface *iface, pm_message_t message) -{ - struct rts51x_chip *chip = usb_get_intfdata(iface); - - RTS51X_DEBUGP("%s, message.event = 0x%x\n", __func__, message.event); - - /* Wait until no command is running */ - mutex_lock(&chip->usb->dev_mutex); - - chip->fake_card_ready = chip->card_ready; - rts51x_do_before_power_down(chip); - - if (message.event == PM_EVENT_AUTO_SUSPEND) { - RTS51X_DEBUGP("Enter SS state"); - chip->resume_from_scsi = 0; - RTS51X_SET_STAT(chip, STAT_SS); - } else { - RTS51X_DEBUGP("Enter SUSPEND state"); - RTS51X_SET_STAT(chip, STAT_SUSPEND); - } - - /* When runtime PM is working, we'll set a flag to indicate - * whether we should autoresume when a SCSI request arrives. */ - - mutex_unlock(&chip->usb->dev_mutex); - return 0; -} - -int rts51x_resume(struct usb_interface *iface) -{ - struct rts51x_chip *chip = usb_get_intfdata(iface); - - RTS51X_DEBUGP("%s\n", __func__); - - if (!RTS51X_CHK_STAT(chip, STAT_SS) || !chip->resume_from_scsi) { - mutex_lock(&chip->usb->dev_mutex); - - if (chip->option.ss_en) { - if (GET_PM_USAGE_CNT(chip) <= 0) { - /* Remote wake up, increase pm_usage_cnt */ - RTS51X_DEBUGP("Incr pm_usage_cnt\n"); - SET_PM_USAGE_CNT(chip, 1); - } - } - - RTS51X_SET_STAT(chip, STAT_RUN); - - rts51x_init_chip(chip); - rts51x_init_cards(chip); - - mutex_unlock(&chip->usb->dev_mutex); - } - - return 0; -} - -int rts51x_reset_resume(struct usb_interface *iface) -{ - struct rts51x_chip *chip = usb_get_intfdata(iface); - - RTS51X_DEBUGP("%s\n", __func__); - - mutex_lock(&chip->usb->dev_mutex); - - RTS51X_SET_STAT(chip, STAT_RUN); - - if (chip->option.ss_en) - SET_PM_USAGE_CNT(chip, 1); - - rts51x_init_chip(chip); - rts51x_init_cards(chip); - - mutex_unlock(&chip->usb->dev_mutex); - - /* FIXME: Notify the subdrivers that they need to reinitialize - * the device */ - return 0; -} - -#else /* CONFIG_PM */ - -void rts51x_try_to_enter_ss(struct rts51x_chip *chip) -{ -} - -void rts51x_try_to_exit_ss(struct rts51x_chip *chip) -{ -} - -#endif /* CONFIG_PM */ - -/* - * The next two routines get called just before and just after - * a USB port reset, whether from this driver or a different one. - */ - -int rts51x_pre_reset(struct usb_interface *iface) -{ - struct rts51x_chip *chip = usb_get_intfdata(iface); - - RTS51X_DEBUGP("%s\n", __func__); - - /* Make sure no command runs during the reset */ - mutex_lock(&chip->usb->dev_mutex); - return 0; -} - -int rts51x_post_reset(struct usb_interface *iface) -{ - struct rts51x_chip *chip = usb_get_intfdata(iface); - - RTS51X_DEBUGP("%s\n", __func__); - - /* Report the reset to the SCSI core */ - /* usb_stor_report_bus_reset(us); */ - - /* FIXME: Notify the subdrivers that they need to reinitialize - * the device */ - - mutex_unlock(&chip->usb->dev_mutex); - return 0; -} - -static int rts51x_control_thread(void *__chip) -{ - struct rts51x_chip *chip = (struct rts51x_chip *)__chip; - struct Scsi_Host *host = rts51x_to_host(chip); - - for (;;) { - if (wait_for_completion_interruptible(&chip->usb->cmnd_ready)) - break; - - if (test_bit(FLIDX_DISCONNECTING, &chip->usb->dflags)) { - RTS51X_DEBUGP("-- exiting from rts51x-control\n"); - break; - } - - /* lock the device pointers */ - mutex_lock(&(chip->usb->dev_mutex)); - - /* lock access to the state */ - scsi_lock(host); - - /* When we are called with no command pending, we're done */ - if (chip->srb == NULL) { - scsi_unlock(host); - mutex_unlock(&chip->usb->dev_mutex); - RTS51X_DEBUGP("-- exiting from control thread\n"); - break; - } - - /* has the command timed out *already* ? */ - if (test_bit(FLIDX_TIMED_OUT, &chip->usb->dflags)) { - chip->srb->result = DID_ABORT << 16; - goto SkipForAbort; - } - - scsi_unlock(host); - - /* reject the command if the direction indicator - * is UNKNOWN - */ - if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) { - RTS51X_DEBUGP("UNKNOWN data direction\n"); - chip->srb->result = DID_ERROR << 16; - } - - /* reject if target != 0 or if LUN is higher than - * the maximum known LUN - */ - else if (chip->srb->device->id) { - RTS51X_DEBUGP("Bad target number (%d:%d)\n", - chip->srb->device->id, - chip->srb->device->lun); - chip->srb->result = DID_BAD_TARGET << 16; - } - - else if (chip->srb->device->lun > chip->max_lun) { - RTS51X_DEBUGP("Bad LUN (%d:%d)\n", - chip->srb->device->id, - chip->srb->device->lun); - chip->srb->result = DID_BAD_TARGET << 16; - } - - /* we've got a command, let's do it! */ - else { - RTS51X_DEBUG(scsi_show_command(chip->srb)); - rts51x_invoke_transport(chip->srb, chip); - } - - /* lock access to the state */ - scsi_lock(host); - - /* indicate that the command is done */ - if (chip->srb->result != DID_ABORT << 16) - chip->srb->scsi_done(chip->srb); - else -SkipForAbort : - RTS51X_DEBUGP("scsi command aborted\n"); - - /* If an abort request was received we need to signal that - * the abort has finished. The proper test for this is - * the TIMED_OUT flag, not srb->result == DID_ABORT, because - * the timeout might have occurred after the command had - * already completed with a different result code. */ - if (test_bit(FLIDX_TIMED_OUT, &chip->usb->dflags)) { - complete(&(chip->usb->notify)); - - /* Allow USB transfers to resume */ - clear_bit(FLIDX_ABORTING, &chip->usb->dflags); - clear_bit(FLIDX_TIMED_OUT, &chip->usb->dflags); - } - - /* finished working on this command */ - chip->srb = NULL; - scsi_unlock(host); - - /* unlock the device pointers */ - mutex_unlock(&chip->usb->dev_mutex); - } /* for (;;) */ - - complete(&chip->usb->control_exit); - - /* Wait until we are told to stop */ -/* for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (kthread_should_stop()) - break; - schedule(); - } - __set_current_state(TASK_RUNNING);*/ - return 0; -} - -static int rts51x_polling_thread(void *__chip) -{ - struct rts51x_chip *chip = (struct rts51x_chip *)__chip; - -#ifdef SCSI_SCAN_DELAY - /* Wait until SCSI scan finished */ - wait_timeout((delay_use + 5) * HZ); -#endif - - for (;;) { - wait_timeout(POLLING_INTERVAL); - - /* if the device has disconnected, we are free to exit */ - if (test_bit(FLIDX_DISCONNECTING, &chip->usb->dflags)) { - RTS51X_DEBUGP("-- exiting from rts51x-polling\n"); - break; - } - - /* if the device has disconnected, we are free to exit */ - /* if (kthread_should_stop()) { - printk(KERN_INFO "Stop polling thread!\n"); - break; - } */ - -#ifdef CONFIG_PM - if (RTS51X_CHK_STAT(chip, STAT_SS) || - RTS51X_CHK_STAT(chip, STAT_SS_PRE) || - RTS51X_CHK_STAT(chip, STAT_SUSPEND)) { - continue; - } - - if (ss_en) { - if (RTS51X_CHK_STAT(chip, STAT_IDLE)) { - if (chip->ss_counter < - (ss_delay * 1000 / POLLING_INTERVAL)) { - chip->ss_counter++; - } else { - /* Prepare SS state */ - RTS51X_SET_STAT(chip, STAT_SS_PRE); - rts51x_try_to_enter_ss(chip); - continue; - } - } else { - chip->ss_counter = 0; - } - } -#endif - - mspro_polling_format_status(chip); - - /* lock the device pointers */ - mutex_lock(&(chip->usb->dev_mutex)); - - rts51x_polling_func(chip); - - /* unlock the device pointers */ - mutex_unlock(&chip->usb->dev_mutex); - } /* for (;;) */ - - complete(&chip->usb->polling_exit); - - /* Wait until we are told to stop */ - /* for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (kthread_should_stop()) - break; - schedule(); - } - __set_current_state(TASK_RUNNING); */ - return 0; -} - -#ifdef SCSI_SCAN_DELAY -/* Thread to carry out delayed SCSI-device scanning */ -static int rts51x_scan_thread(void *__chip) -{ - struct rts51x_chip *chip = (struct rts51x_chip *)__chip; - - printk(KERN_DEBUG - "rts51x: device found at %d\n", chip->usb->pusb_dev->devnum); - - set_freezable(); - /* Wait for the timeout to expire or for a disconnect */ - if (delay_use > 0) { - printk(KERN_DEBUG "rts51x: waiting for device " - "to settle before scanning\n"); - wait_event_freezable_timeout(chip->usb->delay_wait, - test_bit(FLIDX_DONT_SCAN, - &chip->usb->dflags), - delay_use * HZ); - } - - /* If the device is still connected, perform the scanning */ - if (!test_bit(FLIDX_DONT_SCAN, &chip->usb->dflags)) { - scsi_scan_host(rts51x_to_host(chip)); - printk(KERN_DEBUG "rts51x: device scan complete\n"); - - /* Should we unbind if no devices were detected? */ - } - - complete_and_exit(&chip->usb->scanning_done, 0); -} -#endif - -/* Associate our private data with the USB device */ -static int associate_dev(struct rts51x_chip *chip, struct usb_interface *intf) -{ - struct rts51x_usb *rts51x = chip->usb; -#ifdef SUPPORT_FILE_OP - int retval; -#endif - - /* Fill in the device-related fields */ - rts51x->pusb_dev = interface_to_usbdev(intf); - rts51x->pusb_intf = intf; - rts51x->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - RTS51X_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n", - le16_to_cpu(rts51x->pusb_dev->descriptor.idVendor), - le16_to_cpu(rts51x->pusb_dev->descriptor.idProduct), - le16_to_cpu(rts51x->pusb_dev->descriptor.bcdDevice)); - RTS51X_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n", - intf->cur_altsetting->desc.bInterfaceSubClass, - intf->cur_altsetting->desc.bInterfaceProtocol); - - /* Store our private data in the interface */ - usb_set_intfdata(intf, chip); - -#ifdef SUPPORT_FILE_OP - /* we can register the device now, as it is ready */ - retval = usb_register_dev(intf, &rts51x_class); - if (retval) { - /* something prevented us from registering this driver */ - RTS51X_DEBUGP("Not able to get a minor for this device."); - usb_set_intfdata(intf, NULL); - return -ENOMEM; - } -#endif - - /* Allocate the device-related DMA-mapped buffers */ - rts51x->cr = usb_buffer_alloc(rts51x->pusb_dev, sizeof(*rts51x->cr), - GFP_KERNEL, &rts51x->cr_dma); - if (!rts51x->cr) { - RTS51X_DEBUGP("usb_ctrlrequest allocation failed\n"); - usb_set_intfdata(intf, NULL); - return -ENOMEM; - } - - rts51x->iobuf = usb_buffer_alloc(rts51x->pusb_dev, RTS51X_IOBUF_SIZE, - GFP_KERNEL, &rts51x->iobuf_dma); - if (!rts51x->iobuf) { - RTS51X_DEBUGP("I/O buffer allocation failed\n"); - usb_set_intfdata(intf, NULL); - return -ENOMEM; - } - return 0; -} - -static void rts51x_init_options(struct rts51x_chip *chip) -{ - struct rts51x_option *option = &(chip->option); - - option->led_blink_speed = 7; - option->mspro_formatter_enable = 1; - - option->fpga_sd_sdr104_clk = CLK_100; - option->fpga_sd_sdr50_clk = CLK_100; - option->fpga_sd_ddr50_clk = CLK_100; - option->fpga_sd_hs_clk = CLK_100; - option->fpga_mmc_52m_clk = CLK_80; - option->fpga_ms_hg_clk = CLK_80; - option->fpga_ms_4bit_clk = CLK_80; - - option->asic_sd_sdr104_clk = 98; - option->asic_sd_sdr50_clk = 98; - option->asic_sd_ddr50_clk = 98; - option->asic_sd_hs_clk = 97; - option->asic_mmc_52m_clk = 95; - option->asic_ms_hg_clk = 116; - option->asic_ms_4bit_clk = 77; - - option->sd_ddr_tx_phase = 0; - option->mmc_ddr_tx_phase = 1; - - option->sd_speed_prior = 0; - option->sd_ctl = - SD_PUSH_POINT_AUTO | SD_SAMPLE_POINT_AUTO | SUPPORT_UHS50_MMC44; - - option->ss_en = ss_en; - option->ss_delay = ss_delay; - option->needs_remote_wakeup = needs_remote_wakeup; - - option->auto_delink_en = auto_delink_en; - - option->FT2_fast_mode = 0; - option->pwr_delay = 800; - option->xd_rw_step = 0; - option->D3318_off_delay = 50; - option->delink_delay = 100; - option->rts5129_D3318_off_enable = 0; - option->sd20_pad_drive = 0; - option->reset_or_rw_fail_set_pad_drive = 1; - option->rcc_fail_flag = 0; - option->rcc_bug_fix_en = 1; - option->debounce_num = 2; - option->polling_time = 100; - option->led_toggle_interval = 6; - option->xd_rwn_step = 0; - option->sd_send_status_en = 0; - option->sdr50_tx_phase = 0x01; - option->sdr50_rx_phase = 0x05; - option->ddr50_tx_phase = 0x09; - option->ddr50_rx_phase = 0x06; - option->sdr50_phase_sel = 0; - option->sd30_pad_drive = 1; - option->ms_errreg_fix = 0; - option->reset_mmc_first = 0; - option->speed_mmc = 1; - option->led_always_on = 0; -} - -/* Get the pipe settings */ -static int get_pipes(struct rts51x_chip *chip) -{ - struct rts51x_usb *rts51x = chip->usb; - struct usb_host_interface *altsetting = - rts51x->pusb_intf->cur_altsetting; - int i; - struct usb_endpoint_descriptor *ep; - struct usb_endpoint_descriptor *ep_in = NULL; - struct usb_endpoint_descriptor *ep_out = NULL; - struct usb_endpoint_descriptor *ep_int = NULL; - - /* - * Find the first endpoint of each type we need. - * We are expecting a minimum of 2 endpoints - in and out (bulk). - * An optional interrupt-in is OK (necessary for CBI protocol). - * We will ignore any others. - */ - for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { - ep = &altsetting->endpoint[i].desc; - - if (usb_endpoint_xfer_bulk(ep)) { - if (usb_endpoint_dir_in(ep)) { - if (!ep_in) - ep_in = ep; - } else { - if (!ep_out) - ep_out = ep; - } - } - - else if (usb_endpoint_is_int_in(ep)) { - if (!ep_int) - ep_int = ep; - } - } - - if (!ep_in || !ep_out) { - RTS51X_DEBUGP("Endpoint sanity check failed!" - "Rejecting dev.\n"); - return -EIO; - } - - /* Calculate and store the pipe values */ - rts51x->send_ctrl_pipe = usb_sndctrlpipe(rts51x->pusb_dev, 0); - rts51x->recv_ctrl_pipe = usb_rcvctrlpipe(rts51x->pusb_dev, 0); - rts51x->send_bulk_pipe = usb_sndbulkpipe(rts51x->pusb_dev, - usb_endpoint_num(ep_out)); - rts51x->recv_bulk_pipe = usb_rcvbulkpipe(rts51x->pusb_dev, - usb_endpoint_num(ep_in)); - if (ep_int) { - rts51x->recv_intr_pipe = usb_rcvintpipe(rts51x->pusb_dev, - usb_endpoint_num - (ep_int)); - rts51x->ep_bInterval = ep_int->bInterval; - } - return 0; -} - -/* Initialize all the dynamic resources we need */ -static int rts51x_acquire_resources(struct rts51x_chip *chip) -{ - struct rts51x_usb *rts51x = chip->usb; - int retval; - - rts51x->current_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rts51x->current_urb) { - RTS51X_DEBUGP("URB allocation failed\n"); - return -ENOMEM; - } - - rts51x->intr_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rts51x->intr_urb) { - RTS51X_DEBUGP("URB allocation failed\n"); - return -ENOMEM; - } - - chip->cmd_buf = chip->rsp_buf = rts51x->iobuf; - - rts51x_init_options(chip); - - /* Init rts51xx device */ - retval = rts51x_init_chip(chip); - if (retval != STATUS_SUCCESS) - return -EIO; - - return 0; -} - -/* Release all our dynamic resources */ -static void rts51x_release_resources(struct rts51x_chip *chip) -{ - RTS51X_DEBUGP("-- %s\n", __func__); - - /* Tell the control thread to exit. The SCSI host must - * already have been removed and the DISCONNECTING flag set - * so that we won't accept any more commands. - */ - RTS51X_DEBUGP("-- sending exit command to thread\n"); - complete(&chip->usb->cmnd_ready); - if (chip->usb->ctl_thread) - wait_for_completion(&chip->usb->control_exit); - /* kthread_stop(chip->usb->ctl_thread); */ - if (chip->usb->polling_thread) - wait_for_completion(&chip->usb->polling_exit); - - /* if (chip->usb->polling_thread) - kthread_stop(chip->usb->polling_thread); */ - - wait_timeout(200); - - /* Release rts51xx device here */ - rts51x_release_chip(chip); - - usb_free_urb(chip->usb->current_urb); - usb_free_urb(chip->usb->intr_urb); -} - -/* Dissociate from the USB device */ -static void dissociate_dev(struct rts51x_chip *chip) -{ - struct rts51x_usb *rts51x = chip->usb; - - RTS51X_DEBUGP("-- %s\n", __func__); - - /* Free the device-related DMA-mapped buffers */ - if (rts51x->cr) - usb_buffer_free(rts51x->pusb_dev, sizeof(*rts51x->cr), - rts51x->cr, rts51x->cr_dma); - if (rts51x->iobuf) - usb_buffer_free(rts51x->pusb_dev, RTS51X_IOBUF_SIZE, - rts51x->iobuf, rts51x->iobuf_dma); - - /* Remove our private data from the interface */ - usb_set_intfdata(rts51x->pusb_intf, NULL); - -#ifdef SUPPORT_FILE_OP - /* give back our minor */ - usb_deregister_dev(rts51x->pusb_intf, &rts51x_class); -#endif - - kfree(rts51x); - chip->usb = NULL; -} - -/* First stage of disconnect processing: stop SCSI scanning, - * remove the host, and stop accepting new commands - */ -static void quiesce_and_remove_host(struct rts51x_chip *chip) -{ - struct rts51x_usb *rts51x = chip->usb; - struct Scsi_Host *host = rts51x_to_host(chip); - - /* If the device is really gone, cut short reset delays */ - if (rts51x->pusb_dev->state == USB_STATE_NOTATTACHED) - set_bit(FLIDX_DISCONNECTING, &rts51x->dflags); - -#ifdef SCSI_SCAN_DELAY - /* Prevent SCSI-scanning (if it hasn't started yet) - * and wait for the SCSI-scanning thread to stop. - */ - set_bit(FLIDX_DONT_SCAN, &rts51x->dflags); - wake_up(&rts51x->delay_wait); - wait_for_completion(&rts51x->scanning_done); -#endif - - /* Removing the host will perform an orderly shutdown: caches - * synchronized, disks spun down, etc. - */ - scsi_remove_host(host); - - /* Prevent any new commands from being accepted and cut short - * reset delays. - */ - scsi_lock(host); - set_bit(FLIDX_DISCONNECTING, &rts51x->dflags); - scsi_unlock(host); -#ifdef SCSI_SCAN_DELAY - wake_up(&rts51x->delay_wait); -#endif -} - -/* Second stage of disconnect processing: deallocate all resources */ -static void release_everything(struct rts51x_chip *chip) -{ - rts51x_release_resources(chip); - dissociate_dev(chip); - - /* Drop our reference to the host; the SCSI core will free it - * (and "chip" along with it) when the refcount becomes 0. */ - scsi_host_put(rts51x_to_host(chip)); -} - -static int rts51x_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct Scsi_Host *host; - struct rts51x_chip *chip; - struct rts51x_usb *rts51x; - int result; - struct task_struct *th; - - RTS51X_DEBUGP("%s detected\n", RTS51X_NAME); - - rts51x = kzalloc(sizeof(struct rts51x_usb), GFP_KERNEL); - if (!rts51x) { - printk(KERN_WARNING RTS51X_TIP - "Unable to allocate rts51x_usb\n"); - return -ENOMEM; - } - - /* - * Ask the SCSI layer to allocate a host structure, with extra - * space at the end for our private us_data structure. - */ - host = scsi_host_alloc(&rts51x_host_template, sizeof(*chip)); - if (!host) { - printk(KERN_WARNING RTS51X_TIP - "Unable to allocate the scsi host\n"); - kfree(rts51x); - return -ENOMEM; - } - - /* - * Allow 16-byte CDBs and thus > 2TB - */ - host->max_cmd_len = 16; - chip = host_to_rts51x(host); - memset(chip, 0, sizeof(struct rts51x_chip)); - - chip->vendor_id = id->idVendor; - chip->product_id = id->idProduct; - - mutex_init(&(rts51x->dev_mutex)); - init_completion(&rts51x->cmnd_ready); - init_completion(&rts51x->control_exit); - init_completion(&rts51x->polling_exit); - init_completion(&(rts51x->notify)); -#ifdef SCSI_SCAN_DELAY - init_waitqueue_head(&rts51x->delay_wait); - init_completion(&rts51x->scanning_done); -#endif - - chip->usb = rts51x; - - /* Associate the us_data structure with the USB device */ - result = associate_dev(chip, intf); - if (result) - goto BadDevice; - - /* Find the endpoints and calculate pipe values */ - result = get_pipes(chip); - if (result) - goto BadDevice; - - /* Acquire all the other resources and add the host */ - result = rts51x_acquire_resources(chip); - if (result) - goto BadDevice; - - /* Start up our control thread */ - th = kthread_run(rts51x_control_thread, chip, RTS51X_CTL_THREAD); - if (IS_ERR(th)) { - printk(KERN_WARNING RTS51X_TIP - "Unable to start control thread\n"); - result = PTR_ERR(th); - goto BadDevice; - } - rts51x->ctl_thread = th; - - result = scsi_add_host(rts51x_to_host(chip), &rts51x->pusb_intf->dev); - if (result) { - printk(KERN_WARNING RTS51X_TIP "Unable to add the scsi host\n"); - goto BadDevice; - } -#ifdef SCSI_SCAN_DELAY - /* Start up the thread for delayed SCSI-device scanning */ - th = kthread_create(rts51x_scan_thread, chip, RTS51X_SCAN_THREAD); - if (IS_ERR(th)) { - printk(KERN_WARNING RTS51X_TIP - "Unable to start the device-scanning thread\n"); - complete(&rts51x->scanning_done); - quiesce_and_remove_host(chip); - result = PTR_ERR(th); - goto BadDevice; - } - - wake_up_process(th); -#else - scsi_scan_host(rts51x_to_host(chip)); -#endif - - /* Start up our polling thread */ - th = kthread_run(rts51x_polling_thread, chip, RTS51X_POLLING_THREAD); - if (IS_ERR(th)) { - printk(KERN_WARNING RTS51X_TIP - "Unable to start polling thread\n"); - result = PTR_ERR(th); - goto BadDevice; - } - rts51x->polling_thread = th; - -#ifdef CONFIG_PM - if (ss_en) { - rts51x->pusb_intf->needs_remote_wakeup = needs_remote_wakeup; - SET_PM_USAGE_CNT(chip, 1); - RTS51X_DEBUGP("pm_usage_cnt = %d\n", GET_PM_USAGE_CNT(chip)); - } -#endif - - return 0; - - /* We come here if there are any problems */ -BadDevice: - RTS51X_DEBUGP("rts51x_probe() failed\n"); - release_everything(chip); - return result; -} - -static void rts51x_disconnect(struct usb_interface *intf) -{ - struct rts51x_chip *chip = (struct rts51x_chip *)usb_get_intfdata(intf); - - RTS51X_DEBUGP("rts51x_disconnect() called\n"); - quiesce_and_remove_host(chip); - release_everything(chip); -} - -/*********************************************************************** - * Initialization and registration - ***********************************************************************/ - -struct usb_device_id rts5139_usb_ids[] = { - {USB_DEVICE(0x0BDA, 0x0139)}, - {USB_DEVICE(0x0BDA, 0x0129)}, - {} /* Terminating entry */ -}; -EXPORT_SYMBOL_GPL(rts5139_usb_ids); - -MODULE_DEVICE_TABLE(usb, rts5139_usb_ids); - -struct usb_driver rts51x_driver = { - .name = RTS51X_NAME, - .probe = rts51x_probe, - .disconnect = rts51x_disconnect, - .suspend = rts51x_suspend, - .resume = rts51x_resume, - .reset_resume = rts51x_reset_resume, - .pre_reset = rts51x_pre_reset, - .post_reset = rts51x_post_reset, - .id_table = rts5139_usb_ids, - .soft_unbind = 1, -}; - -static int __init rts51x_init(void) -{ - int retval; - - printk(KERN_INFO "Initializing %s USB card reader driver...\n", - RTS51X_NAME); - - /* register the driver, return usb_register return code if error */ - retval = usb_register(&rts51x_driver); - if (retval == 0) { - printk(KERN_INFO - "Realtek %s USB card reader support registered.\n", - RTS51X_NAME); - } - return retval; -} - -static void __exit rts51x_exit(void) -{ - RTS51X_DEBUGP("rts51x_exit() called\n"); - - /* Deregister the driver - * This will cause disconnect() to be called for each - * attached unit - */ - RTS51X_DEBUGP("-- calling usb_deregister()\n"); - usb_deregister(&rts51x_driver); -} - -module_init(rts51x_init); -module_exit(rts51x_exit); diff --git a/trunk/drivers/staging/rts5139/rts51x.h b/trunk/drivers/staging/rts5139/rts51x.h deleted file mode 100644 index 9415d5c05502..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x.h +++ /dev/null @@ -1,205 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_H -#define __RTS51X_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define DRIVER_VERSION "v1.04" - -#define RTS51X_DESC "Realtek RTS5139/29 USB card reader driver" -#define RTS51X_NAME "rts5139" -#define RTS51X_CTL_THREAD "rts5139-control" -#define RTS51X_SCAN_THREAD "rts5139-scan" -#define RTS51X_POLLING_THREAD "rts5139-polling" - -#define POLLING_IN_THREAD -/* #define SCSI_SCAN_DELAY */ -#define SUPPORT_FILE_OP - -#define wait_timeout_x(task_state, msecs) \ -do { \ - set_current_state((task_state)); \ - schedule_timeout((msecs) * HZ / 1000); \ -} while (0) - -#define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs)) - -#define SCSI_LUN(srb) ((srb)->device->lun) - -/* Size of the DMA-mapped I/O buffer */ -#define RTS51X_IOBUF_SIZE 1024 -/* Size of the autosense data buffer */ -#define RTS51X_SENSE_SIZE 18 - -/* Dynamic bitflag definitions (dflags): used in set_bit() etc. */ -#define FLIDX_URB_ACTIVE 0 /* current_urb is in use */ -#define FLIDX_SG_ACTIVE 1 /* current_sg is in use */ -#define FLIDX_ABORTING 2 /* abort is in progress */ -#define FLIDX_DISCONNECTING 3 /* disconnect in progress */ -#define FLIDX_RESETTING 4 /* device reset in progress */ -#define FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */ -#define FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */ - -struct rts51x_chip; - -struct rts51x_usb { - /* The device we're working with - * It's important to note: - * (o) you must hold dev_mutex to change pusb_dev - */ - struct mutex dev_mutex; /* protect pusb_dev */ - struct usb_device *pusb_dev; /* this usb_device */ - struct usb_interface *pusb_intf; /* this interface */ - - unsigned long dflags; /* dynamic atomic bitflags */ - - unsigned int send_bulk_pipe; /* cached pipe values */ - unsigned int recv_bulk_pipe; - unsigned int send_ctrl_pipe; - unsigned int recv_ctrl_pipe; - unsigned int recv_intr_pipe; - - u8 ifnum; /* interface number */ - u8 ep_bInterval; /* interrupt interval */ - - /* control and bulk communications data */ - struct urb *current_urb; /* USB requests */ - struct urb *intr_urb; /* Interrupt USB request */ - struct usb_ctrlrequest *cr; /* control requests */ - struct usb_sg_request current_sg; /* scatter-gather req. */ - unsigned char *iobuf; /* I/O buffer */ - dma_addr_t cr_dma; /* buffer DMA addresses */ - dma_addr_t iobuf_dma; - struct task_struct *ctl_thread; /* the control thread */ - struct task_struct *polling_thread; /* the polling thread */ - - /* mutual exclusion and synchronization structures */ - struct completion cmnd_ready; /* to sleep thread on */ - struct completion control_exit; /* control thread exit */ - struct completion polling_exit; /* polling thread exit */ - struct completion notify; /* thread begin/end */ -#ifdef SCSI_SCAN_DELAY - wait_queue_head_t delay_wait; /* wait during scan, reset */ - struct completion scanning_done; /* wait for scan thread */ -#endif -}; - -extern struct usb_driver rts51x_driver; - -static inline void get_current_time(u8 *timeval_buf, int buf_len) -{ - struct timeval tv; - - if (!timeval_buf || (buf_len < 8)) - return; - - do_gettimeofday(&tv); - - timeval_buf[0] = (u8) (tv.tv_sec >> 24); - timeval_buf[1] = (u8) (tv.tv_sec >> 16); - timeval_buf[2] = (u8) (tv.tv_sec >> 8); - timeval_buf[3] = (u8) (tv.tv_sec); - timeval_buf[4] = (u8) (tv.tv_usec >> 24); - timeval_buf[5] = (u8) (tv.tv_usec >> 16); - timeval_buf[6] = (u8) (tv.tv_usec >> 8); - timeval_buf[7] = (u8) (tv.tv_usec); -} - -#define SND_CTRL_PIPE(chip) ((chip)->usb->send_ctrl_pipe) -#define RCV_CTRL_PIPE(chip) ((chip)->usb->recv_ctrl_pipe) -#define SND_BULK_PIPE(chip) ((chip)->usb->send_bulk_pipe) -#define RCV_BULK_PIPE(chip) ((chip)->usb->recv_bulk_pipe) -#define RCV_INTR_PIPE(chip) ((chip)->usb->recv_intr_pipe) - -/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the - * single queue element srb for write access */ -#define scsi_unlock(host) spin_unlock_irq(host->host_lock) -#define scsi_lock(host) spin_lock_irq(host->host_lock) - -#define GET_PM_USAGE_CNT(chip) \ - atomic_read(&((chip)->usb->pusb_intf->pm_usage_cnt)) -#define SET_PM_USAGE_CNT(chip, cnt) \ - atomic_set(&((chip)->usb->pusb_intf->pm_usage_cnt), (cnt)) - -/* Compatible macros while we switch over */ -static inline void *usb_buffer_alloc(struct usb_device *dev, size_t size, - gfp_t mem_flags, dma_addr_t *dma) -{ - return usb_alloc_coherent(dev, size, mem_flags, dma); -} - -static inline void usb_buffer_free(struct usb_device *dev, size_t size, - void *addr, dma_addr_t dma) -{ - return usb_free_coherent(dev, size, addr, dma); -} - -/* Convert between us_data and the corresponding Scsi_Host */ -static inline struct Scsi_Host *rts51x_to_host(struct rts51x_chip *chip) -{ - return container_of((void *)chip, struct Scsi_Host, hostdata); -} - -static inline struct rts51x_chip *host_to_rts51x(struct Scsi_Host *host) -{ - return (struct rts51x_chip *)(host->hostdata); -} - -/* struct scsi_cmnd transfer buffer access utilities */ -enum xfer_buf_dir { TO_XFER_BUF, FROM_XFER_BUF }; - -/* General routines provided by the usb-storage standard core */ -#ifdef CONFIG_PM -void rts51x_try_to_enter_ss(struct rts51x_chip *chip); -void rts51x_try_to_exit_ss(struct rts51x_chip *chip); -int rts51x_suspend(struct usb_interface *iface, pm_message_t message); -int rts51x_resume(struct usb_interface *iface); -int rts51x_reset_resume(struct usb_interface *iface); -#else -#define rts51x_suspend NULL -#define rts51x_resume NULL -#define rts51x_reset_resume NULL -#endif - -extern struct scsi_host_template rts51x_host_template; - -#endif /* __RTS51X_H */ diff --git a/trunk/drivers/staging/rts5139/rts51x_card.c b/trunk/drivers/staging/rts5139/rts51x_card.c deleted file mode 100644 index 424a84581b86..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_card.c +++ /dev/null @@ -1,986 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "debug.h" -#include "rts51x.h" -#include "rts51x_chip.h" -#include "rts51x_card.h" -#include "rts51x_transport.h" -#include "rts51x_sys.h" -#include "xd.h" -#include "sd.h" -#include "ms.h" - -void do_remaining_work(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - struct xd_info *xd_card = &(chip->xd_card); - struct ms_info *ms_card = &(chip->ms_card); - - if (chip->card_ready & SD_CARD) { - if (sd_card->seq_mode) { - RTS51X_SET_STAT(chip, STAT_RUN); - sd_card->counter++; - } else { - sd_card->counter = 0; - } - } - - if (chip->card_ready & XD_CARD) { - if (xd_card->delay_write.delay_write_flag) { - RTS51X_SET_STAT(chip, STAT_RUN); - xd_card->counter++; - } else { - xd_card->counter = 0; - } - } - - if (chip->card_ready & MS_CARD) { - if (CHK_MSPRO(ms_card)) { - if (ms_card->seq_mode) { - RTS51X_SET_STAT(chip, STAT_RUN); - ms_card->counter++; - } else { - ms_card->counter = 0; - } - } else { - if (ms_card->delay_write.delay_write_flag) { - RTS51X_SET_STAT(chip, STAT_RUN); - ms_card->counter++; - } else { - ms_card->counter = 0; - } - } - } - - if (sd_card->counter > POLLING_WAIT_CNT) - sd_cleanup_work(chip); - - if (xd_card->counter > POLLING_WAIT_CNT) - xd_cleanup_work(chip); - - if (ms_card->counter > POLLING_WAIT_CNT) - ms_cleanup_work(chip); -} - -void do_reset_xd_card(struct rts51x_chip *chip) -{ - int retval; - - if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT) - return; - - retval = reset_xd_card(chip); - if (retval == STATUS_SUCCESS) { - chip->card_ready |= XD_CARD; - chip->card_fail &= ~XD_CARD; - chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw; - } else { - chip->card_ready &= ~XD_CARD; - chip->card_fail |= XD_CARD; - chip->capacity[chip->card2lun[XD_CARD]] = 0; - chip->rw_card[chip->card2lun[XD_CARD]] = NULL; - - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, - POWER_OFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, XD_CLK_EN, 0); - rts51x_send_cmd(chip, MODE_C, 100); - } -} - -void do_reset_sd_card(struct rts51x_chip *chip) -{ - int retval; - - if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) - return; - - retval = reset_sd_card(chip); - if (retval == STATUS_SUCCESS) { - chip->card_ready |= SD_CARD; - chip->card_fail &= ~SD_CARD; - chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw; - } else { - chip->card_ready &= ~SD_CARD; - chip->card_fail |= SD_CARD; - chip->capacity[chip->card2lun[SD_CARD]] = 0; - chip->rw_card[chip->card2lun[SD_CARD]] = NULL; - - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, - POWER_OFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); - rts51x_send_cmd(chip, MODE_C, 100); - } -} - -void do_reset_ms_card(struct rts51x_chip *chip) -{ - int retval; - - if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) - return; - - retval = reset_ms_card(chip); - if (retval == STATUS_SUCCESS) { - chip->card_ready |= MS_CARD; - chip->card_fail &= ~MS_CARD; - chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw; - } else { - chip->card_ready &= ~MS_CARD; - chip->card_fail |= MS_CARD; - chip->capacity[chip->card2lun[MS_CARD]] = 0; - chip->rw_card[chip->card2lun[MS_CARD]] = NULL; - - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, - POWER_OFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0); - rts51x_send_cmd(chip, MODE_C, 100); - } -} - -void card_cd_debounce(struct rts51x_chip *chip, u8 *need_reset, - u8 *need_release) -{ - int retval; - u8 release_map = 0, reset_map = 0; - u8 value; - - retval = rts51x_get_card_status(chip, &(chip->card_status)); -#ifdef SUPPORT_OCP - chip->ocp_stat = (chip->card_status >> 4) & 0x03; -#endif - - if (retval != STATUS_SUCCESS) - goto Exit_Debounce; - - if (chip->card_exist) { - rts51x_clear_start_time(chip); - retval = rts51x_read_register(chip, CARD_INT_PEND, &value); - if (retval != STATUS_SUCCESS) { - rts51x_ep0_write_register(chip, MC_FIFO_CTL, FIFO_FLUSH, - FIFO_FLUSH); - rts51x_ep0_write_register(chip, SFSM_ED, 0xf8, 0xf8); - value = 0; - } - - if (chip->card_exist & XD_CARD) { - if (!(chip->card_status & XD_CD)) - release_map |= XD_CARD; - } else if (chip->card_exist & SD_CARD) { - /* if (!(chip->card_status & SD_CD)) { */ - if (!(chip->card_status & SD_CD) || (value & SD_INT)) - release_map |= SD_CARD; - } else if (chip->card_exist & MS_CARD) { - /* if (!(chip->card_status & MS_CD)) { */ - if (!(chip->card_status & MS_CD) || (value & MS_INT)) - release_map |= MS_CARD; - } - } else { - if (chip->card_status & XD_CD) { - rts51x_clear_start_time(chip); - reset_map |= XD_CARD; - } else if (chip->card_status & SD_CD) { - rts51x_clear_start_time(chip); - reset_map |= SD_CARD; - } else if (chip->card_status & MS_CD) { - rts51x_clear_start_time(chip); - reset_map |= MS_CARD; - } else { - if (rts51x_check_start_time(chip)) - rts51x_set_start_time(chip); - } - } - - if (CHECK_PKG(chip, QFN24) && reset_map) { - if (chip->card_exist & XD_CARD) { - reset_map = 0; - goto Exit_Debounce; - } - } - - if (reset_map) { - int xd_cnt = 0, sd_cnt = 0, ms_cnt = 0; - int i; - - for (i = 0; i < (chip->option.debounce_num); i++) { - retval = - rts51x_get_card_status(chip, &(chip->card_status)); - if (retval != STATUS_SUCCESS) { - reset_map = release_map = 0; - goto Exit_Debounce; - } - if (chip->card_status & XD_CD) - xd_cnt++; - else - xd_cnt = 0; - if (chip->card_status & SD_CD) - sd_cnt++; - else - sd_cnt = 0; - if (chip->card_status & MS_CD) - ms_cnt++; - else - ms_cnt = 0; - wait_timeout(30); - } - - reset_map = 0; - if (!(chip->card_exist & XD_CARD) - && (xd_cnt > (chip->option.debounce_num - 1))) { - reset_map |= XD_CARD; - } - if (!(chip->card_exist & SD_CARD) - && (sd_cnt > (chip->option.debounce_num - 1))) { - reset_map |= SD_CARD; - } - if (!(chip->card_exist & MS_CARD) - && (ms_cnt > (chip->option.debounce_num - 1))) { - reset_map |= MS_CARD; - } - } - rts51x_write_register(chip, CARD_INT_PEND, XD_INT | MS_INT | SD_INT, - XD_INT | MS_INT | SD_INT); - -Exit_Debounce: - if (need_reset) - *need_reset = reset_map; - if (need_release) - *need_release = release_map; -} - -void rts51x_init_cards(struct rts51x_chip *chip) -{ - u8 need_reset = 0, need_release = 0; - - card_cd_debounce(chip, &need_reset, &need_release); - - if (need_release) { - RTS51X_DEBUGP("need_release = 0x%x\n", need_release); - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - -#ifdef SUPPORT_OCP - if (chip->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) { - rts51x_write_register(chip, OCPCTL, MS_OCP_CLEAR, - MS_OCP_CLEAR); - chip->ocp_stat = 0; - RTS51X_DEBUGP("Clear OCP status.\n"); - } -#endif - - if (need_release & XD_CARD) { - chip->card_exist &= ~XD_CARD; - chip->card_ejected = 0; - if (chip->card_ready & XD_CARD) { - release_xd_card(chip); - chip->rw_card[chip->card2lun[XD_CARD]] = NULL; - clear_bit(chip->card2lun[XD_CARD], - &(chip->lun_mc)); - } - } - - if (need_release & SD_CARD) { - chip->card_exist &= ~SD_CARD; - chip->card_ejected = 0; - if (chip->card_ready & SD_CARD) { - release_sd_card(chip); - chip->rw_card[chip->card2lun[SD_CARD]] = NULL; - clear_bit(chip->card2lun[SD_CARD], - &(chip->lun_mc)); - } - } - - if (need_release & MS_CARD) { - chip->card_exist &= ~MS_CARD; - chip->card_ejected = 0; - if (chip->card_ready & MS_CARD) { - release_ms_card(chip); - chip->rw_card[chip->card2lun[MS_CARD]] = NULL; - clear_bit(chip->card2lun[MS_CARD], - &(chip->lun_mc)); - } - } - } - - if (need_reset && !chip->card_ready) { - RTS51X_DEBUGP("need_reset = 0x%x\n", need_reset); - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - if (need_reset & XD_CARD) { - chip->card_exist |= XD_CARD; - do_reset_xd_card(chip); - } else if (need_reset & SD_CARD) { - chip->card_exist |= SD_CARD; - do_reset_sd_card(chip); - } else if (need_reset & MS_CARD) { - chip->card_exist |= MS_CARD; - do_reset_ms_card(chip); - } - } -} - -void rts51x_release_cards(struct rts51x_chip *chip) -{ - if (chip->card_ready & SD_CARD) { - sd_cleanup_work(chip); - release_sd_card(chip); - chip->card_ready &= ~SD_CARD; - } - - if (chip->card_ready & XD_CARD) { - xd_cleanup_work(chip); - release_xd_card(chip); - chip->card_ready &= ~XD_CARD; - } - - if (chip->card_ready & MS_CARD) { - ms_cleanup_work(chip); - release_ms_card(chip); - chip->card_ready &= ~MS_CARD; - } -} - -static inline u8 double_depth(u8 depth) -{ - return ((depth > 1) ? (depth - 1) : depth); -} - -int switch_ssc_clock(struct rts51x_chip *chip, int clk) -{ - struct sd_info *sd_card = &(chip->sd_card); - struct ms_info *ms_card = &(chip->ms_card); - int retval; - u8 N = (u8) (clk - 2), min_N, max_N; - u8 mcu_cnt, div, max_div, ssc_depth; - int sd_vpclk_phase_reset = 0; - - if (chip->cur_clk == clk) - return STATUS_SUCCESS; - - min_N = 60; - max_N = 120; - max_div = CLK_DIV_4; - - RTS51X_DEBUGP("Switch SSC clock to %dMHz\n", clk); - - if ((clk <= 2) || (N > max_N)) - TRACE_RET(chip, STATUS_FAIL); - - mcu_cnt = (u8) (60 / clk + 3); - if (mcu_cnt > 15) - mcu_cnt = 15; - /* To make sure that the SSC clock div_n is - * equal or greater than min_N */ - div = CLK_DIV_1; - while ((N < min_N) && (div < max_div)) { - N = (N + 2) * 2 - 2; - div++; - } - RTS51X_DEBUGP("N = %d, div = %d\n", N, div); - - if (chip->option.ssc_en) { - if (chip->cur_card == SD_CARD) { - if (CHK_SD_SDR104(sd_card)) { - ssc_depth = chip->option.ssc_depth_sd_sdr104; - } else if (CHK_SD_SDR50(sd_card)) { - ssc_depth = chip->option.ssc_depth_sd_sdr50; - } else if (CHK_SD_DDR50(sd_card)) { - ssc_depth = - double_depth(chip->option. - ssc_depth_sd_ddr50); - } else if (CHK_SD_HS(sd_card)) { - ssc_depth = - double_depth(chip->option.ssc_depth_sd_hs); - } else if (CHK_MMC_52M(sd_card) - || CHK_MMC_DDR52(sd_card)) { - ssc_depth = - double_depth(chip->option. - ssc_depth_mmc_52m); - } else { - ssc_depth = - double_depth(chip->option. - ssc_depth_low_speed); - } - } else if (chip->cur_card == MS_CARD) { - if (CHK_MSPRO(ms_card)) { - if (CHK_HG8BIT(ms_card)) { - ssc_depth = - double_depth(chip->option. - ssc_depth_ms_hg); - } else { - ssc_depth = - double_depth(chip->option. - ssc_depth_ms_4bit); - } - } else { - if (CHK_MS4BIT(ms_card)) { - ssc_depth = - double_depth(chip->option. - ssc_depth_ms_4bit); - } else { - ssc_depth = - double_depth(chip->option. - ssc_depth_low_speed); - } - } - } else { - ssc_depth = - double_depth(chip->option.ssc_depth_low_speed); - } - - if (ssc_depth) { - if (div == CLK_DIV_2) { - /* If clock divided by 2, ssc depth must - * be multiplied by 2 */ - if (ssc_depth > 1) - ssc_depth -= 1; - else - ssc_depth = SSC_DEPTH_2M; - } else if (div == CLK_DIV_4) { - /* If clock divided by 4, ssc depth must - * be multiplied by 4 */ - if (ssc_depth > 2) - ssc_depth -= 2; - else - ssc_depth = SSC_DEPTH_2M; - } - } - } else { - /* Disable SSC */ - ssc_depth = 0; - } - - RTS51X_DEBUGP("ssc_depth = %d\n", ssc_depth); - - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE); - rts51x_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0x3F, - (div << 4) | mcu_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, SSC_DEPTH_MASK, - ssc_depth); - rts51x_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N); - if (sd_vpclk_phase_reset) { - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, - PHASE_NOT_RESET, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, - PHASE_NOT_RESET, PHASE_NOT_RESET); - } - - retval = rts51x_send_cmd(chip, MODE_C, 2000); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (chip->option.ssc_en && ssc_depth) - rts51x_write_register(chip, SSC_CTL1, 0xff, 0xD0); - else - rts51x_write_register(chip, SSC_CTL1, 0xff, 0x50); - udelay(100); - RTS51X_WRITE_REG(chip, CLK_DIV, CLK_CHANGE, 0); - - chip->cur_clk = clk; - - return STATUS_SUCCESS; -} - -int switch_normal_clock(struct rts51x_chip *chip, int clk) -{ - int retval; - u8 sel, div, mcu_cnt; - int sd_vpclk_phase_reset = 0; - - if (chip->cur_clk == clk) - return STATUS_SUCCESS; - - if (chip->cur_card == SD_CARD) { - struct sd_info *sd_card = &(chip->sd_card); - if (CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card)) - sd_vpclk_phase_reset = 1; - } - - switch (clk) { - case CLK_20: - RTS51X_DEBUGP("Switch clock to 20MHz\n"); - sel = SSC_80; - div = CLK_DIV_4; - mcu_cnt = 5; - break; - - case CLK_30: - RTS51X_DEBUGP("Switch clock to 30MHz\n"); - sel = SSC_60; - div = CLK_DIV_2; - mcu_cnt = 4; - break; - - case CLK_40: - RTS51X_DEBUGP("Switch clock to 40MHz\n"); - sel = SSC_80; - div = CLK_DIV_2; - mcu_cnt = 3; - break; - - case CLK_50: - RTS51X_DEBUGP("Switch clock to 50MHz\n"); - sel = SSC_100; - div = CLK_DIV_2; - mcu_cnt = 3; - break; - - case CLK_60: - RTS51X_DEBUGP("Switch clock to 60MHz\n"); - sel = SSC_60; - div = CLK_DIV_1; - mcu_cnt = 3; - break; - - case CLK_80: - RTS51X_DEBUGP("Switch clock to 80MHz\n"); - sel = SSC_80; - div = CLK_DIV_1; - mcu_cnt = 2; - break; - - case CLK_100: - RTS51X_DEBUGP("Switch clock to 100MHz\n"); - sel = SSC_100; - div = CLK_DIV_1; - mcu_cnt = 2; - break; - - /* case CLK_120: - RTS51X_DEBUGP("Switch clock to 120MHz\n"); - sel = SSC_120; - div = CLK_DIV_1; - mcu_cnt = 2; - break; - - case CLK_150: - RTS51X_DEBUGP("Switch clock to 150MHz\n"); - sel = SSC_150; - div = CLK_DIV_1; - mcu_cnt = 2; - break; */ - - default: - RTS51X_DEBUGP("Try to switch to an illegal clock (%d)\n", - clk); - TRACE_RET(chip, STATUS_FAIL); - } - - if (!sd_vpclk_phase_reset) { - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, - CLK_CHANGE); - rts51x_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0x3F, - (div << 4) | mcu_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, SSC_CLK_FPGA_SEL, 0xFF, - sel); - rts51x_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, 0); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, - CLK_CHANGE); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, - PHASE_NOT_RESET, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK1_CTL, - PHASE_NOT_RESET, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0x3F, - (div << 4) | mcu_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, SSC_CLK_FPGA_SEL, 0xFF, - sel); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - udelay(200); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, - PHASE_NOT_RESET, PHASE_NOT_RESET); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK1_CTL, - PHASE_NOT_RESET, PHASE_NOT_RESET); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - udelay(200); - - RTS51X_WRITE_REG(chip, CLK_DIV, CLK_CHANGE, 0); - } - - chip->cur_clk = clk; - - return STATUS_SUCCESS; -} - -int card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr, - u16 sec_cnt) -{ - int retval; - unsigned int lun = SCSI_LUN(srb); - int i; - - if (chip->rw_card[lun] == NULL) - return STATUS_FAIL; - - RTS51X_DEBUGP("%s card, sector addr: 0x%x, sector cnt: %d\n", - (srb->sc_data_direction == - DMA_TO_DEVICE) ? "Write" : "Read", sec_addr, sec_cnt); - - chip->rw_need_retry = 0; - for (i = 0; i < 3; i++) { - retval = chip->rw_card[lun] (srb, chip, sec_addr, sec_cnt); - if (retval != STATUS_SUCCESS) { - CATCH_TRIGGER(chip); - if (chip->option.reset_or_rw_fail_set_pad_drive) { - rts51x_write_register(chip, CARD_DRIVE_SEL, - SD20_DRIVE_MASK, - DRIVE_8mA); - } - } - - if (!chip->rw_need_retry) - break; - - RTS51X_DEBUGP("Retry RW, (i = %d\n)", i); - } - - return retval; -} - -u8 get_lun_card(struct rts51x_chip *chip, unsigned int lun) -{ - if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) - return (u8) XD_CARD; - else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) - return (u8) SD_CARD; - else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) - return (u8) MS_CARD; - - return 0; -} - -int card_share_mode(struct rts51x_chip *chip, int card) -{ - u8 value; - - if (card == SD_CARD) - value = CARD_SHARE_SD; - else if (card == MS_CARD) - value = CARD_SHARE_MS; - else if (card == XD_CARD) - value = CARD_SHARE_XD; - else - TRACE_RET(chip, STATUS_FAIL); - - RTS51X_WRITE_REG(chip, CARD_SHARE_MODE, CARD_SHARE_MASK, value); - - return STATUS_SUCCESS; -} - -int rts51x_select_card(struct rts51x_chip *chip, int card) -{ - int retval; - - if (chip->cur_card != card) { - u8 mod; - - if (card == SD_CARD) - mod = SD_MOD_SEL; - else if (card == MS_CARD) - mod = MS_MOD_SEL; - else if (card == XD_CARD) - mod = XD_MOD_SEL; - else - TRACE_RET(chip, STATUS_FAIL); - RTS51X_WRITE_REG(chip, CARD_SELECT, 0x07, mod); - chip->cur_card = card; - - retval = card_share_mode(chip, card); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -void eject_card(struct rts51x_chip *chip, unsigned int lun) -{ - RTS51X_DEBUGP("eject card\n"); - RTS51X_SET_STAT(chip, STAT_RUN); - do_remaining_work(chip); - - if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) { - release_sd_card(chip); - chip->card_ejected |= SD_CARD; - chip->card_ready &= ~SD_CARD; - chip->capacity[lun] = 0; - } else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) { - release_xd_card(chip); - chip->card_ejected |= XD_CARD; - chip->card_ready &= ~XD_CARD; - chip->capacity[lun] = 0; - } else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) { - release_ms_card(chip); - chip->card_ejected |= MS_CARD; - chip->card_ready &= ~MS_CARD; - chip->capacity[lun] = 0; - } - rts51x_write_register(chip, CARD_INT_PEND, XD_INT | MS_INT | SD_INT, - XD_INT | MS_INT | SD_INT); -} - -void trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip, - u32 byte_cnt, u8 pack_size) -{ - if (pack_size > DMA_1024) - pack_size = DMA_512; - - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - RING_BUFFER); - - rts51x_add_cmd(chip, WRITE_REG_CMD, MC_DMA_TC3, 0xFF, - (u8) (byte_cnt >> 24)); - rts51x_add_cmd(chip, WRITE_REG_CMD, MC_DMA_TC2, 0xFF, - (u8) (byte_cnt >> 16)); - rts51x_add_cmd(chip, WRITE_REG_CMD, MC_DMA_TC1, 0xFF, - (u8) (byte_cnt >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, MC_DMA_TC0, 0xFF, (u8) byte_cnt); - - if (dir == DMA_FROM_DEVICE) { - rts51x_add_cmd(chip, WRITE_REG_CMD, MC_DMA_CTL, - 0x03 | DMA_PACK_SIZE_MASK, - DMA_DIR_FROM_CARD | DMA_EN | pack_size); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, MC_DMA_CTL, - 0x03 | DMA_PACK_SIZE_MASK, - DMA_DIR_TO_CARD | DMA_EN | pack_size); - } -} - -int enable_card_clock(struct rts51x_chip *chip, u8 card) -{ - u8 clk_en = 0; - - if (card & XD_CARD) - clk_en |= XD_CLK_EN; - if (card & SD_CARD) - clk_en |= SD_CLK_EN; - if (card & MS_CARD) - clk_en |= MS_CLK_EN; - - RTS51X_WRITE_REG(chip, CARD_CLK_EN, clk_en, clk_en); - - return STATUS_SUCCESS; -} - -int disable_card_clock(struct rts51x_chip *chip, u8 card) -{ - u8 clk_en = 0; - - if (card & XD_CARD) - clk_en |= XD_CLK_EN; - if (card & SD_CARD) - clk_en |= SD_CLK_EN; - if (card & MS_CARD) - clk_en |= MS_CLK_EN; - - RTS51X_WRITE_REG(chip, CARD_CLK_EN, clk_en, 0); - - return STATUS_SUCCESS; -} - -int card_power_on(struct rts51x_chip *chip, u8 card) -{ - u8 mask, val1, val2; - - mask = POWER_MASK; - val1 = PARTIAL_POWER_ON; - val2 = POWER_ON; - -#ifdef SD_XD_IO_FOLLOW_PWR - if ((card == SD_CARD) || (card == XD_CARD)) { - RTS51X_WRITE_REG(chip, CARD_PWR_CTL, mask | LDO3318_PWR_MASK, - val1 | LDO_SUSPEND); - /* RTS51X_WRITE_REG(chip, CARD_PWR_CTL, - LDO3318_PWR_MASK, LDO_SUSPEND); */ - } - /* else if(card==XD_CARD) - { - RTS51X_WRITE_REG(chip, CARD_PWR_CTL, - mask|LDO3318_PWR_MASK, val1|LDO_SUSPEND); - //RTS51X_WRITE_REG(chip, CARD_PWR_CTL, - // LDO3318_PWR_MASK, LDO_SUSPEND); - } */ - else { -#endif - RTS51X_WRITE_REG(chip, CARD_PWR_CTL, mask, val1); -#ifdef SD_XD_IO_FOLLOW_PWR - } -#endif - udelay(chip->option.pwr_delay); - RTS51X_WRITE_REG(chip, CARD_PWR_CTL, mask, val2); -#ifdef SD_XD_IO_FOLLOW_PWR - if (card == SD_CARD) { - rts51x_write_register(chip, CARD_PWR_CTL, LDO3318_PWR_MASK, - LDO_ON); - } -#endif - - return STATUS_SUCCESS; -} - -int card_power_off(struct rts51x_chip *chip, u8 card) -{ - u8 mask, val; - - mask = POWER_MASK; - val = POWER_OFF; - RTS51X_WRITE_REG(chip, CARD_PWR_CTL, mask, val); - - return STATUS_SUCCESS; -} - -int monitor_card_cd(struct rts51x_chip *chip, u8 card) -{ - int retval; - u8 card_cd[32] = { 0 }; - - card_cd[SD_CARD] = SD_CD; - card_cd[XD_CARD] = XD_CD; - card_cd[MS_CARD] = MS_CD; - - retval = rts51x_get_card_status(chip, &(chip->card_status)); - if (retval != STATUS_SUCCESS) - return CD_NOT_EXIST; - - if (chip->card_status & card_cd[card]) - return CD_EXIST; - - return CD_NOT_EXIST; -} - -int toggle_gpio(struct rts51x_chip *chip, u8 gpio) -{ - int retval; - u8 temp_reg; - u8 gpio_output[4] = { - 0x01, - }; - u8 gpio_oe[4] = { - 0x02, - }; - if (chip->rts5179) { - retval = rts51x_ep0_read_register(chip, CARD_GPIO, &temp_reg); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - temp_reg ^= gpio_oe[gpio]; - temp_reg &= 0xfe; /* bit 0 always set 0 */ - retval = - rts51x_ep0_write_register(chip, CARD_GPIO, 0x03, temp_reg); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } else { - retval = rts51x_ep0_read_register(chip, CARD_GPIO, &temp_reg); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - temp_reg ^= gpio_output[gpio]; - retval = - rts51x_ep0_write_register(chip, CARD_GPIO, 0xFF, - temp_reg | gpio_oe[gpio]); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -int turn_on_led(struct rts51x_chip *chip, u8 gpio) -{ - int retval; - u8 gpio_oe[4] = { - 0x02, - }; - u8 gpio_mask[4] = { - 0x03, - }; - - retval = - rts51x_ep0_write_register(chip, CARD_GPIO, gpio_mask[gpio], - gpio_oe[gpio]); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -int turn_off_led(struct rts51x_chip *chip, u8 gpio) -{ - int retval; - u8 gpio_output[4] = { - 0x01, - }; - u8 gpio_oe[4] = { - 0x02, - }; - u8 gpio_mask[4] = { - 0x03, - }; - - retval = - rts51x_ep0_write_register(chip, CARD_GPIO, gpio_mask[gpio], - gpio_oe[gpio] | gpio_output[gpio]); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} diff --git a/trunk/drivers/staging/rts5139/rts51x_card.h b/trunk/drivers/staging/rts5139/rts51x_card.h deleted file mode 100644 index ac3c1e741ab9..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_card.h +++ /dev/null @@ -1,881 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_CARD_H -#define __RTS51X_CARD_H - -#include "rts51x_chip.h" - -/* Register bit definition */ - -/* Card Power Control Register */ -#define POWER_OFF 0x03 -#define PARTIAL_POWER_ON 0x02 -#define POWER_ON 0x00 -#define POWER_MASK 0x03 -#define LDO3318_PWR_MASK 0x0C -#define LDO_ON 0x00 -#define LDO_SUSPEND 0x08 -#define LDO_OFF 0x0C -#define DV3318_AUTO_PWR_OFF 0x10 -#define FORCE_LDO_POWERB 0x60 - -/* Card Output Enable Register */ -#define XD_OUTPUT_EN 0x02 -#define SD_OUTPUT_EN 0x04 -#define MS_OUTPUT_EN 0x08 - -/* System Clock Control Register */ - -/* System Clock Divider Register */ -#define CLK_CHANGE 0x80 -#define CLK_DIV_1 0x00 -#define CLK_DIV_2 0x01 -#define CLK_DIV_4 0x02 -#define CLK_DIV_8 0x03 - -/* System Clock Select Register */ -#define SSC_60 0 -#define SSC_80 1 -#define SSC_100 2 -#define SSC_120 3 -#define SSC_150 4 - -/* Card Clock Enable Register */ -#define XD_CLK_EN 0x02 -#define SD_CLK_EN 0x04 -#define MS_CLK_EN 0x08 - -/* Card Select Register */ -#define XD_MOD_SEL 1 -#define SD_MOD_SEL 2 -#define MS_MOD_SEL 3 - -/* Card Transfer Reset Register */ -#define XD_STOP 0x02 -#define SD_STOP 0x04 -#define MS_STOP 0x08 -#define XD_CLR_ERR 0x20 -#define SD_CLR_ERR 0x40 -#define MS_CLR_ERR 0x80 - -/* SD30_drive_sel */ -#define SD30_DRIVE_MASK 0x07 - -/* CARD_DRIVE_SEL */ -#define SD20_DRIVE_MASK 0x03 -#define DRIVE_4mA 0x00 -#define DRIVE_8mA 0x01 -#define DRIVE_12mA 0x02 - -/* FPGA_PULL_CTL */ -#define FPGA_MS_PULL_CTL_EN 0xEF -#define FPGA_SD_PULL_CTL_EN 0xF7 -#define FPGA_XD_PULL_CTL_EN1 0xFE -#define FPGA_XD_PULL_CTL_EN2 0xFD -#define FPGA_XD_PULL_CTL_EN3 0xFB - -#define FPGA_MS_PULL_CTL_BIT 0x10 -#define FPGA_SD_PULL_CTL_BIT 0x08 - -/* Card Data Source Register */ -#define PINGPONG_BUFFER 0x01 -#define RING_BUFFER 0x00 - -/* SFSM_ED */ -#define HW_CMD_STOP 0x80 -#define CLR_STAGE_STALL 0x08 -#define CARD_ERR 0x10 - -/* CARD_SHARE_MODE */ -#define CARD_SHARE_LQFP48 0x04 -#define CARD_SHARE_QFN24 0x00 -#define CARD_SHARE_LQFP_SEL 0x04 -#define CARD_SHARE_XD 0x00 -#define CARD_SHARE_SD 0x01 -#define CARD_SHARE_MS 0x02 -#define CARD_SHARE_MASK 0x03 - -/* CARD_AUTO_BLINK */ -#define BLINK_ENABLE 0x08 -#define BLINK_SPEED_MASK 0x07 - -/* CARD_GPIO */ -#define GPIO_OE 0x02 -#define GPIO_OUTPUT 0x01 - -/* CARD_CLK_SOURCE */ -#define CRC_FIX_CLK (0x00 << 0) -#define CRC_VAR_CLK0 (0x01 << 0) -#define CRC_VAR_CLK1 (0x02 << 0) -#define SD30_FIX_CLK (0x00 << 2) -#define SD30_VAR_CLK0 (0x01 << 2) -#define SD30_VAR_CLK1 (0x02 << 2) -#define SAMPLE_FIX_CLK (0x00 << 4) -#define SAMPLE_VAR_CLK0 (0x01 << 4) -#define SAMPLE_VAR_CLK1 (0x02 << 4) - -/* DCM_DRP_CTL */ -#define DCM_RESET 0x08 -#define DCM_LOCKED 0x04 -#define DCM_208M 0x00 -#define DCM_TX 0x01 -#define DCM_RX 0x02 - -/* DCM_DRP_TRIG */ -#define DRP_START 0x80 -#define DRP_DONE 0x40 - -/* DCM_DRP_CFG */ -#define DRP_WRITE 0x80 -#define DRP_READ 0x00 -#define DCM_WRITE_ADDRESS_50 0x50 -#define DCM_WRITE_ADDRESS_51 0x51 -#define DCM_READ_ADDRESS_00 0x00 -#define DCM_READ_ADDRESS_51 0x51 - -/* HW_VERSION */ -#define FPGA_VER 0x80 -#define HW_VER_MASK 0x0F - -/* CD_DEGLITCH_EN */ -#define DISABLE_SD_CD 0x08 -#define DISABLE_MS_CD 0x10 -#define DISABLE_XD_CD 0x20 -#define SD_CD_DEGLITCH_EN 0x01 -#define MS_CD_DEGLITCH_EN 0x02 -#define XD_CD_DEGLITCH_EN 0x04 - -/* OCPCTL */ -#define CARD_OC_DETECT_EN 0x08 -#define CARD_OC_CLR 0x01 - -/* CARD_DMA1_CTL */ -#define EXTEND_DMA1_ASYNC_SIGNAL 0x02 - -/* HS_USB_STAT */ -#define USB_HI_SPEED 0x01 - -/* CFG_MODE_1 */ -#define RTS5179 0x02 - -/* SYS_DUMMY0 */ -#define NYET_EN 0x01 -#define NYET_MSAK 0x01 - -/* SSC_CTL1 */ -#define SSC_RSTB 0x80 -#define SSC_8X_EN 0x40 -#define SSC_FIX_FRAC 0x20 -#define SSC_SEL_1M 0x00 -#define SSC_SEL_2M 0x08 -#define SSC_SEL_4M 0x10 -#define SSC_SEL_8M 0x18 - -/* SSC_CTL2 */ -#define SSC_DEPTH_MASK 0x03 -#define SSC_DEPTH_DISALBE 0x00 -#define SSC_DEPTH_2M 0x01 -#define SSC_DEPTH_1M 0x02 -#define SSC_DEPTH_512K 0x03 - -/* LDO_POWER_CFG */ -#define TUNE_SD18_MASK 0x1C -#define TUNE_SD18_1V7 0x00 -#define TUNE_SD18_1V8 (0x01 << 2) -#define TUNE_SD18_1V9 (0x02 << 2) -#define TUNE_SD18_2V0 (0x03 << 2) -#define TUNE_SD18_2V7 (0x04 << 2) -#define TUNE_SD18_2V8 (0x05 << 2) -#define TUNE_SD18_2V9 (0x06 << 2) -#define TUNE_SD18_3V3 (0x07 << 2) - -/* XD_CP_WAITTIME */ -#define WAIT_1F 0x00 -#define WAIT_3F 0x01 -#define WAIT_7F 0x02 -#define WAIT_FF 0x03 - -/* XD_INIT */ -#define XD_PWR_OFF_DELAY0 0x00 -#define XD_PWR_OFF_DELAY1 0x02 -#define XD_PWR_OFF_DELAY2 0x04 -#define XD_PWR_OFF_DELAY3 0x06 -#define XD_AUTO_PWR_OFF_EN 0xF7 -#define XD_NO_AUTO_PWR_OFF 0x08 - -/* XD_DTCTL */ -/* XD_CATCTL */ -#define XD_TIME_RWN_1 0x00 -#define XD_TIME_RWN_STEP 0x20 -#define XD_TIME_RW_1 0x00 -#define XD_TIME_RW_STEP 0x04 -#define XD_TIME_SETUP_1 0x00 -#define XD_TIME_SETUP_STEP 0x01 - -/* XD_CTL */ -#define XD_ECC2_UNCORRECTABLE 0x80 -#define XD_ECC2_ERROR 0x40 -#define XD_ECC1_UNCORRECTABLE 0x20 -#define XD_ECC1_ERROR 0x10 -#define XD_RDY 0x04 -#define XD_CE_EN 0xFD -#define XD_CE_DISEN 0x02 -#define XD_WP_EN 0xFE -#define XD_WP_DISEN 0x01 - -/* XD_TRANSFER */ -#define XD_TRANSFER_START 0x80 -#define XD_TRANSFER_END 0x40 -#define XD_PPB_EMPTY 0x20 -#define XD_ERR 0x10 -#define XD_RESET 0x00 -#define XD_ERASE 0x01 -#define XD_READ_STATUS 0x02 -#define XD_READ_ID 0x03 -#define XD_READ_REDUNDANT 0x04 -#define XD_READ_PAGES 0x05 -#define XD_SET_CMD 0x06 -#define XD_NORMAL_READ 0x07 -#define XD_WRITE_PAGES 0x08 -#define XD_NORMAL_WRITE 0x09 -#define XD_WRITE_REDUNDANT 0x0A -#define XD_SET_ADDR 0x0B -#define XD_COPY_PAGES 0x0C - -/* XD_CFG */ -#define XD_PPB_TO_SIE 0x80 -#define XD_TO_PPB_ONLY 0x00 -#define XD_BA_TRANSFORM 0x40 -#define XD_BA_NO_TRANSFORM 0x00 -#define XD_NO_CALC_ECC 0x20 -#define XD_CALC_ECC 0x00 -#define XD_IGNORE_ECC 0x10 -#define XD_CHECK_ECC 0x00 -#define XD_DIRECT_TO_RB 0x08 -#define XD_ADDR_MASK 0x07 -#define XD_ADDR_LENGTH_0 0x00 -#define XD_ADDR_LENGTH_1 0x01 -#define XD_ADDR_LENGTH_2 0x02 -#define XD_ADDR_LENGTH_3 0x03 -#define XD_ADDR_LENGTH_4 0x04 - -/* XD_PAGE_STATUS */ -#define XD_GPG 0xFF -#define XD_BPG 0x00 - -/* XD_BLOCK_STATUS */ -#define XD_GBLK 0xFF -#define XD_LATER_BBLK 0xF0 - -/* XD_PARITY */ -#define XD_ECC2_ALL1 0x80 -#define XD_ECC1_ALL1 0x40 -#define XD_BA2_ALL0 0x20 -#define XD_BA1_ALL0 0x10 -#define XD_BA1_BA2_EQL 0x04 -#define XD_BA2_VALID 0x02 -#define XD_BA1_VALID 0x01 - -/* XD_CHK_DATA_STATUS */ -#define XD_PGSTS_ZEROBIT_OVER4 0x00 -#define XD_PGSTS_NOT_FF 0x02 -#define XD_AUTO_CHK_DATA_STATUS 0x01 - -/* SD_CFG1 */ -#define SD_CLK_DIVIDE_0 0x00 -#define SD_CLK_DIVIDE_256 0xC0 -#define SD_CLK_DIVIDE_128 0x80 -#define SD_CLK_DIVIDE_MASK 0xC0 -#define SD_BUS_WIDTH_1 0x00 -#define SD_BUS_WIDTH_4 0x01 -#define SD_BUS_WIDTH_8 0x02 -#define SD_ASYNC_FIFO_RST 0x10 -#define SD_20_MODE 0x00 -#define SD_DDR_MODE 0x04 -#define SD_30_MODE 0x08 - -/* SD_CFG2 */ -#define SD_CALCULATE_CRC7 0x00 -#define SD_NO_CALCULATE_CRC7 0x80 -#define SD_CHECK_CRC16 0x00 -#define SD_NO_CHECK_CRC16 0x40 -#define SD_WAIT_CRC_TO_EN 0x20 -#define SD_WAIT_BUSY_END 0x08 -#define SD_NO_WAIT_BUSY_END 0x00 -#define SD_CHECK_CRC7 0x00 -#define SD_NO_CHECK_CRC7 0x04 -#define SD_RSP_LEN_0 0x00 -#define SD_RSP_LEN_6 0x01 -#define SD_RSP_LEN_17 0x02 -/* SD/MMC Response Type Definition */ -/* SD_CALCULATE_CRC7, SD_CHECK_CRC16, - * SD_NO_WAIT_BUSY_END, SD_NO_CHECK_CRC7, - * SD_RSP_LEN_0 */ -#define SD_RSP_TYPE_R0 0x04 -/* SD_CALCULATE_CRC7, SD_CHECK_CRC16, - * SD_NO_WAIT_BUSY_END, SD_CHECK_CRC7, - * SD_RSP_LEN_6 */ -#define SD_RSP_TYPE_R1 0x01 -/* SD_CALCULATE_CRC7, SD_CHECK_CRC16, - * SD_WAIT_BUSY_END, SD_CHECK_CRC7, - * SD_RSP_LEN_6 */ -#define SD_RSP_TYPE_R1b 0x09 -/* SD_CALCULATE_CRC7, SD_CHECK_CRC16, - * SD_NO_WAIT_BUSY_END, SD_CHECK_CRC7, - * SD_RSP_LEN_17 */ -#define SD_RSP_TYPE_R2 0x02 -/* SD_CALCULATE_CRC7, SD_CHECK_CRC16, - * SD_NO_WAIT_BUSY_END, SD_NO_CHECK_CRC7, - * SD_RSP_LEN_6 */ -#define SD_RSP_TYPE_R3 0x05 -/* SD_CALCULATE_CRC7, SD_CHECK_CRC16, - * SD_NO_WAIT_BUSY_END, SD_NO_CHECK_CRC7, - * SD_RSP_LEN_6 */ -#define SD_RSP_TYPE_R4 0x05 -/* SD_CALCULATE_CRC7, SD_CHECK_CRC16, - * SD_NO_WAIT_BUSY_END, SD_CHECK_CRC7, - * SD_RSP_LEN_6 */ -#define SD_RSP_TYPE_R5 0x01 -/* SD_CALCULATE_CRC7, SD_CHECK_CRC16, - * SD_NO_WAIT_BUSY_END, SD_CHECK_CRC7, - * SD_RSP_LEN_6 */ -#define SD_RSP_TYPE_R6 0x01 -/* SD_CALCULATE_CRC7, SD_CHECK_CRC16, - * SD_NO_WAIT_BUSY_END, SD_CHECK_CRC7, - * SD_RSP_LEN_6 */ -#define SD_RSP_TYPE_R7 0x01 - -/* SD_CFG3 */ -#define SD_RSP_80CLK_TIMEOUT_EN 0x01 - -/* SD_STAT1 */ -#define SD_CRC7_ERR 0x80 -#define SD_CRC16_ERR 0x40 -#define SD_CRC_WRITE_ERR 0x20 -#define SD_CRC_WRITE_ERR_MASK 0x1C -#define GET_CRC_TIME_OUT 0x02 -#define SD_TUNING_COMPARE_ERR 0x01 - -/* SD_STAT2 */ -#define SD_RSP_80CLK_TIMEOUT 0x01 - -/* SD_BUS_STAT */ -#define SD_CLK_TOGGLE_EN 0x80 -#define SD_CLK_FORCE_STOP 0x40 -#define SD_DAT3_STATUS 0x10 -#define SD_DAT2_STATUS 0x08 -#define SD_DAT1_STATUS 0x04 -#define SD_DAT0_STATUS 0x02 -#define SD_CMD_STATUS 0x01 - -/* SD_PAD_CTL */ -#define SD_IO_USING_1V8 0x80 -#define SD_IO_USING_3V3 0x7F -#define TYPE_A_DRIVING 0x00 -#define TYPE_B_DRIVING 0x01 -#define TYPE_C_DRIVING 0x02 -#define TYPE_D_DRIVING 0x03 - -/* SD_SAMPLE_POINT_CTL */ -#define DDR_FIX_RX_DAT 0x00 -#define DDR_VAR_RX_DAT 0x80 -#define DDR_FIX_RX_DAT_EDGE 0x00 -#define DDR_FIX_RX_DAT_14_DELAY 0x40 -#define DDR_FIX_RX_CMD 0x00 -#define DDR_VAR_RX_CMD 0x20 -#define DDR_FIX_RX_CMD_POS_EDGE 0x00 -#define DDR_FIX_RX_CMD_14_DELAY 0x10 -#define SD20_RX_POS_EDGE 0x00 -#define SD20_RX_14_DELAY 0x08 -#define SD20_RX_SEL_MASK 0x08 - -/* SD_PUSH_POINT_CTL */ -#define DDR_FIX_TX_CMD_DAT 0x00 -#define DDR_VAR_TX_CMD_DAT 0x80 -#define DDR_FIX_TX_DAT_14_TSU 0x00 -#define DDR_FIX_TX_DAT_12_TSU 0x40 -#define DDR_FIX_TX_CMD_NEG_EDGE 0x00 -#define DDR_FIX_TX_CMD_14_AHEAD 0x20 -#define SD20_TX_NEG_EDGE 0x00 -#define SD20_TX_14_AHEAD 0x10 -#define SD20_TX_SEL_MASK 0x10 -#define DDR_VAR_SDCLK_POL_SWAP 0x01 - -/* SD_TRANSFER */ -#define SD_TRANSFER_START 0x80 -#define SD_TRANSFER_END 0x40 -#define SD_STAT_IDLE 0x20 -#define SD_TRANSFER_ERR 0x10 -/* SD Transfer Mode definition */ -#define SD_TM_NORMAL_WRITE 0x00 -#define SD_TM_AUTO_WRITE_3 0x01 -#define SD_TM_AUTO_WRITE_4 0x02 -#define SD_TM_AUTO_READ_3 0x05 -#define SD_TM_AUTO_READ_4 0x06 -#define SD_TM_CMD_RSP 0x08 -#define SD_TM_AUTO_WRITE_1 0x09 -#define SD_TM_AUTO_WRITE_2 0x0A -#define SD_TM_NORMAL_READ 0x0C -#define SD_TM_AUTO_READ_1 0x0D -#define SD_TM_AUTO_READ_2 0x0E -#define SD_TM_AUTO_TUNING 0x0F - -/* SD_VPTX_CTL / SD_VPRX_CTL */ -#define PHASE_CHANGE 0x80 -#define PHASE_NOT_RESET 0x40 - -/* SD_DCMPS_TX_CTL / SD_DCMPS_RX_CTL */ -#define DCMPS_CHANGE 0x80 -#define DCMPS_CHANGE_DONE 0x40 -#define DCMPS_ERROR 0x20 -#define DCMPS_CURRENT_PHASE 0x1F - -/* SD_CMD_STATE */ -#define SD_CMD_IDLE 0x80 - -/* SD_DATA_STATE */ -#define SD_DATA_IDLE 0x80 - -/* MS_BLKEND */ -#define SET_BLKEND 0x01 - -/* MS_CFG */ -#define SAMPLE_TIME_RISING 0x00 -#define SAMPLE_TIME_FALLING 0x80 -#define PUSH_TIME_DEFAULT 0x00 -#define PUSH_TIME_ODD 0x40 -#define NO_EXTEND_TOGGLE 0x00 -#define EXTEND_TOGGLE_CHK 0x20 -#define MS_BUS_WIDTH_1 0x00 -#define MS_BUS_WIDTH_4 0x10 -#define MS_BUS_WIDTH_8 0x18 -#define MS_2K_SECTOR_MODE 0x04 -#define MS_512_SECTOR_MODE 0x00 -#define MS_TOGGLE_TIMEOUT_EN 0x00 -#define MS_TOGGLE_TIMEOUT_DISEN 0x01 -#define MS_NO_CHECK_INT 0x02 - -/* MS_TRANS_CFG */ -#define WAIT_INT 0x80 -#define NO_WAIT_INT 0x00 -#define NO_AUTO_READ_INT_REG 0x00 -#define AUTO_READ_INT_REG 0x40 -#define MS_CRC16_ERR 0x20 -#define MS_RDY_TIMEOUT 0x10 -#define MS_INT_CMDNK 0x08 -#define MS_INT_BREQ 0x04 -#define MS_INT_ERR 0x02 -#define MS_INT_CED 0x01 - -/* MS_TRANSFER */ -#define MS_TRANSFER_START 0x80 -#define MS_TRANSFER_END 0x40 -#define MS_TRANSFER_ERR 0x20 -#define MS_BS_STATE 0x10 -#define MS_TM_READ_BYTES 0x00 -#define MS_TM_NORMAL_READ 0x01 -#define MS_TM_WRITE_BYTES 0x04 -#define MS_TM_NORMAL_WRITE 0x05 -#define MS_TM_AUTO_READ 0x08 -#define MS_TM_AUTO_WRITE 0x0C -#define MS_TM_SET_CMD 0x06 -#define MS_TM_COPY_PAGE 0x07 -#define MS_TM_MULTI_READ 0x02 -#define MS_TM_MULTI_WRITE 0x03 - -/* MC_DMA_CTL */ -#define DMA_TC_EQ_0 0x80 -#define DMA_DIR_TO_CARD 0x00 -#define DMA_DIR_FROM_CARD 0x02 -#define DMA_EN 0x01 -#define DMA_128 (0 << 2) -#define DMA_256 (1 << 2) -#define DMA_512 (2 << 2) -#define DMA_1024 (3 << 2) -#define DMA_PACK_SIZE_MASK 0x0C - -/* CARD_INT_PEND */ -#define XD_INT 0x10 -#define MS_INT 0x08 -#define SD_INT 0x04 - -/* MC_FIFO_CTL */ -#define FIFO_FLUSH 0x01 - -/* AUTO_DELINK_EN */ -#define AUTO_DELINK 0x02 -#define FORCE_DELINK 0x01 - -/* MC_DMA_RST */ -#define DMA_RESET 0x01 - -#define SSC_POWER_MASK 0x01 -#define SSC_POWER_DOWN 0x01 -#define SSC_POWER_ON 0x00 - -/* OCPCTL */ -#define MS_OCP_DETECT_EN 0x08 -#define MS_OCP_INT_EN 0x04 -#define MS_OCP_INT_CLR 0x02 -#define MS_OCP_CLEAR 0x01 - -/* OCPSTAT */ -#define MS_OCP_DETECT 0x80 -#define MS_OCP_NOW 0x02 -#define MS_OCP_EVER 0x01 - -/* MC_FIFO_STAT */ -#define FIFO_FULL 0x01 -#define FIFO_EMPTY 0x02 - -/* RCCTL */ -#define U_HW_CMD_EN_MASK 0x02 -#define U_HW_CMD_EN 0x02 -#define U_HW_CMD_DIS 0x00 - -/* Register address */ -#define FPDCTL 0xFC00 -#define SSC_DIV_N_0 0xFC07 -#define SSC_CTL1 0xFC09 -#define SSC_CTL2 0xFC0A -#define CFG_MODE_1 0xFC0F -#define RCCTL 0xFC14 -#define SYS_DUMMY0 0xFC30 -#define XD_CP_WAITTIME 0xFD00 -#define XD_CP_PAGELEN 0xFD01 -#define XD_CP_READADDR0 0xFD02 -#define XD_CP_READADDR1 0xFD03 -#define XD_CP_READADDR2 0xFD04 -#define XD_CP_READADDR3 0xFD05 -#define XD_CP_READADDR4 0xFD06 -#define XD_CP_WRITEADDR0 0xFD07 -#define XD_CP_WRITEADDR1 0xFD08 -#define XD_CP_WRITEADDR2 0xFD09 -#define XD_CP_WRITEADDR3 0xFD0A -#define XD_CP_WRITEADDR4 0xFD0B -#define XD_INIT 0xFD10 -#define XD_DTCTL 0xFD11 -#define XD_CTL 0xFD12 -#define XD_TRANSFER 0xFD13 -#define XD_CFG 0xFD14 -#define XD_ADDRESS0 0xFD15 -#define XD_ADDRESS1 0xFD16 -#define XD_ADDRESS2 0xFD17 -#define XD_ADDRESS3 0xFD18 -#define XD_ADDRESS4 0xFD19 -#define XD_DAT 0xFD1A -#define XD_PAGE_CNT 0xFD1B -#define XD_PAGE_STATUS 0xFD1C -#define XD_BLOCK_STATUS 0xFD1D -#define XD_BLOCK_ADDR1_L 0xFD1E -#define XD_BLOCK_ADDR1_H 0xFD1F -#define XD_BLOCK_ADDR2_L 0xFD20 -#define XD_BLOCK_ADDR2_H 0xFD21 -#define XD_BYTE_CNT_L 0xFD22 -#define XD_BYTE_CNT_H 0xFD23 -#define XD_PARITY 0xFD24 -#define XD_ECC_BIT1 0xFD25 -#define XD_ECC_BYTE1 0xFD26 -#define XD_ECC_BIT2 0xFD27 -#define XD_ECC_BYTE2 0xFD28 -#define XD_RESERVED0 0xFD29 -#define XD_RESERVED1 0xFD2A -#define XD_RESERVED2 0xFD2B -#define XD_RESERVED3 0xFD2C -#define XD_CHK_DATA_STATUS 0xFD2D -#define XD_CATCTL 0xFD2E - -#define MS_BLKEND 0xFD30 -#define MS_READ_START 0xFD31 -#define MS_READ_COUNT 0xFD32 -#define MS_WRITE_START 0xFD33 -#define MS_WRITE_COUNT 0xFD34 -#define MS_COMMAND 0xFD35 -#define MS_OLD_BLOCK_0 0xFD36 -#define MS_OLD_BLOCK_1 0xFD37 -#define MS_NEW_BLOCK_0 0xFD38 -#define MS_NEW_BLOCK_1 0xFD39 -#define MS_LOG_BLOCK_0 0xFD3A -#define MS_LOG_BLOCK_1 0xFD3B -#define MS_BUS_WIDTH 0xFD3C -#define MS_PAGE_START 0xFD3D -#define MS_PAGE_LENGTH 0xFD3E -#define MS_CFG 0xFD40 -#define MS_TPC 0xFD41 -#define MS_TRANS_CFG 0xFD42 -#define MS_TRANSFER 0xFD43 -#define MS_INT_REG 0xFD44 -#define MS_BYTE_CNT 0xFD45 -#define MS_SECTOR_CNT_L 0xFD46 -#define MS_SECTOR_CNT_H 0xFD47 -#define MS_DBUS_H 0xFD48 - -#define CARD_DMA1_CTL 0xFD5C -#define CARD_PULL_CTL1 0xFD60 -#define CARD_PULL_CTL2 0xFD61 -#define CARD_PULL_CTL3 0xFD62 -#define CARD_PULL_CTL4 0xFD63 -#define CARD_PULL_CTL5 0xFD64 -#define CARD_PULL_CTL6 0xFD65 -#define CARD_EXIST 0xFD6F -#define CARD_INT_PEND 0xFD71 - -#define LDO_POWER_CFG 0xFD7B - -#define SD_CFG1 0xFDA0 -#define SD_CFG2 0xFDA1 -#define SD_CFG3 0xFDA2 -#define SD_STAT1 0xFDA3 -#define SD_STAT2 0xFDA4 -#define SD_BUS_STAT 0xFDA5 -#define SD_PAD_CTL 0xFDA6 -#define SD_SAMPLE_POINT_CTL 0xFDA7 -#define SD_PUSH_POINT_CTL 0xFDA8 -#define SD_CMD0 0xFDA9 -#define SD_CMD1 0xFDAA -#define SD_CMD2 0xFDAB -#define SD_CMD3 0xFDAC -#define SD_CMD4 0xFDAD -#define SD_CMD5 0xFDAE -#define SD_BYTE_CNT_L 0xFDAF -#define SD_BYTE_CNT_H 0xFDB0 -#define SD_BLOCK_CNT_L 0xFDB1 -#define SD_BLOCK_CNT_H 0xFDB2 -#define SD_TRANSFER 0xFDB3 -#define SD_CMD_STATE 0xFDB5 -#define SD_DATA_STATE 0xFDB6 -#define SD_VPCLK0_CTL 0xFC2A -#define SD_VPCLK1_CTL 0xFC2B -#define SD_DCMPS0_CTL 0xFC2C -#define SD_DCMPS1_CTL 0xFC2D - -#define CARD_DMA1_CTL 0xFD5C - -#define HW_VERSION 0xFC01 - -#define SSC_CLK_FPGA_SEL 0xFC02 -#define CLK_DIV 0xFC03 -#define SFSM_ED 0xFC04 - -#define CD_DEGLITCH_WIDTH 0xFC20 -#define CD_DEGLITCH_EN 0xFC21 -#define AUTO_DELINK_EN 0xFC23 - -#define FPGA_PULL_CTL 0xFC1D -#define CARD_CLK_SOURCE 0xFC2E - -#define CARD_SHARE_MODE 0xFD51 -#define CARD_DRIVE_SEL 0xFD52 -#define CARD_STOP 0xFD53 -#define CARD_OE 0xFD54 -#define CARD_AUTO_BLINK 0xFD55 -#define CARD_GPIO 0xFD56 -#define SD30_DRIVE_SEL 0xFD57 - -#define CARD_DATA_SOURCE 0xFD5D -#define CARD_SELECT 0xFD5E - -#define CARD_CLK_EN 0xFD79 -#define CARD_PWR_CTL 0xFD7A - -#define OCPCTL 0xFD80 -#define OCPPARA1 0xFD81 -#define OCPPARA2 0xFD82 -#define OCPSTAT 0xFD83 - -#define HS_USB_STAT 0xFE01 -#define HS_VCONTROL 0xFE26 -#define HS_VSTAIN 0xFE27 -#define HS_VLOADM 0xFE28 -#define HS_VSTAOUT 0xFE29 - -#define MC_IRQ 0xFF00 -#define MC_IRQEN 0xFF01 -#define MC_FIFO_CTL 0xFF02 -#define MC_FIFO_BC0 0xFF03 -#define MC_FIFO_BC1 0xFF04 -#define MC_FIFO_STAT 0xFF05 -#define MC_FIFO_MODE 0xFF06 -#define MC_FIFO_RD_PTR0 0xFF07 -#define MC_FIFO_RD_PTR1 0xFF08 -#define MC_DMA_CTL 0xFF10 -#define MC_DMA_TC0 0xFF11 -#define MC_DMA_TC1 0xFF12 -#define MC_DMA_TC2 0xFF13 -#define MC_DMA_TC3 0xFF14 -#define MC_DMA_RST 0xFF15 - -/* Memory mapping */ -#define RBUF_SIZE_MASK 0xFBFF -#define RBUF_BASE 0xF000 -#define PPBUF_BASE1 0xF800 -#define PPBUF_BASE2 0xFA00 - -/* int monitor_card_cd */ -#define CD_EXIST 0 -#define CD_NOT_EXIST 1 - -#define DEBOUNCE_CNT 5 - -int monitor_card_cd(struct rts51x_chip *chip, u8 card); - -void do_remaining_work(struct rts51x_chip *chip); -void do_reset_xd_card(struct rts51x_chip *chip); -void do_reset_sd_card(struct rts51x_chip *chip); -void do_reset_ms_card(struct rts51x_chip *chip); -void rts51x_init_cards(struct rts51x_chip *chip); -void rts51x_release_cards(struct rts51x_chip *chip); -int switch_ssc_clock(struct rts51x_chip *chip, int clk); -int switch_normal_clock(struct rts51x_chip *chip, int clk); -int card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr, - u16 sec_cnt); -u8 get_lun_card(struct rts51x_chip *chip, unsigned int lun); -int card_share_mode(struct rts51x_chip *chip, int card); -int rts51x_select_card(struct rts51x_chip *chip, int card); -void eject_card(struct rts51x_chip *chip, unsigned int lun); -void trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip, - u32 byte_cnt, u8 pack_size); -int enable_card_clock(struct rts51x_chip *chip, u8 card); -int disable_card_clock(struct rts51x_chip *chip, u8 card); -int card_power_on(struct rts51x_chip *chip, u8 card); -int card_power_off(struct rts51x_chip *chip, u8 card); -int toggle_gpio(struct rts51x_chip *chip, u8 gpio); -int turn_on_led(struct rts51x_chip *chip, u8 gpio); -int turn_off_led(struct rts51x_chip *chip, u8 gpio); - -static inline int check_card_ready(struct rts51x_chip *chip, unsigned int lun) -{ - if (chip->card_ready & chip->lun2card[lun]) - return 1; - - return 0; -} - -static inline int check_card_exist(struct rts51x_chip *chip, unsigned int lun) -{ - if (chip->card_exist & chip->lun2card[lun]) - return 1; - - return 0; -} - -static inline int check_card_wp(struct rts51x_chip *chip, unsigned int lun) -{ - if (chip->card_wp & chip->lun2card[lun]) - return 1; - - return 0; -} - -static inline int check_card_fail(struct rts51x_chip *chip, unsigned int lun) -{ - if (chip->card_fail & chip->lun2card[lun]) - return 1; - - return 0; -} - -static inline int check_card_ejected(struct rts51x_chip *chip, unsigned int lun) -{ - if (chip->card_ejected & chip->lun2card[lun]) - return 1; - - return 0; -} - -static inline int check_fake_card_ready(struct rts51x_chip *chip, - unsigned int lun) -{ - if (chip->fake_card_ready & chip->lun2card[lun]) - return 1; - - return 0; -} - -static inline u8 get_lun2card(struct rts51x_chip *chip, unsigned int lun) -{ - return chip->lun2card[lun]; -} - -static inline int check_lun_mc(struct rts51x_chip *chip, unsigned int lun) -{ - return CHK_BIT(chip->lun_mc, lun); -} - -static inline void set_lun_mc(struct rts51x_chip *chip, unsigned int lun) -{ - SET_BIT(chip->lun_mc, lun); -} - -static inline void clear_lun_mc(struct rts51x_chip *chip, unsigned int lun) -{ - CLR_BIT(chip->lun_mc, lun); -} - -static inline int switch_clock(struct rts51x_chip *chip, int clk) -{ - int retval = 0; - - if (chip->asic_code) - retval = switch_ssc_clock(chip, clk); - else - retval = switch_normal_clock(chip, clk); - - return retval; -} - -static inline void rts51x_clear_xd_error(struct rts51x_chip *chip) -{ - rts51x_ep0_write_register(chip, CARD_STOP, - XD_STOP | XD_CLR_ERR, XD_STOP | XD_CLR_ERR); - - rts51x_ep0_write_register(chip, MC_FIFO_CTL, FIFO_FLUSH, FIFO_FLUSH); - rts51x_ep0_write_register(chip, MC_DMA_RST, DMA_RESET, DMA_RESET); - rts51x_ep0_write_register(chip, SFSM_ED, 0xf8, 0xf8); -} - -static inline void rts51x_clear_sd_error(struct rts51x_chip *chip) -{ - rts51x_ep0_write_register(chip, CARD_STOP, - SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR); - - rts51x_ep0_write_register(chip, MC_FIFO_CTL, FIFO_FLUSH, FIFO_FLUSH); - rts51x_ep0_write_register(chip, MC_DMA_RST, DMA_RESET, DMA_RESET); - rts51x_ep0_write_register(chip, SFSM_ED, 0xf8, 0xf8); -} - -static inline void rts51x_clear_ms_error(struct rts51x_chip *chip) -{ - rts51x_ep0_write_register(chip, CARD_STOP, - MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR); - - rts51x_ep0_write_register(chip, MC_FIFO_CTL, FIFO_FLUSH, FIFO_FLUSH); - rts51x_ep0_write_register(chip, MC_DMA_RST, DMA_RESET, DMA_RESET); - rts51x_ep0_write_register(chip, SFSM_ED, 0xf8, 0xf8); -} - -#endif /* __RTS51X_CARD_H */ diff --git a/trunk/drivers/staging/rts5139/rts51x_chip.c b/trunk/drivers/staging/rts5139/rts51x_chip.c deleted file mode 100644 index adc0d0005735..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_chip.c +++ /dev/null @@ -1,1167 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include -#include - -#include "debug.h" -#include "trace.h" -#include "rts51x.h" -#include "rts51x_chip.h" -#include "rts51x_card.h" -#include "rts51x_transport.h" -#include "rts51x_sys.h" -#include "xd.h" -#include "ms.h" -#include "sd.h" - -static int check_sd_speed_prior(u32 sd_speed_prior) -{ - int i, fake_para = 0; - - /* Check the legality of sd_speed_prior */ - for (i = 0; i < 4; i++) { - u8 tmp = (u8) (sd_speed_prior >> (i * 8)); - if ((tmp < 0x01) || (tmp > 0x04)) { - fake_para = 1; - break; - } - } - - return !fake_para; -} - -int rts51x_reset_chip(struct rts51x_chip *chip) -{ - int retval; - - if (CHECK_PKG(chip, LQFP48)) { - RTS51X_WRITE_REG(chip, CARD_PWR_CTL, LDO3318_PWR_MASK, - LDO_SUSPEND); - RTS51X_WRITE_REG(chip, CARD_PWR_CTL, FORCE_LDO_POWERB, - FORCE_LDO_POWERB); - RTS51X_WRITE_REG(chip, CARD_PULL_CTL1, 0x30, 0x10); - RTS51X_WRITE_REG(chip, CARD_PULL_CTL5, 0x03, 0x01); - RTS51X_WRITE_REG(chip, CARD_PULL_CTL6, 0x0C, 0x04); - } - if (chip->asic_code) { - RTS51X_WRITE_REG(chip, SYS_DUMMY0, NYET_MSAK, NYET_EN); - RTS51X_WRITE_REG(chip, CD_DEGLITCH_WIDTH, 0xFF, 0x08); - rts51x_write_register(chip, CD_DEGLITCH_EN, XD_CD_DEGLITCH_EN, - 0x00); - rts51x_write_register(chip, SD30_DRIVE_SEL, SD30_DRIVE_MASK, - chip->option.sd30_pad_drive); - rts51x_write_register(chip, CARD_DRIVE_SEL, SD20_DRIVE_MASK, - chip->option.sd20_pad_drive); - if (chip->rts5179) - rts51x_write_register(chip, CARD_PULL_CTL5, 0x03, 0x01); - if (!chip->option.ww_enable) { - if (CHECK_PKG(chip, LQFP48)) { - rts51x_write_register(chip, CARD_PULL_CTL3, - 0x80, 0x80); - rts51x_write_register(chip, CARD_PULL_CTL6, - 0xf0, 0xA0); - } else { - rts51x_write_register(chip, CARD_PULL_CTL1, - 0x30, 0x20); - rts51x_write_register(chip, CARD_PULL_CTL3, - 0x80, 0x80); - rts51x_write_register(chip, CARD_PULL_CTL6, - 0x0c, 0x08); - } - } - } - if (chip->option.sd_ctl & SUPPORT_UHS50_MMC44) { - SET_UHS50(chip); - RTS51X_DEBUGP("option enable UHS50&MMC44,sd_ctl:0x%x\n", - chip->option.sd_ctl); - } else { - /* if(CHECK_PID(chip, 0x0139)&&CHECK_PKG(chip, LQFP48)) */ - if ((CHECK_PID(chip, 0x0139) && CHECK_PKG(chip, LQFP48)) - || chip->rts5179) { - SET_UHS50(chip); - RTS51X_DEBUGP("PID enable UHS50&MMC44\n"); - } else { - CLEAR_UHS50(chip); - RTS51X_DEBUGP("PID disable UHS50&MMC44\n"); - } - } - - if (chip->option.ms_errreg_fix && (chip->ic_version > 1)) - rts51x_write_register(chip, 0xFD4D, 0x01, 0x01); - retval = rts51x_write_phy_register(chip, 0xC2, 0x7C); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - rts51x_init_cmd(chip); - - /* GPIO OE */ - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO, GPIO_OE, GPIO_OE); -#ifdef LED_AUTO_BLINK - /* LED autoblink */ - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_AUTO_BLINK, - BLINK_ENABLE | BLINK_SPEED_MASK, - BLINK_ENABLE | chip->option.led_blink_speed); -#endif - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DMA1_CTL, - EXTEND_DMA1_ASYNC_SIGNAL, EXTEND_DMA1_ASYNC_SIGNAL); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#ifdef SUPPORT_OCP - if (chip->asic_code) { - rts51x_write_register(chip, OCPCTL, MS_OCP_DETECT_EN, - MS_OCP_DETECT_EN); - RTS51X_DEBUGP("Enable OCP detect!\n"); - } -#endif - if (chip->option.FT2_fast_mode) { - card_power_on(chip, SD_CARD | MS_CARD | XD_CARD); - wait_timeout(10); - } - rts51x_clear_start_time(chip); - - return STATUS_SUCCESS; -} - -int rts51x_init_chip(struct rts51x_chip *chip) -{ - int retval; - u8 val; - - chip->max_lun = 0; - chip->cur_clk = 0; - chip->cur_card = 0; - - chip->card2lun[XD_CARD] = 0; - chip->card2lun[SD_CARD] = 0; - chip->card2lun[MS_CARD] = 0; - chip->card_ejected = 0; - - chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD; -#if 0 - chip->option.sdr50_tx_phase = 0x01; - chip->option.sdr50_rx_phase = 0x05; - chip->option.ddr50_tx_phase = 0x09; - chip->option.ddr50_rx_phase = 0x06; /* add for debug */ -#endif -#ifdef CLOSE_SSC_POWER - rts51x_write_register(chip, FPDCTL, SSC_POWER_MASK, SSC_POWER_ON); - udelay(100); - rts51x_write_register(chip, CLK_DIV, CLK_CHANGE, 0x00); -#endif - RTS51X_SET_STAT(chip, STAT_RUN); - - RTS51X_READ_REG(chip, HW_VERSION, &val); - if ((val & 0x0f) >= 2) - chip->option.rcc_bug_fix_en = 0; - RTS51X_DEBUGP("rcc bug fix enable:%d\n", chip->option.rcc_bug_fix_en); - RTS51X_DEBUGP("HW_VERSION: 0x%x\n", val); - if (val & FPGA_VER) { - chip->asic_code = 0; - RTS51X_DEBUGP("FPGA!\n"); - } else { - chip->asic_code = 1; - RTS51X_DEBUGP("ASIC!\n"); - } - chip->ic_version = val & HW_VER_MASK; - - if (!check_sd_speed_prior(chip->option.sd_speed_prior)) - chip->option.sd_speed_prior = 0x01020403; - RTS51X_DEBUGP("sd_speed_prior = 0x%08x\n", - chip->option.sd_speed_prior); - - RTS51X_READ_REG(chip, CARD_SHARE_MODE, &val); - if (val & CARD_SHARE_LQFP_SEL) { - chip->package = LQFP48; - RTS51X_DEBUGP("Package: LQFP48\n"); - } else { - chip->package = QFN24; - RTS51X_DEBUGP("Package: QFN24\n"); - } - - RTS51X_READ_REG(chip, HS_USB_STAT, &val); - if (val & USB_HI_SPEED) { - chip->usb_speed = USB_20; - RTS51X_DEBUGP("USB High Speed\n"); - } else { - chip->usb_speed = USB_11; - RTS51X_DEBUGP("USB Full Speed\n"); - } - - RTS51X_READ_REG(chip, CFG_MODE_1, &val); - if (val & RTS5179) { - chip->rts5179 = 1; - RTS51X_DEBUGP("device is rts5179\n"); - } else { - chip->rts5179 = 0; - } - - retval = rts51x_reset_chip(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -int rts51x_release_chip(struct rts51x_chip *chip) -{ - xd_free_l2p_tbl(chip); - ms_free_l2p_tbl(chip); - chip->card_ready = 0; - return STATUS_SUCCESS; -} - -#ifndef LED_AUTO_BLINK -static inline void rts51x_blink_led(struct rts51x_chip *chip) -{ - /* Read/Write */ - if (chip->card_ready) { - if (chip->led_toggle_counter < - chip->option.led_toggle_interval) { - chip->led_toggle_counter++; - } else { - chip->led_toggle_counter = 0; - toggle_gpio(chip, LED_GPIO); - } - } -} -#endif - -int rts51x_check_start_time(struct rts51x_chip *chip) -{ - return 0; -} - -void rts51x_set_start_time(struct rts51x_chip *chip) -{ -} - -void rts51x_clear_start_time(struct rts51x_chip *chip) -{ -} - -static void rts51x_auto_delink_cmd(struct rts51x_chip *chip) -{ - rts51x_write_register(chip, AUTO_DELINK_EN, - AUTO_DELINK, AUTO_DELINK); -} - -static void rts51x_auto_delink_force_cmd(struct rts51x_chip *chip) -{ - rts51x_write_register(chip, AUTO_DELINK_EN, - AUTO_DELINK | FORCE_DELINK, - AUTO_DELINK | FORCE_DELINK); -} - -#ifdef USING_POLLING_CYCLE_DELINK -/* using polling cycle as delink time */ -static void rts51x_auto_delink_polling_cycle(struct rts51x_chip *chip) -{ - if (chip->auto_delink_counter <= - chip->option.delink_delay * 2) { - if (chip->auto_delink_counter == - chip->option.delink_delay) { - clear_first_install_mark(chip); - if (chip->card_exist) { - /* False card */ - if (!chip->card_ejected) { - /* if card is not ejected or safely - * remove,then do force delink */ - RTS51X_DEBUGP("False card inserted," - "do force delink\n"); - rts51x_auto_delink_force_cmd(chip); - chip->auto_delink_counter = - chip->option.delink_delay * 2 + 1; - } - } else { - RTS51X_DEBUGP("No card inserted, do delink\n"); - /* rts51x_write_register(chip, CARD_PWR_CTL, - DV3318_AUTO_PWR_OFF, 0); */ - rts51x_auto_delink_cmd(chip); - } - } - if (chip->auto_delink_counter == - chip->option.delink_delay * 2) { - RTS51X_DEBUGP("Try to do force delink\n"); - rts51x_auto_delink_force_cmd(chip); - } - chip->auto_delink_counter++; - } -} - -static void rts51x_auto_delink(struct rts51x_chip *chip) -{ - rts51x_auto_delink_polling_cycle(chip); -} -#else -/* some of called funcs are not implemented, so comment it out */ -#if 0 -/* using precise time as delink time */ -static void rts51x_auto_delink_precise_time(struct rts51x_chip *chip) -{ - int retvalue = 0; - - retvalue = rts51x_get_card_status(chip, &chip->card_status); - /* get card CD status success and card CD not exist, - * then check whether delink */ - if ((retvalue == STATUS_SUCCESS) - && (!(chip->card_status & (SD_CD | MS_CD | XD_CD)))) { - if (rts51x_count_delink_time(chip) >= - chip->option.delink_delay) { - clear_first_install_mark(chip); - RTS51X_DEBUGP("No card inserted, do delink\n"); - /* sangdy2010-05-17:disable because there is error - * after SSC clock closed and card power - * has been closed before */ - /* rts51x_write_register(chip, CARD_PWR_CTL, - DV3318_AUTO_PWR_OFF, 0); */ - rts51x_auto_delink_cmd(chip); - } - /* card CD exist and not ready, then do force delink */ - if ((retvalue == STATUS_SUCCESS) - && (chip->card_status & (SD_CD | MS_CD | XD_CD))) { - /* if card is not ejected or safely remove, - * then do force delink */ - if (!chip->card_ejected) { - /* sangdy2010-11-16:polling at least 2 cycles - * then do force delink for card may force delink - * if card is extracted and insert quickly - * after ready. */ - if (chip->auto_delink_counter > 1) { - if (rts51x_count_delink_time(chip) > - chip->option.delink_delay * 2) { - RTS51X_DEBUGP("Try to do force" - "delink\n"); - rts51x_auto_delink_force_cmd(chip); - } - } - } - } - chip->auto_delink_counter++; -} -#else -static void rts51x_auto_delink_precise_time(struct rts51x_chip *chip) -{ -} -#endif - -static void rts51x_auto_delink(struct rts51x_chip *chip) -{ - rts51x_auto_delink_precise_time(chip); -} -#endif - -void rts51x_polling_func(struct rts51x_chip *chip) -{ -#ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &(chip->sd_card); - - if (sd_card->sd_erase_status) { - if (chip->card_exist & SD_CARD) { - u8 val; - rts51x_read_register(chip, SD_BUS_STAT, &val); - if (val & SD_DAT0_STATUS) { - /* Erase completed */ - sd_card->sd_erase_status = SD_NOT_ERASE; - sd_card->sd_lock_notify = 1; - - /* SD card should be reinited, - * so we release it here. */ - sd_cleanup_work(chip); - release_sd_card(chip); - chip->card_ready &= ~SD_CARD; - chip->card_exist &= ~SD_CARD; - chip->rw_card[chip->card2lun[SD_CARD]] = NULL; - clear_bit(chip->card2lun[SD_CARD], - &(chip->lun_mc)); - } - } else { - sd_card->sd_erase_status = SD_NOT_ERASE; - } - } -#endif - - rts51x_init_cards(chip); - -#ifdef SUPPORT_OCP - /* if OCP happen and card exist, then close card OE */ - if ((chip->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) && - (chip->card_exist)) { - - rts51x_prepare_run(chip); - - if (chip->card_exist & SD_CARD) - rts51x_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0); - else if (chip->card_exist & MS_CARD) - rts51x_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0); - else if (chip->card_exist & XD_CARD) - rts51x_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0); - } -#endif - - if (chip->idle_counter < IDLE_MAX_COUNT) { - chip->idle_counter++; - } else { - if (!RTS51X_CHK_STAT(chip, STAT_IDLE)) { - RTS51X_DEBUGP("Idle state!\n"); - RTS51X_SET_STAT(chip, STAT_IDLE); -#ifndef LED_AUTO_BLINK - chip->led_toggle_counter = 0; -#endif - /* Idle state, turn off LED - * to reduce power consumption */ - if (chip->option.led_always_on - && (chip->card_exist & - (SD_CARD | MS_CARD | XD_CARD)) - && (!chip->card_ejected)) { - turn_on_led(chip, LED_GPIO); - } else { - if (chip->rts5179) { - rts51x_ep0_write_register(chip, - CARD_GPIO, - 0x03, 0x00); - } else { - turn_off_led(chip, LED_GPIO); - } - - } - -#ifdef CLOSE_SSC_POWER - if (!chip->card_ready) { - rts51x_write_register(chip, CLK_DIV, CLK_CHANGE, - CLK_CHANGE); - rts51x_write_register(chip, FPDCTL, - SSC_POWER_MASK, - SSC_POWER_DOWN); - RTS51X_DEBUGP("Close SSC clock power!\n"); - } -#endif - } - } - - switch (RTS51X_GET_STAT(chip)) { - case STAT_RUN: -#ifndef LED_AUTO_BLINK - rts51x_blink_led(chip); -#endif - do_remaining_work(chip); - break; - - case STAT_IDLE: - break; - - default: - break; - } - - if (chip->option.auto_delink_en && !chip->card_ready) { - rts51x_auto_delink(chip); - } else { - chip->auto_delink_counter = 0; - rts51x_clear_start_time(chip); - } -} - -void rts51x_add_cmd(struct rts51x_chip *chip, - u8 cmd_type, u16 reg_addr, u8 mask, u8 data) -{ - int i; - - if (chip->cmd_idx < ((CMD_BUF_LEN - CMD_OFFSET) / 4)) { - i = CMD_OFFSET + chip->cmd_idx * 4; - chip->cmd_buf[i++] = - ((cmd_type & 0x03) << 6) | (u8) ((reg_addr >> 8) & 0x3F); - chip->cmd_buf[i++] = (u8) reg_addr; - chip->cmd_buf[i++] = mask; - chip->cmd_buf[i++] = data; - chip->cmd_idx++; - } -} - -int rts51x_send_cmd(struct rts51x_chip *chip, u8 flag, int timeout) -{ - int result; - - chip->cmd_buf[CNT_H] = (u8) (chip->cmd_idx >> 8); - chip->cmd_buf[CNT_L] = (u8) (chip->cmd_idx); - chip->cmd_buf[STAGE_FLAG] = flag; - - result = rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), - (void *)(chip->cmd_buf), - chip->cmd_idx * 4 + CMD_OFFSET, - 0, NULL, timeout, MODE_C); - if (result != STATUS_SUCCESS) - TRACE_RET(chip, result); - - return STATUS_SUCCESS; -} - -int rts51x_get_rsp(struct rts51x_chip *chip, int rsp_len, int timeout) -{ - int result; - - if (rsp_len <= 0) - TRACE_RET(chip, STATUS_ERROR); - /* rsp_len must aligned to dword */ - if (rsp_len % 4) - rsp_len += (4 - rsp_len % 4); - - result = rts51x_transfer_data_rcc(chip, RCV_BULK_PIPE(chip), - (void *)chip->rsp_buf, rsp_len, - 0, NULL, timeout, STAGE_R); - if (result != STATUS_SUCCESS) - TRACE_RET(chip, result); - - return STATUS_SUCCESS; -} - -int rts51x_get_card_status(struct rts51x_chip *chip, u16 * status) -{ - int retval; - u16 val; - -#ifdef GET_CARD_STATUS_USING_EPC - retval = rts51x_get_epc_status(chip, &val); - - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#else - retval = rts51x_ctrl_transfer(chip, RCV_CTRL_PIPE(chip), 0x02, 0xC0, - 0, 0, &val, 2, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#endif - - if (status) - *status = val; - - return STATUS_SUCCESS; -} - -int rts51x_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, u8 data) -{ - int retval; - - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, addr, mask, data); - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -int rts51x_read_register(struct rts51x_chip *chip, u16 addr, u8 * data) -{ - int retval; - - if (data) - *data = 0; - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, READ_REG_CMD, addr, 0, 0); - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = rts51x_get_rsp(chip, 1, 100); - - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (data) - *data = chip->rsp_buf[0]; - - return STATUS_SUCCESS; -} - -int rts51x_ep0_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, - u8 data) -{ - int retval; - u16 value = 0, index = 0; - - value |= (u16) (3 & 0x03) << 14; - value |= (u16) (addr & 0x3FFF); - index |= (u16) mask << 8; - index |= (u16) data; - - retval = rts51x_ctrl_transfer(chip, SND_CTRL_PIPE(chip), 0x00, 0x40, - cpu_to_be16(value), cpu_to_be16(index), - NULL, 0, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -int rts51x_ep0_read_register(struct rts51x_chip *chip, u16 addr, u8 * data) -{ - int retval; - u16 value = 0; - u8 val; - - if (data) - *data = 0; - - value |= (u16) (2 & 0x03) << 14; - value |= (u16) (addr & 0x3FFF); - - retval = rts51x_ctrl_transfer(chip, RCV_CTRL_PIPE(chip), 0x00, 0xC0, - cpu_to_be16(value), 0, &val, 1, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (data) - *data = val; - - return STATUS_SUCCESS; -} - -int rts51x_seq_write_register(struct rts51x_chip *chip, u16 addr, u16 len, - u8 *data) -{ - int result; - u16 cmd_len = len + 12; - - if (!data) - TRACE_RET(chip, STATUS_ERROR); - - cmd_len = (cmd_len <= CMD_BUF_LEN) ? cmd_len : CMD_BUF_LEN; - - /* cmd_len must aligned to dword */ - if (cmd_len % 4) - cmd_len += (4 - cmd_len % 4); - - chip->cmd_buf[0] = 'R'; - chip->cmd_buf[1] = 'T'; - chip->cmd_buf[2] = 'C'; - chip->cmd_buf[3] = 'R'; - chip->cmd_buf[PACKET_TYPE] = SEQ_WRITE; - chip->cmd_buf[5] = (u8) (len >> 8); - chip->cmd_buf[6] = (u8) len; - chip->cmd_buf[STAGE_FLAG] = 0; - chip->cmd_buf[8] = (u8) (addr >> 8); - chip->cmd_buf[9] = (u8) addr; - - memcpy(chip->cmd_buf + 12, data, len); - - result = rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), - (void *)(chip->cmd_buf), cmd_len, 0, - NULL, 100, MODE_C); - if (result != STATUS_SUCCESS) - TRACE_RET(chip, result); - - return STATUS_SUCCESS; -} - -int rts51x_seq_read_register(struct rts51x_chip *chip, u16 addr, u16 len, - u8 *data) -{ - int result; - u16 rsp_len; - - if (!data) - TRACE_RET(chip, STATUS_ERROR); - /* rsp_len must aligned to dword */ - if (len % 4) - rsp_len = len + (4 - len % 4); - else - rsp_len = len; - - chip->cmd_buf[0] = 'R'; - chip->cmd_buf[1] = 'T'; - chip->cmd_buf[2] = 'C'; - chip->cmd_buf[3] = 'R'; - chip->cmd_buf[PACKET_TYPE] = SEQ_READ; - chip->cmd_buf[5] = (u8) (rsp_len >> 8); - chip->cmd_buf[6] = (u8) rsp_len; - chip->cmd_buf[STAGE_FLAG] = STAGE_R; - chip->cmd_buf[8] = (u8) (addr >> 8); - chip->cmd_buf[9] = (u8) addr; - - result = rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), - (void *)(chip->cmd_buf), 12, 0, NULL, - 100, MODE_C); - if (result != STATUS_SUCCESS) - TRACE_RET(chip, result); - - result = rts51x_transfer_data_rcc(chip, RCV_BULK_PIPE(chip), - (void *)data, rsp_len, 0, NULL, 100, - STAGE_DI); - if (result != STATUS_SUCCESS) - TRACE_RET(chip, result); - - return STATUS_SUCCESS; -} - -int rts51x_read_ppbuf(struct rts51x_chip *chip, u8 * buf, int buf_len) -{ - int retval; - - if (!buf) - TRACE_RET(chip, STATUS_ERROR); - - retval = - rts51x_seq_read_register(chip, PPBUF_BASE2, (u16) buf_len, buf); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -int rts51x_write_ppbuf(struct rts51x_chip *chip, u8 * buf, int buf_len) -{ - int retval; - - if (!buf) - TRACE_RET(chip, STATUS_ERROR); - - retval = - rts51x_seq_write_register(chip, PPBUF_BASE2, (u16) buf_len, buf); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -int rts51x_write_phy_register(struct rts51x_chip *chip, u8 addr, u8 val) -{ - int retval; - - RTS51X_DEBUGP("Write 0x%x to phy register 0x%x\n", val, addr); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VSTAIN, 0xFF, val); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, - (addr >> 4) & 0x0F); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -int rts51x_read_phy_register(struct rts51x_chip *chip, u8 addr, u8 * val) -{ - int retval; - - RTS51X_DEBUGP("Read from phy register 0x%x\n", addr); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, 0x07); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, - (addr >> 4) & 0x0F); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); - rts51x_add_cmd(chip, READ_REG_CMD, HS_VSTAOUT, 0, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 1, 100); - - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (val) - *val = chip->rsp_buf[0]; - - RTS51X_DEBUGP("Return value: 0x%x\n", chip->rsp_buf[0]); - - return STATUS_SUCCESS; -} - -void rts51x_do_before_power_down(struct rts51x_chip *chip) -{ - RTS51X_DEBUGP("rts51x_do_before_power_down\n"); - - rts51x_prepare_run(chip); - - rts51x_release_cards(chip); - if (chip->rts5179) - rts51x_ep0_write_register(chip, CARD_GPIO, 0x03, 0x00); - else - turn_off_led(chip, LED_GPIO); - - chip->cur_clk = 0; - chip->card_exist = 0; - chip->cur_card = 0; - if (chip->asic_code && !chip->option.ww_enable) { - if (CHECK_PKG(chip, LQFP48)) { - rts51x_write_register(chip, CARD_PULL_CTL3, 0x80, 0x00); - rts51x_write_register(chip, CARD_PULL_CTL6, 0xf0, 0x50); - } else { - rts51x_write_register(chip, CARD_PULL_CTL1, 0x30, 0x10); - rts51x_write_register(chip, CARD_PULL_CTL3, 0x80, 0x00); - rts51x_write_register(chip, CARD_PULL_CTL6, 0x0c, 0x04); - } - } - if (CHECK_PKG(chip, LQFP48)) - rts51x_write_register(chip, CARD_PWR_CTL, LDO3318_PWR_MASK, - LDO_OFF); -} - -void rts51x_clear_hw_error(struct rts51x_chip *chip) -{ - rts51x_ep0_write_register(chip, SFSM_ED, 0xf8, 0xf8); -} - -void rts51x_prepare_run(struct rts51x_chip *chip) -{ -#ifdef CLOSE_SSC_POWER - if (RTS51X_CHK_STAT(chip, STAT_IDLE) && (!chip->card_ready)) { - rts51x_write_register(chip, FPDCTL, SSC_POWER_MASK, - SSC_POWER_ON); - udelay(100); - RTS51X_DEBUGP("Open SSC clock power.\n"); - - rts51x_write_register(chip, CLK_DIV, CLK_CHANGE, 0x00); - } -#endif -#if 0 - if (chip->option.ss_en && RTS51X_CHK_STAT(chip, STAT_SS)) { - rts51x_try_to_exit_ss(chip); - wait_timeout(100); - rts51x_init_chip(chip); - rts51x_init_cards(chip); - } - - RTS51X_SET_STAT(chip, STAT_RUN); -#endif -} - -#ifdef _MSG_TRACE -void rts51x_trace_msg(struct rts51x_chip *chip, unsigned char *buf, int clear) -{ - unsigned char *ptr; - int i, msg_cnt; - - if (!buf) - return; - - ptr = buf; - - if (chip->trace_msg[chip->msg_idx].valid) - msg_cnt = TRACE_ITEM_CNT; - else - msg_cnt = chip->msg_idx; - *(ptr++) = (u8) (msg_cnt >> 24); - *(ptr++) = (u8) (msg_cnt >> 16); - *(ptr++) = (u8) (msg_cnt >> 8); - *(ptr++) = (u8) msg_cnt; - RTS51X_DEBUGP("Trace message count is %d\n", msg_cnt); - - for (i = 1; i <= msg_cnt; i++) { - int j, idx; - - idx = chip->msg_idx - i; - if (idx < 0) - idx += TRACE_ITEM_CNT; - - *(ptr++) = (u8) (chip->trace_msg[idx].line >> 8); - *(ptr++) = (u8) (chip->trace_msg[idx].line); - for (j = 0; j < MSG_FUNC_LEN; j++) - *(ptr++) = chip->trace_msg[idx].func[j]; - for (j = 0; j < MSG_FILE_LEN; j++) - *(ptr++) = chip->trace_msg[idx].file[j]; - for (j = 0; j < TIME_VAL_LEN; j++) - *(ptr++) = chip->trace_msg[idx].timeval_buf[j]; - } - - if (clear) { - chip->msg_idx = 0; - for (i = 0; i < TRACE_ITEM_CNT; i++) - chip->trace_msg[i].valid = 0; - } -} -#endif - -void rts51x_pp_status(struct rts51x_chip *chip, unsigned int lun, u8 * status, - u8 status_len) -{ - struct sd_info *sd_card = &(chip->sd_card); - struct ms_info *ms_card = &(chip->ms_card); - u8 card = get_lun_card(chip, lun); -#ifdef SUPPORT_OC - u8 oc_now_mask = 0, oc_ever_mask = 0; -#endif - - if (!status || (status_len < 32)) - return; - /* IC Version */ - status[0] = (u8) RTS51X_GET_PID(chip); - status[1] = (u8) (chip->ic_version); - - /* Auto delink mode */ - if (chip->option.auto_delink_en) - status[2] = 0x10; - else - status[2] = 0x00; - - /* Spec version */ - status[3] = 20; - status[4] = 10; - status[5] = 05; - status[6] = 21; - - /* Card WP */ - if (chip->card_wp) - status[7] = 0x20; - else - status[7] = 0x00; - -#ifdef SUPPORT_OC - /* Over current status */ - status[8] = 0; - oc_now_mask = MS_OCP_NOW; - oc_ever_mask = MS_OCP_EVER; - - if (chip->ocp_stat & oc_now_mask) - status[8] |= 0x02; - if (chip->ocp_stat & oc_ever_mask) - status[8] |= 0x01; -#endif - - if (card == SD_CARD) { - if (CHK_SD(sd_card)) { - if (CHK_SD_HCXC(sd_card)) { - if (sd_card->capacity > 0x4000000) - /* SDXC */ - status[0x0E] = 0x02; - else /* SDHC */ - status[0x0E] = 0x01; - } else { /* SDSC */ - status[0x0E] = 0x00; - } - - if (CHK_SD_SDR104(sd_card)) - status[0x0F] = 0x03; - else if (CHK_SD_DDR50(sd_card)) - status[0x0F] = 0x04; - else if (CHK_SD_SDR50(sd_card)) - status[0x0F] = 0x02; - else if (CHK_SD_HS(sd_card)) - status[0x0F] = 0x01; - else - status[0x0F] = 0x00; /* Normal speed */ - } else { - if (CHK_MMC_SECTOR_MODE(sd_card)) - status[0x0E] = 0x01; /* High capacity */ - else - status[0x0E] = 0x00; /* Normal capacity */ - - if (CHK_MMC_DDR52(sd_card)) - status[0x0F] = 0x03; /* DDR 52M */ - else if (CHK_MMC_52M(sd_card)) - status[0x0F] = 0x02; /* SDR 52M */ - else if (CHK_MMC_26M(sd_card)) - status[0x0F] = 0x01; /* SDR 26M */ - else - status[0x0F] = 0x00; /* Normal speed */ - } - } else if (card == MS_CARD) { - if (CHK_MSPRO(ms_card)) { - if (CHK_MSXC(ms_card)) - status[0x0E] = 0x01; /* XC */ - else - status[0x0E] = 0x00; - - if (CHK_HG8BIT(ms_card)) - status[0x0F] = 0x01; - else - status[0x0F] = 0x00; - } - } -#ifdef SUPPORT_SD_LOCK - /* SD Lock/Unlock */ - if (card == SD_CARD) { - status[0x17] = 0x80; - if (sd_card->sd_erase_status) - status[0x17] |= 0x01; /* Under erasing */ - if (sd_card->sd_lock_status & SD_LOCKED) { - status[0x17] |= 0x02; /* Locked */ - status[0x07] |= 0x40; /* Read protected */ - } - if (sd_card->sd_lock_status & SD_PWD_EXIST) - status[0x17] |= 0x04; /* Contain PWD */ - } else { - status[0x17] = 0x00; - } - - RTS51X_DEBUGP("status[0x17] = 0x%x\n", status[0x17]); -#endif - - /* Function 0 - * Support Magic Gate, CPRM and PhyRegister R/W */ - status[0x18] = 0x8A; - - /* Function 2 - * Support OC LUN status & WP LUN status */ - status[0x1A] = 0x28; - - /* Function 7 */ -#ifdef SUPPORT_SD_LOCK - /* Support SD Lock/Unlock */ - status[0x1F] = 0x01; -#endif - - /* Function 2 - * Support OC LUN status & WP LUN status */ - status[0x1A] = 0x28; -} - -void rts51x_read_status(struct rts51x_chip *chip, unsigned int lun, - u8 *rts51x_status, u8 status_len) -{ - if (!rts51x_status || (status_len < 16)) - return; - /* VID */ - rts51x_status[0] = (u8) (RTS51X_GET_VID(chip) >> 8); - rts51x_status[1] = (u8) RTS51X_GET_VID(chip); - - /* PID */ - rts51x_status[2] = (u8) (RTS51X_GET_PID(chip) >> 8); - rts51x_status[3] = (u8) RTS51X_GET_PID(chip); - - /* gbLUN */ - rts51x_status[4] = (u8) lun; - - /* Lun Card Number */ - if (chip->card_exist) { - if (chip->card_exist & XD_CARD) - rts51x_status[5] = 4; /* xD Card */ - else if (chip->card_exist & SD_CARD) - rts51x_status[5] = 2; /* SD Card */ - else if (chip->card_exist & MS_CARD) - rts51x_status[5] = 3; /* MS Card */ - else - rts51x_status[5] = 7; /* Multi */ - } else { - rts51x_status[5] = 7; /* Multi */ - } - - /* Total LUNs */ - rts51x_status[6] = 1; - - /* IC Version */ - rts51x_status[7] = (u8) RTS51X_GET_PID(chip); - rts51x_status[8] = chip->ic_version; - - /* Physical Exist */ - if (check_card_exist(chip, lun)) - rts51x_status[9] = 1; - else - rts51x_status[9] = 0; - - /* Multi Flag */ - rts51x_status[10] = 1; - - /* LUN Valid Map */ - rts51x_status[11] = XD_CARD | SD_CARD | MS_CARD; - - /* Logical Exist */ - if (check_card_ready(chip, lun)) - rts51x_status[12] = 1; - else - rts51x_status[12] = 0; - - /* Detailed Type */ - if (get_lun_card(chip, lun) == XD_CARD) { - rts51x_status[13] = 0x40; - } else if (get_lun_card(chip, lun) == SD_CARD) { - struct sd_info *sd_card = &(chip->sd_card); - - rts51x_status[13] = 0x20; - if (CHK_SD(sd_card)) { - if (CHK_SD_HCXC(sd_card)) - rts51x_status[13] |= 0x04; /* Hi capacity SD */ - if (CHK_SD_HS(sd_card)) - rts51x_status[13] |= 0x02; /* Hi speed SD */ - } else { - rts51x_status[13] |= 0x08; /* MMC card */ - if (CHK_MMC_52M(sd_card)) - rts51x_status[13] |= 0x02; /* Hi speed */ - if (CHK_MMC_SECTOR_MODE(sd_card)) - rts51x_status[13] |= 0x04; /* Hi capacity */ - } - } else if (get_lun_card(chip, lun) == MS_CARD) { - struct ms_info *ms_card = &(chip->ms_card); - - if (CHK_MSPRO(ms_card)) { - rts51x_status[13] = 0x38; /* MS Pro */ - if (CHK_HG8BIT(ms_card)) - rts51x_status[13] |= 0x04; /* HG */ -#ifdef SUPPORT_MSXC - if (CHK_MSXC(ms_card)) - rts51x_status[13] |= 0x01; /* MSXC */ -#endif - } else { - rts51x_status[13] = 0x30; - } - } else { - rts51x_status[13] = 0x70; - } -/* Support OC, auto delink, vendor r/w, get bus width */ - rts51x_status[14] = 0x78; - - rts51x_status[15] = 0x82; -} - -int rts51x_transfer_data_rcc(struct rts51x_chip *chip, unsigned int pipe, - void *buf, unsigned int len, int use_sg, - unsigned int *act_len, int timeout, u8 stage_flag) -{ - int retval; - - retval = - rts51x_transfer_data(chip, pipe, buf, len, use_sg, act_len, - timeout); - - return retval; - -} diff --git a/trunk/drivers/staging/rts5139/rts51x_chip.h b/trunk/drivers/staging/rts5139/rts51x_chip.h deleted file mode 100644 index 321ece750ede..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_chip.h +++ /dev/null @@ -1,904 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_CHIP_H -#define __RTS51X_CHIP_H - -#include -#include -#include -#include -#include -#include - -#include "trace.h" - -#define SUPPORT_CPRM -#define SUPPORT_MAGIC_GATE -#define SUPPORT_MSXC -/* #define LED_AUTO_BLINK */ - -/* { wwang, 2010-07-26 - * Add support for SD lock/unlock */ -/* #define SUPPORT_SD_LOCK */ -/* } wwang, 2010-07-26 */ - -#ifdef SUPPORT_MAGIC_GA -/* Using NORMAL_WRITE instead of AUTO_WRITE to set ICVTE */ -#define MG_SET_ICV_SLOW -#endif - -#ifdef SUPPORT_MSXC -#define XC_POWERCLASS -#define SUPPORT_PCGL_1P18 -#endif - -#define GET_CARD_STATUS_USING_EPC - -#define CLOSE_SSC_POWER - -#define SUPPORT_OCP - -#define MS_SPEEDUP -/* #define XD_SPEEDUP */ - -#define SD_XD_IO_FOLLOW_PWR - -#define SD_NR 2 -#define MS_NR 3 -#define XD_NR 4 -#define SD_CARD (1 << SD_NR) -#define MS_CARD (1 << MS_NR) -#define XD_CARD (1 << XD_NR) - -#define SD_CD 0x01 -#define MS_CD 0x02 -#define XD_CD 0x04 -#define SD_WP 0x08 - -#define MAX_ALLOWED_LUN_CNT 8 -#define CMD_BUF_LEN 1024 -#define RSP_BUF_LEN 1024 -#define POLLING_INTERVAL 50 /* 50ms */ - -#define XD_FREE_TABLE_CNT 1200 -#define MS_FREE_TABLE_CNT 512 - -/* Bit Operation */ -#define SET_BIT(data, idx) ((data) |= 1 << (idx)) -#define CLR_BIT(data, idx) ((data) &= ~(1 << (idx))) -#define CHK_BIT(data, idx) ((data) & (1 << (idx))) - -/* Command type */ -#define READ_REG_CMD 0 -#define WRITE_REG_CMD 1 -#define CHECK_REG_CMD 2 - -#define PACKET_TYPE 4 -#define CNT_H 5 -#define CNT_L 6 -#define STAGE_FLAG 7 -#define CMD_OFFSET 8 - -/* Packet type */ -#define BATCH_CMD 0 -#define SEQ_READ 1 -#define SEQ_WRITE 2 - -/* Stage flag */ -#define STAGE_R 0x01 -#define STAGE_DI 0x02 -#define STAGE_DO 0x04 -/* Return MS_TRANS_CFG, GET_INT */ -#define STAGE_MS_STATUS 0x08 -/* Return XD_CFG, XD_CTL, XD_PAGE_STATUS */ -#define STAGE_XD_STATUS 0x10 -/* Command stage mode */ -#define MODE_C 0x00 -#define MODE_CR (STAGE_R) -#define MODE_CDIR (STAGE_R | STAGE_DI) -#define MODE_CDOR (STAGE_R | STAGE_DO) - -/* Function return code */ -#ifndef STATUS_SUCCESS -#define STATUS_SUCCESS 0 -#endif - -#define STATUS_FAIL 1 -#define STATUS_READ_FAIL 2 -#define STATUS_WRITE_FAIL 3 -#define STATUS_TIMEDOUT 4 -#define STATUS_NOMEM 5 -#define STATUS_TRANS_SHORT 6 -#define STATUS_TRANS_LONG 7 -#define STATUS_STALLED 8 -#define STATUS_ERROR 10 - -#define IDLE_MAX_COUNT 10 -#define POLLING_WAIT_CNT 1 -#define DELINK_DELAY 100 -#define LED_TOGGLE_INTERVAL 6 -#define LED_GPIO 0 - -/* package */ -#define QFN24 0 -#define LQFP48 1 - -#define USB_11 0 -#define USB_20 1 - -/* - * Transport return codes - */ -/* Transport good, command good */ -#define TRANSPORT_GOOD 0 -/* Transport good, command failed */ -#define TRANSPORT_FAILED 1 -/* Command failed, no auto-sense */ -#define TRANSPORT_NO_SENSE 2 -/* Transport bad (i.e. device dead) */ -#define TRANSPORT_ERROR 3 - -/* Supported Clock */ -enum card_clock { CLK_20 = 1, CLK_30, CLK_40, CLK_50, CLK_60, CLK_80, CLK_100 }; - -#ifdef _MSG_TRACE - -#define TRACE_ITEM_CNT 64 - -struct trace_msg_t { - u16 line; -#define MSG_FUNC_LEN 64 - char func[MSG_FUNC_LEN]; -#define MSG_FILE_LEN 32 - char file[MSG_FILE_LEN]; -#define TIME_VAL_LEN 16 - u8 timeval_buf[TIME_VAL_LEN]; - u8 valid; -}; - -#endif /* _MSG_TRACE */ - -/* Size of the autosense data buffer */ -#define SENSE_SIZE 18 - -/* Sense type */ -#define SENSE_TYPE_NO_SENSE 0 -#define SENSE_TYPE_MEDIA_CHANGE 1 -#define SENSE_TYPE_MEDIA_NOT_PRESENT 2 -#define SENSE_TYPE_MEDIA_LBA_OVER_RANGE 3 -#define SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT 4 -#define SENSE_TYPE_MEDIA_WRITE_PROTECT 5 -#define SENSE_TYPE_MEDIA_INVALID_CMD_FIELD 6 -#define SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR 7 -#define SENSE_TYPE_MEDIA_WRITE_ERR 8 -#define SENSE_TYPE_FORMAT_IN_PROGRESS 9 -#define SENSE_TYPE_FORMAT_CMD_FAILED 10 -#ifdef SUPPORT_MAGIC_GATE -/* COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED */ -#define SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB 0x0b -/* COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE */ -#define SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN 0x0c -/* INCOMPATIBLE MEDIUM INSTALLED */ -#define SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM 0x0d -/* WRITE ERROR */ -#define SENSE_TYPE_MG_WRITE_ERR 0x0e -#endif -#ifdef SUPPORT_SD_LOCK -/* FOR Locked SD card */ -#define SENSE_TYPE_MEDIA_READ_FORBIDDEN 0x10 -#endif - -/*---- sense key ----*/ -#define ILI 0x20 /* ILI bit is on */ - -#define NO_SENSE 0x00 /* not exist sense key */ -#define RECOVER_ERR 0x01 /* Target/Logical unit is recoverd */ -#define NOT_READY 0x02 /* Logical unit is not ready */ -#define MEDIA_ERR 0x03 /* medium/data error */ -#define HARDWARE_ERR 0x04 /* hardware error */ -#define ILGAL_REQ 0x05 /* CDB/parameter/identify msg error */ -#define UNIT_ATTENTION 0x06 /* unit attention condition occur */ -#define DAT_PRTCT 0x07 /* read/write is desable */ -#define BLNC_CHK 0x08 /* find blank/DOF in read */ - /* write to unblank area */ -#define CPY_ABRT 0x0a /* Copy/Compare/Copy&Verify illgal */ -#define ABRT_CMD 0x0b /* Target make the command in error */ -#define EQUAL 0x0c /* Search Data end with Equal */ -#define VLM_OVRFLW 0x0d /* Some data are left in buffer */ -#define MISCMP 0x0e /* find inequality */ - -/*----------------------------------- - SENSE_DATA ------------------------------------*/ -/*---- valid ----*/ -#define SENSE_VALID 0x80 /* Sense data is valid as SCSI2 */ -#define SENSE_INVALID 0x00 /* Sense data is invalid as SCSI2 */ - -/*---- error code ----*/ -#define CUR_ERR 0x70 /* current error */ -#define DEF_ERR 0x71 /* specific command error */ - -/*---- sense key Infomation ----*/ -#define SNSKEYINFO_LEN 3 /* length of sense key infomation */ - -#define SKSV 0x80 -#define CDB_ILLEGAL 0x40 -#define DAT_ILLEGAL 0x00 -#define BPV 0x08 -#define BIT_ILLEGAL0 0 /* bit0 is illegal */ -#define BIT_ILLEGAL1 1 /* bit1 is illegal */ -#define BIT_ILLEGAL2 2 /* bit2 is illegal */ -#define BIT_ILLEGAL3 3 /* bit3 is illegal */ -#define BIT_ILLEGAL4 4 /* bit4 is illegal */ -#define BIT_ILLEGAL5 5 /* bit5 is illegal */ -#define BIT_ILLEGAL6 6 /* bit6 is illegal */ -#define BIT_ILLEGAL7 7 /* bit7 is illegal */ - -/*---- ASC ----*/ -#define ASC_NO_INFO 0x00 -#define ASC_MISCMP 0x1d -#define ASC_INVLD_CDB 0x24 -#define ASC_INVLD_PARA 0x26 -#define ASC_LU_NOT_READY 0x04 -#define ASC_WRITE_ERR 0x0c -#define ASC_READ_ERR 0x11 -#define ASC_LOAD_EJCT_ERR 0x53 -#define ASC_MEDIA_NOT_PRESENT 0x3A -#define ASC_MEDIA_CHANGED 0x28 -#define ASC_MEDIA_IN_PROCESS 0x04 -#define ASC_WRITE_PROTECT 0x27 -#define ASC_LUN_NOT_SUPPORTED 0x25 - -/*---- ASQC ----*/ -#define ASCQ_NO_INFO 0x00 -#define ASCQ_MEDIA_IN_PROCESS 0x01 -#define ASCQ_MISCMP 0x00 -#define ASCQ_INVLD_CDB 0x00 -#define ASCQ_INVLD_PARA 0x02 -#define ASCQ_LU_NOT_READY 0x02 -#define ASCQ_WRITE_ERR 0x02 -#define ASCQ_READ_ERR 0x00 -#define ASCQ_LOAD_EJCT_ERR 0x00 -#define ASCQ_WRITE_PROTECT 0x00 - -struct sense_data_t { - unsigned char err_code; /* error code */ - /* bit7 : valid */ - /* (1 : SCSI2) */ - /* (0 : Vendor specific) */ - /* bit6-0 : error code */ - /* (0x70 : current error) */ - /* (0x71 : specific command error) */ - unsigned char seg_no; /* segment No. */ - unsigned char sense_key; /* byte5 : ILI */ - /* bit3-0 : sense key */ - unsigned char info[4]; /* infomation */ - unsigned char ad_sense_len; /* additional sense data length */ - unsigned char cmd_info[4]; /* command specific infomation */ - unsigned char asc; /* ASC */ - unsigned char ascq; /* ASCQ */ - unsigned char rfu; /* FRU */ - unsigned char sns_key_info[3]; /* sense key specific infomation */ -}; - -/* sd_ctl bit map */ -/* SD push point control, bit 0, 1 */ -#define SD_PUSH_POINT_CTL_MASK 0x03 -#define SD_PUSH_POINT_DELAY 0x01 -#define SD_PUSH_POINT_AUTO 0x02 -/* SD sample point control, bit 2, 3 */ -#define SD_SAMPLE_POINT_CTL_MASK 0x0C -#define SD_SAMPLE_POINT_DELAY 0x04 -#define SD_SAMPLE_POINT_AUTO 0x08 -/* SD DDR Tx phase set by user, bit 4 */ -#define SD_DDR_TX_PHASE_SET_BY_USER 0x10 -/* MMC DDR Tx phase set by user, bit 5 */ -#define MMC_DDR_TX_PHASE_SET_BY_USER 0x20 -/* Support MMC DDR mode, bit 6 */ -/*#define SUPPORT_MMC_DDR_MODE 0x40 */ -#define SUPPORT_UHS50_MMC44 0x40 - -struct rts51x_option { - u8 led_blink_speed; - - int mspro_formatter_enable; - - /* card clock expected by user for fpga platform */ - int fpga_sd_sdr104_clk; - int fpga_sd_ddr50_clk; - int fpga_sd_sdr50_clk; - int fpga_sd_hs_clk; - int fpga_mmc_52m_clk; - int fpga_ms_hg_clk; - int fpga_ms_4bit_clk; - - /* card clock expected by user for asic platform */ - int asic_sd_sdr104_clk; - int asic_sd_ddr50_clk; - int asic_sd_sdr50_clk; - int asic_sd_hs_clk; - int asic_mmc_52m_clk; - int asic_ms_hg_clk; - int asic_ms_4bit_clk; - - u8 ssc_depth_sd_sdr104; /* sw */ - u8 ssc_depth_sd_ddr50; /* sw */ - u8 ssc_depth_sd_sdr50; /* sw */ - u8 ssc_depth_sd_hs; /* sw */ - u8 ssc_depth_mmc_52m; /* sw */ - u8 ssc_depth_ms_hg; /* sw */ - u8 ssc_depth_ms_4bit; /* sw */ - u8 ssc_depth_low_speed; /* sw */ - - /* SD/MMC Tx phase */ - int sd_ddr_tx_phase; /* Enabled by bit 4 of sd_ctl */ - int mmc_ddr_tx_phase; /* Enabled by bit 5 of sd_ctl */ - - /* priority of choosing sd speed funciton */ - u32 sd_speed_prior; - - /* sd card control */ - u32 sd_ctl; - - /* Enable Selective Suspend */ - int ss_en; - /* Interval to enter SS from IDLE state (second) */ - int ss_delay; - int needs_remote_wakeup; - u8 ww_enable; /* sangdy2010-08-03:add for remote wakeup */ - - /* Enable SSC clock */ - int ssc_en; - - int auto_delink_en; - - /* sangdy2010-07-13:add FT2 fast mode */ - int FT2_fast_mode; - /* sangdy2010-07-15: - * add for config delay between 1/4 PMOS and 3/4 PMOS */ - int pwr_delay; - - int xd_rw_step; /* add to tune xd tRP */ - int D3318_off_delay; /* add to tune D3318 off delay time */ - int delink_delay; /* add to tune delink delay time */ - /* add for rts5129 to enable/disable D3318 off */ - u8 rts5129_D3318_off_enable; - u8 sd20_pad_drive; /* add to config SD20 PAD drive */ - u8 sd30_pad_drive; /* add to config SD30 pad drive */ - /*if reset or rw fail,then set SD20 pad drive again */ - u8 reset_or_rw_fail_set_pad_drive; - - u8 rcc_fail_flag; /* add to indicate whether rcc bug happen */ - u8 rcc_bug_fix_en; /* if set,then support fixing rcc bug */ - u8 debounce_num; /* debounce number */ - int polling_time; /* polling delay time */ - u8 led_toggle_interval; /* used to control led toggle speed */ - int xd_rwn_step; - u8 sd_send_status_en; - /* used to store default phase which is - * used when phase tune all pass. */ - u8 ddr50_tx_phase; - u8 ddr50_rx_phase; - u8 sdr50_tx_phase; - u8 sdr50_rx_phase; - /* used to enable select sdr50 tx phase according to proportion. */ - u8 sdr50_phase_sel; - u8 ms_errreg_fix; - u8 reset_mmc_first; - u8 speed_mmc; /* when set, then try CMD55 only twice */ - u8 led_always_on; /* if set, then led always on when card exist */ - u8 dv18_voltage; /* add to tune dv18 voltage */ -}; - -#define MS_FORMATTER_ENABLED(chip) ((chip)->option.mspro_formatter_enable) - -struct rts51x_chip; - -typedef int (*card_rw_func) (struct scsi_cmnd *srb, struct rts51x_chip *chip, - u32 sec_addr, u16 sec_cnt); - -/* For MS Card */ -#define MAX_DEFECTIVE_BLOCK 10 - -struct zone_entry { - u16 *l2p_table; - u16 *free_table; - u16 defect_list[MAX_DEFECTIVE_BLOCK]; /* For MS card only */ - int set_index; - int get_index; - int unused_blk_cnt; - int disable_count; - /* To indicate whether the L2P table of this zone has been built. */ - int build_flag; -}; - -struct xd_delay_write_tag { - u32 old_phyblock; - u32 new_phyblock; - u32 logblock; - u8 pageoff; - u8 delay_write_flag; -}; - -struct xd_info { - u8 maker_code; - u8 device_code; - u8 block_shift; - u8 page_off; - u8 addr_cycle; - u16 cis_block; - u8 multi_flag; - u8 err_code; - u32 capacity; - - struct zone_entry *zone; - int zone_cnt; - - struct xd_delay_write_tag delay_write; - - int counter; - - int xd_clock; -}; - -#define TYPE_SD 0x0000 -#define TYPE_MMC 0x0001 - -/* TYPE_SD */ -#define SD_HS 0x0100 -#define SD_SDR50 0x0200 -#define SD_DDR50 0x0400 -#define SD_SDR104 0x0800 -#define SD_HCXC 0x1000 - -/* TYPE_MMC */ -#define MMC_26M 0x0100 -#define MMC_52M 0x0200 -#define MMC_4BIT 0x0400 -#define MMC_8BIT 0x0800 -#define MMC_SECTOR_MODE 0x1000 -#define MMC_DDR52 0x2000 - -/* SD card */ -#define CHK_SD(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_SD) -#define CHK_SD_HS(sd_card) \ - (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HS)) -#define CHK_SD_SDR50(sd_card) \ - (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR50)) -#define CHK_SD_DDR50(sd_card) \ - (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_DDR50)) -#define CHK_SD_SDR104(sd_card) \ - (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR104)) -#define CHK_SD_HCXC(sd_card) \ - (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HCXC)) -#define CHK_SD30_SPEED(sd_card) \ - (CHK_SD_SDR50(sd_card) || CHK_SD_DDR50(sd_card) ||\ - CHK_SD_SDR104(sd_card)) - -#define SET_SD(sd_card) ((sd_card)->sd_type = TYPE_SD) -#define SET_SD_HS(sd_card) ((sd_card)->sd_type |= SD_HS) -#define SET_SD_SDR50(sd_card) ((sd_card)->sd_type |= SD_SDR50) -#define SET_SD_DDR50(sd_card) ((sd_card)->sd_type |= SD_DDR50) -#define SET_SD_SDR104(sd_card) ((sd_card)->sd_type |= SD_SDR104) -#define SET_SD_HCXC(sd_card) ((sd_card)->sd_type |= SD_HCXC) - -#define CLR_SD_HS(sd_card) ((sd_card)->sd_type &= ~SD_HS) -#define CLR_SD_SDR50(sd_card) ((sd_card)->sd_type &= ~SD_SDR50) -#define CLR_SD_DDR50(sd_card) ((sd_card)->sd_type &= ~SD_DDR50) -#define CLR_SD_SDR104(sd_card) ((sd_card)->sd_type &= ~SD_SDR104) -#define CLR_SD_HCXC(sd_card) ((sd_card)->sd_type &= ~SD_HCXC) -#define CLR_SD30_SPEED(sd_card) \ - ((sd_card)->sd_type &= ~(SD_SDR50|SD_DDR50|SD_SDR104)) - -/* MMC card */ -#define CHK_MMC(sd_card) \ - (((sd_card)->sd_type & 0xFF) == TYPE_MMC) -#define CHK_MMC_26M(sd_card) \ - (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_26M)) -#define CHK_MMC_52M(sd_card) \ - (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_52M)) -#define CHK_MMC_4BIT(sd_card) \ - (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_4BIT)) -#define CHK_MMC_8BIT(sd_card) \ - (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_8BIT)) -#define CHK_MMC_SECTOR_MODE(sd_card)\ - (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_SECTOR_MODE)) -#define CHK_MMC_DDR52(sd_card) \ - (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_DDR52)) - -#define SET_MMC(sd_card) ((sd_card)->sd_type = TYPE_MMC) -#define SET_MMC_26M(sd_card) ((sd_card)->sd_type |= MMC_26M) -#define SET_MMC_52M(sd_card) ((sd_card)->sd_type |= MMC_52M) -#define SET_MMC_4BIT(sd_card) ((sd_card)->sd_type |= MMC_4BIT) -#define SET_MMC_8BIT(sd_card) ((sd_card)->sd_type |= MMC_8BIT) -#define SET_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type |= MMC_SECTOR_MODE) -#define SET_MMC_DDR52(sd_card) ((sd_card)->sd_type |= MMC_DDR52) - -#define CLR_MMC_26M(sd_card) ((sd_card)->sd_type &= ~MMC_26M) -#define CLR_MMC_52M(sd_card) ((sd_card)->sd_type &= ~MMC_52M) -#define CLR_MMC_4BIT(sd_card) ((sd_card)->sd_type &= ~MMC_4BIT) -#define CLR_MMC_8BIT(sd_card) ((sd_card)->sd_type &= ~MMC_8BIT) -#define CLR_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type &= ~MMC_SECTOR_MODE) -#define CLR_MMC_DDR52(sd_card) ((sd_card)->sd_type &= ~MMC_DDR52) - -#define CHK_MMC_HS(sd_card) \ - (CHK_MMC_52M(sd_card) && CHK_MMC_26M(sd_card)) -#define CLR_MMC_HS(sd_card) \ -do { \ - CLR_MMC_DDR52(sd_card); \ - CLR_MMC_52M(sd_card); \ - CLR_MMC_26M(sd_card); \ -} while (0) - -#define SD_SUPPORT_CLASS_TEN 0x01 -#define SD_SUPPORT_1V8 0x02 - -#define SD_SET_CLASS_TEN(sd_card) \ - ((sd_card)->sd_setting |= SD_SUPPORT_CLASS_TEN) -#define SD_CHK_CLASS_TEN(sd_card) \ - ((sd_card)->sd_setting & SD_SUPPORT_CLASS_TEN) -#define SD_CLR_CLASS_TEN(sd_card) \ - ((sd_card)->sd_setting &= ~SD_SUPPORT_CLASS_TEN) -#define SD_SET_1V8(sd_card) \ - ((sd_card)->sd_setting |= SD_SUPPORT_1V8) -#define SD_CHK_1V8(sd_card) \ - ((sd_card)->sd_setting & SD_SUPPORT_1V8) -#define SD_CLR_1V8(sd_card) \ - ((sd_card)->sd_setting &= ~SD_SUPPORT_1V8) -#define CLR_RETRY_SD20_MODE(sd_card) \ - ((sd_card)->retry_SD20_mode = 0) -#define SET_RETRY_SD20_MODE(sd_card) \ - ((sd_card)->retry_SD20_mode = 1) -#define CHK_RETRY_SD20_MODE(sd_card) \ - ((sd_card)->retry_SD20_mode == 1) - -struct sd_info { - u16 sd_type; - u8 err_code; - u8 sd_data_buf_ready; - u32 sd_addr; - u32 capacity; - - u8 raw_csd[16]; - u8 raw_scr[8]; - - /* Sequential RW */ - int seq_mode; - enum dma_data_direction pre_dir; - u32 pre_sec_addr; - u16 pre_sec_cnt; - - int counter; - - int sd_clock; - -#ifdef SUPPORT_CPRM - int sd_pass_thru_en; - int pre_cmd_err; - u8 last_rsp_type; - u8 rsp[17]; -#endif - - u8 func_group1_mask; - u8 func_group2_mask; - u8 func_group3_mask; - u8 func_group4_mask; - - u8 sd_switch_fail; - u8 sd_read_phase; - u8 retry_SD20_mode; /* sangdy2010-06-10 */ - u8 sd_reset_fail; /* sangdy2010-07-01 */ - u8 sd_send_status_en; - -#ifdef SUPPORT_SD_LOCK - u8 sd_lock_status; - u8 sd_erase_status; - u8 sd_lock_notify; -#endif -}; - -#define MODE_512_SEQ 0x01 -#define MODE_2K_SEQ 0x02 - -#define TYPE_MS 0x0000 -#define TYPE_MSPRO 0x0001 - -#define MS_4BIT 0x0100 -#define MS_8BIT 0x0200 -#define MS_HG 0x0400 -#define MS_XC 0x0800 - -#define HG8BIT (MS_HG | MS_8BIT) - -#define CHK_MSPRO(ms_card) \ - (((ms_card)->ms_type & 0xFF) == TYPE_MSPRO) -#define CHK_HG8BIT(ms_card) \ - (CHK_MSPRO(ms_card) && (((ms_card)->ms_type & HG8BIT) == HG8BIT)) -#define CHK_MSXC(ms_card) \ - (CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_XC)) -#define CHK_MSHG(ms_card) \ - (CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_HG)) - -#define CHK_MS8BIT(ms_card) (((ms_card)->ms_type & MS_8BIT)) -#define CHK_MS4BIT(ms_card) (((ms_card)->ms_type & MS_4BIT)) - -struct ms_delay_write_tag { - u16 old_phyblock; - u16 new_phyblock; - u16 logblock; - u8 pageoff; - u8 delay_write_flag; -}; - -struct ms_info { - u16 ms_type; - u8 block_shift; - u8 page_off; - u16 total_block; - u16 boot_block; - u32 capacity; - - u8 check_ms_flow; - u8 switch_8bit_fail; - u8 err_code; - - struct zone_entry *segment; - int segment_cnt; - - int pro_under_formatting; - int format_status; - u16 progress; - u8 raw_sys_info[96]; -#ifdef SUPPORT_PCGL_1P18 - u8 raw_model_name[48]; -#endif - - u8 multi_flag; - - /* Sequential RW */ - u8 seq_mode; - enum dma_data_direction pre_dir; - u32 pre_sec_addr; - u16 pre_sec_cnt; - u32 total_sec_cnt; - u8 last_rw_int; - - struct ms_delay_write_tag delay_write; - - int counter; - - int ms_clock; - -#ifdef SUPPORT_MAGIC_GATE - u8 magic_gate_id[16]; - u8 mg_entry_num; - int mg_auth; /* flag to indicate authentication process */ -#endif -}; - -#define PRO_UNDER_FORMATTING(ms_card) \ - ((ms_card)->pro_under_formatting) -#define SET_FORMAT_STATUS(ms_card, status) \ - ((ms_card)->format_status = (status)) -#define CHK_FORMAT_STATUS(ms_card, status) \ - ((ms_card)->format_status == (status)) - -struct scsi_cmnd; - -enum CHIP_STAT { STAT_INIT, STAT_IDLE, STAT_RUN, STAT_SS_PRE, STAT_SS, - STAT_SUSPEND }; - -struct rts51x_chip { - u16 vendor_id; - u16 product_id; - char max_lun; - - struct scsi_cmnd *srb; - struct sense_data_t sense_buffer[MAX_ALLOWED_LUN_CNT]; - -#ifndef LED_AUTO_BLINK - int led_toggle_counter; -#endif - int ss_counter; - int idle_counter; - int auto_delink_counter; - enum CHIP_STAT chip_stat; - - int resume_from_scsi; - - /* Card information */ - struct xd_info xd_card; - struct sd_info sd_card; - struct ms_info ms_card; - - int cur_clk; /* current card clock */ - int cur_card; /* Current card module */ - - u8 card_exist; /* card exist bit map (physical exist) */ - u8 card_ready; /* card ready bit map (reset successfully) */ - u8 card_fail; /* card reset fail bit map */ - u8 card_ejected; /* card ejected bit map */ - u8 card_wp; /* card write protected bit map */ - - u8 fake_card_ready; - /* flag to indicate whether to answer MediaChange */ - unsigned long lun_mc; - - /* card bus width */ - u8 card_bus_width[MAX_ALLOWED_LUN_CNT]; - /* card capacity */ - u32 capacity[MAX_ALLOWED_LUN_CNT]; - - /* read/write card function pointer */ - card_rw_func rw_card[MAX_ALLOWED_LUN_CNT]; - /* read/write capacity, used for GPIO Toggle */ - u32 rw_cap[MAX_ALLOWED_LUN_CNT]; - /* card to lun mapping table */ - u8 card2lun[32]; - /* lun to card mapping table */ - u8 lun2card[MAX_ALLOWED_LUN_CNT]; - -#ifdef _MSG_TRACE - struct trace_msg_t trace_msg[TRACE_ITEM_CNT]; - int msg_idx; -#endif - - int rw_need_retry; - - /* ASIC or FPGA */ - int asic_code; - - /* QFN24 or LQFP48 */ - int package; - - /* Full Speed or High Speed */ - int usb_speed; - - /*sangdy:enable or disable UHS50 and MMC4.4 */ - int uhs50_mmc44_en; - - u8 ic_version; - - /* Command buffer */ - u8 *cmd_buf; - unsigned int cmd_idx; - /* Response buffer */ - u8 *rsp_buf; - - u16 card_status; - -#ifdef SUPPORT_OCP - u16 ocp_stat; -#endif - - struct rts51x_option option; - struct rts51x_usb *usb; - - u8 rcc_read_response; - int reset_need_retry; - u8 rts5179; -}; - -#define UHS50_EN 0x0001 -#define UHS50_DIS 0x0000 -#define SET_UHS50(chip) ((chip)->uhs50_mmc44_en = UHS50_EN) -#define CLEAR_UHS50(chip) ((chip)->uhs50_mmc44_en = UHS50_DIS) -#define CHECK_UHS50(chip) (((chip)->uhs50_mmc44_en&0xff) == UHS50_EN) - -#define RTS51X_GET_VID(chip) ((chip)->vendor_id) -#define RTS51X_GET_PID(chip) ((chip)->product_id) - -#define RTS51X_SET_STAT(chip, stat) \ -do { \ - if ((stat) != STAT_IDLE) { \ - (chip)->idle_counter = 0; \ - } \ - (chip)->chip_stat = (enum CHIP_STAT)(stat); \ -} while (0) -#define RTS51X_CHK_STAT(chip, stat) ((chip)->chip_stat == (stat)) -#define RTS51X_GET_STAT(chip) ((chip)->chip_stat) - -#define CHECK_PID(chip, pid) (RTS51X_GET_PID(chip) == (pid)) -#define CHECK_PKG(chip, pkg) ((chip)->package == (pkg)) -#define CHECK_USB(chip, speed) ((chip)->usb_speed == (speed)) - -int rts51x_reset_chip(struct rts51x_chip *chip); -int rts51x_init_chip(struct rts51x_chip *chip); -int rts51x_release_chip(struct rts51x_chip *chip); -void rts51x_polling_func(struct rts51x_chip *chip); - -static inline void rts51x_init_cmd(struct rts51x_chip *chip) -{ - chip->cmd_idx = 0; - chip->cmd_buf[0] = 'R'; - chip->cmd_buf[1] = 'T'; - chip->cmd_buf[2] = 'C'; - chip->cmd_buf[3] = 'R'; - chip->cmd_buf[PACKET_TYPE] = BATCH_CMD; -} - -void rts51x_add_cmd(struct rts51x_chip *chip, - u8 cmd_type, u16 reg_addr, u8 mask, u8 data); -int rts51x_send_cmd(struct rts51x_chip *chip, u8 flag, int timeout); -int rts51x_get_rsp(struct rts51x_chip *chip, int rsp_len, int timeout); - -static inline void rts51x_read_rsp_buf(struct rts51x_chip *chip, int offset, - u8 *buf, int buf_len) -{ - memcpy(buf, chip->rsp_buf + offset, buf_len); -} - -static inline u8 *rts51x_get_rsp_data(struct rts51x_chip *chip) -{ - return chip->rsp_buf; -} - -int rts51x_get_card_status(struct rts51x_chip *chip, u16 * status); -int rts51x_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, u8 data); -int rts51x_read_register(struct rts51x_chip *chip, u16 addr, u8 * data); -int rts51x_ep0_write_register(struct rts51x_chip *chip, u16 addr, u8 mask, - u8 data); -int rts51x_ep0_read_register(struct rts51x_chip *chip, u16 addr, u8 * data); -int rts51x_seq_write_register(struct rts51x_chip *chip, u16 addr, u16 len, - u8 *data); -int rts51x_seq_read_register(struct rts51x_chip *chip, u16 addr, u16 len, - u8 *data); -int rts51x_read_ppbuf(struct rts51x_chip *chip, u8 *buf, int buf_len); -int rts51x_write_ppbuf(struct rts51x_chip *chip, u8 *buf, int buf_len); -int rts51x_write_phy_register(struct rts51x_chip *chip, u8 addr, u8 val); -int rts51x_read_phy_register(struct rts51x_chip *chip, u8 addr, u8 *val); -void rts51x_do_before_power_down(struct rts51x_chip *chip); -void rts51x_clear_hw_error(struct rts51x_chip *chip); -void rts51x_prepare_run(struct rts51x_chip *chip); -void rts51x_trace_msg(struct rts51x_chip *chip, unsigned char *buf, int clear); -void rts51x_pp_status(struct rts51x_chip *chip, unsigned int lun, u8 *status, - u8 status_len); -void rts51x_read_status(struct rts51x_chip *chip, unsigned int lun, - u8 *rts51x_status, u8 status_len); -int rts51x_transfer_data_rcc(struct rts51x_chip *chip, unsigned int pipe, - void *buf, unsigned int len, int use_sg, - unsigned int *act_len, int timeout, u8 stage_flag); - -#define RTS51X_WRITE_REG(chip, addr, mask, data) \ -do { \ - int _retval = rts51x_write_register((chip), \ - (addr), (mask), (data)); \ - if (_retval != STATUS_SUCCESS) { \ - TRACE_RET((chip), _retval); \ - } \ -} while (0) - -#define RTS51X_READ_REG(chip, addr, data) \ -do { \ - int _retval = rts51x_read_register((chip), \ - (addr), (data)); \ - if (_retval != STATUS_SUCCESS) { \ - TRACE_RET((chip), _retval); \ - } \ -} while (0) - -#endif /* __RTS51X_CHIP_H */ diff --git a/trunk/drivers/staging/rts5139/rts51x_fop.c b/trunk/drivers/staging/rts5139/rts51x_fop.c deleted file mode 100644 index 6eaebb6223c9..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_fop.c +++ /dev/null @@ -1,298 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include "rts51x.h" - -#ifdef SUPPORT_FILE_OP - -#include -#include -#include -#include - -#include "rts51x_chip.h" -#include "rts51x_card.h" -#include "rts51x_fop.h" -#include "sd_cprm.h" -#include "rts51x.h" - -#define RTS5139_IOC_MAGIC 0x39 - -#define RTS5139_IOC_SD_DIRECT _IOWR(RTS5139_IOC_MAGIC, 0xA0, int) -#define RTS5139_IOC_SD_GET_RSP _IOWR(RTS5139_IOC_MAGIC, 0xA1, int) - -static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip, - struct sd_direct_cmnd *cmnd) -{ - int retval; - u8 dir, cmd12, standby, acmd, cmd_idx, rsp_code; - u8 *buf; - u32 arg, len; - - dir = (cmnd->cmnd[0] >> 3) & 0x03; - cmd12 = (cmnd->cmnd[0] >> 2) & 0x01; - standby = (cmnd->cmnd[0] >> 1) & 0x01; - acmd = cmnd->cmnd[0] & 0x01; - cmd_idx = cmnd->cmnd[1]; - arg = ((u32) (cmnd->cmnd[2]) << 24) | ((u32) (cmnd->cmnd[3]) << 16) | - ((u32) (cmnd->cmnd[4]) << 8) | cmnd->cmnd[5]; - len = - ((u32) (cmnd->cmnd[6]) << 16) | ((u32) (cmnd->cmnd[7]) << 8) | - cmnd->cmnd[8]; - rsp_code = cmnd->cmnd[9]; - - if (dir) { - if (!cmnd->buf || (cmnd->buf_len < len)) - TRACE_RET(chip, STATUS_FAIL); - } - - switch (dir) { - case 0: - /* No data */ - retval = ext_sd_execute_no_data(chip, chip->card2lun[SD_CARD], - cmd_idx, standby, acmd, - rsp_code, arg); - if (retval != TRANSPORT_GOOD) - TRACE_RET(chip, STATUS_FAIL); - break; - - case 1: - /* Read from card */ - buf = kmalloc(cmnd->buf_len, GFP_KERNEL); - if (!buf) - TRACE_RET(chip, STATUS_NOMEM); - - retval = ext_sd_execute_read_data(chip, chip->card2lun[SD_CARD], - cmd_idx, cmd12, standby, acmd, - rsp_code, arg, len, buf, - cmnd->buf_len, 0); - if (retval != TRANSPORT_GOOD) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = - copy_to_user((void *)cmnd->buf, (void *)buf, cmnd->buf_len); - if (retval) { - kfree(buf); - TRACE_RET(chip, STATUS_NOMEM); - } - - kfree(buf); - break; - - case 2: - /* Write to card */ - buf = kmalloc(cmnd->buf_len, GFP_KERNEL); - if (!buf) - TRACE_RET(chip, STATUS_NOMEM); - - retval = - copy_from_user((void *)buf, (void *)cmnd->buf, - cmnd->buf_len); - if (retval) { - kfree(buf); - TRACE_RET(chip, STATUS_NOMEM); - } - - retval = - ext_sd_execute_write_data(chip, chip->card2lun[SD_CARD], - cmd_idx, cmd12, standby, acmd, - rsp_code, arg, len, buf, - cmnd->buf_len, 0); - if (retval != TRANSPORT_GOOD) { - kfree(buf); - TRACE_RET(chip, STATUS_FAIL); - } - - kfree(buf); - - break; - - default: - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int rts51x_sd_get_rsp(struct rts51x_chip *chip, struct sd_rsp *rsp) -{ - struct sd_info *sd_card = &(chip->sd_card); - int count = 0, retval; - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - TRACE_RET(chip, STATUS_FAIL); - } - - if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) - TRACE_RET(chip, STATUS_FAIL); - else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) - count = (rsp->rsp_len < 17) ? rsp->rsp_len : 17; - else - count = (rsp->rsp_len < 6) ? rsp->rsp_len : 6; - - retval = copy_to_user((void *)rsp->rsp, (void *)sd_card->rsp, count); - if (retval) - TRACE_RET(chip, STATUS_NOMEM); - - RTS51X_DEBUGP("Response length: %d\n", count); - RTS51X_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n", - sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2], - sd_card->rsp[3]); - - return STATUS_SUCCESS; -} - -int rts51x_open(struct inode *inode, struct file *filp) -{ - struct rts51x_chip *chip; - struct usb_interface *interface; - int subminor; - int retval = 0; - - subminor = iminor(inode); - - interface = usb_find_interface(&rts51x_driver, subminor); - if (!interface) { - RTS51X_DEBUGP("%s - error, can't find device for minor %d\n", - __func__, subminor); - retval = -ENODEV; - goto exit; - } - - chip = (struct rts51x_chip *)usb_get_intfdata(interface); - if (!chip) { - RTS51X_DEBUGP("Can't find chip\n"); - retval = -ENODEV; - goto exit; - } - - /* Increase our reference to the host */ - scsi_host_get(rts51x_to_host(chip)); - - /* lock the device pointers */ - mutex_lock(&(chip->usb->dev_mutex)); - - /* save our object in the file's private structure */ - filp->private_data = chip; - - /* unlock the device pointers */ - mutex_unlock(&chip->usb->dev_mutex); - -exit: - return retval; -} - -int rts51x_release(struct inode *inode, struct file *filp) -{ - struct rts51x_chip *chip; - - chip = (struct rts51x_chip *)filp->private_data; - if (chip == NULL) - return -ENODEV; - - /* Drop our reference to the host; the SCSI core will free it - * (and "chip" along with it) when the refcount becomes 0. */ - scsi_host_put(rts51x_to_host(chip)); - - return 0; -} - -ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count, - loff_t *f_pos) -{ - return 0; -} - -ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count, - loff_t *f_pos) -{ - return 0; -} - -#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) */ -int rts51x_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) -#else -long rts51x_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -#endif -{ - struct rts51x_chip *chip; - struct sd_direct_cmnd cmnd; - struct sd_rsp rsp; - int retval = 0; - - chip = (struct rts51x_chip *)filp->private_data; - if (chip == NULL) - return -ENODEV; - - /* lock the device pointers */ - mutex_lock(&(chip->usb->dev_mutex)); - - switch (cmd) { - case RTS5139_IOC_SD_DIRECT: - retval = - copy_from_user((void *)&cmnd, (void *)arg, - sizeof(struct sd_direct_cmnd)); - if (retval) { - retval = -ENOMEM; - TRACE_GOTO(chip, exit); - } - retval = rts51x_sd_direct_cmnd(chip, &cmnd); - if (retval != STATUS_SUCCESS) { - retval = -EIO; - TRACE_GOTO(chip, exit); - } - break; - - case RTS5139_IOC_SD_GET_RSP: - retval = - copy_from_user((void *)&rsp, (void *)arg, - sizeof(struct sd_rsp)); - if (retval) { - retval = -ENOMEM; - TRACE_GOTO(chip, exit); - } - retval = rts51x_sd_get_rsp(chip, &rsp); - if (retval != STATUS_SUCCESS) { - retval = -EIO; - TRACE_GOTO(chip, exit); - } - break; - - default: - break; - } - -exit: - /* unlock the device pointers */ - mutex_unlock(&chip->usb->dev_mutex); - - return retval; -} - -#endif diff --git a/trunk/drivers/staging/rts5139/rts51x_fop.h b/trunk/drivers/staging/rts5139/rts51x_fop.h deleted file mode 100644 index 0453f57d1a84..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_fop.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_FOP_H -#define __RTS51X_FOP_H - -#include "rts51x.h" - -#ifdef SUPPORT_FILE_OP - -#include -#include - -struct sd_direct_cmnd { - u8 cmnd[12]; - void *buf; - int buf_len; -}; - -struct sd_rsp { - void *rsp; - int rsp_len; -}; - -int rts51x_open(struct inode *inode, struct file *filp); -int rts51x_release(struct inode *inode, struct file *filp); -ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count, - loff_t *f_pos); -ssize_t rts51x_write(struct file *filp, const char __user * buf, size_t count, - loff_t *f_pos); -#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) */ -int rts51x_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg); -#else -long rts51x_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -#endif - -#endif - -#endif /* __RTS51X_FOP_H */ diff --git a/trunk/drivers/staging/rts5139/rts51x_scsi.c b/trunk/drivers/staging/rts5139/rts51x_scsi.c deleted file mode 100644 index 3b32f9e6e4f0..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_scsi.c +++ /dev/null @@ -1,2234 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "debug.h" -#include "rts51x.h" -#include "rts51x_chip.h" -#include "rts51x_scsi.h" -#include "rts51x_card.h" -#include "rts51x_transport.h" -#include "rts51x_sys.h" -#include "sd_cprm.h" -#include "ms_mg.h" -#include "trace.h" - -void scsi_show_command(struct scsi_cmnd *srb) -{ - char *what = NULL; - int i, unknown_cmd = 0; - - switch (srb->cmnd[0]) { - case TEST_UNIT_READY: - what = (char *)"TEST_UNIT_READY"; - break; - case REZERO_UNIT: - what = (char *)"REZERO_UNIT"; - break; - case REQUEST_SENSE: - what = (char *)"REQUEST_SENSE"; - break; - case FORMAT_UNIT: - what = (char *)"FORMAT_UNIT"; - break; - case READ_BLOCK_LIMITS: - what = (char *)"READ_BLOCK_LIMITS"; - break; - case 0x07: - what = (char *)"REASSIGN_BLOCKS"; - break; - case READ_6: - what = (char *)"READ_6"; - break; - case WRITE_6: - what = (char *)"WRITE_6"; - break; - case SEEK_6: - what = (char *)"SEEK_6"; - break; - case READ_REVERSE: - what = (char *)"READ_REVERSE"; - break; - case WRITE_FILEMARKS: - what = (char *)"WRITE_FILEMARKS"; - break; - case SPACE: - what = (char *)"SPACE"; - break; - case INQUIRY: - what = (char *)"INQUIRY"; - break; - case RECOVER_BUFFERED_DATA: - what = (char *)"RECOVER_BUFFERED_DATA"; - break; - case MODE_SELECT: - what = (char *)"MODE_SELECT"; - break; - case RESERVE: - what = (char *)"RESERVE"; - break; - case RELEASE: - what = (char *)"RELEASE"; - break; - case COPY: - what = (char *)"COPY"; - break; - case ERASE: - what = (char *)"ERASE"; - break; - case MODE_SENSE: - what = (char *)"MODE_SENSE"; - break; - case START_STOP: - what = (char *)"START_STOP"; - break; - case RECEIVE_DIAGNOSTIC: - what = (char *)"RECEIVE_DIAGNOSTIC"; - break; - case SEND_DIAGNOSTIC: - what = (char *)"SEND_DIAGNOSTIC"; - break; - case ALLOW_MEDIUM_REMOVAL: - what = (char *)"ALLOW_MEDIUM_REMOVAL"; - break; - case SET_WINDOW: - what = (char *)"SET_WINDOW"; - break; - case READ_CAPACITY: - what = (char *)"READ_CAPACITY"; - break; - case READ_10: - what = (char *)"READ_10"; - break; - case WRITE_10: - what = (char *)"WRITE_10"; - break; - case SEEK_10: - what = (char *)"SEEK_10"; - break; - case WRITE_VERIFY: - what = (char *)"WRITE_VERIFY"; - break; - case VERIFY: - what = (char *)"VERIFY"; - break; - case SEARCH_HIGH: - what = (char *)"SEARCH_HIGH"; - break; - case SEARCH_EQUAL: - what = (char *)"SEARCH_EQUAL"; - break; - case SEARCH_LOW: - what = (char *)"SEARCH_LOW"; - break; - case SET_LIMITS: - what = (char *)"SET_LIMITS"; - break; - case READ_POSITION: - what = (char *)"READ_POSITION"; - break; - case SYNCHRONIZE_CACHE: - what = (char *)"SYNCHRONIZE_CACHE"; - break; - case LOCK_UNLOCK_CACHE: - what = (char *)"LOCK_UNLOCK_CACHE"; - break; - case READ_DEFECT_DATA: - what = (char *)"READ_DEFECT_DATA"; - break; - case MEDIUM_SCAN: - what = (char *)"MEDIUM_SCAN"; - break; - case COMPARE: - what = (char *)"COMPARE"; - break; - case COPY_VERIFY: - what = (char *)"COPY_VERIFY"; - break; - case WRITE_BUFFER: - what = (char *)"WRITE_BUFFER"; - break; - case READ_BUFFER: - what = (char *)"READ_BUFFER"; - break; - case UPDATE_BLOCK: - what = (char *)"UPDATE_BLOCK"; - break; - case READ_LONG: - what = (char *)"READ_LONG"; - break; - case WRITE_LONG: - what = (char *)"WRITE_LONG"; - break; - case CHANGE_DEFINITION: - what = (char *)"CHANGE_DEFINITION"; - break; - case WRITE_SAME: - what = (char *)"WRITE_SAME"; - break; - case GPCMD_READ_SUBCHANNEL: - what = (char *)"READ SUBCHANNEL"; - break; - case READ_TOC: - what = (char *)"READ_TOC"; - break; - case GPCMD_READ_HEADER: - what = (char *)"READ HEADER"; - break; - case GPCMD_PLAY_AUDIO_10: - what = (char *)"PLAY AUDIO (10)"; - break; - case GPCMD_PLAY_AUDIO_MSF: - what = (char *)"PLAY AUDIO MSF"; - break; - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - what = (char *)"GET EVENT/STATUS NOTIFICATION"; - break; - case GPCMD_PAUSE_RESUME: - what = (char *)"PAUSE/RESUME"; - break; - case LOG_SELECT: - what = (char *)"LOG_SELECT"; - break; - case LOG_SENSE: - what = (char *)"LOG_SENSE"; - break; - case GPCMD_STOP_PLAY_SCAN: - what = (char *)"STOP PLAY/SCAN"; - break; - case GPCMD_READ_DISC_INFO: - what = (char *)"READ DISC INFORMATION"; - break; - case GPCMD_READ_TRACK_RZONE_INFO: - what = (char *)"READ TRACK INFORMATION"; - break; - case GPCMD_RESERVE_RZONE_TRACK: - what = (char *)"RESERVE TRACK"; - break; - case GPCMD_SEND_OPC: - what = (char *)"SEND OPC"; - break; - case MODE_SELECT_10: - what = (char *)"MODE_SELECT_10"; - break; - case GPCMD_REPAIR_RZONE_TRACK: - what = (char *)"REPAIR TRACK"; - break; - case 0x59: - what = (char *)"READ MASTER CUE"; - break; - case MODE_SENSE_10: - what = (char *)"MODE_SENSE_10"; - break; - case GPCMD_CLOSE_TRACK: - what = (char *)"CLOSE TRACK/SESSION"; - break; - case 0x5C: - what = (char *)"READ BUFFER CAPACITY"; - break; - case 0x5D: - what = (char *)"SEND CUE SHEET"; - break; - case GPCMD_BLANK: - what = (char *)"BLANK"; - break; - case REPORT_LUNS: - what = (char *)"REPORT LUNS"; - break; - case MOVE_MEDIUM: - what = (char *)"MOVE_MEDIUM or PLAY AUDIO (12)"; - break; - case READ_12: - what = (char *)"READ_12"; - break; - case WRITE_12: - what = (char *)"WRITE_12"; - break; - case WRITE_VERIFY_12: - what = (char *)"WRITE_VERIFY_12"; - break; - case SEARCH_HIGH_12: - what = (char *)"SEARCH_HIGH_12"; - break; - case SEARCH_EQUAL_12: - what = (char *)"SEARCH_EQUAL_12"; - break; - case SEARCH_LOW_12: - what = (char *)"SEARCH_LOW_12"; - break; - case SEND_VOLUME_TAG: - what = (char *)"SEND_VOLUME_TAG"; - break; - case READ_ELEMENT_STATUS: - what = (char *)"READ_ELEMENT_STATUS"; - break; - case GPCMD_READ_CD_MSF: - what = (char *)"READ CD MSF"; - break; - case GPCMD_SCAN: - what = (char *)"SCAN"; - break; - case GPCMD_SET_SPEED: - what = (char *)"SET CD SPEED"; - break; - case GPCMD_MECHANISM_STATUS: - what = (char *)"MECHANISM STATUS"; - break; - case GPCMD_READ_CD: - what = (char *)"READ CD"; - break; - case 0xE1: - what = (char *)"WRITE CONTINUE"; - break; - case WRITE_LONG_2: - what = (char *)"WRITE_LONG_2"; - break; - case VENDOR_CMND: - what = (char *)"Realtek's vendor command"; - break; - default: - what = (char *)"(unknown command)"; - unknown_cmd = 1; - break; - } - - if (srb->cmnd[0] != TEST_UNIT_READY) - RTS51X_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len); - if (unknown_cmd) { - RTS51X_DEBUGP(""); - for (i = 0; i < srb->cmd_len && i < 16; i++) - RTS51X_DEBUGPN(" %02x", srb->cmnd[i]); - RTS51X_DEBUGPN("\n"); - } -} - -void set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type) -{ - switch (sense_type) { - case SENSE_TYPE_MEDIA_CHANGE: - set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_NOT_PRESENT: - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_LBA_OVER_RANGE: - set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT: - set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_WRITE_PROTECT: - set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR: - set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_WRITE_ERR: - set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0); - break; - - case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD: - set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0, - ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1); - break; - - case SENSE_TYPE_FORMAT_IN_PROGRESS: - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0); - break; - - case SENSE_TYPE_FORMAT_CMD_FAILED: - set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0); - break; - -#ifdef SUPPORT_MAGIC_GATE - case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB: - set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0); - break; - - case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN: - set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0); - break; - - case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM: - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0); - break; - - case SENSE_TYPE_MG_WRITE_ERR: - set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0); - break; -#endif - -#ifdef SUPPORT_SD_LOCK - case SENSE_TYPE_MEDIA_READ_FORBIDDEN: - set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0); - break; -#endif - - case SENSE_TYPE_NO_SENSE: - default: - set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0); - break; - } -} - -void set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code, - u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0, - u16 sns_key_info1) -{ - struct sense_data_t *sense = &(chip->sense_buffer[lun]); - - sense->err_code = err_code; - sense->sense_key = sense_key; - sense->info[0] = (u8) (info >> 24); - sense->info[1] = (u8) (info >> 16); - sense->info[2] = (u8) (info >> 8); - sense->info[3] = (u8) info; - - sense->ad_sense_len = sizeof(struct sense_data_t) - 8; - sense->asc = asc; - sense->ascq = ascq; - if (sns_key_info0 != 0) { - sense->sns_key_info[0] = SKSV | sns_key_info0; - sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 8; - sense->sns_key_info[2] = sns_key_info1 & 0x0f; - } -} - -static int test_unit_ready(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - - rts51x_init_cards(chip); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - - if (!check_lun_mc(chip, lun)) { - set_lun_mc(chip, lun); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } -#ifdef SUPPORT_SD_LOCK - if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) { - struct sd_info *sd_card = &(chip->sd_card); - if (sd_card->sd_lock_notify) { - sd_card->sd_lock_notify = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } else if (sd_card->sd_lock_status & SD_LOCKED) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_READ_FORBIDDEN); - return TRANSPORT_FAILED; - } - } -#endif - - return TRANSPORT_GOOD; -} - -unsigned char formatter_inquiry_str[20] = { - 'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K', - '-', 'M', 'G', /* Byte[47:49] */ - 0x0B, /* Byte[50]: MG, MS, MSPro, MSXC */ - 0x00, /* Byte[51]: Category Specific Commands */ - 0x00, /* Byte[52]: Access Control and feature */ - 0x20, 0x20, 0x20, /* Byte[53:55] */ -}; - -static int inquiry(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - char *inquiry_default = (char *)"Generic-xD/SD/M.S. 1.00 "; - char *inquiry_string; - unsigned char sendbytes; - unsigned char *buf; - u8 card = get_lun_card(chip, lun); - int pro_formatter_flag = 0; - unsigned char inquiry_buf[] = { - QULIFIRE | DRCT_ACCESS_DEV, - RMB_DISC | 0x0D, - 0x00, - 0x01, - 0x1f, - 0x02, - 0, - REL_ADR | WBUS_32 | WBUS_16 | SYNC | LINKED | CMD_QUE | SFT_RE, - }; - - inquiry_string = inquiry_default; - - buf = vmalloc(scsi_bufflen(srb)); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - if (MS_FORMATTER_ENABLED(chip) && (get_lun2card(chip, lun) & MS_CARD)) { - if (!card || (card == MS_CARD)) - pro_formatter_flag = 1; - } - - if (pro_formatter_flag) { - if (scsi_bufflen(srb) < 56) - sendbytes = (unsigned char)(scsi_bufflen(srb)); - else - sendbytes = 56; - } else { - if (scsi_bufflen(srb) < 36) - sendbytes = (unsigned char)(scsi_bufflen(srb)); - else - sendbytes = 36; - } - - if (sendbytes > 8) { - memcpy(buf, inquiry_buf, 8); - memcpy(buf + 8, inquiry_string, sendbytes - 8); - if (pro_formatter_flag) - buf[4] = 0x33; /* Additional Length */ - } else { - memcpy(buf, inquiry_buf, sendbytes); - } - - if (pro_formatter_flag) { - if (sendbytes > 36) - memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36); - } - - scsi_set_resid(srb, 0); - - rts51x_set_xfer_buf(buf, scsi_bufflen(srb), srb); - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int start_stop_unit(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - - scsi_set_resid(srb, scsi_bufflen(srb)); - - if (srb->cmnd[1] == 1) - return TRANSPORT_GOOD; - - switch (srb->cmnd[0x4]) { - case STOP_MEDIUM: - /* Media disabled */ - return TRANSPORT_GOOD; - - case UNLOAD_MEDIUM: - /* Media shall be unload */ - if (check_card_ready(chip, lun)) - eject_card(chip, lun); - return TRANSPORT_GOOD; - - case MAKE_MEDIUM_READY: - case LOAD_MEDIUM: - if (check_card_ready(chip, lun)) { - return TRANSPORT_GOOD; - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - break; - } - - TRACE_RET(chip, TRANSPORT_ERROR); -} - -static int allow_medium_removal(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int prevent; - - prevent = srb->cmnd[4] & 0x1; - - scsi_set_resid(srb, 0); - - if (prevent) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return TRANSPORT_GOOD; -} - -static void ms_mode_sense(struct rts51x_chip *chip, u8 cmd, - int lun, u8 *buf, int buf_len) -{ - struct ms_info *ms_card = &(chip->ms_card); - int sys_info_offset; - int data_size = buf_len; - int support_format = 0; - int i = 0; - - if (cmd == MODE_SENSE) { - sys_info_offset = 8; - if (data_size > 0x68) - data_size = 0x68; - buf[i++] = 0x67; /* Mode Data Length */ - } else { - sys_info_offset = 12; - if (data_size > 0x6C) - data_size = 0x6C; - buf[i++] = 0x00; /* Mode Data Length (MSB) */ - buf[i++] = 0x6A; /* Mode Data Length (LSB) */ - } - - /* Medium Type Code */ - if (check_card_ready(chip, lun)) { - if (CHK_MSXC(ms_card)) { - support_format = 1; - buf[i++] = 0x40; - } else if (CHK_MSPRO(ms_card)) { - support_format = 1; - buf[i++] = 0x20; - } else { - buf[i++] = 0x10; - } - - /* WP */ - if (check_card_wp(chip, lun)) - buf[i++] = 0x80; - else - buf[i++] = 0x00; - } else { - buf[i++] = 0x00; /* MediaType */ - buf[i++] = 0x00; /* WP */ - } - - buf[i++] = 0x00; /* Reserved */ - - if (cmd == MODE_SENSE_10) { - buf[i++] = 0x00; /* Reserved */ - buf[i++] = 0x00; /* Block descriptor length(MSB) */ - buf[i++] = 0x00; /* Block descriptor length(LSB) */ - - /* The Following Data is the content of "Page 0x20" */ - if (data_size >= 9) - buf[i++] = 0x20; /* Page Code */ - if (data_size >= 10) - buf[i++] = 0x62; /* Page Length */ - if (data_size >= 11) - buf[i++] = 0x00; /* No Access Control */ - if (data_size >= 12) { - if (support_format) - buf[i++] = 0xC0; /* SF, SGM */ - else - buf[i++] = 0x00; - } - } else { - /* The Following Data is the content of "Page 0x20" */ - if (data_size >= 5) - buf[i++] = 0x20; /* Page Code */ - if (data_size >= 6) - buf[i++] = 0x62; /* Page Length */ - if (data_size >= 7) - buf[i++] = 0x00; /* No Access Control */ - if (data_size >= 8) { - if (support_format) - buf[i++] = 0xC0; /* SF, SGM */ - else - buf[i++] = 0x00; - } - } - - if (data_size > sys_info_offset) { - /* 96 Bytes Attribute Data */ - int len = data_size - sys_info_offset; - len = (len < 96) ? len : 96; - - memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len); - } -} - -static int mode_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - unsigned int dataSize; - int status; - int pro_formatter_flag; - unsigned char pageCode, *buf; - u8 card = get_lun_card(chip, lun); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - scsi_set_resid(srb, scsi_bufflen(srb)); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - pro_formatter_flag = 0; - dataSize = 8; - /* In Combo mode, device responses ModeSense command as a MS LUN - * when no card is inserted */ - if ((get_lun2card(chip, lun) & MS_CARD)) { - if (!card || (card == MS_CARD)) { - dataSize = 108; - if (chip->option.mspro_formatter_enable) - pro_formatter_flag = 1; - } - } - - buf = kmalloc(dataSize, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - pageCode = srb->cmnd[2] & 0x3f; - - if ((pageCode == 0x3F) || (pageCode == 0x1C) || - (pageCode == 0x00) || (pro_formatter_flag && (pageCode == 0x20))) { - if (srb->cmnd[0] == MODE_SENSE) { - if ((pageCode == 0x3F) || (pageCode == 0x20)) { - ms_mode_sense(chip, srb->cmnd[0], lun, buf, - dataSize); - } else { - dataSize = 4; - buf[0] = 0x03; - buf[1] = 0x00; - if (check_card_wp(chip, lun)) - buf[2] = 0x80; - else - buf[3] = 0x00; - } - } else { - if ((pageCode == 0x3F) || (pageCode == 0x20)) { - ms_mode_sense(chip, srb->cmnd[0], lun, buf, - dataSize); - } else { - dataSize = 8; - buf[0] = 0x00; - buf[1] = 0x06; - buf[2] = 0x00; - if (check_card_wp(chip, lun)) - buf[3] = 0x80; - else - buf[3] = 0x00; - buf[4] = 0x00; - buf[5] = 0x00; - buf[6] = 0x00; - buf[7] = 0x00; - } - } - status = TRANSPORT_GOOD; - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - scsi_set_resid(srb, scsi_bufflen(srb)); - status = TRANSPORT_FAILED; - } - - if (status == TRANSPORT_GOOD) { - unsigned int len = min(scsi_bufflen(srb), dataSize); - rts51x_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - } - kfree(buf); - - return status; -} - -static int request_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sense_data_t *sense; - unsigned int lun = SCSI_LUN(srb); - struct ms_info *ms_card = &(chip->ms_card); - unsigned char *tmp, *buf; - - sense = &(chip->sense_buffer[lun]); - - if ((get_lun_card(chip, lun) == MS_CARD) - && PRO_UNDER_FORMATTING(ms_card)) { - mspro_format_sense(chip, lun); - } - - buf = vmalloc(scsi_bufflen(srb)); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - tmp = (unsigned char *)sense; - memcpy(buf, tmp, scsi_bufflen(srb)); - - rts51x_set_xfer_buf(buf, scsi_bufflen(srb), srb); - vfree(buf); - - scsi_set_resid(srb, 0); - /* Reset Sense Data */ - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - return TRANSPORT_GOOD; -} - -static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ -#ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &(chip->sd_card); -#endif - unsigned int lun = SCSI_LUN(srb); - int retval; - u32 start_sec; - u16 sec_cnt; - - if (!check_card_ready(chip, lun) || (chip->capacity[lun] == 0)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!check_lun_mc(chip, lun)) { - set_lun_mc(chip, lun); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_erase_status) { - /* Accessing to any card is forbidden - * until the erase procedure of SD is completed */ - RTS51X_DEBUGP("SD card being erased!\n"); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (get_lun_card(chip, lun) == SD_CARD) { - if (sd_card->sd_lock_status & SD_LOCKED) { - RTS51X_DEBUGP("SD card locked!\n"); - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_READ_FORBIDDEN); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } -#endif - - if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) { - start_sec = - ((u32) srb->cmnd[2] << 24) | - ((u32) srb->cmnd[3] << 16) | - ((u32) srb->cmnd[4] << 8) | - ((u32) srb->cmnd[5]); - sec_cnt = ((u16) (srb->cmnd[7]) << 8) | srb->cmnd[8]; - } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) { - start_sec = ((u32) (srb->cmnd[1] & 0x1F) << 16) | - ((u32) srb->cmnd[2] << 8) | ((u32) srb->cmnd[3]); - sec_cnt = srb->cmnd[4]; - } else if ((srb->cmnd[0] == VENDOR_CMND) && - (srb->cmnd[1] == SCSI_APP_CMD) && - ((srb->cmnd[2] == PP_READ10) || - (srb->cmnd[2] == PP_WRITE10))) { - start_sec = ((u32) srb->cmnd[4] << 24) | - ((u32) srb->cmnd[5] << 16) | - ((u32) srb->cmnd[6] << 8) | - ((u32) srb->cmnd[7]); - sec_cnt = ((u16) (srb->cmnd[9]) << 8) | srb->cmnd[10]; - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((start_sec > chip->capacity[lun]) || - ((start_sec + sec_cnt) > chip->capacity[lun])) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (sec_cnt == 0) { - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - } - - if ((srb->sc_data_direction == DMA_TO_DEVICE) - && check_card_wp(chip, lun)) { - RTS51X_DEBUGP("Write protected card!\n"); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - retval = card_rw(srb, chip, start_sec, sec_cnt); - if (retval != STATUS_SUCCESS) { -#if 0 - if (chip->need_release & chip->lun2card[lun]) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - } else { -#endif - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - } -#if 0 - } -#endif - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - - return TRANSPORT_GOOD; -} - -static int read_format_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned char *buf; - unsigned int lun = SCSI_LUN(srb); - unsigned int buf_len; - u8 card = get_lun_card(chip, lun); - int desc_cnt; - int i = 0; - - if (!check_card_ready(chip, lun)) { - if (!chip->option.mspro_formatter_enable) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12; - - buf = kmalloc(buf_len, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - buf[i++] = 0; - buf[i++] = 0; - buf[i++] = 0; - - /* Capacity List Length */ - if ((buf_len > 12) && chip->option.mspro_formatter_enable && - (chip->lun2card[lun] & MS_CARD) && (!card || (card == MS_CARD))) { - buf[i++] = 0x10; - desc_cnt = 2; - } else { - buf[i++] = 0x08; - desc_cnt = 1; - } - - while (desc_cnt) { - if (check_card_ready(chip, lun)) { - buf[i++] = (unsigned char)((chip->capacity[lun]) >> 24); - buf[i++] = (unsigned char)((chip->capacity[lun]) >> 16); - buf[i++] = (unsigned char)((chip->capacity[lun]) >> 8); - buf[i++] = (unsigned char)(chip->capacity[lun]); - - if (desc_cnt == 2) - /* Byte[8]: Descriptor Type: Formatted medium */ - buf[i++] = 2; - else - buf[i++] = 0; /* Byte[16] */ - } else { - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - - if (desc_cnt == 2) - /* Byte[8]: Descriptor Type: No medium */ - buf[i++] = 3; - else - buf[i++] = 0; /*Byte[16] */ - } - - buf[i++] = 0x00; - buf[i++] = 0x02; - buf[i++] = 0x00; - - desc_cnt--; - } - - buf_len = min(scsi_bufflen(srb), buf_len); - rts51x_set_xfer_buf(buf, buf_len, srb); - kfree(buf); - - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - return TRANSPORT_GOOD; -} - -static int read_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned char *buf; - unsigned int lun = SCSI_LUN(srb); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!check_lun_mc(chip, lun)) { - set_lun_mc(chip, lun); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - buf = kmalloc(8, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - buf[0] = (unsigned char)((chip->capacity[lun] - 1) >> 24); - buf[1] = (unsigned char)((chip->capacity[lun] - 1) >> 16); - buf[2] = (unsigned char)((chip->capacity[lun] - 1) >> 8); - buf[3] = (unsigned char)(chip->capacity[lun] - 1); - - buf[4] = 0x00; - buf[5] = 0x00; - buf[6] = 0x02; - buf[7] = 0x00; - - rts51x_set_xfer_buf(buf, scsi_bufflen(srb), srb); - kfree(buf); - - scsi_set_resid(srb, 0); - - return TRANSPORT_GOOD; -} - -static int get_dev_status(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - unsigned int buf_len; - u8 status[32] = { 0 }; - - rts51x_pp_status(chip, lun, status, 32); - - buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(status)); - rts51x_set_xfer_buf(status, buf_len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - return TRANSPORT_GOOD; -} - -static int read_status(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - u8 rts51x_status[16]; - unsigned int buf_len; - unsigned int lun = SCSI_LUN(srb); - - rts51x_read_status(chip, lun, rts51x_status, 16); - - buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(rts51x_status)); - rts51x_set_xfer_buf(rts51x_status, buf_len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - return TRANSPORT_GOOD; -} - -static int read_mem(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - unsigned short addr, len, i; - int retval; - u8 *buf; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - addr = ((u16) srb->cmnd[2] << 8) | srb->cmnd[3]; - len = ((u16) srb->cmnd[4] << 8) | srb->cmnd[5]; - - if (addr < 0xe000) { - RTS51X_DEBUGP("filter!addr=0x%x\n", addr); - return TRANSPORT_GOOD; - } - - buf = vmalloc(len); - if (!buf) - TRACE_RET(chip, TRANSPORT_ERROR); - - for (i = 0; i < len; i++) { - retval = rts51x_ep0_read_register(chip, addr + i, buf + i); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len); - rts51x_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int write_mem(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - unsigned short addr, len, i; - int retval; - u8 *buf; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - addr = ((u16) srb->cmnd[2] << 8) | srb->cmnd[3]; - len = ((u16) srb->cmnd[4] << 8) | srb->cmnd[5]; - - if (addr < 0xe000) { - RTS51X_DEBUGP("filter!addr=0x%x\n", addr); - return TRANSPORT_GOOD; - } - - len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len); - buf = vmalloc(len); - if (!buf) - TRACE_RET(chip, TRANSPORT_ERROR); - - rts51x_get_xfer_buf(buf, len, srb); - - for (i = 0; i < len; i++) { - retval = - rts51x_ep0_write_register(chip, addr + i, 0xFF, buf[i]); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - vfree(buf); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - return TRANSPORT_GOOD; -} - -static int get_sd_csd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (get_lun_card(chip, lun) != SD_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - rts51x_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb); - - return TRANSPORT_GOOD; -} - -static int read_phy_register(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval; - u8 addr, len, i; - u8 *buf; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - addr = srb->cmnd[5]; - len = srb->cmnd[7]; - - if (len) { - buf = vmalloc(len); - if (!buf) - TRACE_RET(chip, TRANSPORT_ERROR); - - for (i = 0; i < len; i++) { - retval = - rts51x_read_phy_register(chip, addr + i, buf + i); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - len = min(scsi_bufflen(srb), (unsigned int)len); - rts51x_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - } - - return TRANSPORT_GOOD; -} - -static int write_phy_register(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval; - u8 addr, len, i; - u8 *buf; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - addr = srb->cmnd[5]; - len = srb->cmnd[7]; - - if (len) { - len = min(scsi_bufflen(srb), (unsigned int)len); - - buf = vmalloc(len); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - rts51x_get_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - for (i = 0; i < len; i++) { - retval = - rts51x_write_phy_register(chip, addr + i, buf[i]); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - vfree(buf); - } - - return TRANSPORT_GOOD; -} - -static int get_card_bus_width(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - u8 card, bus_width; - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - card = get_lun_card(chip, lun); - if ((card == SD_CARD) || (card == MS_CARD)) { - bus_width = chip->card_bus_width[lun]; - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - rts51x_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb); - - return TRANSPORT_GOOD; -} - -#ifdef _MSG_TRACE -static int trace_msg_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned char *buf = NULL; - u8 clear; - unsigned int buf_len; - - buf_len = - 4 + - ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * TRACE_ITEM_CNT); - - if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - clear = srb->cmnd[2]; - - buf = vmalloc(scsi_bufflen(srb)); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - rts51x_trace_msg(chip, buf, clear); - - rts51x_set_xfer_buf(buf, scsi_bufflen(srb), srb); - vfree(buf); - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} -#endif - -static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval = STATUS_SUCCESS; - unsigned int lun = SCSI_LUN(srb); - u8 cmd_type, mask, value, idx, mode, len; - u16 addr; - u32 timeout; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - switch (srb->cmnd[3]) { - case INIT_BATCHCMD: - rts51x_init_cmd(chip); - break; - - case ADD_BATCHCMD: - cmd_type = srb->cmnd[4]; - if (cmd_type > 2) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - addr = (srb->cmnd[5] << 8) | srb->cmnd[6]; - mask = srb->cmnd[7]; - value = srb->cmnd[8]; - rts51x_add_cmd(chip, cmd_type, addr, mask, value); - break; - - case SEND_BATCHCMD: - mode = srb->cmnd[4]; - len = srb->cmnd[5]; - timeout = - ((u32) srb->cmnd[6] << 24) | ((u32) srb-> - cmnd[7] << 16) | ((u32) srb-> - cmnd[8] << - 8) | ((u32) - srb-> - cmnd - [9]); - retval = rts51x_send_cmd(chip, mode, 1000); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if (mode & STAGE_R) { - retval = rts51x_get_rsp(chip, len, timeout); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - break; - - case GET_BATCHRSP: - idx = srb->cmnd[4]; - value = chip->rsp_buf[idx]; - if (scsi_bufflen(srb) < 1) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - rts51x_set_xfer_buf(&value, 1, srb); - scsi_set_resid(srb, 0); - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return TRANSPORT_GOOD; -} - -static int suit_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int result; - - switch (srb->cmnd[3]) { - case INIT_BATCHCMD: - case ADD_BATCHCMD: - case SEND_BATCHCMD: - case GET_BATCHRSP: - result = rw_mem_cmd_buf(srb, chip); - break; - default: - result = TRANSPORT_ERROR; - } - - return result; -} - -static int app_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int result; - - switch (srb->cmnd[2]) { - case PP_READ10: - case PP_WRITE10: - result = read_write(srb, chip); - break; - - case SUIT_CMD: - result = suit_cmd(srb, chip); - break; - - case READ_PHY: - result = read_phy_register(srb, chip); - break; - - case WRITE_PHY: - result = write_phy_register(srb, chip); - break; - - case GET_DEV_STATUS: - result = get_dev_status(srb, chip); - break; - - default: - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return result; -} - -static int vendor_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int result = TRANSPORT_GOOD; - - switch (srb->cmnd[1]) { - case READ_STATUS: - result = read_status(srb, chip); - break; - - case READ_MEM: - result = read_mem(srb, chip); - break; - - case WRITE_MEM: - result = write_mem(srb, chip); - break; - - case GET_BUS_WIDTH: - result = get_card_bus_width(srb, chip); - break; - - case GET_SD_CSD: - result = get_sd_csd(srb, chip); - break; - -#ifdef _MSG_TRACE - case TRACE_MSG: - result = trace_msg_cmd(srb, chip); - break; -#endif - - case SCSI_APP_CMD: - result = app_cmd(srb, chip); - break; - - default: - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return result; -} - -static int ms_format_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - int retval, quick_format; - - if (get_lun_card(chip, lun) != MS_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47) - || (srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) - || (srb->cmnd[7] != 0x74)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (srb->cmnd[8] & 0x01) - quick_format = 0; - else - quick_format = 1; - - if (!(chip->card_ready & MS_CARD)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (chip->card_wp & MS_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!CHK_MSPRO(ms_card)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} - -#ifdef SUPPORT_PCGL_1P18 -int get_ms_information(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - u8 dev_info_id, data_len; - u8 *buf; - unsigned int buf_len; - int i; - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if ((get_lun_card(chip, lun) != MS_CARD)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) || - (srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) || - (srb->cmnd[7] != 0x44)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - dev_info_id = srb->cmnd[3]; - if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) || - (!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) || - !CHK_MSPRO(ms_card)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (dev_info_id == 0x15) - buf_len = data_len = 0x3A; - else - buf_len = data_len = 0x6A; - - buf = kmalloc(buf_len, GFP_KERNEL); - if (!buf) - TRACE_RET(chip, TRANSPORT_ERROR); - - i = 0; - /* GET Memory Stick Media Information Response Header */ - buf[i++] = 0x00; /* Data length MSB */ - buf[i++] = data_len; /* Data length LSB */ - /* Device Information Type Code */ - if (CHK_MSXC(ms_card)) - buf[i++] = 0x03; - else - buf[i++] = 0x02; - /* SGM bit */ - buf[i++] = 0x01; - /* Reserved */ - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0x00; - /* Number of Device Information */ - buf[i++] = 0x01; - - /* Device Information Body - * Device Information ID Number */ - buf[i++] = dev_info_id; - /* Device Information Length */ - if (dev_info_id == 0x15) - data_len = 0x31; - else - data_len = 0x61; - buf[i++] = 0x00; /* Data length MSB */ - buf[i++] = data_len; /* Data length LSB */ - /* Valid Bit */ - buf[i++] = 0x80; - if ((dev_info_id == 0x10) || (dev_info_id == 0x13)) { - /* System Information */ - memcpy(buf + i, ms_card->raw_sys_info, 96); - } else { - /* Model Name */ - memcpy(buf + i, ms_card->raw_model_name, 48); - } - - rts51x_set_xfer_buf(buf, buf_len, srb); - - if (dev_info_id == 0x15) - scsi_set_resid(srb, scsi_bufflen(srb) - 0x3C); - else - scsi_set_resid(srb, scsi_bufflen(srb) - 0x6C); - - kfree(buf); - return STATUS_SUCCESS; -} -#endif - -static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int retval = TRANSPORT_ERROR; - - if (srb->cmnd[2] == MS_FORMAT) - retval = ms_format_cmnd(srb, chip); -#ifdef SUPPORT_PCGL_1P18 - else if (srb->cmnd[2] == GET_MS_INFORMATION) - retval = get_ms_information(srb, chip); -#endif - - return retval; -} - -#ifdef SUPPORT_CPRM -static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - int result; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - sd_cleanup_work(chip); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if ((get_lun_card(chip, lun) != SD_CARD)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - switch (srb->cmnd[0]) { - case SD_PASS_THRU_MODE: - result = sd_pass_thru_mode(srb, chip); - break; - - case SD_EXECUTE_NO_DATA: - result = sd_execute_no_data(srb, chip); - break; - - case SD_EXECUTE_READ: - result = sd_execute_read_data(srb, chip); - break; - - case SD_EXECUTE_WRITE: - result = sd_execute_write_data(srb, chip); - break; - - case SD_GET_RSP: - result = sd_get_cmd_rsp(srb, chip); - break; - - case SD_HW_RST: - result = sd_hw_rst(srb, chip); - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - return result; -} -#endif - -#ifdef SUPPORT_MAGIC_GATE -int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - int retval; - u8 key_format; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - ms_cleanup_work(chip); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if ((get_lun_card(chip, lun) != MS_CARD)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (srb->cmnd[7] != KC_MG_R_PRO) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!CHK_MSPRO(ms_card)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - key_format = srb->cmnd[10] & 0x3F; - - switch (key_format) { - case KF_GET_LOC_EKB: - if ((scsi_bufflen(srb) == 0x41C) && - (srb->cmnd[8] == 0x04) && (srb->cmnd[9] == 0x1C)) { - retval = mg_get_local_EKB(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_RSP_CHG: - if ((scsi_bufflen(srb) == 0x24) && - (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x24)) { - retval = mg_get_rsp_chg(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_GET_ICV: - ms_card->mg_entry_num = srb->cmnd[5]; - if ((scsi_bufflen(srb) == 0x404) && - (srb->cmnd[8] == 0x04) && - (srb->cmnd[9] == 0x04) && - (srb->cmnd[2] == 0x00) && - (srb->cmnd[3] == 0x00) && - (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) { - retval = mg_get_ICV(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} - -int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - int retval; - u8 key_format; - - rts51x_prepare_run(chip); - RTS51X_SET_STAT(chip, STAT_RUN); - - ms_cleanup_work(chip); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if (check_card_wp(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - if ((get_lun_card(chip, lun) != MS_CARD)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (srb->cmnd[7] != KC_MG_R_PRO) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (!CHK_MSPRO(ms_card)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - key_format = srb->cmnd[10] & 0x3F; - - switch (key_format) { - case KF_SET_LEAF_ID: - if ((scsi_bufflen(srb) == 0x0C) && - (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) { - retval = mg_set_leaf_id(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_CHG_HOST: - if ((scsi_bufflen(srb) == 0x0C) && - (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) { - retval = mg_chg(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_RSP_HOST: - if ((scsi_bufflen(srb) == 0x0C) && - (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) { - retval = mg_rsp(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - case KF_SET_ICV: - ms_card->mg_entry_num = srb->cmnd[5]; - if ((scsi_bufflen(srb) == 0x404) && - (srb->cmnd[8] == 0x04) && - (srb->cmnd[9] == 0x04) && - (srb->cmnd[2] == 0x00) && - (srb->cmnd[3] == 0x00) && - (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) { - retval = mg_set_ICV(srb, chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} -#endif - -int rts51x_scsi_handler(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ -#ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &(chip->sd_card); -#endif - struct ms_info *ms_card = &(chip->ms_card); - unsigned int lun = SCSI_LUN(srb); - int result = TRANSPORT_GOOD; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_erase_status) { - /* Block all SCSI command except for REQUEST_SENSE - * and rs_ppstatus */ - if (! - ((srb->cmnd[0] == VENDOR_CMND) - && (srb->cmnd[1] == SCSI_APP_CMD) - && (srb->cmnd[2] == GET_DEV_STATUS)) - && (srb->cmnd[0] != REQUEST_SENSE)) { - /* Logical Unit Not Ready Format in Progress */ - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, - 0, 0); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } -#endif - - if ((get_lun_card(chip, lun) == MS_CARD) && - (ms_card->format_status == FORMAT_IN_PROGRESS)) { - if ((srb->cmnd[0] != REQUEST_SENSE) - && (srb->cmnd[0] != INQUIRY)) { - /* Logical Unit Not Ready Format in Progress */ - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, - 0, (u16) (ms_card->progress)); - TRACE_RET(chip, TRANSPORT_FAILED); - } - } - - switch (srb->cmnd[0]) { - case READ_10: - case WRITE_10: - case READ_6: - case WRITE_6: - result = read_write(srb, chip); - break; - - case TEST_UNIT_READY: - result = test_unit_ready(srb, chip); - break; - - case INQUIRY: - result = inquiry(srb, chip); - break; - - case READ_CAPACITY: - result = read_capacity(srb, chip); - break; - - case START_STOP: - result = start_stop_unit(srb, chip); - break; - - case ALLOW_MEDIUM_REMOVAL: - result = allow_medium_removal(srb, chip); - break; - - case REQUEST_SENSE: - result = request_sense(srb, chip); - break; - - case MODE_SENSE: - case MODE_SENSE_10: - result = mode_sense(srb, chip); - break; - - case 0x23: - result = read_format_capacity(srb, chip); - break; - - case VENDOR_CMND: - result = vendor_cmnd(srb, chip); - break; - - case MS_SP_CMND: - result = ms_sp_cmnd(srb, chip); - break; - -#ifdef SUPPORT_CPRM - case SD_PASS_THRU_MODE: - case SD_EXECUTE_NO_DATA: - case SD_EXECUTE_READ: - case SD_EXECUTE_WRITE: - case SD_GET_RSP: - case SD_HW_RST: - result = sd_extention_cmnd(srb, chip); - break; -#endif - -#ifdef SUPPORT_MAGIC_GATE - case CMD_MSPRO_MG_RKEY: - result = mg_report_key(srb, chip); - break; - - case CMD_MSPRO_MG_SKEY: - result = mg_send_key(srb, chip); - break; -#endif - - case FORMAT_UNIT: - case MODE_SELECT: - case VERIFY: - result = TRANSPORT_GOOD; - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - result = TRANSPORT_FAILED; - } - - return result; -} - -/*********************************************************************** - * Host functions - ***********************************************************************/ - -const char *host_info(struct Scsi_Host *host) -{ - return "SCSI emulation for RTS51xx USB driver-based card reader"; -} - -int slave_alloc(struct scsi_device *sdev) -{ - /* - * Set the INQUIRY transfer length to 36. We don't use any of - * the extra data and many devices choke if asked for more or - * less than 36 bytes. - */ - sdev->inquiry_len = 36; - return 0; -} - -int slave_configure(struct scsi_device *sdev) -{ - /* Scatter-gather buffers (all but the last) must have a length - * divisible by the bulk maxpacket size. Otherwise a data packet - * would end up being short, causing a premature end to the data - * transfer. Since high-speed bulk pipes have a maxpacket size - * of 512, we'll use that as the scsi device queue's DMA alignment - * mask. Guaranteeing proper alignment of the first buffer will - * have the desired effect because, except at the beginning and - * the end, scatter-gather buffers follow page boundaries. */ - blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); - - /* Set the SCSI level to at least 2. We'll leave it at 3 if that's - * what is originally reported. We need this to avoid confusing - * the SCSI layer with devices that report 0 or 1, but need 10-byte - * commands (ala ATAPI devices behind certain bridges, or devices - * which simply have broken INQUIRY data). - * - * NOTE: This means /dev/sg programs (ala cdrecord) will get the - * actual information. This seems to be the preference for - * programs like that. - * - * NOTE: This also means that /proc/scsi/scsi and sysfs may report - * the actual value or the modified one, depending on where the - * data comes from. - */ - if (sdev->scsi_level < SCSI_2) - sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2; - - return 0; -} - -/*********************************************************************** - * /proc/scsi/ functions - ***********************************************************************/ - -/* we use this macro to help us write into the buffer */ -#undef SPRINTF -#define SPRINTF(args...) \ - do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) - -int proc_info(struct Scsi_Host *host, char *buffer, - char **start, off_t offset, int length, int inout) -{ - char *pos = buffer; - - /* if someone is sending us data, just throw it away */ - if (inout) - return length; - - /* print the controller name */ - SPRINTF(" Host scsi%d: %s\n", host->host_no, RTS51X_NAME); - - /* print product, vendor, and driver version strings */ - SPRINTF(" Vendor: Realtek Corp.\n"); - SPRINTF(" Product: RTS51xx USB Card Reader\n"); - SPRINTF(" Version: %s\n", DRIVER_VERSION); - SPRINTF(" Build: %s\n", __TIME__); - - /* - * Calculate start of next buffer, and return value. - */ - *start = buffer + offset; - - if ((pos - buffer) < offset) - return 0; - else if ((pos - buffer - offset) < length) - return pos - buffer - offset; - else - return length; -} - -/* queue a command */ -/* This is always called with scsi_lock(host) held */ -int queuecommand_lck(struct scsi_cmnd *srb, void (*done) (struct scsi_cmnd *)) -{ - struct rts51x_chip *chip = host_to_rts51x(srb->device->host); - - /* check for state-transition errors */ - if (chip->srb != NULL) { - RTS51X_DEBUGP("Error in %s: chip->srb = %p\n", - __func__, chip->srb); - return SCSI_MLQUEUE_HOST_BUSY; - } - - /* fail the command if we are disconnecting */ - if (test_bit(FLIDX_DISCONNECTING, &chip->usb->dflags)) { - RTS51X_DEBUGP("Fail command during disconnect\n"); - srb->result = DID_NO_CONNECT << 16; - done(srb); - return 0; - } - - /* enqueue the command and wake up the control thread */ - srb->scsi_done = done; - chip->srb = srb; - complete(&chip->usb->cmnd_ready); - - return 0; -} - -#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) */ -int queuecommand(struct scsi_cmnd *srb, void (*done) (struct scsi_cmnd *)) -{ - return queuecommand_lck(srb, done); -} -#else -DEF_SCSI_QCMD(queuecommand) -#endif -/*********************************************************************** - * Error handling functions - ***********************************************************************/ -/* Command timeout and abort */ -int command_abort(struct scsi_cmnd *srb) -{ - struct rts51x_chip *chip = host_to_rts51x(srb->device->host); - - RTS51X_DEBUGP("%s called\n", __func__); - - /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING - * bits are protected by the host lock. */ - scsi_lock(rts51x_to_host(chip)); - - /* Is this command still active? */ - if (chip->srb != srb) { - scsi_unlock(rts51x_to_host(chip)); - RTS51X_DEBUGP("-- nothing to abort\n"); - return FAILED; - } - - /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if - * a device reset isn't already in progress (to avoid interfering - * with the reset). Note that we must retain the host lock while - * calling usb_stor_stop_transport(); otherwise it might interfere - * with an auto-reset that begins as soon as we release the lock. */ - set_bit(FLIDX_TIMED_OUT, &chip->usb->dflags); - if (!test_bit(FLIDX_RESETTING, &chip->usb->dflags)) { - set_bit(FLIDX_ABORTING, &chip->usb->dflags); - /* rts51x_stop_transport(us); */ - } - scsi_unlock(rts51x_to_host(chip)); - - /* Wait for the aborted command to finish */ - wait_for_completion(&chip->usb->notify); - return SUCCESS; -} - -/* This invokes the transport reset mechanism to reset the state of the - * device */ -int device_reset(struct scsi_cmnd *srb) -{ - int result = 0; - - RTS51X_DEBUGP("%s called\n", __func__); - - return result < 0 ? FAILED : SUCCESS; -} - -/* Simulate a SCSI bus reset by resetting the device's USB port. */ -int bus_reset(struct scsi_cmnd *srb) -{ - int result = 0; - - RTS51X_DEBUGP("%s called\n", __func__); - - return result < 0 ? FAILED : SUCCESS; -} - -static const char *rts5139_info(struct Scsi_Host *host) -{ - return "SCSI emulation for RTS5139 USB card reader"; -} - -struct scsi_host_template rts51x_host_template = { - /* basic userland interface stuff */ - .name = RTS51X_NAME, - .proc_name = RTS51X_NAME, - .proc_info = proc_info, - .info = rts5139_info, - - /* command interface -- queued only */ - .queuecommand = queuecommand, - - /* error and abort handlers */ - .eh_abort_handler = command_abort, - .eh_device_reset_handler = device_reset, - .eh_bus_reset_handler = bus_reset, - - /* queue commands only, only one command per LUN */ - .can_queue = 1, - .cmd_per_lun = 1, - - /* unknown initiator id */ - .this_id = -1, - - .slave_alloc = slave_alloc, - .slave_configure = slave_configure, - - /* lots of sg segments can be handled */ - .sg_tablesize = SG_ALL, - - /* limit the total size of a transfer to 120 KB */ - .max_sectors = 240, - - /* merge commands... this seems to help performance, but - * periodically someone should test to see which setting is more - * optimal. - */ - .use_clustering = 1, - - /* emulated HBA */ - .emulated = 1, - - /* we do our own delay after a device or bus reset */ - .skip_settle_delay = 1, - - /* sysfs device attributes */ - /* .sdev_attrs = sysfs_device_attr_list, */ - - /* module management */ - .module = THIS_MODULE -}; - diff --git a/trunk/drivers/staging/rts5139/rts51x_scsi.h b/trunk/drivers/staging/rts5139/rts51x_scsi.h deleted file mode 100644 index 3a8ca069b278..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_scsi.h +++ /dev/null @@ -1,162 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_SCSI_H -#define __RTS51X_SCSI_H - -#include -#include -#include -#include -#include -#include - -#include "rts51x_chip.h" - -#define MS_SP_CMND 0xFA -#define MS_FORMAT 0xA0 -#define GET_MS_INFORMATION 0xB0 - -#define VENDOR_CMND 0xF0 - -#define READ_STATUS 0x09 - -#define READ_MEM 0x0D -#define WRITE_MEM 0x0E -#define GET_BUS_WIDTH 0x13 -#define GET_SD_CSD 0x14 -#define TOGGLE_GPIO 0x15 -#define TRACE_MSG 0x18 - -#define SCSI_APP_CMD 0x10 - -#define PP_READ10 0x1A -#define PP_WRITE10 0x0A -#define READ_HOST_REG 0x1D -#define WRITE_HOST_REG 0x0D -#define SET_VAR 0x05 -#define GET_VAR 0x15 -#define DMA_READ 0x16 -#define DMA_WRITE 0x06 -#define GET_DEV_STATUS 0x10 -#define SET_CHIP_MODE 0x27 -#define SUIT_CMD 0xE0 -#define WRITE_PHY 0x07 -#define READ_PHY 0x17 - -#define INIT_BATCHCMD 0x41 -#define ADD_BATCHCMD 0x42 -#define SEND_BATCHCMD 0x43 -#define GET_BATCHRSP 0x44 - -#ifdef SUPPORT_CPRM -/* SD Pass Through Command Extention */ -#define SD_PASS_THRU_MODE 0xD0 -#define SD_EXECUTE_NO_DATA 0xD1 -#define SD_EXECUTE_READ 0xD2 -#define SD_EXECUTE_WRITE 0xD3 -#define SD_GET_RSP 0xD4 -#define SD_HW_RST 0xD6 -#endif - -#ifdef SUPPORT_MAGIC_GATE -#define CMD_MSPRO_MG_RKEY 0xA4 /* Report Key Command */ -#define CMD_MSPRO_MG_SKEY 0xA3 /* Send Key Command */ - -/* CBWCB field: key class */ -#define KC_MG_R_PRO 0xBE /* MG-R PRO */ - -/* CBWCB field: key format */ -#define KF_SET_LEAF_ID 0x31 /* Set Leaf ID */ -#define KF_GET_LOC_EKB 0x32 /* Get Local EKB */ -#define KF_CHG_HOST 0x33 /* Challenge (host) */ -#define KF_RSP_CHG 0x34 /* Response and Challenge (device) */ -#define KF_RSP_HOST 0x35 /* Response (host) */ -#define KF_GET_ICV 0x36 /* Get ICV */ -#define KF_SET_ICV 0x37 /* SSet ICV */ -#endif - -struct rts51x_chip; - -/*----------------------------------- - Start-Stop-Unit ------------------------------------*/ -#define STOP_MEDIUM 0x00 /* access disable */ -#define MAKE_MEDIUM_READY 0x01 /* access enable */ -#define UNLOAD_MEDIUM 0x02 /* unload */ -#define LOAD_MEDIUM 0x03 /* load */ - -/*----------------------------------- - STANDARD_INQUIRY ------------------------------------*/ -#define QULIFIRE 0x00 -#define AENC_FNC 0x00 -#define TRML_IOP 0x00 -#define REL_ADR 0x00 -#define WBUS_32 0x00 -#define WBUS_16 0x00 -#define SYNC 0x00 -#define LINKED 0x00 -#define CMD_QUE 0x00 -#define SFT_RE 0x00 - -#define VEN_ID_LEN 8 /* Vendor ID Length */ -#define PRDCT_ID_LEN 16 /* Product ID Length */ -#define PRDCT_REV_LEN 4 /* Product LOT Length */ - -#define DRCT_ACCESS_DEV 0x00 /* Direct Access Device */ -#define RMB_DISC 0x80 /* The Device is Removable */ -#define ANSI_SCSI2 0x02 /* Based on ANSI-SCSI2 */ - -#define SCSI 0x00 /* Interface ID */ - -void scsi_show_command(struct scsi_cmnd *srb); -void set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type); -void set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code, - u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0, - u16 sns_key_info1); - -int rts51x_scsi_handler(struct scsi_cmnd *srb, struct rts51x_chip *chip); - -struct Scsi_Host; -struct scsi_device; -struct scsi_cmnd; - -const char *host_info(struct Scsi_Host *host); -int slave_alloc(struct scsi_device *sdev); -int slave_configure(struct scsi_device *sdev); -int proc_info(struct Scsi_Host *host, char *buffer, - char **start, off_t offset, int length, int inout); -#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) */ -int queuecommand(struct scsi_cmnd *srb, void (*done) (struct scsi_cmnd *)); -#else -int queuecommand(struct Scsi_Host *, struct scsi_cmnd *); -#endif -int command_abort(struct scsi_cmnd *srb); -int device_reset(struct scsi_cmnd *srb); -int bus_reset(struct scsi_cmnd *srb); - -#endif /* __RTS51X_SCSI_H */ diff --git a/trunk/drivers/staging/rts5139/rts51x_sys.h b/trunk/drivers/staging/rts5139/rts51x_sys.h deleted file mode 100644 index b09cd34a6c02..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_sys.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Driver for Realtek USB RTS51xx card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_SYS_H -#define __RTS51X_SYS_H - -#include "rts51x.h" -#include "rts51x_chip.h" -#include "rts51x_card.h" - -#define USING_POLLING_CYCLE_DELINK - -extern int rts51x_check_start_time(struct rts51x_chip *chip); -extern void rts51x_set_start_time(struct rts51x_chip *chip); -extern void rts51x_clear_start_time(struct rts51x_chip *chip); - -/* typedef dma_addr_t ULONG_PTR; */ - -static inline void rts51x_reset_detected_cards(struct rts51x_chip *chip) -{ -/* rts51x_reset_cards(chip); */ -} - -static inline void clear_first_install_mark(struct rts51x_chip *chip) -{ -} - -void rts51x_enter_ss(struct rts51x_chip *chip); -void rts51x_exit_ss(struct rts51x_chip *chip); - -#endif /* __RTS51X_SYS_H */ diff --git a/trunk/drivers/staging/rts5139/rts51x_transport.c b/trunk/drivers/staging/rts5139/rts51x_transport.c deleted file mode 100644 index e11467acc57b..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_transport.c +++ /dev/null @@ -1,1000 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "debug.h" -#include "rts51x.h" -#include "rts51x_chip.h" -#include "rts51x_card.h" -#include "rts51x_scsi.h" -#include "rts51x_transport.h" -#include "trace.h" - -/*********************************************************************** - * Scatter-gather transfer buffer access routines - ***********************************************************************/ - -/* Copy a buffer of length buflen to/from the srb's transfer buffer. - * Update the **sgptr and *offset variables so that the next copy will - * pick up from where this one left off. - */ - -unsigned int rts51x_access_sglist(unsigned char *buffer, - unsigned int buflen, void *sglist, - void **sgptr, unsigned int *offset, - enum xfer_buf_dir dir) -{ - unsigned int cnt; - struct scatterlist *sg = (struct scatterlist *)*sgptr; - - /* We have to go through the list one entry - * at a time. Each s-g entry contains some number of pages, and - * each page has to be kmap()'ed separately. If the page is already - * in kernel-addressable memory then kmap() will return its address. - * If the page is not directly accessible -- such as a user buffer - * located in high memory -- then kmap() will map it to a temporary - * position in the kernel's virtual address space. - */ - - if (!sg) - sg = (struct scatterlist *)sglist; - - /* This loop handles a single s-g list entry, which may - * include multiple pages. Find the initial page structure - * and the starting offset within the page, and update - * the *offset and **sgptr values for the next loop. - */ - cnt = 0; - while (cnt < buflen && sg) { - struct page *page = sg_page(sg) + - ((sg->offset + *offset) >> PAGE_SHIFT); - unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE - 1); - unsigned int sglen = sg->length - *offset; - - if (sglen > buflen - cnt) { - - /* Transfer ends within this s-g entry */ - sglen = buflen - cnt; - *offset += sglen; - } else { - - /* Transfer continues to next s-g entry */ - *offset = 0; - sg = sg_next(sg); - } - - /* Transfer the data for all the pages in this - * s-g entry. For each page: call kmap(), do the - * transfer, and call kunmap() immediately after. */ - while (sglen > 0) { - unsigned int plen = min(sglen, (unsigned int) - PAGE_SIZE - poff); - unsigned char *ptr = kmap(page); - - if (dir == TO_XFER_BUF) - memcpy(ptr + poff, buffer + cnt, plen); - else - memcpy(buffer + cnt, ptr + poff, plen); - kunmap(page); - - /* Start at the beginning of the next page */ - poff = 0; - ++page; - cnt += plen; - sglen -= plen; - } - } - *sgptr = sg; - - /* Return the amount actually transferred */ - return cnt; -} - -unsigned int rts51x_access_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb, - struct scatterlist **sgptr, - unsigned int *offset, enum xfer_buf_dir dir) -{ - return rts51x_access_sglist(buffer, buflen, (void *)scsi_sglist(srb), - (void **)sgptr, offset, dir); -} - -/* Store the contents of buffer into srb's transfer buffer and set the - * SCSI residue. - */ -void rts51x_set_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb) -{ - unsigned int offset = 0; - struct scatterlist *sg = NULL; - - buflen = min(buflen, scsi_bufflen(srb)); - buflen = rts51x_access_xfer_buf(buffer, buflen, srb, &sg, &offset, - TO_XFER_BUF); - if (buflen < scsi_bufflen(srb)) - scsi_set_resid(srb, scsi_bufflen(srb) - buflen); -} - -void rts51x_get_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb) -{ - unsigned int offset = 0; - struct scatterlist *sg = NULL; - - buflen = min(buflen, scsi_bufflen(srb)); - buflen = rts51x_access_xfer_buf(buffer, buflen, srb, &sg, &offset, - FROM_XFER_BUF); - if (buflen < scsi_bufflen(srb)) - scsi_set_resid(srb, scsi_bufflen(srb) - buflen); -} - -/* This is the completion handler which will wake us up when an URB - * completes. - */ -static void urb_done_completion(struct urb *urb) -{ - struct completion *urb_done_ptr = urb->context; - - if (urb_done_ptr) - complete(urb_done_ptr); -} - -/* This is the common part of the URB message submission code - * - * All URBs from the driver involved in handling a queued scsi - * command _must_ pass through this function (or something like it) for the - * abort mechanisms to work properly. - */ -static int rts51x_msg_common(struct rts51x_chip *chip, struct urb *urb, - int timeout) -{ - struct rts51x_usb *rts51x = chip->usb; - struct completion urb_done; - long timeleft; - int status; - - /* don't submit URBs during abort processing */ - if (test_bit(FLIDX_ABORTING, &rts51x->dflags)) - TRACE_RET(chip, -EIO); - - /* set up data structures for the wakeup system */ - init_completion(&urb_done); - - /* fill the common fields in the URB */ - urb->context = &urb_done; - urb->actual_length = 0; - urb->error_count = 0; - urb->status = 0; - - /* we assume that if transfer_buffer isn't us->iobuf then it - * hasn't been mapped for DMA. Yes, this is clunky, but it's - * easier than always having the caller tell us whether the - * transfer buffer has already been mapped. */ - urb->transfer_flags = URB_NO_SETUP_DMA_MAP; - if (urb->transfer_buffer == rts51x->iobuf) { - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - urb->transfer_dma = rts51x->iobuf_dma; - } - urb->setup_dma = rts51x->cr_dma; - - /* submit the URB */ - status = usb_submit_urb(urb, GFP_NOIO); - if (status) { - /* something went wrong */ - TRACE_RET(chip, status); - } - - /* since the URB has been submitted successfully, it's now okay - * to cancel it */ - set_bit(FLIDX_URB_ACTIVE, &rts51x->dflags); - - /* did an abort occur during the submission? */ - if (test_bit(FLIDX_ABORTING, &rts51x->dflags)) { - - /* cancel the URB, if it hasn't been cancelled already */ - if (test_and_clear_bit(FLIDX_URB_ACTIVE, &rts51x->dflags)) { - RTS51X_DEBUGP("-- cancelling URB\n"); - usb_unlink_urb(urb); - } - } - - /* wait for the completion of the URB */ - timeleft = - wait_for_completion_interruptible_timeout(&urb_done, - (timeout * HZ / - 1000) ? : - MAX_SCHEDULE_TIMEOUT); - - clear_bit(FLIDX_URB_ACTIVE, &rts51x->dflags); - - if (timeleft <= 0) { - RTS51X_DEBUGP("%s -- cancelling URB\n", - timeleft == 0 ? "Timeout" : "Signal"); - usb_kill_urb(urb); - if (timeleft == 0) - status = -ETIMEDOUT; - else - status = -EINTR; - } else { - status = urb->status; - } - - return status; -} - -/* - * Interpret the results of a URB transfer - */ -static int interpret_urb_result(struct rts51x_chip *chip, unsigned int pipe, - unsigned int length, int result, - unsigned int partial) -{ - int retval = STATUS_SUCCESS; - - /* RTS51X_DEBUGP("Status code %d; transferred %u/%u\n", - result, partial, length); */ - switch (result) { - /* no error code; did we send all the data? */ - case 0: - if (partial != length) { - RTS51X_DEBUGP("-- short transfer\n"); - TRACE_RET(chip, STATUS_TRANS_SHORT); - } - /* RTS51X_DEBUGP("-- transfer complete\n"); */ - return STATUS_SUCCESS; - /* stalled */ - case -EPIPE: - /* for control endpoints, (used by CB[I]) a stall indicates - * a failed command */ - if (usb_pipecontrol(pipe)) { - RTS51X_DEBUGP("-- stall on control pipe\n"); - TRACE_RET(chip, STATUS_STALLED); - } - /* for other sorts of endpoint, clear the stall */ - RTS51X_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - if (rts51x_clear_halt(chip, pipe) < 0) - TRACE_RET(chip, STATUS_ERROR); - retval = STATUS_STALLED; - TRACE_GOTO(chip, Exit); - - /* babble - the device tried to send more than - * we wanted to read */ - case -EOVERFLOW: - RTS51X_DEBUGP("-- babble\n"); - retval = STATUS_TRANS_LONG; - TRACE_GOTO(chip, Exit); - - /* the transfer was cancelled by abort, - * disconnect, or timeout */ - case -ECONNRESET: - RTS51X_DEBUGP("-- transfer cancelled\n"); - retval = STATUS_ERROR; - TRACE_GOTO(chip, Exit); - - /* short scatter-gather read transfer */ - case -EREMOTEIO: - RTS51X_DEBUGP("-- short read transfer\n"); - retval = STATUS_TRANS_SHORT; - TRACE_GOTO(chip, Exit); - - /* abort or disconnect in progress */ - case -EIO: - RTS51X_DEBUGP("-- abort or disconnect in progress\n"); - retval = STATUS_ERROR; - TRACE_GOTO(chip, Exit); - - case -ETIMEDOUT: - RTS51X_DEBUGP("-- time out\n"); - retval = STATUS_TIMEDOUT; - TRACE_GOTO(chip, Exit); - - /* the catch-all error case */ - default: - RTS51X_DEBUGP("-- unknown error\n"); - retval = STATUS_ERROR; - TRACE_GOTO(chip, Exit); - } - -Exit: - if ((retval != STATUS_SUCCESS) && !usb_pipecontrol(pipe)) - rts51x_clear_hw_error(chip); - - return retval; -} - -int rts51x_ctrl_transfer(struct rts51x_chip *chip, unsigned int pipe, - u8 request, u8 requesttype, u16 value, u16 index, - void *data, u16 size, int timeout) -{ - struct rts51x_usb *rts51x = chip->usb; - int result; - - RTS51X_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n", - __func__, request, requesttype, value, index, size); - - /* fill in the devrequest structure */ - rts51x->cr->bRequestType = requesttype; - rts51x->cr->bRequest = request; - rts51x->cr->wValue = cpu_to_le16(value); - rts51x->cr->wIndex = cpu_to_le16(index); - rts51x->cr->wLength = cpu_to_le16(size); - - /* fill and submit the URB */ - usb_fill_control_urb(rts51x->current_urb, rts51x->pusb_dev, pipe, - (unsigned char *)rts51x->cr, data, size, - urb_done_completion, NULL); - result = rts51x_msg_common(chip, rts51x->current_urb, timeout); - - return interpret_urb_result(chip, pipe, size, result, - rts51x->current_urb->actual_length); -} - -int rts51x_clear_halt(struct rts51x_chip *chip, unsigned int pipe) -{ - int result; - int endp = usb_pipeendpoint(pipe); - - if (usb_pipein(pipe)) - endp |= USB_DIR_IN; - - result = rts51x_ctrl_transfer(chip, SND_CTRL_PIPE(chip), - USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, - USB_ENDPOINT_HALT, endp, NULL, 0, 3000); - if (result != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - usb_reset_endpoint(chip->usb->pusb_dev, endp); - - return STATUS_SUCCESS; -} - -int rts51x_reset_pipe(struct rts51x_chip *chip, char pipe) -{ - return rts51x_clear_halt(chip, pipe); -} - -static void rts51x_sg_clean(struct usb_sg_request *io) -{ - if (io->urbs) { - while (io->entries--) - usb_free_urb(io->urbs[io->entries]); - kfree(io->urbs); - io->urbs = NULL; - } -#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) */ - if (io->dev->dev.dma_mask != NULL) - usb_buffer_unmap_sg(io->dev, usb_pipein(io->pipe), - io->sg, io->nents); -#endif - io->dev = NULL; -} -#if 0 -static void rts51x_sg_complete(struct urb *urb) -{ - struct usb_sg_request *io = urb->context; - int status = urb->status; - - spin_lock(&io->lock); - - /* In 2.5 we require hcds' endpoint queues not to progress after fault - * reports, until the completion callback (this!) returns. That lets - * device driver code (like this routine) unlink queued urbs first, - * if it needs to, since the HC won't work on them at all. So it's - * not possible for page N+1 to overwrite page N, and so on. - * - * That's only for "hard" faults; "soft" faults (unlinks) sometimes - * complete before the HCD can get requests away from hardware, - * though never during cleanup after a hard fault. - */ - if (io->status - && (io->status != -ECONNRESET - || status != -ECONNRESET) - && urb->actual_length) { - dev_err(io->dev->bus->controller, - "dev %s ep%d%s scatterlist error %d/%d\n", - io->dev->devpath, - usb_endpoint_num(&urb->ep->desc), - usb_urb_dir_in(urb) ? "in" : "out", - status, io->status); - /* BUG (); */ - } - - if (io->status == 0 && status && status != -ECONNRESET) { - int i, found, retval; - - io->status = status; - - /* the previous urbs, and this one, completed already. - * unlink pending urbs so they won't rx/tx bad data. - * careful: unlink can sometimes be synchronous... - */ - spin_unlock(&io->lock); - for (i = 0, found = 0; i < io->entries; i++) { - if (!io->urbs[i] || !io->urbs[i]->dev) - continue; - if (found) { - retval = usb_unlink_urb(io->urbs[i]); - if (retval != -EINPROGRESS && - retval != -ENODEV && - retval != -EBUSY) - dev_err(&io->dev->dev, - "%s, unlink --> %d\n", - __func__, retval); - } else if (urb == io->urbs[i]) - found = 1; - } - spin_lock(&io->lock); - } - urb->dev = NULL; - - /* on the last completion, signal usb_sg_wait() */ - io->bytes += urb->actual_length; - io->count--; - if (!io->count) - complete(&io->complete); - - spin_unlock(&io->lock); -} - -/* This function is ported from usb_sg_init, which can transfer - * sg list partially */ -int rts51x_sg_init_partial(struct usb_sg_request *io, struct usb_device *dev, - unsigned pipe, unsigned period, void *buf, struct scatterlist **sgptr, - unsigned int *offset, int nents, size_t length, gfp_t mem_flags) -{ - int i; - int urb_flags; - int dma; - struct scatterlist *sg = *sgptr, *first_sg; - - first_sg = (struct scatterlist *)buf; - if (!sg) - sg = first_sg; - - if (!io || !dev || !sg - || usb_pipecontrol(pipe) - || usb_pipeisoc(pipe) - || (nents <= 0)) - return -EINVAL; - - spin_lock_init(&io->lock); - io->dev = dev; - io->pipe = pipe; - io->sg = first_sg; /* used by unmap */ - io->nents = nents; - - RTS51X_DEBUGP("Before map, sg address: 0x%x\n", (unsigned int)sg); - RTS51X_DEBUGP("Before map, dev address: 0x%x\n", (unsigned int)dev); - - /* not all host controllers use DMA (like the mainstream pci ones); - * they can use PIO (sl811) or be software over another transport. - */ - dma = (dev->dev.dma_mask != NULL); - if (dma) { - /* map the whole sg list, because here we only know the - * total nents */ - io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe), - first_sg, nents); - } else { - io->entries = nents; - } - - /* initialize all the urbs we'll use */ - if (io->entries <= 0) - return io->entries; - - io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags); - if (!io->urbs) - goto nomem; - - urb_flags = URB_NO_INTERRUPT; - if (dma) - urb_flags |= URB_NO_TRANSFER_DMA_MAP; - if (usb_pipein(pipe)) - urb_flags |= URB_SHORT_NOT_OK; - - RTS51X_DEBUGP("io->entries = %d\n", io->entries); - - for (i = 0; (sg != NULL) && (length > 0); i++) { - unsigned len; - - RTS51X_DEBUGP("sg address: 0x%x\n", (unsigned int)sg); - RTS51X_DEBUGP("length = %d, *offset = %d\n", length, *offset); - - io->urbs[i] = usb_alloc_urb(0, mem_flags); - if (!io->urbs[i]) { - io->entries = i; - goto nomem; - } - - io->urbs[i]->dev = NULL; - io->urbs[i]->pipe = pipe; - io->urbs[i]->interval = period; - io->urbs[i]->transfer_flags = urb_flags; - - io->urbs[i]->complete = rts51x_sg_complete; - io->urbs[i]->context = io; - - if (dma) { - io->urbs[i]->transfer_dma = - sg_dma_address(sg) + *offset; - len = sg_dma_len(sg) - *offset; - io->urbs[i]->transfer_buffer = NULL; - RTS51X_DEBUGP(" -- sg entry dma length = %d\n", - sg_dma_len(sg)); - } else { - /* hc may use _only_ transfer_buffer */ - io->urbs[i]->transfer_buffer = sg_virt(sg) + *offset; - len = sg->length - *offset; - RTS51X_DEBUGP(" -- sg entry length = %d\n", - sg->length); - } - - if (length >= len) { - *offset = 0; - io->urbs[i]->transfer_buffer_length = len; - length -= len; - sg = sg_next(sg); - } else { - *offset += length; - io->urbs[i]->transfer_buffer_length = length; - length = 0; - } - if (length == 0) - io->entries = i + 1; -#if 0 - if (length) { - len = min_t(unsigned, len, length); - length -= len; - if (length == 0) { - io->entries = i + 1; - *offset += len; - } else { - *offset = 0; - } - } -#endif - } - RTS51X_DEBUGP("In %s, urb count: %d\n", __func__, i); - io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT; - - RTS51X_DEBUGP("sg address stored in sgptr: 0x%x\n", (unsigned int)sg); - *sgptr = sg; - - /* transaction state */ - io->count = io->entries; - io->status = 0; - io->bytes = 0; - init_completion(&io->complete); - return 0; - -nomem: - rts51x_sg_clean(io); - return -ENOMEM; -} -#endif -int rts51x_sg_init(struct usb_sg_request *io, struct usb_device *dev, - unsigned pipe, unsigned period, struct scatterlist *sg, - int nents, size_t length, gfp_t mem_flags) -{ - return usb_sg_init(io, dev, pipe, period, sg, nents, length, mem_flags); -} - -int rts51x_sg_wait(struct usb_sg_request *io, int timeout) -{ - long timeleft; - int i; - int entries = io->entries; - - /* queue the urbs. */ - spin_lock_irq(&io->lock); - i = 0; - while (i < entries && !io->status) { - int retval; - - io->urbs[i]->dev = io->dev; - retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC); - - /* after we submit, let completions or cancelations fire; - * we handshake using io->status. - */ - spin_unlock_irq(&io->lock); - switch (retval) { - /* maybe we retrying will recover */ - case -ENXIO: /* hc didn't queue this one */ - case -EAGAIN: - case -ENOMEM: - io->urbs[i]->dev = NULL; - retval = 0; - yield(); - break; - - /* no error? continue immediately. - * - * NOTE: to work better with UHCI (4K I/O buffer may - * need 3K of TDs) it may be good to limit how many - * URBs are queued at once; N milliseconds? - */ - case 0: - ++i; - cpu_relax(); - break; - - /* fail any uncompleted urbs */ - default: - io->urbs[i]->dev = NULL; - io->urbs[i]->status = retval; - dev_dbg(&io->dev->dev, "%s, submit --> %d\n", - __func__, retval); - usb_sg_cancel(io); - } - spin_lock_irq(&io->lock); - if (retval && (io->status == 0 || io->status == -ECONNRESET)) - io->status = retval; - } - io->count -= entries - i; - if (io->count == 0) - complete(&io->complete); - spin_unlock_irq(&io->lock); - - timeleft = - wait_for_completion_interruptible_timeout(&io->complete, - (timeout * HZ / - 1000) ? : - MAX_SCHEDULE_TIMEOUT); - if (timeleft <= 0) { - RTS51X_DEBUGP("%s -- cancelling SG request\n", - timeleft == 0 ? "Timeout" : "Signal"); - usb_sg_cancel(io); - if (timeleft == 0) - io->status = -ETIMEDOUT; - else - io->status = -EINTR; - } - - rts51x_sg_clean(io); - return io->status; -} - -/* - * Transfer a scatter-gather list via bulk transfer - * - * This function does basically the same thing as usb_stor_bulk_transfer_buf() - * above, but it uses the usbcore scatter-gather library. - */ -static int rts51x_bulk_transfer_sglist(struct rts51x_chip *chip, - unsigned int pipe, - struct scatterlist *sg, int num_sg, - unsigned int length, - unsigned int *act_len, int timeout) -{ - int result; - - /* don't submit s-g requests during abort processing */ - if (test_bit(FLIDX_ABORTING, &chip->usb->dflags)) - TRACE_RET(chip, STATUS_ERROR); - - /* initialize the scatter-gather request block */ - RTS51X_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__, - length, num_sg); - result = - rts51x_sg_init(&chip->usb->current_sg, chip->usb->pusb_dev, pipe, 0, - sg, num_sg, length, GFP_NOIO); - if (result) { - RTS51X_DEBUGP("rts51x_sg_init returned %d\n", result); - TRACE_RET(chip, STATUS_ERROR); - } - - /* since the block has been initialized successfully, it's now - * okay to cancel it */ - set_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags); - - /* did an abort occur during the submission? */ - if (test_bit(FLIDX_ABORTING, &chip->usb->dflags)) { - - /* cancel the request, if it hasn't been cancelled already */ - if (test_and_clear_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags)) { - RTS51X_DEBUGP("-- cancelling sg request\n"); - usb_sg_cancel(&chip->usb->current_sg); - } - } - - /* wait for the completion of the transfer */ - result = rts51x_sg_wait(&chip->usb->current_sg, timeout); - - clear_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags); - - /* result = us->current_sg.status; */ - if (act_len) - *act_len = chip->usb->current_sg.bytes; - return interpret_urb_result(chip, pipe, length, result, - chip->usb->current_sg.bytes); -} -#if 0 -static int rts51x_bulk_transfer_sglist_partial(struct rts51x_chip *chip, - unsigned int pipe, void *buf, struct scatterlist **sgptr, - unsigned int *offset, int num_sg, unsigned int length, - unsigned int *act_len, int timeout) -{ - int result; - - /* don't submit s-g requests during abort processing */ - if (test_bit(FLIDX_ABORTING, &chip->usb->dflags)) - TRACE_RET(chip, STATUS_ERROR); - - /* initialize the scatter-gather request block */ - RTS51X_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__, - length, num_sg); - result = rts51x_sg_init_partial(&chip->usb->current_sg, - chip->usb->pusb_dev, pipe, 0, buf, sgptr, offset, - num_sg, length, GFP_NOIO); - if (result) { - RTS51X_DEBUGP("rts51x_sg_init_partial returned %d\n", result); - TRACE_RET(chip, STATUS_ERROR); - } - - /* since the block has been initialized successfully, it's now - * okay to cancel it */ - set_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags); - - /* did an abort occur during the submission? */ - if (test_bit(FLIDX_ABORTING, &chip->usb->dflags)) { - - /* cancel the request, if it hasn't been cancelled already */ - if (test_and_clear_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags)) { - RTS51X_DEBUGP("-- cancelling sg request\n"); - usb_sg_cancel(&chip->usb->current_sg); - } - } - - /* wait for the completion of the transfer */ - result = rts51x_sg_wait(&chip->usb->current_sg, timeout); - - clear_bit(FLIDX_SG_ACTIVE, &chip->usb->dflags); - - /* result = us->current_sg.status; */ - if (act_len) - *act_len = chip->usb->current_sg.bytes; - return interpret_urb_result(chip, pipe, length, result, - chip->usb->current_sg.bytes); -} -#endif -int rts51x_bulk_transfer_buf(struct rts51x_chip *chip, unsigned int pipe, - void *buf, unsigned int length, - unsigned int *act_len, int timeout) -{ - int result; - - /* fill and submit the URB */ - usb_fill_bulk_urb(chip->usb->current_urb, chip->usb->pusb_dev, pipe, - buf, length, urb_done_completion, NULL); - result = rts51x_msg_common(chip, chip->usb->current_urb, timeout); - - /* store the actual length of the data transferred */ - if (act_len) - *act_len = chip->usb->current_urb->actual_length; - return interpret_urb_result(chip, pipe, length, result, - chip->usb->current_urb->actual_length); -} - -int rts51x_transfer_data(struct rts51x_chip *chip, unsigned int pipe, - void *buf, unsigned int len, int use_sg, - unsigned int *act_len, int timeout) -{ - int result; - - if (timeout < 600) - timeout = 600; - - if (use_sg) { - result = - rts51x_bulk_transfer_sglist(chip, pipe, - (struct scatterlist *)buf, - use_sg, len, act_len, timeout); - } else { - result = - rts51x_bulk_transfer_buf(chip, pipe, buf, len, act_len, - timeout); - } - - return result; -} - -int rts51x_transfer_data_partial(struct rts51x_chip *chip, unsigned int pipe, - void *buf, void **ptr, unsigned int *offset, - unsigned int len, int use_sg, - unsigned int *act_len, int timeout) -{ - int result; - - if (timeout < 600) - timeout = 600; - - if (use_sg) { - void *tmp_buf = kmalloc(len, GFP_KERNEL); - if (!tmp_buf) - TRACE_RET(chip, STATUS_NOMEM); - - if (usb_pipeout(pipe)) { - rts51x_access_sglist(tmp_buf, len, buf, ptr, offset, - FROM_XFER_BUF); - } - result = - rts51x_bulk_transfer_buf(chip, pipe, tmp_buf, len, act_len, - timeout); - if (result == STATUS_SUCCESS) { - if (usb_pipein(pipe)) { - rts51x_access_sglist(tmp_buf, len, buf, ptr, - offset, TO_XFER_BUF); - } - } - - kfree(tmp_buf); -#if 0 - result = rts51x_bulk_transfer_sglist_partial(chip, pipe, buf, - (struct scatterlist **)ptr, offset, - use_sg, len, act_len, timeout); -#endif - } else { - unsigned int step = 0; - if (offset) - step = *offset; - result = - rts51x_bulk_transfer_buf(chip, pipe, buf + step, len, - act_len, timeout); - if (act_len) - step += *act_len; - else - step += len; - if (offset) - *offset = step; - } - - return result; -} - -int rts51x_get_epc_status(struct rts51x_chip *chip, u16 * status) -{ - unsigned int pipe = RCV_INTR_PIPE(chip); - struct usb_host_endpoint *ep; - struct completion urb_done; - int result; - - if (!status) - TRACE_RET(chip, STATUS_ERROR); - - /* set up data structures for the wakeup system */ - init_completion(&urb_done); - - ep = chip->usb->pusb_dev->ep_in[usb_pipeendpoint(pipe)]; - - /* fill and submit the URB */ - /* We set interval to 1 here, so the polling interval is controlled - * by our polling thread */ - usb_fill_int_urb(chip->usb->intr_urb, chip->usb->pusb_dev, pipe, - status, 2, urb_done_completion, &urb_done, 1); - - result = rts51x_msg_common(chip, chip->usb->intr_urb, 50); - - return interpret_urb_result(chip, pipe, 2, result, - chip->usb->intr_urb->actual_length); -} - -u8 media_not_present[] = { - 0x70, 0, 0x02, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0x3A, 0, 0, 0, 0, 0 }; -u8 invalid_cmd_field[] = { - 0x70, 0, 0x05, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0x24, 0, 0, 0, 0, 0 }; - -void rts51x_invoke_transport(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - int result; - -#ifdef CONFIG_PM - if (chip->option.ss_en) { - if (srb->cmnd[0] == TEST_UNIT_READY) { - if (RTS51X_CHK_STAT(chip, STAT_SS)) { - if (check_fake_card_ready(chip, - SCSI_LUN(srb))) { - srb->result = SAM_STAT_GOOD; - } else { - srb->result = SAM_STAT_CHECK_CONDITION; - memcpy(srb->sense_buffer, - media_not_present, SENSE_SIZE); - } - return; - } - } else if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { - if (RTS51X_CHK_STAT(chip, STAT_SS)) { - int prevent = srb->cmnd[4] & 0x1; - - if (prevent) { - srb->result = SAM_STAT_CHECK_CONDITION; - memcpy(srb->sense_buffer, - invalid_cmd_field, SENSE_SIZE); - } else { - srb->result = SAM_STAT_GOOD; - } - return; - } - } else { - if (RTS51X_CHK_STAT(chip, STAT_SS) - || RTS51X_CHK_STAT(chip, STAT_SS_PRE)) { - /* Wake up device */ - RTS51X_DEBUGP("Try to wake up device\n"); - chip->resume_from_scsi = 1; - - rts51x_try_to_exit_ss(chip); - - if (RTS51X_CHK_STAT(chip, STAT_SS)) { - wait_timeout(3000); - - rts51x_init_chip(chip); - rts51x_init_cards(chip); - } - } - } - } -#endif - - result = rts51x_scsi_handler(srb, chip); - - /* if there is a transport error, reset and don't auto-sense */ - if (result == TRANSPORT_ERROR) { - RTS51X_DEBUGP("-- transport indicates error, resetting\n"); - srb->result = DID_ERROR << 16; - goto Handle_Errors; - } - - srb->result = SAM_STAT_GOOD; - - /* - * If we have a failure, we're going to do a REQUEST_SENSE - * automatically. Note that we differentiate between a command - * "failure" and an "error" in the transport mechanism. - */ - if (result == TRANSPORT_FAILED) { - /* set the result so the higher layers expect this data */ - srb->result = SAM_STAT_CHECK_CONDITION; - memcpy(srb->sense_buffer, - (unsigned char *)&(chip->sense_buffer[SCSI_LUN(srb)]), - sizeof(struct sense_data_t)); - } - - return; - - /* Error and abort processing: try to resynchronize with the device - * by issuing a port reset. If that fails, try a class-specific - * device reset. */ -Handle_Errors: - return; -} diff --git a/trunk/drivers/staging/rts5139/rts51x_transport.h b/trunk/drivers/staging/rts5139/rts51x_transport.h deleted file mode 100644 index f7aa87f7f1a9..000000000000 --- a/trunk/drivers/staging/rts5139/rts51x_transport.h +++ /dev/null @@ -1,80 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_TRANSPORT_H -#define __RTS51X_TRANSPORT_H - -#include -#include - -#include "rts51x.h" -#include "rts51x_chip.h" - -#if 1 /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34) */ -#define URB_NO_SETUP_DMA_MAP 0 -#endif - -unsigned int rts51x_access_sglist(unsigned char *buffer, - unsigned int buflen, void *sglist, - void **sgptr, unsigned int *offset, - enum xfer_buf_dir dir); -unsigned int rts51x_access_xfer_buf(unsigned char *buffer, unsigned int buflen, - struct scsi_cmnd *srb, - struct scatterlist **sgptr, - unsigned int *offset, - enum xfer_buf_dir dir); -void rts51x_set_xfer_buf(unsigned char *buffer, unsigned int buflen, - struct scsi_cmnd *srb); -void rts51x_get_xfer_buf(unsigned char *buffer, unsigned int buflen, - struct scsi_cmnd *srb); - -int rts51x_ctrl_transfer(struct rts51x_chip *chip, unsigned int pipe, - u8 request, u8 requesttype, u16 value, u16 index, - void *data, u16 size, int timeout); -int rts51x_clear_halt(struct rts51x_chip *chip, unsigned int pipe); -int rts51x_transfer_data(struct rts51x_chip *chip, unsigned int pipe, - void *buf, unsigned int len, int use_sg, - unsigned int *act_len, int timeout); -int rts51x_transfer_data_partial(struct rts51x_chip *chip, unsigned int pipe, - void *buf, void **ptr, unsigned int *offset, - unsigned int len, int use_sg, - unsigned int *act_len, int timeout); - -/* whichPipe: - * 0: bulk in pipe - * 1: bulk out pipe - * 2: intr in pipe */ -int rts51x_reset_pipe(struct rts51x_chip *chip, char pipe); - -#ifndef POLLING_IN_THREAD -int rts51x_start_epc_transfer(struct rts51x_chip *chip); -void rts51x_cancel_epc_transfer(struct rts51x_chip *chip); -#endif - -int rts51x_get_epc_status(struct rts51x_chip *chip, u16 * status); -void rts51x_invoke_transport(struct scsi_cmnd *srb, struct rts51x_chip *chip); - -#endif /* __RTS51X_TRANSPORT_H */ diff --git a/trunk/drivers/staging/rts5139/sd.c b/trunk/drivers/staging/rts5139/sd.c deleted file mode 100644 index d5dd2f926d1d..000000000000 --- a/trunk/drivers/staging/rts5139/sd.c +++ /dev/null @@ -1,3400 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include - -#include "debug.h" -#include "trace.h" -#include "rts51x.h" -#include "rts51x_transport.h" -#include "rts51x_scsi.h" -#include "rts51x_card.h" -#include "sd.h" - -static inline void sd_set_reset_fail(struct rts51x_chip *chip, u8 err_code) -{ - struct sd_info *sd_card = &(chip->sd_card); - - sd_card->sd_reset_fail |= err_code; -} - -static inline void sd_clear_reset_fail(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - - sd_card->sd_reset_fail = 0; -} - -static inline int sd_check_reset_fail(struct rts51x_chip *chip, u8 err_code) -{ - struct sd_info *sd_card = &(chip->sd_card); - - return sd_card->sd_reset_fail & err_code; -} - -static inline void sd_set_err_code(struct rts51x_chip *chip, u8 err_code) -{ - struct sd_info *sd_card = &(chip->sd_card); - - sd_card->err_code |= err_code; -} - -static inline void sd_clr_err_code(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - - sd_card->err_code = 0; -} - -static inline int sd_check_err_code(struct rts51x_chip *chip, u8 err_code) -{ - struct sd_info *sd_card = &(chip->sd_card); - - return sd_card->err_code & err_code; -} - -static int sd_parse_err_code(struct rts51x_chip *chip) -{ - TRACE_RET(chip, STATUS_FAIL); -} - -int sd_check_data0_status(struct rts51x_chip *chip) -{ - int retval; - u8 stat; - - retval = rts51x_ep0_read_register(chip, SD_BUS_STAT, &stat); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (!(stat & SD_DAT0_STATUS)) { - sd_set_err_code(chip, SD_BUSY); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_send_cmd_get_rsp(struct rts51x_chip *chip, u8 cmd_idx, - u32 arg, u8 rsp_type, u8 *rsp, int rsp_len) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int timeout = 50; - u16 reg_addr; - u8 buf[17], stat; - int len = 2; - int rty_cnt = 0; - - sd_clr_err_code(chip); - - RTS51X_DEBUGP("SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg); - - if (rsp_type == SD_RSP_TYPE_R1b) - timeout = 3000; - -RTY_SEND_CMD: - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8) (arg >> 24)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8) (arg >> 16)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8) (arg >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8) arg); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_CMD_RSP | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, - SD_TRANSFER_END | SD_STAT_IDLE, - SD_TRANSFER_END | SD_STAT_IDLE); - - rts51x_add_cmd(chip, READ_REG_CMD, SD_STAT1, 0, 0); - - if (CHECK_USB(chip, USB_20)) { - if (rsp_type == SD_RSP_TYPE_R2) { - /* Read data from ping-pong buffer */ - for (reg_addr = PPBUF_BASE2; - reg_addr < PPBUF_BASE2 + 16; reg_addr++) { - rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0, - 0); - } - len = 18; - } else if (rsp_type != SD_RSP_TYPE_R0) { - /* Read data from SD_CMDx registers */ - for (reg_addr = SD_CMD0; reg_addr <= SD_CMD4; - reg_addr++) { - rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0, - 0); - } - len = 7; - } else { - len = 2; - } - } else { - len = 2; - } - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, len, timeout); - - if (CHECK_SD_TRANS_FAIL(chip, retval)) { - u8 val; - - rts51x_ep0_read_register(chip, SD_STAT1, &val); - RTS51X_DEBUGP("SD_STAT1: 0x%x\n", val); - - rts51x_ep0_read_register(chip, SD_STAT2, &val); - RTS51X_DEBUGP("SD_STAT2: 0x%x\n", val); - - if (val & SD_RSP_80CLK_TIMEOUT) - sd_set_err_code(chip, SD_RSP_TIMEOUT); - - rts51x_ep0_read_register(chip, SD_BUS_STAT, &val); - RTS51X_DEBUGP("SD_BUS_STAT: 0x%x\n", val); - - if (retval == STATUS_TIMEDOUT) { - if (rsp_type & SD_WAIT_BUSY_END) { - retval = sd_check_data0_status(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - sd_set_err_code(chip, SD_TO_ERR); - } - } - rts51x_clear_sd_error(chip); - - TRACE_RET(chip, STATUS_FAIL); - } - - if (rsp_type == SD_RSP_TYPE_R0) - return STATUS_SUCCESS; - - if (CHECK_USB(chip, USB_20)) { - rts51x_read_rsp_buf(chip, 2, buf, len - 2); - } else { - if (rsp_type == SD_RSP_TYPE_R2) { - reg_addr = PPBUF_BASE2; - len = 16; - } else { - reg_addr = SD_CMD0; - len = 5; - } - retval = rts51x_seq_read_register(chip, reg_addr, - (unsigned short)len, buf); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - stat = chip->rsp_buf[1]; - - /* Check (Start,Transmission) bit of Response */ - if ((buf[0] & 0xC0) != 0) { - sd_set_err_code(chip, SD_STS_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - /* Check CRC7 */ - if (!(rsp_type & SD_NO_CHECK_CRC7)) { - if (stat & SD_CRC7_ERR) { - if (cmd_idx == WRITE_MULTIPLE_BLOCK) { - sd_set_err_code(chip, SD_CRC_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - if (rty_cnt < SD_MAX_RETRY_COUNT) { - wait_timeout(20); - rty_cnt++; - goto RTY_SEND_CMD; - } else { - sd_set_err_code(chip, SD_CRC_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - } - } - /* Check Status */ - if ((rsp_type == SD_RSP_TYPE_R1) || (rsp_type == SD_RSP_TYPE_R1b)) { - if ((cmd_idx != SEND_RELATIVE_ADDR) - && (cmd_idx != SEND_IF_COND)) { - if (cmd_idx != STOP_TRANSMISSION) { - if (buf[1] & 0x80) - TRACE_RET(chip, STATUS_FAIL); - } -#ifdef SUPPORT_SD_LOCK - /* exclude bit25 CARD_IS_LOCKED */ - if (buf[1] & 0x7D) { -#else - if (buf[1] & 0x7F) { -#endif - RTS51X_DEBUGP("buf[1]: 0x%02x\n", buf[1]); - TRACE_RET(chip, STATUS_FAIL); - } - if (buf[2] & 0xFF) { - RTS51X_DEBUGP("buf[2]: 0x%02x\n", buf[2]); - TRACE_RET(chip, STATUS_FAIL); - } - if (buf[3] & 0x80) { - RTS51X_DEBUGP("buf[3]: 0x%02x\n", buf[3]); - TRACE_RET(chip, STATUS_FAIL); - } - if (buf[3] & 0x01) { - /* Get "READY_FOR_DATA" bit */ - sd_card->sd_data_buf_ready = 1; - } else { - sd_card->sd_data_buf_ready = 0; - } - } - } - - if (rsp && rsp_len) - memcpy(rsp, buf, rsp_len); - - return STATUS_SUCCESS; -} - -static inline void sd_print_debug_reg(struct rts51x_chip *chip) -{ -#ifdef CONFIG_RTS5139_DEBUG - u8 val = 0; - - rts51x_ep0_read_register(chip, SD_STAT1, &val); - RTS51X_DEBUGP("SD_STAT1: 0x%x\n", val); - rts51x_ep0_read_register(chip, SD_STAT2, &val); - RTS51X_DEBUGP("SD_STAT2: 0x%x\n", val); - rts51x_ep0_read_register(chip, SD_BUS_STAT, &val); - RTS51X_DEBUGP("SD_BUS_STAT: 0x%x\n", val); -#endif -} - -int sd_read_data(struct rts51x_chip *chip, u8 trans_mode, u8 *cmd, int cmd_len, - u16 byte_cnt, u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len, - int timeout) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - - sd_clr_err_code(chip); - - if (!buf) - buf_len = 0; - - if (buf_len > 512) - /* This function can't read data more than one page */ - TRACE_RET(chip, STATUS_FAIL); - - rts51x_init_cmd(chip); - - if (cmd_len) { - RTS51X_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40); - for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) { - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0 + i, 0xFF, - cmd[i]); - } - } - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8) byte_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, - (u8) (byte_cnt >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, (u8) blk_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, - (u8) (blk_cnt >> 8)); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, bus_width); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END - | SD_CHECK_CRC7 | SD_RSP_LEN_6); - if (trans_mode != SD_TM_AUTO_TUNING) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - } - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - trans_mode | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 1, timeout); - - if (CHECK_SD_TRANS_FAIL(chip, retval)) { - sd_print_debug_reg(chip); - if (retval == STATUS_TIMEDOUT) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - - TRACE_RET(chip, STATUS_FAIL); - } - - if (buf && buf_len) { - retval = rts51x_read_ppbuf(chip, buf, buf_len); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -static int sd_write_data(struct rts51x_chip *chip, u8 trans_mode, - u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, - u8 bus_width, u8 *buf, int buf_len, int timeout) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - - sd_clr_err_code(chip); - - if (!buf) - buf_len = 0; - - /* This function can't write data more than one page */ - if (buf_len > 512) - TRACE_RET(chip, STATUS_FAIL); - - if (buf && buf_len) { - retval = rts51x_write_ppbuf(chip, buf, buf_len); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - rts51x_init_cmd(chip); - - if (cmd_len) { - RTS51X_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40); - for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) { - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0 + i, 0xFF, - cmd[i]); - } - } - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8) byte_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, - (u8) (byte_cnt >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, (u8) blk_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, - (u8) (blk_cnt >> 8)); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, bus_width); - - if (cmd_len) { - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | - SD_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); - - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | - SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | - SD_RSP_LEN_6); - } - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - trans_mode | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 1, timeout); - - if (CHECK_SD_TRANS_FAIL(chip, retval)) { - sd_print_debug_reg(chip); - - if (retval == STATUS_TIMEDOUT) - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_check_csd(struct rts51x_chip *chip, char check_wp) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - u8 csd_ver, trans_speed; - u8 rsp[16]; - - for (i = 0; i < 6; i++) { - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) { - sd_set_reset_fail(chip, SD_RESET_FAIL); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = - sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr, - SD_RSP_TYPE_R2, rsp, 16); - if (retval == STATUS_SUCCESS) - break; - } - - if (i == 6) - TRACE_RET(chip, STATUS_FAIL); - memcpy(sd_card->raw_csd, rsp + 1, 15); - /* Get CRC7 */ - RTS51X_READ_REG(chip, SD_CMD5, sd_card->raw_csd + 15); - - RTS51X_DEBUGP("CSD Response:\n"); - RTS51X_DUMP(rsp, 16); - - /* Get CSD Version */ - csd_ver = (rsp[1] & 0xc0) >> 6; - RTS51X_DEBUGP("csd_ver = %d\n", csd_ver); - - trans_speed = rsp[4]; - if ((trans_speed & 0x07) == 0x02) { /* 10Mbits/s */ - if ((trans_speed & 0xf8) >= 0x30) { /* >25Mbits/s */ - if (chip->asic_code) - sd_card->sd_clock = 46; - else - sd_card->sd_clock = CLK_50; - } else if ((trans_speed & 0xf8) == 0x28) { /* 20Mbits/s */ - if (chip->asic_code) - sd_card->sd_clock = 39; - else - sd_card->sd_clock = CLK_40; - } else if ((trans_speed & 0xf8) == 0x20) { /* 15Mbits/s */ - if (chip->asic_code) - sd_card->sd_clock = 29; - else - sd_card->sd_clock = CLK_30; - } else if ((trans_speed & 0xf8) >= 0x10) { /* 12Mbits/s */ - if (chip->asic_code) - sd_card->sd_clock = 23; - else - sd_card->sd_clock = CLK_20; - } else if ((trans_speed & 0x08) >= 0x08) { /* 10Mbits/s */ - if (chip->asic_code) - sd_card->sd_clock = 19; - else - sd_card->sd_clock = CLK_20; - } /*else { */ - /*If this ,then slow card will use 30M clock */ - /* TRACE_RET(chip, STATUS_FAIL); */ - /* } */ - } - /*else { - TRACE_RET(chip, STATUS_FAIL); - } */ - if (CHK_MMC_SECTOR_MODE(sd_card)) { - sd_card->capacity = 0; - } else { - /* For High-Capacity Card, CSD_STRUCTURE always be "0x1" */ - if ((!CHK_SD_HCXC(sd_card)) || (csd_ver == 0)) { - /* Calculate total sector according to C_SIZE, - * C_SIZE_MULT & READ_BL_LEN */ - u8 blk_size, c_size_mult; - u16 c_size; - /* Get READ_BL_LEN */ - blk_size = rsp[6] & 0x0F; - /* Get C_SIZE */ - c_size = ((u16) (rsp[7] & 0x03) << 10) - + ((u16) rsp[8] << 2) - + ((u16) (rsp[9] & 0xC0) >> 6); - /* Get C_SIZE_MUL */ - c_size_mult = (u8) ((rsp[10] & 0x03) << 1); - c_size_mult += (rsp[11] & 0x80) >> 7; - /* Calculate total Capacity */ - sd_card->capacity = - (((u32) (c_size + 1)) * - (1 << (c_size_mult + 2))) << (blk_size - 9); - } else { - /* High Capacity Card and Use CSD2.0 Version */ - u32 total_sector = 0; - total_sector = (((u32) rsp[8] & 0x3f) << 16) | - ((u32) rsp[9] << 8) | (u32) rsp[10]; - /* Total Capacity= (C_SIZE+1) * - * 512K Byte = (C_SIZE+1)K Sector,1K = 1024 Bytes */ - sd_card->capacity = (total_sector + 1) << 10; - } - } - - /* We need check Write-Protected Status by Field PERM WP or TEMP WP */ - if (check_wp) { - if (rsp[15] & 0x30) - chip->card_wp |= SD_CARD; - RTS51X_DEBUGP("CSD WP Status: 0x%x\n", rsp[15]); - } - - return STATUS_SUCCESS; -} - -static int sd_set_sample_push_timing(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - rts51x_init_cmd(chip); - - if (CHK_SD_SDR104(sd_card) || CHK_SD_SDR50(sd_card)) { - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, - 0x0C | SD_ASYNC_FIFO_RST, - SD_30_MODE | SD_ASYNC_FIFO_RST); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, - CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); - } else if (CHK_SD_DDR50(sd_card) || CHK_MMC_DDR52(sd_card)) { - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, - 0x0C | SD_ASYNC_FIFO_RST, - SD_DDR_MODE | SD_ASYNC_FIFO_RST); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, - CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_PUSH_POINT_CTL, - DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, - DDR_VAR_RX_DAT | DDR_VAR_RX_CMD, - DDR_VAR_RX_DAT | DDR_VAR_RX_CMD); - } else { - u8 val = 0; - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x0C, SD_20_MODE); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF, - CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1); - - if ((chip->option.sd_ctl & SD_PUSH_POINT_CTL_MASK) == - SD_PUSH_POINT_AUTO) { - val = SD20_TX_NEG_EDGE; - } else if ((chip->option.sd_ctl & SD_PUSH_POINT_CTL_MASK) == - SD_PUSH_POINT_DELAY) { - val = SD20_TX_14_AHEAD; - } else { - val = SD20_TX_NEG_EDGE; - } - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_PUSH_POINT_CTL, - SD20_TX_SEL_MASK, val); - - if ((chip->option.sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == - SD_SAMPLE_POINT_AUTO) { - if (chip->asic_code) { - if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) - val = SD20_RX_14_DELAY; - else - val = SD20_RX_POS_EDGE; - } else { - val = SD20_RX_14_DELAY; - } - } else if ((chip->option.sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == - SD_SAMPLE_POINT_DELAY) { - val = SD20_RX_14_DELAY; - } else { - val = SD20_RX_POS_EDGE; - } - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, - SD20_RX_SEL_MASK, val); - } - - if (CHK_MMC_DDR52(sd_card) && CHK_MMC_8BIT(sd_card)) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DMA1_CTL, - EXTEND_DMA1_ASYNC_SIGNAL, 0); - } - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static void sd_choose_proper_clock(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - - if (CHK_SD_SDR104(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->option.asic_sd_sdr104_clk; - else - sd_card->sd_clock = chip->option.fpga_sd_sdr104_clk; - } else if (CHK_SD_DDR50(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->option.asic_sd_ddr50_clk; - else - sd_card->sd_clock = chip->option.fpga_sd_ddr50_clk; - } else if (CHK_SD_SDR50(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->option.asic_sd_sdr50_clk; - else - sd_card->sd_clock = chip->option.fpga_sd_sdr50_clk; - } else if (CHK_SD_HS(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->option.asic_sd_hs_clk; - else - sd_card->sd_clock = chip->option.fpga_sd_hs_clk; - } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->option.asic_mmc_52m_clk; - else - sd_card->sd_clock = chip->option.fpga_mmc_52m_clk; - } else if (CHK_MMC_26M(sd_card)) { - if (chip->asic_code) { - sd_card->sd_clock = 46; - RTS51X_DEBUGP("Set MMC clock to 22.5MHz\n"); - } else { - sd_card->sd_clock = CLK_50; - } - } -} - -static int sd_set_init_para(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - retval = sd_set_sample_push_timing(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - sd_choose_proper_clock(chip); - - retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -int sd_select_card(struct rts51x_chip *chip, int select) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd_idx, cmd_type; - u32 addr; - - if (select) { - cmd_idx = SELECT_CARD; - cmd_type = SD_RSP_TYPE_R1; - addr = sd_card->sd_addr; - } else { - cmd_idx = DESELECT_CARD; - cmd_type = SD_RSP_TYPE_R0; - addr = 0; - } - - retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -#ifdef SUPPORT_SD_LOCK -int sd_update_lock_status(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 rsp[5]; - - retval = - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, rsp, 5); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (rsp[1] & 0x02) - sd_card->sd_lock_status |= SD_LOCKED; - else - sd_card->sd_lock_status &= ~SD_LOCKED; - - RTS51X_DEBUGP("sd_card->sd_lock_status = 0x%x\n", - sd_card->sd_lock_status); - - if (rsp[1] & 0x01) { - /* LOCK_UNLOCK_FAILED */ - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} -#endif - -int sd_wait_currentstate_dataready(struct rts51x_chip *chip, u8 statechk, - u8 rdychk, u16 pollingcnt) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 rsp[5]; - u16 i; - - for (i = 0; i < pollingcnt; i++) { - - retval = - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, rsp, 5); - if (retval == STATUS_SUCCESS) { - if (((rsp[3] & 0x1E) == statechk) - && ((rsp[3] & 0x01) == rdychk)) { - return STATUS_SUCCESS; - } - } else { - rts51x_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - } - - return STATUS_TIMEDOUT; -} - -static int sd_voltage_switch(struct rts51x_chip *chip) -{ - int retval; - u8 stat; - - RTS51X_WRITE_REG(chip, SD_BUS_STAT, - SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, - SD_CLK_TOGGLE_EN); - - retval = - sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1, NULL, - 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_READ_REG(chip, SD_BUS_STAT, &stat); - if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | - SD_DAT1_STATUS | SD_DAT0_STATUS)) - TRACE_RET(chip, STATUS_FAIL); - - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BUS_STAT, 0xFF, - SD_CLK_FORCE_STOP); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_PAD_CTL, SD_IO_USING_1V8, - SD_IO_USING_1V8); - if (chip->asic_code) - rts51x_add_cmd(chip, WRITE_REG_CMD, LDO_POWER_CFG, - TUNE_SD18_MASK, TUNE_SD18_1V8); - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - wait_timeout(chip->option.D3318_off_delay); - - RTS51X_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN); - wait_timeout(10); - - RTS51X_READ_REG(chip, SD_BUS_STAT, &stat); - if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | - SD_DAT1_STATUS | SD_DAT0_STATUS)) != - (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | - SD_DAT1_STATUS | SD_DAT0_STATUS)) { - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BUS_STAT, 0xFF, - SD_CLK_FORCE_STOP); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, 0xFF, 0); - rts51x_send_cmd(chip, MODE_C, 100); - TRACE_RET(chip, STATUS_FAIL); - } - RTS51X_WRITE_REG(chip, SD_BUS_STAT, - SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); - - return STATUS_SUCCESS; -} - -static int sd_change_phase(struct rts51x_chip *chip, u8 sample_point, - u8 tune_dir) -{ - u16 SD_VP_CTL, SD_DCMPS_CTL; - u8 val; - int retval; - - RTS51X_DEBUGP("sd_change_phase (sample_point = %d, tune_dir = %d)\n", - sample_point, tune_dir); - - if (tune_dir == TUNE_RX) { - SD_VP_CTL = SD_VPCLK1_CTL; - SD_DCMPS_CTL = SD_DCMPS1_CTL; - } else { - SD_VP_CTL = SD_VPCLK0_CTL; - SD_DCMPS_CTL = SD_DCMPS0_CTL; - } - - if (chip->asic_code) { - RTS51X_WRITE_REG(chip, CLK_DIV, CLK_CHANGE, CLK_CHANGE); - RTS51X_WRITE_REG(chip, SD_VP_CTL, 0x1F, sample_point); - RTS51X_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); - RTS51X_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, - PHASE_NOT_RESET); - RTS51X_WRITE_REG(chip, CLK_DIV, CLK_CHANGE, 0); - } else { -#ifdef CONFIG_RTS5139_DEBUG - RTS51X_READ_REG(chip, SD_VP_CTL, &val); - RTS51X_DEBUGP("SD_VP_CTL: 0x%x\n", val); - RTS51X_READ_REG(chip, SD_DCMPS_CTL, &val); - RTS51X_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val); -#endif - - RTS51X_WRITE_REG(chip, CLK_DIV, CLK_CHANGE, CLK_CHANGE); - udelay(100); - RTS51X_WRITE_REG(chip, SD_VP_CTL, 0xFF, - PHASE_NOT_RESET | sample_point); - udelay(200); - - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE, - DCMPS_CHANGE); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL, - DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE); - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, Fail); - - retval = rts51x_get_rsp(chip, 1, 500); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, Fail); - - val = chip->rsp_buf[0]; - if (val & DCMPS_ERROR) - TRACE_GOTO(chip, Fail); - if ((val & DCMPS_CURRENT_PHASE) != sample_point) - TRACE_GOTO(chip, Fail); - RTS51X_WRITE_REG(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0); - RTS51X_WRITE_REG(chip, CLK_DIV, CLK_CHANGE, 0); - udelay(100); - } - - RTS51X_WRITE_REG(chip, SD_CFG1, SD_ASYNC_FIFO_RST, 0); - - return STATUS_SUCCESS; - -Fail: -#ifdef CONFIG_RTS5139_DEBUG - rts51x_ep0_read_register(chip, SD_VP_CTL, &val); - RTS51X_DEBUGP("SD_VP_CTL: 0x%x\n", val); - rts51x_ep0_read_register(chip, SD_DCMPS_CTL, &val); - RTS51X_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val); -#endif - - RTS51X_WRITE_REG(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0); - RTS51X_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, 0); - wait_timeout(10); - - return STATUS_FAIL; -} - -static int sd_check_spec(struct rts51x_chip *chip, u8 bus_width) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5], buf[8]; - - retval = - sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - cmd[0] = 0x40 | SEND_SCR; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = - sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width, buf, - 8, 250); - if (retval != STATUS_SUCCESS) { - rts51x_clear_sd_error(chip); - TRACE_RET(chip, retval); - } - - memcpy(sd_card->raw_scr, buf, 8); - - if ((buf[0] & 0x0F) == 0) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_query_switch_result(struct rts51x_chip *chip, u8 func_group, - u8 func_to_switch, u8 *buf, int buf_len) -{ - u8 support_mask = 0, query_switch = 0, switch_busy = 0; - int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0; - - if (func_group == SD_FUNC_GROUP_1) { - support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET; - query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET; - check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET; - - switch (func_to_switch) { - case HS_SUPPORT: - support_mask = HS_SUPPORT_MASK; - query_switch = HS_QUERY_SWITCH_OK; - switch_busy = HS_SWITCH_BUSY; - break; - - case SDR50_SUPPORT: - support_mask = SDR50_SUPPORT_MASK; - query_switch = SDR50_QUERY_SWITCH_OK; - switch_busy = SDR50_SWITCH_BUSY; - break; - - case SDR104_SUPPORT: - support_mask = SDR104_SUPPORT_MASK; - query_switch = SDR104_QUERY_SWITCH_OK; - switch_busy = SDR104_SWITCH_BUSY; - break; - - case DDR50_SUPPORT: - support_mask = DDR50_SUPPORT_MASK; - query_switch = DDR50_QUERY_SWITCH_OK; - switch_busy = DDR50_SWITCH_BUSY; - break; - - default: - TRACE_RET(chip, STATUS_FAIL); - } - } else if (func_group == SD_FUNC_GROUP_3) { - support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET; - query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET; - check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET; - - switch (func_to_switch) { - case DRIVING_TYPE_A: - support_mask = DRIVING_TYPE_A_MASK; - query_switch = TYPE_A_QUERY_SWITCH_OK; - switch_busy = TYPE_A_SWITCH_BUSY; - break; - - case DRIVING_TYPE_C: - support_mask = DRIVING_TYPE_C_MASK; - query_switch = TYPE_C_QUERY_SWITCH_OK; - switch_busy = TYPE_C_SWITCH_BUSY; - break; - - case DRIVING_TYPE_D: - support_mask = DRIVING_TYPE_D_MASK; - query_switch = TYPE_D_QUERY_SWITCH_OK; - switch_busy = TYPE_D_SWITCH_BUSY; - break; - - default: - TRACE_RET(chip, STATUS_FAIL); - } - } else if (func_group == SD_FUNC_GROUP_4) { - support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET; - query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET; - check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET; - - switch (func_to_switch) { - case CURRENT_LIMIT_400: - support_mask = CURRENT_LIMIT_400_MASK; - query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK; - switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY; - break; - - case CURRENT_LIMIT_600: - support_mask = CURRENT_LIMIT_600_MASK; - query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK; - switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY; - break; - - case CURRENT_LIMIT_800: - support_mask = CURRENT_LIMIT_800_MASK; - query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK; - switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY; - break; - - default: - TRACE_RET(chip, STATUS_FAIL); - } - } else { - TRACE_RET(chip, STATUS_FAIL); - } - - if (func_group == SD_FUNC_GROUP_4) - buf[query_switch_offset] = - (buf[query_switch_offset] & 0xf0) >> 4; - if (!(buf[support_offset] & support_mask) || - ((buf[query_switch_offset] & 0x0F) != query_switch)) - TRACE_RET(chip, STATUS_FAIL); - - if ((buf[DATA_STRUCTURE_VER_OFFSET] == 0x01) && - ((buf[check_busy_offset] & switch_busy) == switch_busy)) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_check_switch_mode(struct rts51x_chip *chip, u8 mode, - u8 func_group, u8 func_to_switch, u8 bus_width) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5], buf[64]; - - RTS51X_DEBUGP("sd_check_switch_mode (mode = %d, func_group = %d," - "func_to_switch = %d)\n", mode, func_group, func_to_switch); - - cmd[0] = 0x40 | SWITCH; - cmd[1] = mode; - - if (func_group == SD_FUNC_GROUP_1) { - cmd[2] = 0xFF; - cmd[3] = 0xFF; - cmd[4] = 0xF0 + func_to_switch; - } else if (func_group == SD_FUNC_GROUP_3) { - cmd[2] = 0xFF; - cmd[3] = 0xF0 + func_to_switch; - cmd[4] = 0xFF; - } else if (func_group == SD_FUNC_GROUP_4) { - cmd[2] = 0xFF; - cmd[3] = 0x0F + (func_to_switch << 4); - cmd[4] = 0xFF; - } else { - cmd[1] = SD_CHECK_MODE; - cmd[2] = 0xFF; - cmd[3] = 0xFF; - cmd[4] = 0xFF; - } - - retval = - sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width, buf, - 64, 250); - if (retval != STATUS_SUCCESS) { - rts51x_clear_sd_error(chip); - TRACE_RET(chip, retval); - } - - if (func_group == NO_ARGUMENT) { - sd_card->func_group1_mask = buf[0x0D]; - sd_card->func_group2_mask = buf[0x0B]; - sd_card->func_group3_mask = buf[0x09]; - sd_card->func_group4_mask = buf[0x07]; - - RTS51X_DEBUGP("func_group1_mask = 0x%02x\n", buf[0x0D]); - RTS51X_DEBUGP("func_group2_mask = 0x%02x\n", buf[0x0B]); - RTS51X_DEBUGP("func_group3_mask = 0x%02x\n", buf[0x09]); - RTS51X_DEBUGP("func_group4_mask = 0x%02x\n", buf[0x07]); - } else { - if ((buf[0] == 0) && (buf[1] == 0)) - TRACE_RET(chip, STATUS_FAIL); - retval = - sd_query_switch_result(chip, func_group, func_to_switch, - buf, 64); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -static int sd_check_switch(struct rts51x_chip *chip, - u8 func_group, u8 func_to_switch, u8 bus_width) -{ - int retval; - int i; - int switch_good = 0; - - for (i = 0; i < 3; i++) { - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) { - sd_set_reset_fail(chip, SD_RESET_FAIL); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group, - func_to_switch, bus_width); - if (retval == STATUS_SUCCESS) { - u8 stat; - - retval = sd_check_switch_mode(chip, SD_SWITCH_MODE, - func_group, func_to_switch, bus_width); - if (retval == STATUS_SUCCESS) { - switch_good = 1; - break; - } - - RTS51X_READ_REG(chip, SD_STAT1, &stat); - - if (stat & SD_CRC16_ERR) { - RTS51X_DEBUGP("SD CRC16 error when switching" - "mode\n"); - TRACE_RET(chip, STATUS_FAIL); - } - } - - wait_timeout(20); - } - - if (!switch_good) - TRACE_RET(chip, STATUS_FAIL); - - return STATUS_SUCCESS; -} - -static int sd_switch_function(struct rts51x_chip *chip, u8 bus_width) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - u8 func_to_switch = 0; - - /* Get supported functions */ - retval = sd_check_switch_mode(chip, SD_CHECK_MODE, - NO_ARGUMENT, NO_ARGUMENT, bus_width); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail); - - for (i = 0; i < 4; i++) { - switch ((u8) (chip->option.sd_speed_prior >> (i * 8))) { - case DDR50_SUPPORT: - if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK) - && (CHECK_UHS50(chip))) - func_to_switch = DDR50_SUPPORT; - break; - - case SDR50_SUPPORT: - if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK) - && (CHECK_UHS50(chip))) - func_to_switch = SDR50_SUPPORT; - break; - - case HS_SUPPORT: - if (sd_card->func_group1_mask & HS_SUPPORT_MASK) - func_to_switch = HS_SUPPORT; - break; - - default: - continue; - } - - if (func_to_switch) - break; - } - RTS51X_DEBUGP("SD_FUNC_GROUP_1: func_to_switch = 0x%02x", - func_to_switch); - -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_SDR_RST) - && (DDR50_SUPPORT == func_to_switch) - && (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) { - func_to_switch = SDR50_SUPPORT; - RTS51X_DEBUGP("Using SDR50 instead of DDR50 for SD Lock\n"); - } -#endif - - if (func_to_switch) { - retval = - sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch, - bus_width); - if (retval != STATUS_SUCCESS) { - if (func_to_switch == SDR104_SUPPORT) - sd_card->sd_switch_fail = SDR104_SUPPORT_MASK; - else if (func_to_switch == DDR50_SUPPORT) - sd_card->sd_switch_fail = DDR50_SUPPORT_MASK; - else if (func_to_switch == SDR50_SUPPORT) - sd_card->sd_switch_fail = SDR50_SUPPORT_MASK; - else if (func_to_switch == HS_SUPPORT) - sd_card->sd_switch_fail = HS_SUPPORT_MASK; - - TRACE_RET(chip, retval); - } - - if (func_to_switch == SDR104_SUPPORT) - SET_SD_SDR104(sd_card); - else if (func_to_switch == DDR50_SUPPORT) - SET_SD_DDR50(sd_card); - else if (func_to_switch == SDR50_SUPPORT) - SET_SD_SDR50(sd_card); - else - SET_SD_HS(sd_card); - } - - if (CHK_SD_DDR50(sd_card)) - RTS51X_WRITE_REG(chip, SD_CFG1, 0x0C, SD_DDR_MODE); - - func_to_switch = 0; - if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK) - func_to_switch = CURRENT_LIMIT_400; - - if (func_to_switch) { - RTS51X_DEBUGP("Try to switch current_limit_400\n"); - retval = - sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch, - bus_width); - RTS51X_DEBUGP("Switch current_limit_400 status: (%d)\n", - retval); - } - - return STATUS_SUCCESS; -} - -static int sd_wait_data_idle(struct rts51x_chip *chip) -{ - int retval = STATUS_TIMEDOUT; - int i; - u8 val = 0; - - for (i = 0; i < 100; i++) { - retval = rts51x_ep0_read_register(chip, SD_DATA_STATE, &val); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - if (val & SD_DATA_IDLE) { - retval = STATUS_SUCCESS; - break; - } - udelay(100); - } - RTS51X_DEBUGP("SD_DATA_STATE: 0x%02x\n", val); - - return retval; -} - -static int sd_sdr_tuning_rx_cmd(struct rts51x_chip *chip, u8 sample_point) -{ - int retval; - u8 cmd[5]; - - retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - cmd[0] = 0x40 | SEND_TUNING_PATTERN; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_AUTO_TUNING, - cmd, 5, 0x40, 1, SD_BUS_WIDTH_4, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - /* Wait till SD DATA IDLE */ - (void)sd_wait_data_idle(chip); - - rts51x_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_ddr_tuning_rx_cmd(struct rts51x_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5]; - - retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_DEBUGP("sd ddr tuning rx\n"); - - retval = - sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - cmd[0] = 0x40 | SD_STATUS; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, - cmd, 5, 64, 1, SD_BUS_WIDTH_4, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - /* Wait till SD DATA IDLE */ - (void)sd_wait_data_idle(chip); - - rts51x_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int mmc_ddr_tunning_rx_cmd(struct rts51x_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5], bus_width; - - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - - retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_DEBUGP("mmc ddr tuning rx\n"); - - cmd[0] = 0x40 | SEND_EXT_CSD; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, - cmd, 5, 0x200, 1, bus_width, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - /* Wait till SD DATA IDLE */ - (void)sd_wait_data_idle(chip); - - rts51x_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int sd_sdr_tuning_tx_cmd(struct rts51x_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - retval = sd_change_phase(chip, sample_point, TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, - SD_RSP_80CLK_TIMEOUT_EN); - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) { - /* Tunning TX fail */ - rts51x_ep0_write_register(chip, SD_CFG3, - SD_RSP_80CLK_TIMEOUT_EN, 0); - TRACE_RET(chip, STATUS_FAIL); - } - } - - RTS51X_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); - - return STATUS_SUCCESS; -} - -static int sd_ddr_tuning_tx_cmd(struct rts51x_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 cmd[5], bus_width; - - retval = sd_change_phase(chip, sample_point, TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (CHK_SD(sd_card)) { - bus_width = SD_BUS_WIDTH_4; - } else { - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - } - retval = sd_wait_currentstate_dataready(chip, 0x08, 1, 20); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - RTS51X_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, - SD_RSP_80CLK_TIMEOUT_EN); - - cmd[0] = 0x40 | PROGRAM_CSD; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2, - cmd, 5, 16, 1, bus_width, sd_card->raw_csd, 16, 100); - if (retval != STATUS_SUCCESS) { - rts51x_clear_sd_error(chip); - /* Tunning TX fail */ - rts51x_ep0_write_register(chip, SD_CFG3, - SD_RSP_80CLK_TIMEOUT_EN, 0); - TRACE_RET(chip, STATUS_FAIL); - } - - RTS51X_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); - - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - - return STATUS_SUCCESS; -} - -static u8 sd_search_final_phase(struct rts51x_chip *chip, u32 phase_map, - u8 tune_dir) -{ - struct sd_info *sd_card = &(chip->sd_card); - struct timing_phase_path path[MAX_PHASE + 1]; - int i, j, cont_path_cnt; - int new_block, max_len; - u8 final_phase = 0xFF; - int final_path_idx; - - if (phase_map == 0xffff) { - if (CHK_SD_DDR50(sd_card)) { - if (tune_dir == TUNE_TX) - final_phase = chip->option.ddr50_tx_phase; - else - final_phase = chip->option.ddr50_rx_phase; - RTS51X_DEBUGP("DDR50 tuning dir:%d all pass," - "so select default phase:0x%x.\n", - tune_dir, final_phase); - } else { - if (tune_dir == TUNE_TX) - final_phase = chip->option.sdr50_tx_phase; - else - final_phase = chip->option.sdr50_rx_phase; - RTS51X_DEBUGP("SDR50 tuning dir:%d all pass," - "so select default phase:0x%x.\n", - tune_dir, final_phase); - } - goto Search_Finish; - } - - cont_path_cnt = 0; - new_block = 1; - j = 0; - for (i = 0; i < MAX_PHASE + 1; i++) { - if (phase_map & (1 << i)) { - if (new_block) { - new_block = 0; - j = cont_path_cnt++; - path[j].start = i; - path[j].end = i; - } else { - path[j].end = i; - } - } else { - new_block = 1; - if (cont_path_cnt) { - int idx = cont_path_cnt - 1; - path[idx].len = - path[idx].end - path[idx].start + 1; - path[idx].mid = - path[idx].start + path[idx].len / 2; - } - } - } - - if (cont_path_cnt == 0) { - RTS51X_DEBUGP("No continuous phase path\n"); - goto Search_Finish; - } else { - int idx = cont_path_cnt - 1; - path[idx].len = path[idx].end - path[idx].start + 1; - path[idx].mid = path[idx].start + path[idx].len / 2; - } - - if ((path[0].start == 0) && - (path[cont_path_cnt - 1].end == MAX_PHASE)) { - path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1; - path[0].len += path[cont_path_cnt - 1].len; - path[0].mid = path[0].start + path[0].len / 2; - if (path[0].mid < 0) - path[0].mid += MAX_PHASE + 1; - cont_path_cnt--; - } - max_len = 0; - final_phase = 0; - final_path_idx = 0; - for (i = 0; i < cont_path_cnt; i++) { - if (path[i].len > max_len) { - max_len = path[i].len; - final_phase = (u8) path[i].mid; - final_path_idx = i; - } - - RTS51X_DEBUGP("path[%d].start = %d\n", i, path[i].start); - RTS51X_DEBUGP("path[%d].end = %d\n", i, path[i].end); - RTS51X_DEBUGP("path[%d].len = %d\n", i, path[i].len); - RTS51X_DEBUGP("path[%d].mid = %d\n", i, path[i].mid); - RTS51X_DEBUGP("\n"); - } - - if ((tune_dir == TUNE_TX) && (CHK_SD_SDR50(sd_card)) - && chip->option.sdr50_phase_sel) { - if (max_len > 6) { - int temp_mid = (max_len - 6) / 2; - int temp_final_phase = - path[final_path_idx].end - (max_len - - (3 + temp_mid)); - - if (temp_final_phase < 0) - final_phase = temp_final_phase + MAX_PHASE + 1; - else - final_phase = (u8) temp_final_phase; - } - } - -Search_Finish: - RTS51X_DEBUGP("Final choosen phase: %d\n", final_phase); - return final_phase; -} - -static int sd_tuning_rx(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i, j; - u32 raw_phase_map[3], phase_map; - u8 final_phase; - int (*tuning_cmd) (struct rts51x_chip *chip, u8 sample_point); - - if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) - tuning_cmd = sd_ddr_tuning_rx_cmd; - else - tuning_cmd = sd_sdr_tuning_rx_cmd; - } else { - if (CHK_MMC_DDR52(sd_card)) - tuning_cmd = mmc_ddr_tunning_rx_cmd; - else - TRACE_RET(chip, STATUS_FAIL); - } - - for (i = 0; i < 3; i++) { - raw_phase_map[i] = 0; - for (j = MAX_PHASE; j >= 0; j--) { - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) { - sd_set_reset_fail(chip, SD_RESET_FAIL); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = tuning_cmd(chip, (u8) j); - if (retval == STATUS_SUCCESS) - raw_phase_map[i] |= 1 << j; - else - RTS51X_DEBUGP("Tuning phase %d fail\n", j); - } - } - - phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; - for (i = 0; i < 3; i++) - RTS51X_DEBUGP("RX raw_phase_map[%d] = 0x%04x\n", i, - raw_phase_map[i]); - RTS51X_DEBUGP("RX phase_map = 0x%04x\n", phase_map); - - final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX); - if (final_phase == 0xFF) - TRACE_RET(chip, STATUS_FAIL); - - retval = tuning_cmd(chip, final_phase); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static int sd_ddr_pre_tuning_tx(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 i; - u8 pre_tune_tx_phase; - u32 pre_tune_phase_map; - - RTS51X_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, - SD_RSP_80CLK_TIMEOUT_EN); - - pre_tune_tx_phase = 0xFF; - pre_tune_phase_map = 0x0000; - for (i = 0; i < MAX_PHASE + 1; i++) { - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) { - sd_set_reset_fail(chip, SD_RESET_FAIL); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = sd_change_phase(chip, (u8) i, TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if ((retval == STATUS_SUCCESS) - || !sd_check_err_code(chip, SD_RSP_TIMEOUT)) - pre_tune_phase_map |= (u32) 1 << i; - } - - RTS51X_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); - - pre_tune_tx_phase = - sd_search_final_phase(chip, pre_tune_phase_map, TUNE_TX); - if (pre_tune_tx_phase == 0xFF) - TRACE_RET(chip, STATUS_FAIL); - - sd_change_phase(chip, pre_tune_tx_phase, TUNE_TX); - RTS51X_DEBUGP("DDR TX pre tune phase: %d\n", (int)pre_tune_tx_phase); - - return STATUS_SUCCESS; -} - -static int sd_tuning_tx(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i, j; - u32 raw_phase_map[3], phase_map; - u8 final_phase; - int (*tuning_cmd) (struct rts51x_chip *chip, u8 sample_point); - - if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) - tuning_cmd = sd_ddr_tuning_tx_cmd; - else - tuning_cmd = sd_sdr_tuning_tx_cmd; - } else { - if (CHK_MMC_DDR52(sd_card)) - tuning_cmd = sd_ddr_tuning_tx_cmd; - else - TRACE_RET(chip, STATUS_FAIL); - } - - for (i = 0; i < 3; i++) { - raw_phase_map[i] = 0; - for (j = MAX_PHASE; j >= 0; j--) { - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) { - sd_set_reset_fail(chip, SD_RESET_FAIL); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = tuning_cmd(chip, (u8) j); - if (retval == STATUS_SUCCESS) - raw_phase_map[i] |= 1 << j; - else - RTS51X_DEBUGP("Tuning phase %d fail\n", j); - } - } - - phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; - for (i = 0; i < 3; i++) - RTS51X_DEBUGP("TX raw_phase_map[%d] = 0x%04x\n", i, - raw_phase_map[i]); - RTS51X_DEBUGP("TX phase_map = 0x%04x\n", phase_map); - - final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX); - if (final_phase == 0xFF) - TRACE_RET(chip, STATUS_FAIL); - - retval = tuning_cmd(chip, final_phase); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static int sd_sdr_tuning(struct rts51x_chip *chip) -{ - int retval; - - retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static int sd_ddr_tuning(struct rts51x_chip *chip) -{ - int retval; - - if (!(chip->option.sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_ddr_pre_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - retval = - sd_change_phase(chip, (u8) chip->option.sd_ddr_tx_phase, - TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (!(chip->option.sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -static int mmc_ddr_tuning(struct rts51x_chip *chip) -{ - int retval; - - if (!(chip->option.sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_ddr_pre_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - retval = - sd_change_phase(chip, (u8) chip->option.mmc_ddr_tx_phase, - TUNE_TX); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (!(chip->option.sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -int sd_switch_clock(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int re_tuning = 0; - - retval = rts51x_select_card(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card)) { - if (sd_card->sd_clock != chip->cur_clk) - re_tuning = 1; - } - - retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (re_tuning) { - if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) - retval = sd_ddr_tuning(chip); - else - retval = sd_sdr_tuning(chip); - } else { - if (CHK_MMC_DDR52(sd_card)) - retval = mmc_ddr_tuning(chip); - } - - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -static int sd_prepare_reset(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - if (chip->asic_code) - sd_card->sd_clock = 29; - else - sd_card->sd_clock = CLK_30; - - /* Set SD Clocks */ - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0xFF, - SD_CLK_DIVIDE_128 | SD_20_MODE | SD_BUS_WIDTH_1); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL, 0xFF, - SD20_RX_POS_EDGE); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_PUSH_POINT_CTL, 0xFF, 0); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_select_card(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static void sd_pull_ctl_disable(struct rts51x_chip *chip) -{ - if (CHECK_PKG(chip, LQFP48)) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); - } -} - -static void sd_pull_ctl_enable(struct rts51x_chip *chip) -{ - if (CHECK_PKG(chip, LQFP48)) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA9); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA5); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x9A); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA5); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x9A); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x65); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x5A); - } -} - -static int sd_init_power(struct rts51x_chip *chip) -{ - int retval; - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, LDO3318_PWR_MASK, - LDO_ON); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_PAD_CTL, SD_IO_USING_1V8, - SD_IO_USING_3V3); - if (chip->asic_code) - rts51x_add_cmd(chip, WRITE_REG_CMD, LDO_POWER_CFG, - TUNE_SD18_MASK, TUNE_SD18_3V3); - if (chip->asic_code) - sd_pull_ctl_disable(chip); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, - FPGA_SD_PULL_CTL_BIT); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0); - if (!chip->option.FT2_fast_mode) - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, - POWER_OFF); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (!chip->option.FT2_fast_mode) { -#ifdef SD_XD_IO_FOLLOW_PWR - if (CHECK_PKG(chip, LQFP48) - || chip->option.rts5129_D3318_off_enable) - rts51x_write_register(chip, CARD_PWR_CTL, - LDO_OFF, LDO_OFF); -#endif - wait_timeout(250); - -#ifdef SD_XD_IO_FOLLOW_PWR - if (CHECK_PKG(chip, LQFP48) - || chip->option.rts5129_D3318_off_enable) { - rts51x_init_cmd(chip); - if (chip->asic_code) - sd_pull_ctl_enable(chip); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, - FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, 0); - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - if (chip->asic_code) - rts51x_write_register(chip, CARD_PULL_CTL6, - 0x03, 0x00); - } -#endif - - /* Power on card */ - retval = card_power_on(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - wait_timeout(260); - -#ifdef SUPPORT_OCP - rts51x_get_card_status(chip, &(chip->card_status)); - chip->ocp_stat = (chip->card_status >> 4) & 0x03; - - if (chip->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) { - RTS51X_DEBUGP("Over current, OCPSTAT is 0x%x\n", - chip->ocp_stat); - TRACE_RET(chip, STATUS_FAIL); - } -#endif - } - - rts51x_init_cmd(chip); - if (chip->asic_code) { - sd_pull_ctl_enable(chip); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, 0); - } - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#ifdef SD_XD_IO_FOLLOW_PWR - rts51x_write_register(chip, CARD_INT_PEND, XD_INT | MS_INT | SD_INT, - XD_INT | MS_INT | SD_INT); -#endif - - RTS51X_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN); - - return STATUS_SUCCESS; -} - -static int sd_dummy_clock(struct rts51x_chip *chip) -{ - RTS51X_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN); - wait_timeout(5); - RTS51X_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0x00); - - return STATUS_SUCCESS; -} - -int reset_sd(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval, i = 0, j = 0, k = 0, hi_cap_flow = 0; - int sd_dont_switch = 0; - int support_1v8 = 0; - u8 rsp[16]; - u8 switch_bus_width; - u32 voltage = 0; - u8 cmd[5], buf[64]; - u16 sd_card_type; - - SET_SD(sd_card); - CLR_RETRY_SD20_MODE(sd_card); -Switch_Fail: - i = 0; - j = 0; - k = 0; - hi_cap_flow = 0; - support_1v8 = 0; -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) - goto SD_UNLOCK_ENTRY; -#endif - - retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - sd_dummy_clock(chip); - - /* Start Initialization Process of SD Card */ -RTY_SD_RST: - retval = - sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, - 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - wait_timeout(20); - - retval = - sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA, SD_RSP_TYPE_R7, - rsp, 5); - if (retval == STATUS_SUCCESS) { - if ((rsp[4] == 0xAA) && ((rsp[3] & 0x0f) == 0x01)) { - hi_cap_flow = 1; - if (CHK_RETRY_SD20_MODE(sd_card)) { - voltage = - SUPPORT_VOLTAGE | - SUPPORT_HIGH_AND_EXTENDED_CAPACITY; - } else { - voltage = - SUPPORT_VOLTAGE | - SUPPORT_HIGH_AND_EXTENDED_CAPACITY | - SUPPORT_MAX_POWER_PERMANCE | SUPPORT_1V8; - } - } - } - - if (!hi_cap_flow) { - voltage = SUPPORT_VOLTAGE; - - retval = - sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, - NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - wait_timeout(20); - } - - /* ACMD41 */ - do { - { - u8 temp = 0; - rts51x_read_register(chip, CARD_INT_PEND, &temp); - RTS51X_DEBUGP("CARD_INT_PEND:%x\n", temp); - if (temp & SD_INT) { - chip->reset_need_retry = 1; - rts51x_write_register(chip, CARD_INT_PEND, - XD_INT | SD_INT | MS_INT, - XD_INT | SD_INT | MS_INT); - sd_set_reset_fail(chip, SD_RESET_FAIL); - TRACE_RET(chip, STATUS_FAIL); - } - } - -RTY_CMD55: - retval = - sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1, NULL, - 0); - if (retval != STATUS_SUCCESS) { - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) { - sd_set_reset_fail(chip, SD_RESET_FAIL); - TRACE_RET(chip, STATUS_FAIL); - } - - j++; - if (chip->option.speed_mmc) { - if (j < 2) - goto RTY_CMD55; - else - TRACE_RET(chip, STATUS_FAIL); - } else { - if (j < 3) - goto RTY_SD_RST; - else - TRACE_RET(chip, STATUS_FAIL); - } - } - - retval = - sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, - SD_RSP_TYPE_R3, rsp, 5); - if (retval != STATUS_SUCCESS) { - k++; - if (k < 3) - goto RTY_SD_RST; - else - TRACE_RET(chip, STATUS_FAIL); - } - - i++; - wait_timeout(20); - } while (!(rsp[1] & 0x80) && (i < 255)); /* Not complete power on */ - - if (i == 255) { - /* Time out */ - TRACE_RET(chip, STATUS_FAIL); - } - - if (hi_cap_flow) { - if (rsp[1] & 0x40) - SET_SD_HCXC(sd_card); - else - CLR_SD_HCXC(sd_card); - if (!CHK_RETRY_SD20_MODE(sd_card)) { - if ((CHK_SD_HCXC(sd_card)) && (CHECK_UHS50(chip))) { - support_1v8 = (rsp[1] & 0x01) ? 1 : 0; - RTS51X_DEBUGP("support_1v8 = %d\n", - support_1v8); - } - } - } else { - CLR_SD_HCXC(sd_card); - support_1v8 = 0; - } - - /* CMD11: Switch Voltage */ - if (support_1v8 && CHECK_UHS50(chip) - && !(((u8) chip->option.sd_speed_prior & SDR104_SUPPORT) == - HS_SUPPORT)) { - retval = sd_voltage_switch(chip); - if (retval != STATUS_SUCCESS) { - SET_RETRY_SD20_MODE(sd_card); - sd_init_power(chip); - RTS51X_DEBUGP("1.8v switch fail\n"); - goto Switch_Fail; - } - } - - /* CMD 2 */ - retval = - sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - /* CMD 3 */ - retval = - sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, SD_RSP_TYPE_R6, - rsp, 5); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - sd_card->sd_addr = (u32) rsp[1] << 24; - sd_card->sd_addr += (u32) rsp[2] << 16; - - /* Get CSD register for Calculating Timing,Capacity, - * Check CSD to determaine as if this is the SD ROM card */ - retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* Select SD card */ - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#ifdef SUPPORT_SD_LOCK -SD_UNLOCK_ENTRY: - /* Get SD lock status */ - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (sd_card->sd_lock_status & SD_LOCKED) { - sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST); - return STATUS_SUCCESS; - } else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) { - sd_card->sd_lock_status &= ~SD_PWD_EXIST; - } -#endif - - /* ACMD42 */ - retval = - sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (support_1v8) { - /* ACMD6 */ - retval = - sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* Enable 4 bit data bus */ - retval = - sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - switch_bus_width = SD_BUS_WIDTH_4; - } else { - switch_bus_width = SD_BUS_WIDTH_1; - } - - /* Set block length 512 bytes for all block commands */ - retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, - 0x200, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_WRITE_REG(chip, SD_CFG1, SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0); - - if (!(sd_card->raw_csd[4] & 0x40)) { - sd_dont_switch = 1; - RTS51X_DEBUGP("Not support class ten\n"); - } - - if (!sd_dont_switch) { - /* Check the card whether flow SD1.1 spec or higher */ - retval = sd_check_spec(chip, switch_bus_width); - if (retval == STATUS_SUCCESS) { - retval = sd_switch_function(chip, switch_bus_width); - if (retval != STATUS_SUCCESS) { - if ((sd_card->sd_switch_fail == - SDR104_SUPPORT_MASK) - || (sd_card->sd_switch_fail == - DDR50_SUPPORT_MASK) - || (sd_card->sd_switch_fail == - SDR50_SUPPORT_MASK)) { - sd_init_power(chip); - SET_RETRY_SD20_MODE(sd_card); - } else if (sd_card->sd_switch_fail == - HS_SUPPORT_MASK) { - sd_dont_switch = 1; - } - goto Switch_Fail; - } - } else { - if (support_1v8) { - SET_RETRY_SD20_MODE(sd_card); - sd_init_power(chip); - sd_dont_switch = 1; - - goto Switch_Fail; - } - } - } - - if (!support_1v8) { - /* ACMD6 */ - retval = - sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* Enable 4 bit data bus */ - retval = - sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } -#ifdef SUPPORT_SD_LOCK - /* clear 1 bit mode status */ - sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; -#endif - - if (CHK_SD30_SPEED(sd_card)) { - rts51x_write_register(chip, SD30_DRIVE_SEL, SD30_DRIVE_MASK, - 0x03); - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (CHK_SD_DDR50(sd_card)) - retval = sd_ddr_tuning(chip); - else - retval = sd_sdr_tuning(chip); - - if (retval != STATUS_SUCCESS) { - SET_RETRY_SD20_MODE(sd_card); - RTS51X_DEBUGP("tuning phase fail,goto SD20 mode\n"); - sd_init_power(chip); - CLR_SD30_SPEED(sd_card); - goto Switch_Fail; - } - if (STATUS_SUCCESS == - sd_wait_currentstate_dataready(chip, 0x08, 1, 20)) { - cmd[0] = 0x40 | READ_SINGLE_BLOCK; - cmd[1] = 0x00; - cmd[2] = 0x00; - cmd[3] = 0x00; - cmd[4] = 0x00; - retval = - sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 512, - 1, SD_BUS_WIDTH_4, NULL, 0, 600); - if (retval != STATUS_SUCCESS) { - SET_RETRY_SD20_MODE(sd_card); - RTS51X_DEBUGP("read lba0 fail," - "goto SD20 mode\n"); - sd_init_power(chip); - CLR_SD30_SPEED(sd_card); - goto Switch_Fail; - } - } - } - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval == STATUS_SUCCESS) { - int ret; - cmd[0] = 0x40 | SEND_STATUS; - cmd[1] = 0x00; - cmd[2] = 0x00; - cmd[3] = 0x00; - cmd[4] = 0x00; - ret = - sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, - SD_BUS_WIDTH_4, buf, 64, 600); - if (ret == STATUS_SUCCESS) { - sd_card_type = ((u16) buf[2] << 8) | (u16) buf[3]; - RTS51X_DEBUGP("sd_card_type:0x%4x\n", sd_card_type); - if ((sd_card_type == 0x0001) - || (sd_card_type == 0x0002)) - chip->card_wp |= SD_CARD; - } else { - rts51x_clear_sd_error(chip); - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - } else { - rts51x_clear_sd_error(chip); - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - - /* Check SD Machanical Write-Protect Switch */ - retval = rts51x_get_card_status(chip, &(chip->card_status)); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (chip->card_status & SD_WP) - chip->card_wp |= SD_CARD; - - chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) { - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0x02); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 0x00); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } -#endif - - return STATUS_SUCCESS; -} - -static int mmc_test_switch_bus(struct rts51x_chip *chip, u8 width) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 buf[8] = { 0 }, bus_width; - u16 byte_cnt; - int len; - - retval = - sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (width == MMC_8BIT_BUS) { - buf[0] = 0x55; - buf[1] = 0xAA; - len = 8; - byte_cnt = 8; - bus_width = SD_BUS_WIDTH_8; - } else { - buf[0] = 0x5A; - len = 4; - byte_cnt = 4; - bus_width = SD_BUS_WIDTH_4; - } - - retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3, - NULL, 0, byte_cnt, 1, bus_width, buf, len, 100); - if (retval != STATUS_SUCCESS) { - u8 val1 = 0, val2 = 0; - rts51x_ep0_read_register(chip, SD_STAT1, &val1); - rts51x_ep0_read_register(chip, SD_STAT2, &val2); - rts51x_clear_sd_error(chip); - if ((val1 & 0xE0) || val2) - TRACE_RET(chip, STATUS_FAIL); - } - RTS51X_DEBUGP("SD/MMC CMD %d\n", BUSTEST_R); - - rts51x_init_cmd(chip); - - /* CMD14 */ - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | BUSTEST_R); - - if (width == MMC_8BIT_BUS) - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x08); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x04); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_NO_CHECK_CRC16 | - SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_NORMAL_READ | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0); - if (width == MMC_8BIT_BUS) { - len = 3; - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0); - } else { - len = 2; - } - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, len, 100); - if (CHECK_SD_TRANS_FAIL(chip, retval)) { - rts51x_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - rts51x_read_rsp_buf(chip, 1, buf, 2); - - if (width == MMC_8BIT_BUS) { - RTS51X_DEBUGP("BUSTEST_R [8bits]: 0x%02x 0x%02x\n", - buf[0], buf[1]); - if ((buf[0] == 0xAA) && (buf[1] == 0x55)) { - u8 rsp[5]; - u32 arg; - - if (CHK_MMC_DDR52(sd_card)) - arg = 0x03B70600; - else - arg = 0x03B70200; - /* Switch MMC to 8-bit mode */ - retval = - sd_send_cmd_get_rsp(chip, SWITCH, arg, - SD_RSP_TYPE_R1b, rsp, 5); - if ((retval == STATUS_SUCCESS) - && !(rsp[4] & MMC_SWITCH_ERR)) - return STATUS_SUCCESS; - } - } else { - RTS51X_DEBUGP("BUSTEST_R [4bits]: 0x%02x\n", buf[0]); - if (buf[0] == 0xA5) { - u8 rsp[5]; - u32 arg; - - if (CHK_MMC_DDR52(sd_card)) - arg = 0x03B70500; - else - arg = 0x03B70100; - /* Switch MMC to 4-bit mode */ - retval = - sd_send_cmd_get_rsp(chip, SWITCH, arg, - SD_RSP_TYPE_R1b, rsp, 5); - if ((retval == STATUS_SUCCESS) - && !(rsp[4] & MMC_SWITCH_ERR)) - return STATUS_SUCCESS; - } - } - - TRACE_RET(chip, STATUS_FAIL); -} - -static int mmc_switch_timing_bus(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - u8 card_type, card_type_mask = 0; - u8 buf[6]; - - CLR_MMC_HS(sd_card); - - RTS51X_DEBUGP("SD/MMC CMD %d\n", SEND_EXT_CSD); - - rts51x_init_cmd(chip); - - /* SEND_EXT_CSD command */ - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF, - 0x40 | SEND_EXT_CSD); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD1, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD2, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD3, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, 0); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 2); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END - | SD_CHECK_CRC7 | SD_RSP_LEN_6); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_NORMAL_READ | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0); - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0); - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0); - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0); - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 6, 1000); - - if (CHECK_SD_TRANS_FAIL(chip, retval)) { - if (retval == STATUS_TIMEDOUT) { - rts51x_clear_sd_error(chip); - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - TRACE_RET(chip, STATUS_FAIL); - } - - rts51x_read_rsp_buf(chip, 0, buf, 6); - - if (buf[0] & SD_TRANSFER_ERR) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - TRACE_RET(chip, STATUS_FAIL); - } - if (CHK_MMC_SECTOR_MODE(sd_card)) - sd_card->capacity = - ((u32) buf[5] << 24) | ((u32) buf[4] << 16) | - ((u32) buf[3] << 8) | ((u32) buf[2]); -#ifdef SUPPORT_SD_LOCK - if (!(sd_card->sd_lock_status & SD_SDR_RST) && CHECK_UHS50(chip)) - card_type_mask = 0x07; - else - card_type_mask = 0x03; -#else - if (CHECK_UHS50(chip)) - card_type_mask = 0x07; - else - card_type_mask = 0x03; -#endif - - card_type = buf[1] & card_type_mask; - if (card_type) { - /* CARD TYPE FIELD = DDR52MHz, 52MHz or 26MHz */ - u8 rsp[5]; - - if (card_type & 0x04) - SET_MMC_DDR52(sd_card); - else if (card_type & 0x02) - SET_MMC_52M(sd_card); - else - SET_MMC_26M(sd_card); - - retval = - sd_send_cmd_get_rsp(chip, SWITCH, 0x03B90100, - SD_RSP_TYPE_R1b, rsp, 5); - if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR)) - CLR_MMC_HS(sd_card); - } - sd_choose_proper_clock(chip); - retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - /* Test Bus Procedure */ - if (mmc_test_switch_bus(chip, MMC_8BIT_BUS) == STATUS_SUCCESS) { - SET_MMC_8BIT(sd_card); - chip->card_bus_width[chip->card2lun[SD_CARD]] = 8; -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; -#endif - } else if (mmc_test_switch_bus(chip, MMC_4BIT_BUS) == STATUS_SUCCESS) { - SET_MMC_4BIT(sd_card); - chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; -#endif - } else { - CLR_MMC_8BIT(sd_card); - CLR_MMC_4BIT(sd_card); - } - - return STATUS_SUCCESS; -} - -static int reset_mmc(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval, i = 0, j = 0, k = 0; - u8 rsp[16]; - u8 spec_ver = 0; - u8 change_to_ddr52 = 1; - u8 cmd[5]; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) - goto MMC_UNLOCK_ENTRY; -#endif - -MMC_DDR_FAIL: - - retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - SET_MMC(sd_card); - -RTY_MMC_RST: - retval = - sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, - 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - do { - { - u8 temp = 0; - rts51x_read_register(chip, CARD_INT_PEND, &temp); - if (temp & SD_INT) { - chip->reset_need_retry = 1; - rts51x_write_register(chip, CARD_INT_PEND, - XD_INT | SD_INT | MS_INT, - XD_INT | SD_INT | MS_INT); - sd_set_reset_fail(chip, MMC_RESET_FAIL); - TRACE_RET(chip, STATUS_FAIL); - } - } - - /* CMD 1 */ - retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND, - (SUPPORT_VOLTAGE | 0x40000000), - SD_RSP_TYPE_R3, rsp, 5); - if (retval != STATUS_SUCCESS) { - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) { - sd_set_reset_fail(chip, MMC_RESET_FAIL); - TRACE_RET(chip, STATUS_FAIL); - } - - if (sd_check_err_code(chip, SD_BUSY) - || sd_check_err_code(chip, SD_TO_ERR)) { - k++; - if (k < 20) { - sd_clr_err_code(chip); - goto RTY_MMC_RST; - } else { - TRACE_RET(chip, STATUS_FAIL); - } - } else { - j++; - if (j < 100) { - sd_clr_err_code(chip); - goto RTY_MMC_RST; - } else { - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - wait_timeout(20); - i++; - } while (!(rsp[1] & 0x80) && (i < 100)); /* Not complete power on */ - - if (i == 100) { - /* Time out */ - TRACE_RET(chip, STATUS_FAIL); - } - - if ((rsp[1] & 0x60) == 0x40) - SET_MMC_SECTOR_MODE(sd_card); - else - CLR_MMC_SECTOR_MODE(sd_card); - - /* CMD 2 */ - retval = - sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - /* CMD 3 */ - sd_card->sd_addr = 0x00100000; - retval = - sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr, - SD_RSP_TYPE_R6, rsp, 5); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - /* Get CSD register for Calculating Timing,Capacity - * Check CSD to determaine as if this is the SD ROM card */ - retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - /* Get MMC Spec_Ver in the CSD register */ - spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2; - - /* Select MMC card */ - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - /* Set block length 512 bytes for all block commands */ - retval = - sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, - 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#ifdef SUPPORT_SD_LOCK -MMC_UNLOCK_ENTRY: - /* Get SD lock status */ - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); -#endif - - RTS51X_WRITE_REG(chip, SD_CFG1, SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0); - - if (chip->ic_version < 2) - rts51x_write_register(chip, SD30_DRIVE_SEL, SD30_DRIVE_MASK, - 0x02); - rts51x_write_register(chip, CARD_DRIVE_SEL, SD20_DRIVE_MASK, DRIVE_8mA); - - chip->card_bus_width[chip->card2lun[SD_CARD]] = 1; - if (spec_ver == 4) { - /* MMC 4.x Cards */ - (void)mmc_switch_timing_bus(chip); - } - - if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) - TRACE_RET(chip, STATUS_FAIL); - - if (CHK_MMC_DDR52(sd_card) && change_to_ddr52) { - /* Card is extracted while identifying */ - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) - TRACE_RET(chip, STATUS_FAIL); - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) { - CLR_MMC_DDR52(sd_card); - sd_init_power(chip); - change_to_ddr52 = 0; - goto MMC_DDR_FAIL; - } - - retval = mmc_ddr_tuning(chip); - if (retval != STATUS_SUCCESS) { - CLR_MMC_DDR52(sd_card); - sd_init_power(chip); - change_to_ddr52 = 0; - goto MMC_DDR_FAIL; - } - - if (STATUS_SUCCESS == - sd_wait_currentstate_dataready(chip, 0x08, 1, 20)) { - cmd[0] = 0x40 | READ_SINGLE_BLOCK; - cmd[1] = 0x00; - cmd[2] = 0x00; - cmd[3] = 0x00; - cmd[4] = 0x00; - if (CHK_MMC_8BIT(sd_card)) { - retval = - sd_read_data(chip, SD_TM_NORMAL_READ, cmd, - 5, 512, 1, SD_BUS_WIDTH_8, - NULL, 0, 600); - } else if (CHK_MMC_4BIT(sd_card)) { - retval = - sd_read_data(chip, SD_TM_NORMAL_READ, cmd, - 5, 512, 1, SD_BUS_WIDTH_4, - NULL, 0, 600); - } else { - retval = - sd_read_data(chip, SD_TM_NORMAL_READ, cmd, - 5, 512, 1, SD_BUS_WIDTH_1, - NULL, 0, 600); - } - - if (retval != STATUS_SUCCESS) { - CLR_MMC_DDR52(sd_card); - change_to_ddr52 = 0; - RTS51X_DEBUGP("read lba0 fail," - "goto SD20 mode\n"); - sd_init_power(chip); - goto MMC_DDR_FAIL; - } - } - } -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) { - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0x02); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 0x00); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } -#endif - - retval = rts51x_get_card_status(chip, &(chip->card_status)); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (chip->card_status & SD_WP) - chip->card_wp |= SD_CARD; - - return STATUS_SUCCESS; -} - -int reset_sd_card(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - int i; - - memset(sd_card, 0, sizeof(struct sd_info)); - - /* Init variables */ - sd_card->sd_type = 0; - sd_card->seq_mode = 0; - sd_card->sd_data_buf_ready = 0; - sd_card->capacity = 0; - sd_card->sd_switch_fail = 0; - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status = 0; - sd_card->sd_erase_status = 0; -#endif - - sd_clear_reset_fail(chip); - enable_card_clock(chip, SD_CARD); - - sd_init_power(chip); - - chip->reset_need_retry = 0; - for (i = 0; i < 3; i++) { - if (!chip->option.reset_mmc_first) { /* reset sd first */ - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) { - /* Switch SD bus to 3V3 signal */ - RTS51X_WRITE_REG(chip, SD_PAD_CTL, - SD_IO_USING_1V8, 0); - if (sd_check_reset_fail(chip, SD_RESET_FAIL)) - sd_clear_reset_fail(chip); - else - retval = reset_mmc(chip); - } - } else { /* reset MMC first */ - retval = reset_mmc(chip); - if (retval != STATUS_SUCCESS) { - if (sd_check_reset_fail(chip, MMC_RESET_FAIL)) { - sd_clear_reset_fail(chip); - } else { - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) { - /* Switch SD bus to - * 3V3 signal */ - RTS51X_WRITE_REG(chip, - SD_PAD_CTL, - SD_IO_USING_1V8, 0); - } - } - } - } - - if ((retval == STATUS_SUCCESS) || (!chip->reset_need_retry)) { - /* if reset success or don't need retry,then break */ - break; - } - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) { - /* card is extracted */ - break; - } - RTS51X_DEBUGP("retry reset sd card,%d\n", i); - chip->reset_need_retry = 0; - } - - sd_clear_reset_fail(chip); - chip->reset_need_retry = 0; - - if (retval == STATUS_SUCCESS) { - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, SD_CLK_DIVIDE_MASK, - SD_CLK_DIVIDE_0); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 2); - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0; - if (chip->option.reset_or_rw_fail_set_pad_drive) { - rts51x_write_register(chip, CARD_DRIVE_SEL, - SD20_DRIVE_MASK, DRIVE_8mA); - } - TRACE_RET(chip, STATUS_FAIL); - } - - chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity; - - if (chip->option.sd_send_status_en) { - sd_card->sd_send_status_en = 1; - } else { - if (sd_card->capacity > 0x20000) { /* 64MB */ - sd_card->sd_send_status_en = 0; - } else { - sd_card->sd_send_status_en = 1; - } - } - RTS51X_DEBUGP("sd_card->sd_send_status = %d\n", - sd_card->sd_send_status_en); - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_DEBUGP("sd_card->sd_type = 0x%x\n", sd_card->sd_type); - - return STATUS_SUCCESS; -} - -#define WAIT_DATA_READY_RTY_CNT 255 - -static int wait_data_buf_ready(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int i, retval; - - for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) { - if (monitor_card_cd(chip, SD_CARD) == CD_NOT_EXIST) - TRACE_RET(chip, STATUS_FAIL); - - sd_card->sd_data_buf_ready = 0; - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (sd_card->sd_data_buf_ready) - return sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - - sd_set_err_code(chip, SD_TO_ERR); - - TRACE_RET(chip, STATUS_FAIL); -} - -void sd_stop_seq_mode(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - if (sd_card->seq_mode) { - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return; - - retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) - sd_set_err_code(chip, SD_STS_ERR); - sd_card->seq_mode = 0; - - rts51x_ep0_write_register(chip, MC_FIFO_CTL, FIFO_FLUSH, - FIFO_FLUSH); - } -} - -static inline int sd_auto_tune_clock(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - if (chip->asic_code) { - if (sd_card->sd_clock > 30) - sd_card->sd_clock -= 20; - } else { - if (sd_card->sd_clock == CLK_100) - sd_card->sd_clock = CLK_80; - else if (sd_card->sd_clock == CLK_80) - sd_card->sd_clock = CLK_60; - else if (sd_card->sd_clock == CLK_60) - sd_card->sd_clock = CLK_50; - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector, - u16 sector_cnt) -{ - struct sd_info *sd_card = &(chip->sd_card); - u32 data_addr; - int retval; - u8 flag; - unsigned int pipe; - u8 stageflag; - - sd_card->counter = 0; - - if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card)) - data_addr = start_sector << 9; - else - data_addr = start_sector; - - RTS51X_DEBUGP("sd_rw, data_addr = 0x%x\n", data_addr); - - sd_clr_err_code(chip); - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (sd_card->seq_mode && ((sd_card->pre_dir != srb->sc_data_direction) - || - ((sd_card->pre_sec_addr + - sd_card->pre_sec_cnt) != start_sector))) { - if ((sd_card->pre_dir == DMA_FROM_DEVICE) - && !CHK_SD30_SPEED(sd_card) - && !CHK_SD_HS(sd_card) - && !CHK_MMC_HS(sd_card) - && sd_card->sd_send_status_en) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - } - - retval = - sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_STS_ERR); - TRACE_RET(chip, sd_parse_err_code(chip)); - } - - sd_card->seq_mode = 0; - - RTS51X_WRITE_REG(chip, MC_FIFO_CTL, FIFO_FLUSH, FIFO_FLUSH); - - if (!CHK_SD30_SPEED(sd_card) - && !CHK_SD_HS(sd_card) - && !CHK_MMC_HS(sd_card) - && sd_card->sd_send_status_en) { - /* random rw, so pre_sec_cnt < 0x80 */ - sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - } - } - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, - (u8) sector_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, - (u8) (sector_cnt >> 8)); - - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - RING_BUFFER); - - if (CHK_MMC_8BIT(sd_card)) - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, - SD_BUS_WIDTH_8); - else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card)) - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, - SD_BUS_WIDTH_4); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, - SD_BUS_WIDTH_1); - - if (sd_card->seq_mode) { - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, - SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | - SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | - SD_RSP_LEN_0); - - trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, - DMA_512); - - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - flag = MODE_CDIR; - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_AUTO_READ_3 | SD_TRANSFER_START); - } else { - flag = MODE_CDOR; - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - } - - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, flag, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - RTS51X_DEBUGP("SD/MMC CMD %d\n", READ_MULTIPLE_BLOCK); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF, - 0x40 | READ_MULTIPLE_BLOCK); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD1, 0xFF, - (u8) (data_addr >> 24)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD2, 0xFF, - (u8) (data_addr >> 16)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD3, 0xFF, - (u8) (data_addr >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, - (u8) data_addr); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | - SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | - SD_RSP_LEN_6); - - trans_dma_enable(srb->sc_data_direction, chip, - sector_cnt * 512, DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_AUTO_READ_2 | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CDIR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } else { - retval = rts51x_send_cmd(chip, MODE_C, 50); - if (retval != STATUS_SUCCESS) { - rts51x_clear_sd_error(chip); - - sd_set_err_code(chip, SD_TO_ERR); - TRACE_RET(chip, sd_parse_err_code(chip)); - } - - retval = wait_data_buf_ready(chip); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_TO_ERR); - TRACE_RET(chip, sd_parse_err_code(chip)); - } - - retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK, - data_addr, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_CRC_ERR); - TRACE_RET(chip, sd_parse_err_code(chip)); - } - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, - SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | - SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | - SD_RSP_LEN_0); - - trans_dma_enable(srb->sc_data_direction, chip, - sector_cnt * 512, DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CDOR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - sd_card->seq_mode = 1; - } - - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - pipe = RCV_BULK_PIPE(chip); - stageflag = STAGE_DI; - } else { - pipe = SND_BULK_PIPE(chip); - stageflag = STAGE_DO; - } - - retval = - rts51x_transfer_data_rcc(chip, pipe, scsi_sglist(srb), - scsi_bufflen(srb), scsi_sg_count(srb), - NULL, 10000, stageflag); - if (retval != STATUS_SUCCESS) { - u8 stat = 0; - int err = retval; - - sd_print_debug_reg(chip); - - rts51x_ep0_read_register(chip, SD_STAT1, &stat); - RTS51X_DEBUGP("SD_STAT1: 0x%x\n", stat); - - rts51x_clear_sd_error(chip); - - retval = - sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_STS_ERR); - TRACE_RET(chip, retval); - } - - if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) { - RTS51X_DEBUGP("SD CRC error, tune clock!\n"); - sd_auto_tune_clock(chip); - } - - sd_card->seq_mode = 0; - - TRACE_RET(chip, err); - } - retval = rts51x_get_rsp(chip, 1, 2000); - if (CHECK_SD_TRANS_FAIL(chip, retval)) { - rts51x_clear_sd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - sd_card->pre_sec_addr = start_sector; - sd_card->pre_sec_cnt = sector_cnt; - sd_card->pre_dir = srb->sc_data_direction; - - return STATUS_SUCCESS; -} - -void sd_cleanup_work(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - - if (sd_card->seq_mode) { - RTS51X_DEBUGP("SD: stop transmission\n"); - sd_stop_seq_mode(chip); - sd_card->counter = 0; - } -} - -inline void sd_fill_power_off_card3v3(struct rts51x_chip *chip) -{ - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); - - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0); - if (!chip->option.FT2_fast_mode) { -#ifdef SD_XD_IO_FOLLOW_PWR - if (CHECK_PKG(chip, LQFP48) - || chip->option.rts5129_D3318_off_enable) - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, - POWER_MASK | LDO_OFF, - POWER_OFF | LDO_OFF); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, - POWER_MASK, POWER_OFF); -#else - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, - POWER_OFF); -#endif - } -} - -int sd_power_off_card3v3(struct rts51x_chip *chip) -{ - int retval; - - rts51x_init_cmd(chip); - - sd_fill_power_off_card3v3(chip); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#ifdef SD_XD_IO_FOLLOW_PWR - if (!chip->option.FT2_fast_mode) - wait_timeout(chip->option.D3318_off_delay); -#endif - - return STATUS_SUCCESS; -} - -int release_sd_card(struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - - RTS51X_DEBUGP("elease_sd_card\n"); - - chip->card_ready &= ~SD_CARD; - chip->card_fail &= ~SD_CARD; - chip->card_wp &= ~SD_CARD; - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status = 0; - sd_card->sd_erase_status = 0; -#endif - - memset(sd_card->raw_csd, 0, 16); - memset(sd_card->raw_scr, 0, 8); - - rts51x_write_register(chip, SFSM_ED, HW_CMD_STOP, HW_CMD_STOP); - rts51x_write_register(chip, SD_PAD_CTL, SD_IO_USING_1V8, 0); - if (CHECK_PKG(chip, LQFP48) || chip->option.rts5129_D3318_off_enable) - sd_power_off_card3v3(chip); - - rts51x_init_cmd(chip); - if (!(CHECK_PKG(chip, LQFP48) || chip->option.rts5129_D3318_off_enable)) - sd_fill_power_off_card3v3(chip); - - if (chip->asic_code) - sd_pull_ctl_disable(chip); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, - FPGA_SD_PULL_CTL_BIT); - - /* Switch LDO3318 to 3.3V */ - rts51x_add_cmd(chip, WRITE_REG_CMD, LDO_POWER_CFG, TUNE_SD18_MASK, - TUNE_SD18_3V3); - - if (CHK_MMC_DDR52(sd_card) && CHK_MMC_8BIT(sd_card)) - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DMA1_CTL, - EXTEND_DMA1_ASYNC_SIGNAL, - EXTEND_DMA1_ASYNC_SIGNAL); - if (CHK_SD30_SPEED(sd_card) || CHK_MMC(sd_card)) - rts51x_add_cmd(chip, WRITE_REG_CMD, SD30_DRIVE_SEL, - SD30_DRIVE_MASK, chip->option.sd30_pad_drive); - /* Suspend LDO3318 */ - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, LDO3318_PWR_MASK, - LDO_SUSPEND); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - wait_timeout(20); - - return STATUS_SUCCESS; -} diff --git a/trunk/drivers/staging/rts5139/sd.h b/trunk/drivers/staging/rts5139/sd.h deleted file mode 100644 index 0805edcaea86..000000000000 --- a/trunk/drivers/staging/rts5139/sd.h +++ /dev/null @@ -1,304 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_SD_H -#define __RTS51X_SD_H - -#include "rts51x_chip.h" - -#define SD_MAX_RETRY_COUNT 3 - -#define SUPPORT_VOLTAGE 0x003C0000 - -#define SD_RESET_FAIL 0x01 -#define MMC_RESET_FAIL 0x02 - -/* Error Code */ -#define SD_NO_ERROR 0x0 -#define SD_CRC_ERR 0x80 -#define SD_TO_ERR 0x40 -#define SD_NO_CARD 0x20 -#define SD_BUSY 0x10 -#define SD_STS_ERR 0x08 -#define SD_RSP_TIMEOUT 0x04 - -/* MMC/SD Command Index */ -/* Basic command (class 0) */ -#define GO_IDLE_STATE 0 -#define SEND_OP_COND 1 /* reserved for SD */ -#define ALL_SEND_CID 2 -#define SET_RELATIVE_ADDR 3 -#define SEND_RELATIVE_ADDR 3 -#define SET_DSR 4 -#define IO_SEND_OP_COND 5 -#define SWITCH 6 -#define SELECT_CARD 7 -#define DESELECT_CARD 7 -/* CMD8 is "SEND_EXT_CSD" for MMC4.x Spec - * while is "SEND_IF_COND" for SD 2.0 */ -#define SEND_EXT_CSD 8 -#define SEND_IF_COND 8 -/* end */ -#define SEND_CSD 9 -#define SEND_CID 10 -#define VOLTAGE_SWITCH 11 -#define READ_DAT_UTIL_STOP 11 /* reserved for SD */ -#define STOP_TRANSMISSION 12 -#define SEND_STATUS 13 -#define GO_INACTIVE_STATE 15 - -/* Block oriented read commands (class 2) */ -#define SET_BLOCKLEN 16 -#define READ_SINGLE_BLOCK 17 -#define READ_MULTIPLE_BLOCK 18 -#define SEND_TUNING_PATTERN 19 - -/* Bus Width Test */ -#define BUSTEST_R 14 -#define BUSTEST_W 19 -/* end */ - -/* Block oriented write commands (class 4) */ -#define WRITE_BLOCK 24 -#define WRITE_MULTIPLE_BLOCK 25 -#define PROGRAM_CSD 27 - -/* Erase commands */ -#define ERASE_WR_BLK_START 32 -#define ERASE_WR_BLK_END 33 -#define ERASE_CMD 38 - -/* Block Oriented Write Protection Commands */ -#define LOCK_UNLOCK 42 - -#define IO_RW_DIRECT 52 - -/* Application specific commands (class 8) */ -#define APP_CMD 55 -#define GEN_CMD 56 - -/* SD Application command Index */ -#define SET_BUS_WIDTH 6 -#define SD_STATUS 13 -#define SEND_NUM_WR_BLOCKS 22 -#define SET_WR_BLK_ERASE_COUNT 23 -#define SD_APP_OP_COND 41 -#define SET_CLR_CARD_DETECT 42 -#define SEND_SCR 51 - -/* SD TIMEOUT function return error */ -#define SD_READ_COMPLETE 0x00 -#define SD_READ_TO 0x01 -#define SD_READ_ADVENCE 0x02 - -/* SD v1.1 CMD6 SWITCH function */ -#define SD_CHECK_MODE 0x00 -#define SD_SWITCH_MODE 0x80 -#define SD_FUNC_GROUP_1 0x01 -#define SD_FUNC_GROUP_2 0x02 -#define SD_FUNC_GROUP_3 0x03 -#define SD_FUNC_GROUP_4 0x04 -#define SD_CHECK_SPEC_V1_1 0xFF - -/* SD Command Argument */ -#define NO_ARGUMENT 0x00 -#define CHECK_PATTERN 0x000000AA -#define VOLTAGE_SUPPLY_RANGE 0x00000100 /* 2.7~3.6V */ -#define SUPPORT_HIGH_AND_EXTENDED_CAPACITY 0x40000000 -#define SUPPORT_MAX_POWER_PERMANCE 0x10000000 -#define SUPPORT_1V8 0x01000000 - -/* Switch Command Error Code */ -#define SWTICH_NO_ERR 0x00 -#define CARD_NOT_EXIST 0x01 -#define SPEC_NOT_SUPPORT 0x02 -#define CHECK_MODE_ERR 0x03 -#define CHECK_NOT_READY 0x04 -#define SWITCH_CRC_ERR 0x05 -#define SWITCH_MODE_ERR 0x06 -#define SWITCH_PASS 0x07 - -#ifdef SUPPORT_SD_LOCK -/* CMD42 Parameter */ -#define SD_ERASE 0x08 -#define SD_LOCK 0x04 -#define SD_UNLOCK 0x00 -#define SD_CLR_PWD 0x02 -#define SD_SET_PWD 0x01 - -#define SD_PWD_LEN 0x10 - -/* SD lock unlock Status */ -#define SD_LOCKED 0x80 /* Global lock status */ -#define SD_LOCK_1BIT_MODE 0x40 /**/ -#define SD_PWD_EXIST 0x20 -#define SD_UNLOCK_POW_ON 0x01 /**/ -#define SD_SDR_RST 0x02 /* Reset SD30 card with current DDR mode to SDR mode. */ -/* g_bySDEraseStatus */ -#define SD_NOT_ERASE 0x00 -#define SD_UNDER_ERASING 0x01 -#define SD_COMPLETE_ERASE 0x02 -/* SD_RW FAIL status */ -#define SD_RW_FORBIDDEN 0x0F /* read/write is forbidden (SD card) */ -#endif -/* Function Group Definition */ -/* Function Group 1 */ -#define HS_SUPPORT 0x01 -#define SDR50_SUPPORT 0x02 -#define SDR104_SUPPORT 0x03 -#define DDR50_SUPPORT 0x04 -#define HS_SUPPORT_MASK 0x02 -#define SDR50_SUPPORT_MASK 0x04 -#define SDR104_SUPPORT_MASK 0x08 -#define DDR50_SUPPORT_MASK 0x10 -#define HS_QUERY_SWITCH_OK 0x01 -#define SDR50_QUERY_SWITCH_OK 0x02 -#define SDR104_QUERY_SWITCH_OK 0x03 -#define DDR50_QUERY_SWITCH_OK 0x04 -#define HS_SWITCH_BUSY 0x02 -#define SDR50_SWITCH_BUSY 0x04 -#define SDR104_SWITCH_BUSY 0x08 -#define DDR50_SWITCH_BUSY 0x10 -#define FUNCTION_GROUP1_SUPPORT_OFFSET 0x0D -#define FUNCTION_GROUP1_QUERY_SWITCH_OFFSET 0x10 -#define FUNCTION_GROUP1_CHECK_BUSY_OFFSET 0x1D -/* Function Group 3 */ -#define DRIVING_TYPE_A 0x01 -#define DRIVING_TYPE_B 0x00 -#define DRIVING_TYPE_C 0x02 -#define DRIVING_TYPE_D 0x03 -#define DRIVING_TYPE_A_MASK 0x02 -#define DRIVING_TYPE_B_MASK 0x01 -#define DRIVING_TYPE_C_MASK 0x04 -#define DRIVING_TYPE_D_MASK 0x08 -#define TYPE_A_QUERY_SWITCH_OK 0x01 -#define TYPE_B_QUERY_SWITCH_OK 0x00 -#define TYPE_C_QUERY_SWITCH_OK 0x02 -#define TYPE_D_QUERY_SWITCH_OK 0x03 -#define TYPE_A_SWITCH_BUSY 0x02 -#define TYPE_B_SWITCH_BUSY 0x01 -#define TYPE_C_SWITCH_BUSY 0x04 -#define TYPE_D_SWITCH_BUSY 0x08 -#define FUNCTION_GROUP3_SUPPORT_OFFSET 0x09 -#define FUNCTION_GROUP3_QUERY_SWITCH_OFFSET 0x0F -#define FUNCTION_GROUP3_CHECK_BUSY_OFFSET 0x19 -/* Function Group 4 */ -#define CURRENT_LIMIT_200 0x00 -#define CURRENT_LIMIT_400 0x01 -#define CURRENT_LIMIT_600 0x02 -#define CURRENT_LIMIT_800 0x03 -#define CURRENT_LIMIT_200_MASK 0x01 -#define CURRENT_LIMIT_400_MASK 0x02 -#define CURRENT_LIMIT_600_MASK 0x04 -#define CURRENT_LIMIT_800_MASK 0x08 -#define CURRENT_LIMIT_200_QUERY_SWITCH_OK 0x00 -#define CURRENT_LIMIT_400_QUERY_SWITCH_OK 0x01 -#define CURRENT_LIMIT_600_QUERY_SWITCH_OK 0x02 -#define CURRENT_LIMIT_800_QUERY_SWITCH_OK 0x03 -#define CURRENT_LIMIT_200_SWITCH_BUSY 0x01 -#define CURRENT_LIMIT_400_SWITCH_BUSY 0x02 -#define CURRENT_LIMIT_600_SWITCH_BUSY 0x04 -#define CURRENT_LIMIT_800_SWITCH_BUSY 0x08 -#define FUNCTION_GROUP4_SUPPORT_OFFSET 0x07 -#define FUNCTION_GROUP4_QUERY_SWITCH_OFFSET 0x0F -#define FUNCTION_GROUP4_CHECK_BUSY_OFFSET 0x17 -/* Switch Function Status Offset */ -#define DATA_STRUCTURE_VER_OFFSET 0x11 /* The high offset */ -#define MAX_PHASE 15 -/* #define TOTAL_READ_PHASE 0x20 */ -/* #define TOTAL_WRITE_PHASE 0x20 */ -/* MMC v4.0 */ -/* #define MMC_52MHZ_SPEED 0x0001 */ -/* #define MMC_26MHZ_SPEED 0x0002 */ -#define MMC_8BIT_BUS 0x0010 -#define MMC_4BIT_BUS 0x0020 -/* #define MMC_SECTOR_MODE 0x0100 */ -#define MMC_SWITCH_ERR 0x80 -/* Tuning direction RX or TX */ -#define TUNE_TX 0x00 -#define TUNE_RX 0x01 -/* For Change_DCM_FreqMode Function */ -#define CHANGE_TX 0x00 -#define CHANGE_RX 0x01 -#define DCM_HIGH_FREQUENCY_MODE 0x00 -#define DCM_LOW_FREQUENCY_MODE 0x01 -#define DCM_HIGH_FREQUENCY_MODE_SET 0x0C -#define DCM_Low_FREQUENCY_MODE_SET 0x00 -/* For Change_FPGA_SSCClock Function */ -#define MULTIPLY_BY_1 0x00 -#define MULTIPLY_BY_2 0x01 -#define MULTIPLY_BY_3 0x02 -#define MULTIPLY_BY_4 0x03 -#define MULTIPLY_BY_5 0x04 -#define MULTIPLY_BY_6 0x05 -#define MULTIPLY_BY_7 0x06 -#define MULTIPLY_BY_8 0x07 -#define MULTIPLY_BY_9 0x08 -#define MULTIPLY_BY_10 0x09 -#define DIVIDE_BY_2 0x01 -#define DIVIDE_BY_3 0x02 -#define DIVIDE_BY_4 0x03 -#define DIVIDE_BY_5 0x04 -#define DIVIDE_BY_6 0x05 -#define DIVIDE_BY_7 0x06 -#define DIVIDE_BY_8 0x07 -#define DIVIDE_BY_9 0x08 -#define DIVIDE_BY_10 0x09 -#define CHECK_SD_TRANS_FAIL(chip, retval) \ - (((retval) != STATUS_SUCCESS) || \ - (chip->rsp_buf[0] & SD_TRANSFER_ERR)) -/* SD Tuning Data Structure */ -/* Record continuous timing phase path */ -struct timing_phase_path { - int start; - int end; - int mid; - int len; -}; - -int sd_select_card(struct rts51x_chip *chip, int select); -int reset_sd_card(struct rts51x_chip *chip); -int sd_switch_clock(struct rts51x_chip *chip); -void sd_stop_seq_mode(struct rts51x_chip *chip); -int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector, - u16 sector_cnt); -void sd_cleanup_work(struct rts51x_chip *chip); -int sd_power_off_card3v3(struct rts51x_chip *chip); -int release_sd_card(struct rts51x_chip *chip); - -#ifdef SUPPORT_SD_LOCK -int sd_update_lock_status(struct rts51x_chip *chip); -#endif - -#ifdef SUPPORT_CPRM -extern int reset_sd(struct rts51x_chip *chip); -extern int sd_check_data0_status(struct rts51x_chip *chip); -extern int sd_read_data(struct rts51x_chip *chip, u8 trans_mode, u8 *cmd, - int cmd_len, u16 byte_cnt, u16 blk_cnt, u8 bus_width, - u8 *buf, int buf_len, int timeout); -#endif - -#endif /* __RTS51X_SD_H */ diff --git a/trunk/drivers/staging/rts5139/sd_cprm.c b/trunk/drivers/staging/rts5139/sd_cprm.c deleted file mode 100644 index 407cd43ad3b1..000000000000 --- a/trunk/drivers/staging/rts5139/sd_cprm.c +++ /dev/null @@ -1,1215 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include -#include - -#include "debug.h" -#include "trace.h" -#include "rts51x.h" -#include "rts51x_transport.h" -#include "rts51x_scsi.h" -#include "rts51x_card.h" -#include "rts51x_chip.h" -#include "sd.h" - -#ifdef SUPPORT_CPRM - -static inline int get_rsp_type(u8 rsp_code, u8 *rsp_type, int *rsp_len) -{ - if (!rsp_type || !rsp_len) - return STATUS_FAIL; - - switch (rsp_code) { - case 0x03: - *rsp_type = SD_RSP_TYPE_R0; /* no response */ - *rsp_len = 0; - break; - - case 0x04: - *rsp_type = SD_RSP_TYPE_R1; /* R1,R6(,R4,R5) */ - *rsp_len = 6; - break; - - case 0x05: - *rsp_type = SD_RSP_TYPE_R1b; /* R1b */ - *rsp_len = 6; - break; - - case 0x06: - *rsp_type = SD_RSP_TYPE_R2; /* R2 */ - *rsp_len = 17; - break; - - case 0x07: - *rsp_type = SD_RSP_TYPE_R3; /* R3 */ - *rsp_len = 6; - break; - - default: - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int soft_reset_sd_card(struct rts51x_chip *chip) -{ - return reset_sd(chip); -} - -int ext_sd_send_cmd_get_rsp(struct rts51x_chip *chip, u8 cmd_idx, - u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, - int special_check) -{ - int retval; - int timeout = 50; - u16 reg_addr; - u8 buf[17], stat; - int len = 2; - int rty_cnt = 0; - - RTS51X_DEBUGP("EXT SD/MMC CMD %d\n", cmd_idx); - - if (rsp_type == SD_RSP_TYPE_R1b) - timeout = 3000; - -RTY_SEND_CMD: - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8) (arg >> 24)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8) (arg >> 16)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8) (arg >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8) arg); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, - 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - rts51x_add_cmd(chip, READ_REG_CMD, SD_STAT1, 0, 0); - - if (CHECK_USB(chip, USB_20)) { - if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; - reg_addr < PPBUF_BASE2 + 16; reg_addr++) { - rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0, - 0); - } - len = 19; - } else if (rsp_type != SD_RSP_TYPE_R0) { - /* Read data from SD_CMDx registers */ - for (reg_addr = SD_CMD0; reg_addr <= SD_CMD4; - reg_addr++) { - rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0, - 0); - } - len = 8; - } else { - len = 3; - } - rts51x_add_cmd(chip, READ_REG_CMD, SD_CMD5, 0, 0); - } else { - len = 2; - } - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, len, timeout); - - if (CHECK_SD_TRANS_FAIL(chip, retval)) { - rts51x_clear_sd_error(chip); - - if (retval == STATUS_TIMEDOUT) { - if (rsp_type & SD_WAIT_BUSY_END) { - retval = sd_check_data0_status(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - } - TRACE_RET(chip, STATUS_FAIL); - } - - if (rsp_type == SD_RSP_TYPE_R0) - return STATUS_SUCCESS; - - if (CHECK_USB(chip, USB_20)) { - rts51x_read_rsp_buf(chip, 2, buf, len - 2); - } else { - if (rsp_type == SD_RSP_TYPE_R2) { - reg_addr = PPBUF_BASE2; - len = 16; - } else { - reg_addr = SD_CMD0; - len = 5; - } - retval = - rts51x_seq_read_register(chip, reg_addr, - (unsigned short)len, buf); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - RTS51X_READ_REG(chip, SD_CMD5, buf + len); - } - stat = chip->rsp_buf[1]; - - if ((buf[0] & 0xC0) != 0) - TRACE_RET(chip, STATUS_FAIL); - - if (!(rsp_type & SD_NO_CHECK_CRC7)) { - if (stat & SD_CRC7_ERR) { - if (cmd_idx == WRITE_MULTIPLE_BLOCK) - TRACE_RET(chip, STATUS_FAIL); - if (rty_cnt < SD_MAX_RETRY_COUNT) { - wait_timeout(20); - rty_cnt++; - goto RTY_SEND_CMD; - } else { - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) || - (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) { - if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) { - if (buf[1] & 0x80) - TRACE_RET(chip, STATUS_FAIL); - } -#ifdef SUPPORT_SD_LOCK - if (buf[1] & 0x7D) { -#else - if (buf[1] & 0x7F) { -#endif - TRACE_RET(chip, STATUS_FAIL); - } - if (buf[2] & 0xF8) - TRACE_RET(chip, STATUS_FAIL); - - if (cmd_idx == SELECT_CARD) { - if (rsp_type == SD_RSP_TYPE_R2) { - if ((buf[3] & 0x1E) != 0x04) - TRACE_RET(chip, STATUS_FAIL); - } else if (rsp_type == SD_RSP_TYPE_R2) { - if ((buf[3] & 0x1E) != 0x03) - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - if (rsp && rsp_len) - memcpy(rsp, buf, rsp_len); - - return STATUS_SUCCESS; -} - -int ext_sd_get_rsp(struct rts51x_chip *chip, int len, u8 * rsp, u8 rsp_type) -{ - int retval, rsp_len; - u16 reg_addr; - - if (rsp_type == SD_RSP_TYPE_R0) - return STATUS_SUCCESS; - - rts51x_init_cmd(chip); - - if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; - reg_addr++) { - rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); - } - rsp_len = 17; - } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = SD_CMD0; reg_addr <= SD_CMD4; reg_addr++) - rts51x_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); - rsp_len = 6; - } - rts51x_add_cmd(chip, READ_REG_CMD, SD_CMD5, 0xFF, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, rsp_len, 100); - - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (rsp) { - int min_len = (rsp_len < len) ? rsp_len : len; - - memcpy(rsp, rts51x_get_rsp_data(chip), min_len); - - RTS51X_DEBUGP("min_len = %d\n", min_len); - RTS51X_DEBUGP("Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n", - rsp[0], rsp[1], rsp[2], rsp[3]); - } - - return STATUS_SUCCESS; -} - -int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun, - u8 cmd_idx, u8 standby, u8 acmd, u8 rsp_code, - u32 arg) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval, rsp_len; - u8 rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - sd_card->last_rsp_type = rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) { - retval = - rts51x_write_register(chip, SD_CFG1, 0x03, - SD_BUS_WIDTH_8); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { - retval = - rts51x_write_register(chip, SD_CFG1, 0x03, - SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } - } -#else - /* Set H/W SD/MMC Bus Width */ - rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4); -#endif - - if (standby) { - retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); - } - - if (acmd) { - retval = - ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); - } - - retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, - sd_card->rsp, rsp_len, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); - - if (standby) { - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); - } -#ifdef SUPPORT_SD_LOCK - /* Get SD lock status */ - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Cmd_Failed); -#endif - - return TRANSPORT_GOOD; - -SD_Execute_Cmd_Failed: - sd_card->pre_cmd_err = 1; - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - release_sd_card(chip); - do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - - TRACE_RET(chip, TRANSPORT_FAILED); -} - -int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun, - u8 cmd_idx, u8 cmd12, u8 standby, - u8 acmd, u8 rsp_code, u32 arg, u32 data_len, - void *data_buf, unsigned int buf_len, int use_sg) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval, rsp_len, i; - int cmd13_checkbit = 0, read_err = 0; - u8 rsp_type, bus_width; - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - sd_card->last_rsp_type = rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - } else { - bus_width = SD_BUS_WIDTH_4; - } - RTS51X_DEBUGP("bus_width = %d\n", bus_width); -#else - bus_width = SD_BUS_WIDTH_4; -#endif - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (standby) { - retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (acmd) { - retval = - ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (data_len <= 512) { - int min_len; - u8 *buf; - u16 byte_cnt, blk_cnt; - u8 cmd[5]; - unsigned int offset = 0; - void *sg = NULL; - - byte_cnt = (u16) (data_len & 0x3FF); - blk_cnt = 1; - - cmd[0] = 0x40 | cmd_idx; - cmd[1] = (u8) (arg >> 24); - cmd[2] = (u8) (arg >> 16); - cmd[3] = (u8) (arg >> 8); - cmd[4] = (u8) arg; - - buf = kmalloc(data_len, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt, - blk_cnt, bus_width, buf, data_len, 2000); - if (retval != STATUS_SUCCESS) { - read_err = 1; - kfree(buf); - rts51x_write_register(chip, CARD_STOP, - SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - min_len = min(data_len, buf_len); - if (use_sg) - rts51x_access_sglist(buf, min_len, (void *)data_buf, - &sg, &offset, TO_XFER_BUF); - else - memcpy(data_buf, buf, min_len); - - kfree(buf); - } else if (!(data_len & 0x1FF)) { - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, - 0xFF, (u8) (data_len >> 17)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, - 0xFF, (u8) ((data_len & 0x0001FE00) >> 9)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD0, 0xFF, - 0x40 | cmd_idx); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD1, 0xFF, - (u8) (arg >> 24)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD2, 0xFF, - (u8) (arg >> 16)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD3, 0xFF, - (u8) (arg >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8) arg); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, bus_width); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); - trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_AUTO_READ_2 | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - retval = rts51x_send_cmd(chip, MODE_CDIR, 100); - if (retval != STATUS_SUCCESS) { - read_err = 1; - rts51x_ep0_write_register(chip, CARD_STOP, - SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - retval = - rts51x_transfer_data_rcc(chip, RCV_BULK_PIPE(chip), - data_buf, buf_len, use_sg, NULL, - 10000, STAGE_DI); - if (retval != STATUS_SUCCESS) { - read_err = 1; - rts51x_ep0_write_register(chip, CARD_STOP, - SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - retval = rts51x_get_rsp(chip, 1, 500); - if (CHECK_SD_TRANS_FAIL(chip, retval)) { - read_err = 1; - rts51x_ep0_write_register(chip, CARD_STOP, - SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - } else { - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - - if (standby) { - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (cmd12) { - retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, - 0, SD_RSP_TYPE_R1b, NULL, 0, - 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - } - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - - rts51x_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); - rts51x_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); - } - - if (standby || cmd12) - cmd13_checkbit = 1; - - for (i = 0; i < 3; i++) { - retval = - ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, - cmd13_checkbit); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed); - - return TRANSPORT_GOOD; - -SD_Execute_Read_Cmd_Failed: - sd_card->pre_cmd_err = 1; - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - if (read_err) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - release_sd_card(chip); - do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - - TRACE_RET(chip, TRANSPORT_FAILED); -} - -int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun, - u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd, - u8 rsp_code, u32 arg, u32 data_len, - void *data_buf, unsigned int buf_len, int use_sg) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval, rsp_len; - int cmd13_checkbit = 0, write_err = 0; - u8 rsp_type; - u32 i; -#ifdef SUPPORT_SD_LOCK - int lock_cmd_fail = 0; - u8 sd_lock_state = 0; - u8 lock_cmd_type = 0; -#endif - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) { - sd_lock_state = sd_card->sd_lock_status; - sd_lock_state &= SD_LOCKED; - } -#endif - - retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - sd_card->last_rsp_type = rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) { - retval = - rts51x_write_register(chip, SD_CFG1, 0x03, - SD_BUS_WIDTH_8); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { - retval = - rts51x_write_register(chip, SD_CFG1, 0x03, - SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, TRANSPORT_FAILED); - } - } -#else - rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4); -#endif - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (standby) { - retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (acmd) { - retval = - ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, - sd_card->rsp, rsp_len, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - - if (data_len <= 512) { - u8 *buf; - unsigned int offset = 0; - void *sg = NULL; - - buf = kmalloc(data_len, GFP_KERNEL); - if (buf == NULL) - TRACE_RET(chip, TRANSPORT_ERROR); - - if (use_sg) - rts51x_access_sglist(buf, data_len, (void *)data_buf, - &sg, &offset, FROM_XFER_BUF); - else - memcpy(buf, data_buf, data_len); - -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) - lock_cmd_type = buf[0] & 0x0F; -#endif - - if (data_len > 256) { - rts51x_init_cmd(chip); - for (i = 0; i < 256; i++) { - rts51x_add_cmd(chip, WRITE_REG_CMD, - (u16) (PPBUF_BASE2 + i), 0xFF, - buf[i]); - } - retval = rts51x_send_cmd(chip, MODE_C, 250); - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - rts51x_init_cmd(chip); - for (i = 256; i < data_len; i++) { - rts51x_add_cmd(chip, WRITE_REG_CMD, - (u16) (PPBUF_BASE2 + i), 0xFF, - buf[i]); - } - retval = rts51x_send_cmd(chip, MODE_C, 250); - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - } else { - rts51x_init_cmd(chip); - for (i = 0; i < data_len; i++) { - rts51x_add_cmd(chip, WRITE_REG_CMD, - (u16) (PPBUF_BASE2 + i), 0xFF, - buf[i]); - } - retval = rts51x_send_cmd(chip, MODE_C, 250); - if (retval != STATUS_SUCCESS) { - kfree(buf); - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - } - - kfree(buf); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, - (u8) ((data_len >> 8) & 0x03)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, - (u8) data_len); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 0x01); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - - retval = rts51x_get_rsp(chip, 1, 250); - if (CHECK_SD_TRANS_FAIL(chip, retval)) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } else if (!(data_len & 0x1FF)) { - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, - 0xFF, (u8) (data_len >> 17)); - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, - 0xFF, (u8) ((data_len & 0x0001FE00) >> 9)); - - trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CDOR, 100); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - - retval = - rts51x_transfer_data_rcc(chip, SND_BULK_PIPE(chip), - data_buf, buf_len, use_sg, NULL, - 10000, STAGE_DO); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - - retval = rts51x_get_rsp(chip, 1, 10000); - if (CHECK_SD_TRANS_FAIL(chip, retval)) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - - } else { - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (retval < 0) { - write_err = 1; - rts51x_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) { - if (lock_cmd_type == SD_ERASE) { - sd_card->sd_erase_status = SD_UNDER_ERASING; - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - } - - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, CHECK_REG_CMD, SD_BUS_STAT, SD_DAT0_STATUS, - SD_DAT0_STATUS); - retval = rts51x_send_cmd(chip, MODE_CR, 250); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - rts51x_get_rsp(chip, 1, 200); /* Don't care return value */ - - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) { - RTS51X_DEBUGP("Lock command fail!\n"); - lock_cmd_fail = 1; - } - } -#endif /* SUPPORT_SD_LOCK */ - - if (standby) { - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (cmd12) { - retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, - 0, SD_RSP_TYPE_R1b, NULL, 0, - 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - } - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, - SD_RSP_TYPE_R1, NULL, 0, 0); - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); - - rts51x_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); - rts51x_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); - } - - if (cmd12 || standby) { - /* There is CMD7 or CMD12 sent before CMD13 */ - cmd13_checkbit = 1; - } - - for (i = 0; i < 3; i++) { - retval = - ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, - cmd13_checkbit); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed); -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) { - if (!lock_cmd_fail) { - RTS51X_DEBUGP("lock_cmd_type = 0x%x\n", - lock_cmd_type); - if (lock_cmd_type & SD_CLR_PWD) - sd_card->sd_lock_status &= ~SD_PWD_EXIST; - if (lock_cmd_type & SD_SET_PWD) - sd_card->sd_lock_status |= SD_PWD_EXIST; - } - - RTS51X_DEBUGP("sd_lock_state = 0x%x," - "sd_card->sd_lock_status = 0x%x\n", - sd_lock_state, sd_card->sd_lock_status); - if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) { - sd_card->sd_lock_notify = 1; - if (sd_lock_state) { - if (sd_card->sd_lock_status & - SD_LOCK_1BIT_MODE) { - sd_card->sd_lock_status |= - (SD_UNLOCK_POW_ON | SD_SDR_RST); - if (CHK_SD(sd_card)) { - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) { - sd_card->sd_lock_status - &= ~(SD_UNLOCK_POW_ON | - SD_SDR_RST); - TRACE_GOTO(chip, - SD_Execute_Write_Cmd_Failed); - } - } - - sd_card->sd_lock_status &= - ~(SD_UNLOCK_POW_ON | SD_SDR_RST); - } - } - } - } - - if (lock_cmd_fail) { - scsi_set_resid(srb, 0); - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - TRACE_RET(chip, TRANSPORT_FAILED); - } -#endif /* SUPPORT_SD_LOCK */ - - return TRANSPORT_GOOD; - -SD_Execute_Write_Cmd_Failed: - sd_card->pre_cmd_err = 1; - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - if (write_err) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - release_sd_card(chip); - do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - - TRACE_RET(chip, TRANSPORT_FAILED); -} - -int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int len; - u8 buf[18] = { - 0x00, - 0x00, - 0x00, - 0x0E, - 0x00, /* Version Number */ - 0x00, /* WP | Media Type */ - 0x00, /* RCA (Low byte) */ - 0x00, /* RCA (High byte) */ - 0x53, /* 'S' */ - 0x44, /* 'D' */ - 0x20, /* ' ' */ - 0x43, /* 'C' */ - 0x61, /* 'a' */ - 0x72, /* 'r' */ - 0x64, /* 'd' */ - 0x00, /* Max LUN Number */ - 0x00, - 0x00, - }; - - sd_card->pre_cmd_err = 0; - - if (!(CHK_BIT(chip->lun_mc, lun))) { - SET_BIT(chip->lun_mc, lun); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) - || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5]) - || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) - || (0x64 != srb->cmnd[8])) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - switch (srb->cmnd[1] & 0x0F) { - case 0: - sd_card->sd_pass_thru_en = 0; - break; - - case 1: - sd_card->sd_pass_thru_en = 1; - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - /* 0x01:SD Memory Card; 0x02:Other Media; 0x03:Illegal Media; */ - buf[5] = (1 == CHK_SD(sd_card)) ? 0x01 : 0x02; - if (chip->card_wp & SD_CARD) - buf[5] |= 0x80; - - buf[6] = (u8) (sd_card->sd_addr >> 16); - buf[7] = (u8) (sd_card->sd_addr >> 24); - - buf[15] = chip->max_lun; - - len = min(18, (int)scsi_bufflen(srb)); - rts51x_set_xfer_buf(buf, len, srb); - - return TRANSPORT_GOOD; -} - -int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int retval; - u8 cmd_idx, rsp_code; - u8 standby = 0, acmd = 0; - u32 arg; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x02) - standby = 1; - if (srb->cmnd[1] & 0x01) - acmd = 1; - - arg = ((u32) srb->cmnd[3] << 24) | ((u32) srb->cmnd[4] << 16) | - ((u32) srb->cmnd[5] << 8) | srb->cmnd[6]; - - rsp_code = srb->cmnd[10]; - - retval = - ext_sd_execute_no_data(chip, lun, cmd_idx, standby, acmd, rsp_code, - arg); - scsi_set_resid(srb, 0); - return retval; -} - -int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - unsigned int lun = SCSI_LUN(srb); - u8 cmd_idx, rsp_code, send_cmd12 = 0, standby = 0, acmd = 0; - u32 arg, data_len; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x04) - send_cmd12 = 1; - if (srb->cmnd[1] & 0x02) - standby = 1; - if (srb->cmnd[1] & 0x01) - acmd = 1; - - arg = ((u32) srb->cmnd[3] << 24) | ((u32) srb->cmnd[4] << 16) | - ((u32) srb->cmnd[5] << 8) | srb->cmnd[6]; - - data_len = - ((u32) srb->cmnd[7] << 16) | ((u32) srb->cmnd[8] << 8) | - srb->cmnd[9]; - rsp_code = srb->cmnd[10]; - - retval = - ext_sd_execute_read_data(chip, lun, cmd_idx, send_cmd12, standby, - acmd, rsp_code, arg, data_len, - scsi_sglist(srb), scsi_bufflen(srb), - scsi_sg_count(srb)); - scsi_set_resid(srb, 0); - return retval; -} - -int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - int retval; - unsigned int lun = SCSI_LUN(srb); - u8 cmd_idx, rsp_code, send_cmd12 = 0, standby = 0, acmd = 0; - u32 data_len, arg; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x04) - send_cmd12 = 1; - if (srb->cmnd[1] & 0x02) - standby = 1; - if (srb->cmnd[1] & 0x01) - acmd = 1; - - data_len = - ((u32) srb->cmnd[7] << 16) | ((u32) srb->cmnd[8] << 8) | - srb->cmnd[9]; - arg = - ((u32) srb->cmnd[3] << 24) | ((u32) srb->cmnd[4] << 16) | - ((u32) srb->cmnd[5] << 8) | srb->cmnd[6]; - rsp_code = srb->cmnd[10]; - - retval = - ext_sd_execute_write_data(chip, lun, cmd_idx, send_cmd12, standby, - acmd, rsp_code, arg, data_len, - scsi_sglist(srb), scsi_bufflen(srb), - scsi_sg_count(srb)); - scsi_set_resid(srb, 0); - return retval; -} - -int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int count; - u16 data_len; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - data_len = ((u16) srb->cmnd[7] << 8) | srb->cmnd[8]; - - if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) { - count = (data_len < 17) ? data_len : 17; - } else { - count = (data_len < 6) ? data_len : 6; - } - rts51x_set_xfer_buf(sd_card->rsp, count, srb); - - RTS51X_DEBUGP("Response length: %d\n", data_len); - RTS51X_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n", - sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2], - sd_card->rsp[3]); - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} - -int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip) -{ - struct sd_info *sd_card = &(chip->sd_card); - unsigned int lun = SCSI_LUN(srb); - int retval; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) - || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5]) - || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) - || (0x64 != srb->cmnd[8])) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - switch (srb->cmnd[1] & 0x0F) { - case 0: - /* SD Card Power Off -> ON and Initialization */ -#ifdef SUPPORT_SD_LOCK - if (0x64 == srb->cmnd[9]) { - /* Command Mode */ - sd_card->sd_lock_status |= SD_SDR_RST; - } -#endif /* SUPPORT_SD_LOCK */ - retval = reset_sd_card(chip); - if (retval != STATUS_SUCCESS) { -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_SDR_RST; -#endif - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - sd_card->pre_cmd_err = 1; - TRACE_RET(chip, TRANSPORT_FAILED); - } -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_SDR_RST; -#endif - break; - - case 1: - /* reset CMD(CMD0) and Initialization - * (without SD Card Power Off -> ON) */ - retval = soft_reset_sd_card(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - sd_card->pre_cmd_err = 1; - TRACE_RET(chip, TRANSPORT_FAILED); - } - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - TRACE_RET(chip, TRANSPORT_FAILED); - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} -#endif diff --git a/trunk/drivers/staging/rts5139/sd_cprm.h b/trunk/drivers/staging/rts5139/sd_cprm.h deleted file mode 100644 index 75e263b6594c..000000000000 --- a/trunk/drivers/staging/rts5139/sd_cprm.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_SD_CPRM_H -#define __RTS51X_SD_CPRM_H - -#include "rts51x_chip.h" -#include "sd.h" - -#ifdef SUPPORT_CPRM -int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun, - u8 cmd_idx, u8 standby, u8 acmd, u8 rsp_code, - u32 arg); -int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun, - u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd, - u8 rsp_code, u32 arg, u32 data_len, void *data_buf, - unsigned int buf_len, int use_sg); -int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun, - u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd, - u8 rsp_code, u32 arg, u32 data_len, - void *data_buf, unsigned int buf_len, int use_sg); - -int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip); -int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip); -#endif - -#endif /* __RTS51X_SD_CPRM_H */ diff --git a/trunk/drivers/staging/rts5139/trace.h b/trunk/drivers/staging/rts5139/trace.h deleted file mode 100644 index 0584b8ab43ca..000000000000 --- a/trunk/drivers/staging/rts5139/trace.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_TRACE_H -#define __RTS51X_TRACE_H - -#include "debug.h" - -#define _MSG_TRACE - -#ifdef _MSG_TRACE -static inline char *filename(char *path) -{ - char *ptr; - - if (path == NULL) - return NULL; - - ptr = path; - - while (*ptr != '\0') { - if ((*ptr == '\\') || (*ptr == '/')) - path = ptr + 1; - ptr++; - } - - return path; -} - -#define TRACE_RET(chip, ret) \ -do { \ - char *_file = filename((char *)__FILE__); \ - RTS51X_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__); \ - (chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__); \ - strncpy((chip)->trace_msg[(chip)->msg_idx].func, \ - __func__, MSG_FUNC_LEN-1); \ - strncpy((chip)->trace_msg[(chip)->msg_idx].file, \ - _file, MSG_FILE_LEN-1); \ - get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf,\ - TIME_VAL_LEN); \ - (chip)->trace_msg[(chip)->msg_idx].valid = 1; \ - (chip)->msg_idx++; \ - if ((chip)->msg_idx >= TRACE_ITEM_CNT) { \ - (chip)->msg_idx = 0; \ - } \ - return ret; \ -} while (0) - -#define TRACE_GOTO(chip, label) \ -do { \ - char *_file = filename((char *)__FILE__); \ - RTS51X_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__); \ - (chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__); \ - strncpy((chip)->trace_msg[(chip)->msg_idx].func, \ - __func__, MSG_FUNC_LEN-1); \ - strncpy((chip)->trace_msg[(chip)->msg_idx].file, \ - _file, MSG_FILE_LEN-1); \ - get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf,\ - TIME_VAL_LEN); \ - (chip)->trace_msg[(chip)->msg_idx].valid = 1; \ - (chip)->msg_idx++; \ - if ((chip)->msg_idx >= TRACE_ITEM_CNT) { \ - (chip)->msg_idx = 0; \ - } \ - goto label; \ -} while (0) -#else -#define TRACE_RET(chip, ret) return (ret) -#define TRACE_GOTO(chip, label) goto label -#endif - -#ifdef CONFIG_RTS5139_DEBUG -static inline void rts51x_dump(u8 *buf, int buf_len) -{ - int i; - u8 tmp[16] = { 0 }; - u8 *_ptr = buf; - - for (i = 0; i < ((buf_len) / 16); i++) { - RTS51X_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x\n", - _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], - _ptr[5], _ptr[6], _ptr[7], _ptr[8], _ptr[9], - _ptr[10], _ptr[11], _ptr[12], _ptr[13], _ptr[14], - _ptr[15]); - _ptr += 16; - } - if ((buf_len) % 16) { - memcpy(tmp, _ptr, (buf_len) % 16); - _ptr = tmp; - RTS51X_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x\n", - _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], - _ptr[5], _ptr[6], _ptr[7], _ptr[8], _ptr[9], - _ptr[10], _ptr[11], _ptr[12], _ptr[13], _ptr[14], - _ptr[15]); - } -} - -#define RTS51X_DUMP(buf, buf_len) \ - rts51x_dump((u8 *)(buf), (buf_len)) - -#define CATCH_TRIGGER(chip) \ -do { \ - rts51x_ep0_write_register((chip), 0xFC31, 0x01, 0x01); \ - RTS51X_DEBUGP("Catch trigger!\n"); \ -} while (0) - -#else -#define RTS51X_DUMP(buf, buf_len) -#define CATCH_TRIGGER(chip) -#endif - -#endif /* __RTS51X_TRACE_H */ diff --git a/trunk/drivers/staging/rts5139/xd.c b/trunk/drivers/staging/rts5139/xd.c deleted file mode 100644 index 5820605d1806..000000000000 --- a/trunk/drivers/staging/rts5139/xd.c +++ /dev/null @@ -1,2255 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include -#include -#include -#include - -#include "debug.h" -#include "trace.h" -#include "rts51x.h" -#include "rts51x_transport.h" -#include "rts51x_scsi.h" -#include "rts51x_card.h" -#include "xd.h" - -static int xd_build_l2p_tbl(struct rts51x_chip *chip, int zone_no); -static int xd_init_page(struct rts51x_chip *chip, u32 phy_blk, u16 logoff, - u8 start_page, u8 end_page); - -static inline void xd_set_err_code(struct rts51x_chip *chip, u8 err_code) -{ - struct xd_info *xd_card = &(chip->xd_card); - - xd_card->err_code = err_code; -} - -static inline int xd_check_err_code(struct rts51x_chip *chip, u8 err_code) -{ - struct xd_info *xd_card = &(chip->xd_card); - - return (xd_card->err_code == err_code); -} - -static int xd_set_init_para(struct rts51x_chip *chip) -{ - struct xd_info *xd_card = &(chip->xd_card); - int retval; - - if (chip->asic_code) - xd_card->xd_clock = 47; - else - xd_card->xd_clock = CLK_50; - - retval = switch_clock(chip, xd_card->xd_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static int xd_switch_clock(struct rts51x_chip *chip) -{ - struct xd_info *xd_card = &(chip->xd_card); - int retval; - - retval = rts51x_select_card(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = switch_clock(chip, xd_card->xd_clock); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static int xd_read_id(struct rts51x_chip *chip, u8 id_cmd, u8 *id_buf, - u8 buf_len) -{ - int retval, i; - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_ID); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - - for (i = 0; i < 4; i++) { - rts51x_add_cmd(chip, READ_REG_CMD, (u16) (XD_ADDRESS1 + i), 0, - 0); - } - - retval = rts51x_send_cmd(chip, MODE_CR, 20); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 5, 20); - - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - TRACE_RET(chip, retval); - } - - if (id_buf && buf_len) { - if (buf_len > 4) - buf_len = 4; - rts51x_read_rsp_buf(chip, 1, id_buf, buf_len); - } - - return STATUS_SUCCESS; -} - -static void xd_assign_phy_addr(struct rts51x_chip *chip, u32 addr, u8 mode) -{ - struct xd_info *xd_card = &(chip->xd_card); - - switch (mode) { - case XD_RW_ADDR: - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, - (u8) addr); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF, - (u8) (addr >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3, 0xFF, - (u8) (addr >> 16)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, - xd_card->addr_cycle | XD_CALC_ECC | - XD_BA_NO_TRANSFORM); - break; - - case XD_ERASE_ADDR: - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, - (u8) addr); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, - (u8) (addr >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF, - (u8) (addr >> 16)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, - (xd_card->addr_cycle - 1) | - XD_CALC_ECC | XD_BA_NO_TRANSFORM); - break; - - default: - break; - } -} - -static int xd_read_redundant(struct rts51x_chip *chip, u32 page_addr, u8 *buf, - int buf_len) -{ - int retval, i; - - rts51x_init_cmd(chip); - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_REDUNDANT); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - - for (i = 0; i < 6; i++) { - rts51x_add_cmd(chip, READ_REG_CMD, (u16) (XD_PAGE_STATUS + i), - 0, 0); - } - for (i = 0; i < 4; i++) { - rts51x_add_cmd(chip, READ_REG_CMD, (u16) (XD_RESERVED0 + i), 0, - 0); - } - rts51x_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 11, 500); - - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - TRACE_RET(chip, retval); - } - - if (buf && buf_len) { - if (buf_len > 11) - buf_len = 11; - rts51x_read_rsp_buf(chip, 1, buf, buf_len); - } - - return STATUS_SUCCESS; -} - -static int xd_read_data_from_ppb(struct rts51x_chip *chip, int offset, u8 *buf, - int buf_len) -{ - int retval, i; - - if (!buf || (buf_len <= 0)) - TRACE_RET(chip, STATUS_FAIL); - - rts51x_init_cmd(chip); - - for (i = 0; i < buf_len; i++) { - rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i, 0, - 0); - } - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, buf_len, 200); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - rts51x_read_rsp_buf(chip, 0, buf, buf_len); - - return STATUS_SUCCESS; -} - -static int xd_read_cis(struct rts51x_chip *chip, u32 page_addr, u8 *buf, - int buf_len) -{ - int retval; - u8 reg; - - if (!buf || (buf_len < 10)) - TRACE_RET(chip, STATUS_FAIL); - - rts51x_init_cmd(chip); - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_PAGES); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END | XD_PPB_EMPTY, - XD_TRANSFER_END | XD_PPB_EMPTY); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 1, 500); - if (retval == STATUS_TIMEDOUT) { - rts51x_clear_xd_error(chip); - TRACE_RET(chip, retval); - } - - RTS51X_READ_REG(chip, XD_PAGE_STATUS, ®); - if (reg != XD_GPG) { - rts51x_clear_xd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - RTS51X_READ_REG(chip, XD_CTL, ®); - - if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) { - retval = xd_read_data_from_ppb(chip, 0, buf, buf_len); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (reg & XD_ECC1_ERROR) { /* correctable error */ - u8 ecc_bit, ecc_byte; - - RTS51X_READ_REG(chip, XD_ECC_BIT1, &ecc_bit); - RTS51X_READ_REG(chip, XD_ECC_BYTE1, &ecc_byte); - - RTS51X_DEBUGP("ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n", - ecc_bit, ecc_byte); - if (ecc_byte < buf_len) { - RTS51X_DEBUGP("Before correct: 0x%x\n", - buf[ecc_byte]); - buf[ecc_byte] ^= (1 << ecc_bit); - RTS51X_DEBUGP("After correct: 0x%x\n", - buf[ecc_byte]); - } - } - } else if (!(reg & XD_ECC2_ERROR) || !(reg & XD_ECC2_UNCORRECTABLE)) { - RTS51X_WRITE_REG(chip, CARD_STOP, XD_STOP | XD_CLR_ERR, - XD_STOP | XD_CLR_ERR); - - retval = xd_read_data_from_ppb(chip, 256, buf, buf_len); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (reg & XD_ECC2_ERROR) { - u8 ecc_bit, ecc_byte; - - RTS51X_READ_REG(chip, XD_ECC_BIT2, &ecc_bit); - RTS51X_READ_REG(chip, XD_ECC_BYTE2, &ecc_byte); - - RTS51X_DEBUGP("ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n", - ecc_bit, ecc_byte); - if (ecc_byte < buf_len) { - RTS51X_DEBUGP("Before correct: 0x%x\n", - buf[ecc_byte]); - buf[ecc_byte] ^= (1 << ecc_bit); - RTS51X_DEBUGP("After correct: 0x%x\n", - buf[ecc_byte]); - } - } - } else { - rts51x_clear_xd_error(chip); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static void xd_pull_ctl_disable(struct rts51x_chip *chip) -{ - if (CHECK_PKG(chip, LQFP48)) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); - } -} - -static void xd_pull_ctl_enable(struct rts51x_chip *chip) -{ - if (CHECK_PKG(chip, LQFP48)) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA5); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x59); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); - } -} - -static int reset_xd(struct rts51x_chip *chip) -{ - struct xd_info *xd_card = &(chip->xd_card); - int retval, i, j; - u8 id_buf[4], redunt[11]; - - retval = rts51x_select_card(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF, - XD_PGSTS_NOT_FF); - if (chip->asic_code) - xd_pull_ctl_disable(chip); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, - (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3)); - - if (!chip->option.FT2_fast_mode) { - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_INIT, XD_NO_AUTO_PWR_OFF, - 0); - if (CHECK_PKG(chip, LQFP48) || - chip->option.rts5129_D3318_off_enable) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, - DV3318_AUTO_PWR_OFF, - DV3318_AUTO_PWR_OFF); - } - } - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0); - if (!chip->option.FT2_fast_mode) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, - POWER_OFF); - } - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - if (!chip->option.FT2_fast_mode) { -#ifdef SD_XD_IO_FOLLOW_PWR - if (CHECK_PKG(chip, LQFP48) - || chip->option.rts5129_D3318_off_enable) { - rts51x_write_register(chip, CARD_PWR_CTL, - LDO_OFF, LDO_OFF); - } -#endif - - wait_timeout(250); - -#ifdef SD_XD_IO_FOLLOW_PWR - if (CHECK_PKG(chip, LQFP48) - || chip->option.rts5129_D3318_off_enable) { - rts51x_init_cmd(chip); - if (chip->asic_code) { - xd_pull_ctl_enable(chip); - } else { - rts51x_add_cmd(chip, WRITE_REG_CMD, - FPGA_PULL_CTL, 0xFF, - (FPGA_XD_PULL_CTL_EN1 & - FPGA_XD_PULL_CTL_EN2)); - } - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - } -#endif - - retval = card_power_on(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); -#ifdef SUPPORT_OCP - wait_timeout(50); - rts51x_get_card_status(chip, &(chip->card_status)); - chip->ocp_stat = (chip->card_status >> 4) & 0x03; - - if (chip->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) { - RTS51X_DEBUGP("Over current, OCPSTAT is 0x%x\n", - chip->ocp_stat); - TRACE_RET(chip, STATUS_FAIL); - } -#endif - } - - rts51x_init_cmd(chip); - - if (chip->asic_code) - xd_pull_ctl_enable(chip); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, - (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2)); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, - XD_OUTPUT_EN); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN); - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - if (!chip->option.FT2_fast_mode) - wait_timeout(200); - - retval = xd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - /* Read ID to check if the timing setting is right */ - for (i = 0; i < 4; i++) { - u8 xd_dat, xd_ctl; - - if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) - TRACE_RET(chip, STATUS_FAIL); - - rts51x_init_cmd(chip); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF, - XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * - (2 + i + chip->option.xd_rw_step) - + XD_TIME_RWN_STEP * (i + chip->option.xd_rwn_step)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF, - XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (4 + - i) + XD_TIME_RWN_STEP * (3 + i)); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_RESET); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - rts51x_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); - rts51x_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - TRACE_RET(chip, retval); - } - - retval = rts51x_get_rsp(chip, 3, 100); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - TRACE_RET(chip, retval); - } - - xd_dat = chip->rsp_buf[1]; - xd_ctl = chip->rsp_buf[2]; - RTS51X_DEBUGP("XD_DAT: 0x%x, XD_CTL: 0x%x\n", xd_dat, xd_ctl); - - if (((xd_dat & READY_FLAG) != READY_STATE) - || !(xd_ctl & XD_RDY)) - continue; - - retval = xd_read_id(chip, READ_ID, id_buf, 4); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - RTS51X_DEBUGP("READ_ID: 0x%x 0x%x 0x%x 0x%x\n", - id_buf[0], id_buf[1], id_buf[2], id_buf[3]); - - xd_card->device_code = id_buf[1]; - - switch (xd_card->device_code) { - case XD_4M_X8_512_1: - case XD_4M_X8_512_2: - xd_card->block_shift = 4; /* 16 pages per block */ - xd_card->page_off = 0x0F; - xd_card->addr_cycle = 3; - xd_card->zone_cnt = 1; - xd_card->capacity = 8000; /* 500 * 2 ^ 4 */ - XD_SET_4MB(xd_card); - break; - case XD_8M_X8_512: - xd_card->block_shift = 4; - xd_card->page_off = 0x0F; - xd_card->addr_cycle = 3; - xd_card->zone_cnt = 1; - xd_card->capacity = 16000; /* 1000 * 2 ^ 4 */ - break; - case XD_16M_X8_512: - XD_PAGE_512(xd_card); /* 32 pages per block */ - xd_card->addr_cycle = 3; - xd_card->zone_cnt = 1; - xd_card->capacity = 32000; /* 1000 * 2 ^ 5 */ - break; - case XD_32M_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 3; - xd_card->zone_cnt = 2; - xd_card->capacity = 64000; /* 2000 * 2 ^ 5 */ - break; - case XD_64M_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 4; - xd_card->capacity = 128000; /* 4000 * 2 ^ 5 */ - break; - case XD_128M_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 8; - xd_card->capacity = 256000; /* 8000 * 2 ^ 5 */ - break; - case XD_256M_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 16; - xd_card->capacity = 512000; /* 16000 * 2 ^ 5 */ - break; - case XD_512M_X8: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 32; - xd_card->capacity = 1024000; /* 32000 * 2 ^ 5 */ - break; - case xD_1G_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 64; - xd_card->capacity = 2048000; /* 64000 * 2 ^ 5 */ - break; - case xD_2G_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 128; - xd_card->capacity = 4096000; /* 128000 * 2 ^ 5 */ - break; - default: - continue; - } - - /* Confirm timing setting */ - for (j = 0; j < 10; j++) { - retval = xd_read_id(chip, READ_ID, id_buf, 4); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (id_buf[1] != xd_card->device_code) - break; - } - - /* Current timing pass */ - if (j == 10) - break; - } - - if (i == 4) { - xd_card->block_shift = 0; - xd_card->page_off = 0; - xd_card->addr_cycle = 0; - xd_card->capacity = 0; - - TRACE_RET(chip, STATUS_FAIL); - } - - retval = xd_read_id(chip, READ_xD_ID, id_buf, 4); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - RTS51X_DEBUGP("READ_xD_ID: 0x%x 0x%x 0x%x 0x%x\n", - id_buf[0], id_buf[1], id_buf[2], id_buf[3]); - if (id_buf[2] != XD_ID_CODE) - TRACE_RET(chip, STATUS_FAIL); - - /* Search CIS block */ - for (i = 0; i < 24; i++) { - u32 page_addr; - - if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) - TRACE_RET(chip, STATUS_FAIL); - - page_addr = (u32) i << xd_card->block_shift; - - for (j = 0; j < 3; j++) { - retval = xd_read_redundant(chip, page_addr, redunt, 11); - if (retval == STATUS_SUCCESS) - break; - } - if (j == 3) - continue; - - if (redunt[BLOCK_STATUS] != XD_GBLK) - continue; - - j = 0; - /* Check page status */ - if (redunt[PAGE_STATUS] != XD_GPG) { - for (j = 1; j <= 8; j++) { - retval = - xd_read_redundant(chip, page_addr + j, - redunt, 11); - if (retval == STATUS_SUCCESS) { - if (redunt[PAGE_STATUS] == XD_GPG) - break; - } - } - - if (j == 9) - break; - } - - if ((redunt[BLOCK_STATUS] == XD_GBLK) - && (redunt[PARITY] & XD_BA1_ALL0)) { - u8 buf[10]; - - page_addr += j; - - retval = xd_read_cis(chip, page_addr, buf, 10); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if ((buf[0] == 0x01) && (buf[1] == 0x03) - && (buf[2] == 0xD9) - && (buf[3] == 0x01) && (buf[4] == 0xFF) - && (buf[5] == 0x18) && (buf[6] == 0x02) - && (buf[7] == 0xDF) && (buf[8] == 0x01) - && (buf[9] == 0x20)) { - xd_card->cis_block = (u16) i; - } - } - - break; - } - - RTS51X_DEBUGP("CIS block: 0x%x\n", xd_card->cis_block); - if (xd_card->cis_block == 0xFFFF) - TRACE_RET(chip, STATUS_FAIL); - - chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity; - - return STATUS_SUCCESS; -} - -static int xd_check_data_blank(u8 *redunt) -{ - int i; - - for (i = 0; i < 6; i++) { - if (redunt[PAGE_STATUS + i] != 0xFF) - return 0; - } - - if ((redunt[PARITY] & (XD_ECC1_ALL1 | XD_ECC2_ALL1)) != - (XD_ECC1_ALL1 | XD_ECC2_ALL1)) - return 0; - - for (i = 0; i < 4; i++) { - if (redunt[RESERVED0 + i] != 0xFF) - return 0; - } - - return 1; -} - -static u16 xd_load_log_block_addr(u8 *redunt) -{ - u16 addr = 0xFFFF; - - if (redunt[PARITY] & XD_BA1_BA2_EQL) - addr = - ((u16) redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L]; - else if (redunt[PARITY] & XD_BA1_VALID) - addr = - ((u16) redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L]; - else if (redunt[PARITY] & XD_BA2_VALID) - addr = - ((u16) redunt[BLOCK_ADDR2_H] << 8) | redunt[BLOCK_ADDR2_L]; - - return addr; -} - -static int xd_init_l2p_tbl(struct rts51x_chip *chip) -{ - struct xd_info *xd_card = &(chip->xd_card); - int size, i; - - RTS51X_DEBUGP("xd_init_l2p_tbl: zone_cnt = %d\n", xd_card->zone_cnt); - - if (xd_card->zone_cnt < 1) - TRACE_RET(chip, STATUS_FAIL); - - size = xd_card->zone_cnt * sizeof(struct zone_entry); - RTS51X_DEBUGP("Buffer size for l2p table is %d\n", size); - - xd_card->zone = vmalloc(size); - if (!xd_card->zone) - TRACE_RET(chip, STATUS_NOMEM); - - for (i = 0; i < xd_card->zone_cnt; i++) { - xd_card->zone[i].build_flag = 0; - xd_card->zone[i].l2p_table = NULL; - xd_card->zone[i].free_table = NULL; - xd_card->zone[i].get_index = 0; - xd_card->zone[i].set_index = 0; - xd_card->zone[i].unused_blk_cnt = 0; - } - - return STATUS_SUCCESS; -} - -static inline void free_zone(struct zone_entry *zone) -{ - RTS51X_DEBUGP("free_zone\n"); - if (!zone) - return; - zone->build_flag = 0; - zone->set_index = 0; - zone->get_index = 0; - zone->unused_blk_cnt = 0; - if (zone->l2p_table) { - vfree(zone->l2p_table); - zone->l2p_table = NULL; - } - if (zone->free_table) { - vfree(zone->free_table); - zone->free_table = NULL; - } -} - -static void xd_set_unused_block(struct rts51x_chip *chip, u32 phy_blk) -{ - struct xd_info *xd_card = &(chip->xd_card); - struct zone_entry *zone; - int zone_no; - - zone_no = (int)phy_blk >> 10; - if (zone_no >= xd_card->zone_cnt) { - RTS51X_DEBUGP("Set unused block to invalid zone" - "(zone_no = %d, zone_cnt = %d)\n", - zone_no, xd_card->zone_cnt); - return; - } - zone = &(xd_card->zone[zone_no]); - - if (zone->free_table == NULL) { - if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS) - return; - } - - if ((zone->set_index >= XD_FREE_TABLE_CNT) - || (zone->set_index < 0)) { - free_zone(zone); - RTS51X_DEBUGP("Set unused block fail, invalid set_index\n"); - return; - } - - RTS51X_DEBUGP("Set unused block to index %d\n", zone->set_index); - - zone->free_table[zone->set_index++] = (u16) (phy_blk & 0x3ff); - if (zone->set_index >= XD_FREE_TABLE_CNT) - zone->set_index = 0; - zone->unused_blk_cnt++; -} - -static u32 xd_get_unused_block(struct rts51x_chip *chip, int zone_no) -{ - struct xd_info *xd_card = &(chip->xd_card); - struct zone_entry *zone; - u32 phy_blk; - - if (zone_no >= xd_card->zone_cnt) { - RTS51X_DEBUGP("Get unused block from invalid zone" - "(zone_no = %d, zone_cnt = %d)\n", - zone_no, xd_card->zone_cnt); - TRACE_RET(chip, BLK_NOT_FOUND); - } - zone = &(xd_card->zone[zone_no]); - - if ((zone->unused_blk_cnt == 0) || - (zone->set_index == zone->get_index)) { - free_zone(zone); - RTS51X_DEBUGP("Get unused block fail," - "no unused block available\n"); - TRACE_RET(chip, BLK_NOT_FOUND); - } - if ((zone->get_index >= XD_FREE_TABLE_CNT) || (zone->get_index < 0)) { - free_zone(zone); - RTS51X_DEBUGP("Get unused block fail, invalid get_index\n"); - TRACE_RET(chip, BLK_NOT_FOUND); - } - - RTS51X_DEBUGP("Get unused block from index %d\n", zone->get_index); - - phy_blk = zone->free_table[zone->get_index]; - zone->free_table[zone->get_index++] = 0xFFFF; - if (zone->get_index >= XD_FREE_TABLE_CNT) - zone->get_index = 0; - zone->unused_blk_cnt--; - - phy_blk += ((u32) (zone_no) << 10); - return phy_blk; -} - -static void xd_set_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off, - u16 phy_off) -{ - struct xd_info *xd_card = &(chip->xd_card); - struct zone_entry *zone; - - zone = &(xd_card->zone[zone_no]); - zone->l2p_table[log_off] = phy_off; -} - -static u32 xd_get_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off) -{ - struct xd_info *xd_card = &(chip->xd_card); - struct zone_entry *zone; - int retval; - - zone = &(xd_card->zone[zone_no]); - if (zone->l2p_table[log_off] == 0xFFFF) { - u32 phy_blk = 0; - int i; - - retval = xd_delay_write(chip); - if (retval != STATUS_SUCCESS) { - RTS51X_DEBUGP("In xd_get_l2p_tbl," - "delay write fail!\n"); - TRACE_RET(chip, BLK_NOT_FOUND); - } - - if (zone->unused_blk_cnt <= 0) { - RTS51X_DEBUGP("No unused block!\n"); - TRACE_RET(chip, BLK_NOT_FOUND); - } - - for (i = 0; i < zone->unused_blk_cnt; i++) { - phy_blk = xd_get_unused_block(chip, zone_no); - if (phy_blk == BLK_NOT_FOUND) { - RTS51X_DEBUGP("No unused block available!\n"); - TRACE_RET(chip, BLK_NOT_FOUND); - } - - retval = - xd_init_page(chip, phy_blk, log_off, 0, - xd_card->page_off + 1); - if (retval == STATUS_SUCCESS) - break; - } - if (i >= zone->unused_blk_cnt) { - RTS51X_DEBUGP("No good unused block available!\n"); - TRACE_RET(chip, BLK_NOT_FOUND); - } - - xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (phy_blk & 0x3FF)); - return phy_blk; - } - - return (u32) zone->l2p_table[log_off] + ((u32) (zone_no) << 10); -} - -int reset_xd_card(struct rts51x_chip *chip) -{ - struct xd_info *xd_card = &(chip->xd_card); - int retval; - - memset(xd_card, 0, sizeof(struct xd_info)); - - xd_card->block_shift = 0; - xd_card->page_off = 0; - xd_card->addr_cycle = 0; - xd_card->capacity = 0; - xd_card->zone_cnt = 0; - xd_card->cis_block = 0xFFFF; - xd_card->delay_write.delay_write_flag = 0; - - enable_card_clock(chip, XD_CARD); - - retval = reset_xd(chip); - if (retval != STATUS_SUCCESS) { - if (chip->option.reset_or_rw_fail_set_pad_drive) { - rts51x_write_register(chip, CARD_DRIVE_SEL, - SD20_DRIVE_MASK, DRIVE_8mA); - } - TRACE_RET(chip, retval); - } - - retval = xd_init_l2p_tbl(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -static int xd_mark_bad_block(struct rts51x_chip *chip, u32 phy_blk) -{ - struct xd_info *xd_card = &(chip->xd_card); - int retval; - u32 page_addr; - u8 reg = 0; - - RTS51X_DEBUGP("mark block 0x%x as bad block\n", phy_blk); - - if (phy_blk == BLK_NOT_FOUND) - TRACE_RET(chip, STATUS_FAIL); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, - XD_LATER_BBLK); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 0xFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 0xFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_H, 0xFF, 0xFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_L, 0xFF, 0xFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED0, 0xFF, 0xFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED1, 0xFF, 0xFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED2, 0xFF, 0xFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED3, 0xFF, 0xFF); - - page_addr = phy_blk << xd_card->block_shift; - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - /* Specify page count */ - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, - xd_card->page_off + 1); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_WRITE_REDUNDANT); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = rts51x_get_rsp(chip, 1, 100); - - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - rts51x_ep0_read_register(chip, XD_DAT, ®); - if (reg & PROGRAM_ERROR) - xd_set_err_code(chip, XD_PRG_ERROR); - else - xd_set_err_code(chip, XD_TO_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int xd_init_page(struct rts51x_chip *chip, u32 phy_blk, u16 logoff, - u8 start_page, u8 end_page) -{ - struct xd_info *xd_card = &(chip->xd_card); - int retval; - u32 page_addr; - u8 reg = 0; - - RTS51X_DEBUGP("Init block 0x%x\n", phy_blk); - - if (start_page > end_page) - TRACE_RET(chip, STATUS_FAIL); - if (phy_blk == BLK_NOT_FOUND) - TRACE_RET(chip, STATUS_FAIL); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, - (u8) (logoff >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, - (u8) logoff); - - page_addr = (phy_blk << xd_card->block_shift) + start_page; - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, - XD_BA_TRANSFORM); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, - (end_page - start_page)); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_WRITE_REDUNDANT); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, STATUS_FAIL); - - retval = rts51x_get_rsp(chip, 1, 500); - - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - rts51x_ep0_read_register(chip, XD_DAT, ®); - if (reg & PROGRAM_ERROR) { - xd_mark_bad_block(chip, phy_blk); - xd_set_err_code(chip, XD_PRG_ERROR); - } else { - xd_set_err_code(chip, XD_TO_ERROR); - } - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; -} - -static int xd_copy_page(struct rts51x_chip *chip, - u32 old_blk, u32 new_blk, u8 start_page, u8 end_page) -{ - struct xd_info *xd_card = &(chip->xd_card); - u32 old_page, new_page; - u8 i, reg = 0; - int retval; - - RTS51X_DEBUGP("Copy page from block 0x%x to block 0x%x\n", old_blk, - new_blk); - - if (start_page > end_page) - TRACE_RET(chip, STATUS_FAIL); - - if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND)) - TRACE_RET(chip, STATUS_FAIL); - - old_page = (old_blk << xd_card->block_shift) + start_page; - new_page = (new_blk << xd_card->block_shift) + start_page; - - XD_CLR_BAD_NEWBLK(xd_card); - - RTS51X_WRITE_REG(chip, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); - - for (i = start_page; i < end_page; i++) { - if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) { - RTS51X_WRITE_REG(chip, CARD_STOP, XD_STOP | XD_CLR_ERR, - XD_STOP | XD_CLR_ERR); - xd_set_err_code(chip, XD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - rts51x_init_cmd(chip); - - xd_assign_phy_addr(chip, old_page, XD_RW_ADDR); - - /* Single page read */ - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_PAGES); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR | STAGE_XD_STATUS, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 4, 500); - if ((retval != STATUS_SUCCESS) || - (chip->rsp_buf[2] & (XD_ECC1_ERROR | XD_ECC2_ERROR))) { - rts51x_clear_xd_error(chip); - reg = 0; - rts51x_ep0_read_register(chip, XD_CTL, ®); - if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) { - wait_timeout(100); - - if (monitor_card_cd(chip, XD_CARD) == - CD_NOT_EXIST) { - xd_set_err_code(chip, XD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - if (((reg & - (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) - == (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) - || ((reg & (XD_ECC2_ERROR | - XD_ECC2_UNCORRECTABLE)) == - (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { - RTS51X_WRITE_REG(chip, XD_PAGE_STATUS, - 0xFF, XD_BPG); - RTS51X_WRITE_REG(chip, XD_BLOCK_STATUS, - 0xFF, XD_GBLK); - XD_SET_BAD_OLDBLK(xd_card); - RTS51X_DEBUGP("old block 0x%x" - "ecc error\n", old_blk); - } - } else { - xd_set_err_code(chip, XD_TO_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - } - if (XD_CHK_BAD_OLDBLK(xd_card)) - rts51x_clear_xd_error(chip); - - rts51x_init_cmd(chip); - - xd_assign_phy_addr(chip, new_page, XD_RW_ADDR); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_WRITE_PAGES); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 1, 300); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - reg = 0; - rts51x_ep0_read_register(chip, XD_DAT, ®); - if (reg & PROGRAM_ERROR) { - xd_mark_bad_block(chip, new_blk); - xd_set_err_code(chip, XD_PRG_ERROR); - XD_SET_BAD_NEWBLK(xd_card); - } else { - xd_set_err_code(chip, XD_TO_ERROR); - } - TRACE_RET(chip, retval); - } - - old_page++; - new_page++; - } - - return STATUS_SUCCESS; -} - -#ifdef XD_SPEEDUP -static int xd_auto_copy_page(struct rts51x_chip *chip, - u32 old_blk, u32 new_blk, - u8 start_page, u8 end_page) -{ - struct xd_info *xd_card = &(chip->xd_card); - u32 old_page, new_page; - int retval; - u8 page_count; - - RTS51X_DEBUGP("Auto copy page from block 0x%x to block 0x%x\n", - old_blk, new_blk); - - if (start_page > end_page) - TRACE_RET(chip, STATUS_FAIL); - - page_count = end_page - start_page; - - if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND)) - TRACE_RET(chip, STATUS_FAIL); - - old_page = (old_blk << xd_card->block_shift) + start_page; - new_page = (new_blk << xd_card->block_shift) + start_page; - - XD_CLR_BAD_NEWBLK(xd_card); - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WAITTIME, 0x03, WAIT_FF); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_PAGELEN, 0xFF, page_count); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR0, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR1, 0xFF, - (u8) old_page); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR2, 0xFF, - (u8) (old_page >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR3, 0xFF, - (u8) (old_page >> 16)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR4, 0xFF, 0); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR0, 0xFF, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR1, 0xFF, - (u8) new_page); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR2, 0xFF, - (u8) (new_page >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR3, 0xFF, - (u8) (new_page >> 16)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR4, 0xFF, 0); - - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, - XD_BA_TRANSFORM | XD_ADDR_MASK, 0 | xd_card->addr_cycle); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, 0); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_COPY_PAGES); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - TRACE_GOTO(chip, Copy_Fail); - } - - retval = rts51x_get_rsp(chip, 1, 800); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - TRACE_GOTO(chip, Copy_Fail); - } - - return STATUS_SUCCESS; - -Copy_Fail: - retval = xd_copy_page(chip, old_blk, new_blk, start_page, end_page); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} -#endif - -static int xd_reset_cmd(struct rts51x_chip *chip) -{ - int retval; - u8 xd_dat, xd_ctl; - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_RESET); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - rts51x_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); - rts51x_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 3, 100); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - TRACE_RET(chip, retval); - } - - xd_dat = chip->rsp_buf[1]; - xd_ctl = chip->rsp_buf[2]; - if (((xd_dat & READY_FLAG) == READY_STATE) && (xd_ctl & XD_RDY)) - return STATUS_SUCCESS; - - TRACE_RET(chip, STATUS_FAIL); -} - -static int xd_erase_block(struct rts51x_chip *chip, u32 phy_blk) -{ - struct xd_info *xd_card = &(chip->xd_card); - u32 page_addr; - u8 reg = 0, xd_dat; - int i, retval; - - if (phy_blk == BLK_NOT_FOUND) - TRACE_RET(chip, STATUS_FAIL); - - page_addr = phy_blk << xd_card->block_shift; - - for (i = 0; i < 3; i++) { - rts51x_init_cmd(chip); - - xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_ERASE); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - rts51x_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 2, 300); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - rts51x_ep0_read_register(chip, XD_DAT, ®); - if (reg & PROGRAM_ERROR) { - xd_mark_bad_block(chip, phy_blk); - xd_set_err_code(chip, XD_PRG_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } else { - xd_set_err_code(chip, XD_ERASE_FAIL); - } - retval = xd_reset_cmd(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - continue; - } - xd_dat = chip->rsp_buf[1]; - if (xd_dat & PROGRAM_ERROR) { - xd_mark_bad_block(chip, phy_blk); - xd_set_err_code(chip, XD_PRG_ERROR); - TRACE_RET(chip, STATUS_FAIL); - } - - return STATUS_SUCCESS; - } - - xd_mark_bad_block(chip, phy_blk); - xd_set_err_code(chip, XD_ERASE_FAIL); - TRACE_RET(chip, STATUS_FAIL); -} - -static int xd_build_l2p_tbl(struct rts51x_chip *chip, int zone_no) -{ - struct xd_info *xd_card = &(chip->xd_card); - struct zone_entry *zone; - int retval; - u32 start, end, i; - u16 max_logoff, cur_fst_page_logoff, cur_lst_page_logoff, - ent_lst_page_logoff; - u8 redunt[11]; - - RTS51X_DEBUGP("xd_build_l2p_tbl: %d\n", zone_no); - - if (xd_card->zone == NULL) { - retval = xd_init_l2p_tbl(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - if (xd_card->zone[zone_no].build_flag) { - RTS51X_DEBUGP("l2p table of zone %d has been built\n", - zone_no); - return STATUS_SUCCESS; - } - - zone = &(xd_card->zone[zone_no]); - - if (zone->l2p_table == NULL) { - zone->l2p_table = vmalloc(2000); - if (zone->l2p_table == NULL) - TRACE_GOTO(chip, Build_Fail); - } - memset((u8 *) (zone->l2p_table), 0xff, 2000); - - if (zone->free_table == NULL) { - zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2); - if (zone->free_table == NULL) - TRACE_GOTO(chip, Build_Fail); - } - memset((u8 *) (zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2); - - if (zone_no == 0) { - if (xd_card->cis_block == 0xFFFF) - start = 0; - else - start = xd_card->cis_block + 1; - if (XD_CHK_4MB(xd_card)) { - end = 0x200; - max_logoff = 499; - } else { - end = 0x400; - max_logoff = 999; - } - } else { - start = (u32) (zone_no) << 10; - end = (u32) (zone_no + 1) << 10; - max_logoff = 999; - } - - RTS51X_DEBUGP("start block 0x%x, end block 0x%x\n", start, end); - - zone->set_index = zone->get_index = 0; - zone->unused_blk_cnt = 0; - - for (i = start; i < end; i++) { - u32 page_addr = i << xd_card->block_shift; - u32 phy_block; - - retval = xd_read_redundant(chip, page_addr, redunt, 11); - if (retval != STATUS_SUCCESS) - continue; - - if (redunt[BLOCK_STATUS] != 0xFF) { - RTS51X_DEBUGP("bad block\n"); - continue; - } - - if (xd_check_data_blank(redunt)) { - RTS51X_DEBUGP("blank block\n"); - xd_set_unused_block(chip, i); - continue; - } - - cur_fst_page_logoff = xd_load_log_block_addr(redunt); - if ((cur_fst_page_logoff == 0xFFFF) - || (cur_fst_page_logoff > max_logoff)) { - retval = xd_erase_block(chip, i); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, i); - continue; - } - if ((zone_no == 0) && (cur_fst_page_logoff == 0) - && (redunt[PAGE_STATUS] != XD_GPG)) - XD_SET_MBR_FAIL(xd_card); - - if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) { - zone->l2p_table[cur_fst_page_logoff] = - (u16) (i & 0x3FF); - continue; - } - - phy_block = - zone->l2p_table[cur_fst_page_logoff] + - ((u32) ((zone_no) << 10)); - - page_addr = ((i + 1) << xd_card->block_shift) - 1; - - retval = xd_read_redundant(chip, page_addr, redunt, 11); - if (retval != STATUS_SUCCESS) - continue; - - cur_lst_page_logoff = xd_load_log_block_addr(redunt); - if (cur_lst_page_logoff == cur_fst_page_logoff) { - int m; - - page_addr = - ((phy_block + 1) << xd_card->block_shift) - 1; - - for (m = 0; m < 3; m++) { - retval = - xd_read_redundant(chip, page_addr, redunt, - 11); - if (retval == STATUS_SUCCESS) - break; - } - - if (m == 3) { - zone->l2p_table[cur_fst_page_logoff] = - (u16) (i & 0x3FF); - retval = xd_erase_block(chip, phy_block); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, phy_block); - continue; - } - - ent_lst_page_logoff = xd_load_log_block_addr(redunt); - if (ent_lst_page_logoff != cur_fst_page_logoff) { - zone->l2p_table[cur_fst_page_logoff] = - (u16) (i & 0x3FF); - retval = xd_erase_block(chip, phy_block); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, phy_block); - continue; - } else { - retval = xd_erase_block(chip, i); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, i); - } - } else { - retval = xd_erase_block(chip, i); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, i); - } - } - - if (XD_CHK_4MB(xd_card)) - end = 500; - else - end = 1000; - - i = 0; - for (start = 0; start < end; start++) { - if (zone->l2p_table[start] == 0xFFFF) - i++; - } - - RTS51X_DEBUGP("Block count %d, invalid L2P entry %d\n", end, i); - RTS51X_DEBUGP("Total unused block: %d\n", zone->unused_blk_cnt); - - if ((zone->unused_blk_cnt - i) < 1) - chip->card_wp |= XD_CARD; - - zone->build_flag = 1; - - return STATUS_SUCCESS; - -Build_Fail: - if (zone->l2p_table) { - vfree(zone->l2p_table); - zone->l2p_table = NULL; - } - if (zone->free_table) { - vfree(zone->free_table); - zone->free_table = NULL; - } - - return STATUS_FAIL; -} - -static int xd_send_cmd(struct rts51x_chip *chip, u8 cmd) -{ - int retval; - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_SET_CMD); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = rts51x_get_rsp(chip, 1, 200); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -static int xd_read_multiple_pages(struct rts51x_chip *chip, u32 phy_blk, - u32 log_blk, u8 start_page, u8 end_page, - u8 *buf, void **ptr, unsigned int *offset) -{ - struct xd_info *xd_card = &(chip->xd_card); - u32 page_addr, new_blk; - u16 log_off; - u8 reg_val, page_cnt; - int zone_no, retval, i; - - if (start_page > end_page) - TRACE_RET(chip, STATUS_FAIL); - - page_cnt = end_page - start_page; - zone_no = (int)(log_blk / 1000); - log_off = (u16) (log_blk % 1000); - - if ((phy_blk & 0x3FF) == 0x3FF) { - for (i = 0; i < 256; i++) { - page_addr = ((u32) i) << xd_card->block_shift; - - retval = xd_read_redundant(chip, page_addr, NULL, 0); - if (retval == STATUS_SUCCESS) - break; - - if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) { - xd_set_err_code(chip, XD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - } - } - - page_addr = (phy_blk << xd_card->block_shift) + start_page; - - rts51x_init_cmd(chip); - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_PPB_TO_SIE, - XD_PPB_TO_SIE); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - RING_BUFFER); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); - - trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512, - DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_PAGES); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END | XD_PPB_EMPTY, - XD_TRANSFER_END | XD_PPB_EMPTY); - - retval = rts51x_send_cmd(chip, MODE_CDIR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - rts51x_transfer_data_partial(chip, RCV_BULK_PIPE(chip), (void *)buf, - ptr, offset, page_cnt * 512, - scsi_sg_count(chip->srb), NULL, 2000); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - - if (retval == STATUS_TIMEDOUT) { - xd_set_err_code(chip, XD_TO_ERROR); - TRACE_RET(chip, retval); - } else { - TRACE_GOTO(chip, Fail); - } - } - retval = rts51x_get_rsp(chip, 1, 200); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - - if (retval == STATUS_TIMEDOUT) { - xd_set_err_code(chip, XD_TO_ERROR); - TRACE_RET(chip, retval); - } else { - TRACE_GOTO(chip, Fail); - } - } - - return STATUS_SUCCESS; - -Fail: - rts51x_ep0_read_register(chip, XD_PAGE_STATUS, ®_val); - RTS51X_DEBUGP("XD_PAGE_STATUS: 0x%x\n", reg_val); - - if (reg_val != XD_GPG) - xd_set_err_code(chip, XD_PRG_ERROR); - - rts51x_ep0_read_register(chip, XD_CTL, ®_val); - RTS51X_DEBUGP("XD_CTL: 0x%x\n", reg_val); - - /* Handle uncorrectable ECC error */ - if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) - == (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) - || ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) - == (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { - wait_timeout(100); - - if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) { - xd_set_err_code(chip, XD_NO_CARD); - TRACE_RET(chip, STATUS_FAIL); - } - - xd_set_err_code(chip, XD_ECC_ERROR); - - new_blk = xd_get_unused_block(chip, zone_no); - if (new_blk == NO_NEW_BLK) { - XD_CLR_BAD_OLDBLK(xd_card); - TRACE_RET(chip, STATUS_FAIL); - } -#ifdef XD_SPEEDUP - retval = - xd_auto_copy_page(chip, phy_blk, new_blk, 0, - xd_card->page_off + 1); -#else - retval = - xd_copy_page(chip, phy_blk, new_blk, 0, - xd_card->page_off + 1); -#endif - if (retval != STATUS_SUCCESS) { - if (!XD_CHK_BAD_NEWBLK(xd_card)) { - retval = xd_erase_block(chip, new_blk); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, new_blk); - } else { - XD_CLR_BAD_NEWBLK(xd_card); - } - XD_CLR_BAD_OLDBLK(xd_card); - TRACE_RET(chip, STATUS_FAIL); - } - xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (new_blk & 0x3FF)); - xd_erase_block(chip, phy_blk); - xd_mark_bad_block(chip, phy_blk); - XD_CLR_BAD_OLDBLK(xd_card); - } - - TRACE_RET(chip, STATUS_FAIL); -} - -static int xd_finish_write(struct rts51x_chip *chip, - u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) -{ - struct xd_info *xd_card = &(chip->xd_card); - int retval, zone_no; - u16 log_off; - - RTS51X_DEBUGP("xd_finish_write, old_blk = 0x%x, new_blk = 0x%x," - "log_blk = 0x%x\n", old_blk, new_blk, log_blk); - - if (page_off > xd_card->page_off) - TRACE_RET(chip, STATUS_FAIL); - - zone_no = (int)(log_blk / 1000); - log_off = (u16) (log_blk % 1000); - - if (old_blk == BLK_NOT_FOUND) { - retval = xd_init_page(chip, new_blk, log_off, - page_off, xd_card->page_off + 1); - if (retval != STATUS_SUCCESS) { - retval = xd_erase_block(chip, new_blk); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, new_blk); - TRACE_RET(chip, STATUS_FAIL); - } - } else { -#ifdef XD_SPEEDUP - retval = xd_auto_copy_page(chip, old_blk, new_blk, - page_off, xd_card->page_off + 1); -#else - retval = xd_copy_page(chip, old_blk, new_blk, - page_off, xd_card->page_off + 1); -#endif - if (retval != STATUS_SUCCESS) { - if (!XD_CHK_BAD_NEWBLK(xd_card)) { - retval = xd_erase_block(chip, new_blk); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, new_blk); - } - XD_CLR_BAD_NEWBLK(xd_card); - TRACE_RET(chip, STATUS_FAIL); - } - - retval = xd_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) { - if (XD_CHK_BAD_OLDBLK(xd_card)) { - xd_mark_bad_block(chip, old_blk); - XD_CLR_BAD_OLDBLK(xd_card); - } else { - /* Add source block to unused block */ - xd_set_unused_block(chip, old_blk); - } - } else { - xd_set_err_code(chip, XD_NO_ERROR); - XD_CLR_BAD_OLDBLK(xd_card); - } - } - - /* Add target block to L2P table */ - xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (new_blk & 0x3FF)); - - return STATUS_SUCCESS; -} - -static int xd_prepare_write(struct rts51x_chip *chip, - u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) -{ - int retval; - - RTS51X_DEBUGP("xd_prepare_write, old_blk = 0x%x, new_blk = 0x%x," - "log_blk = 0x%x, page_off = %d\n", - old_blk, new_blk, log_blk, (int)page_off); - - if (page_off) { -#ifdef XD_SPEEDUP - retval = xd_auto_copy_page(chip, old_blk, new_blk, 0, page_off); -#else - retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off); -#endif - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -static int xd_write_multiple_pages(struct rts51x_chip *chip, u32 old_blk, - u32 new_blk, u32 log_blk, u8 start_page, - u8 end_page, u8 *buf, void **ptr, - unsigned int *offset) -{ - struct xd_info *xd_card = &(chip->xd_card); - u32 page_addr; - int zone_no, retval; - u16 log_off; - u8 page_cnt, reg_val; - - RTS51X_DEBUGP("xd_write_multiple_pages, old_blk = 0x%x," - "new_blk = 0x%x, log_blk = 0x%x\n", - old_blk, new_blk, log_blk); - - if (start_page > end_page) - TRACE_RET(chip, STATUS_FAIL); - - page_cnt = end_page - start_page; - zone_no = (int)(log_blk / 1000); - log_off = (u16) (log_blk % 1000); - - page_addr = (new_blk << xd_card->block_shift) + start_page; - - /* Send index command */ - retval = xd_send_cmd(chip, READ1_1); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - rts51x_init_cmd(chip); - - /* Prepare redundant field */ - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, - (u8) (log_off >> 8)); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, - (u8) log_off); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK); - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG); - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - /* Transform the block address by hardware */ - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, - XD_BA_TRANSFORM); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - RING_BUFFER); - - trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512, - DMA_512); - - rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_WRITE_PAGES); - rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - - retval = rts51x_send_cmd(chip, MODE_CDOR, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - retval = - rts51x_transfer_data_partial(chip, SND_BULK_PIPE(chip), (void *)buf, - ptr, offset, page_cnt * 512, - scsi_sg_count(chip->srb), NULL, 2000); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - - if (retval == STATUS_TIMEDOUT) { - xd_set_err_code(chip, XD_TO_ERROR); - TRACE_RET(chip, retval); - } else { - TRACE_GOTO(chip, Fail); - } - } - retval = rts51x_get_rsp(chip, 1, 200); - if (retval != STATUS_SUCCESS) { - rts51x_clear_xd_error(chip); - - if (retval == STATUS_TIMEDOUT) { - xd_set_err_code(chip, XD_TO_ERROR); - TRACE_RET(chip, retval); - } else { - TRACE_GOTO(chip, Fail); - } - } - - if (end_page == (xd_card->page_off + 1)) { - xd_card->delay_write.delay_write_flag = 0; - - if (old_blk != BLK_NOT_FOUND) { - retval = xd_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) { - if (XD_CHK_BAD_OLDBLK(xd_card)) { - xd_mark_bad_block(chip, old_blk); - XD_CLR_BAD_OLDBLK(xd_card); - } else { - xd_set_unused_block(chip, old_blk); - } - } else { - xd_set_err_code(chip, XD_NO_ERROR); - XD_CLR_BAD_OLDBLK(xd_card); - } - } - xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (new_blk & 0x3FF)); - } - - return STATUS_SUCCESS; - -Fail: - rts51x_ep0_read_register(chip, XD_DAT, ®_val); - RTS51X_DEBUGP("XD_DAT: 0x%x\n", reg_val); - - if (reg_val & PROGRAM_ERROR) { - xd_set_err_code(chip, XD_PRG_ERROR); - xd_mark_bad_block(chip, new_blk); - } - - TRACE_RET(chip, STATUS_FAIL); -} - -int xd_delay_write(struct rts51x_chip *chip) -{ - struct xd_info *xd_card = &(chip->xd_card); - struct xd_delay_write_tag *delay_write = &(xd_card->delay_write); - int retval; - - if (delay_write->delay_write_flag) { - RTS51X_DEBUGP("xd_delay_write\n"); - retval = xd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - delay_write->delay_write_flag = 0; - retval = xd_finish_write(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - delay_write->logblock, - delay_write->pageoff); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - } - - return STATUS_SUCCESS; -} - -int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector, - u16 sector_cnt) -{ - struct xd_info *xd_card = &(chip->xd_card); - unsigned int lun = SCSI_LUN(srb); - struct xd_delay_write_tag *delay_write = &(xd_card->delay_write); - int retval, zone_no; - u32 log_blk, old_blk = 0, new_blk = 0; - u16 log_off, total_sec_cnt = sector_cnt; - u8 start_page, end_page = 0, page_cnt; - u8 *buf; - void *ptr = NULL; - unsigned int offset = 0; - - xd_set_err_code(chip, XD_NO_ERROR); - - xd_card->counter = 0; - - RTS51X_DEBUGP("xd_rw: scsi_bufflen = %d, scsi_sg_count = %d\n", - scsi_bufflen(srb), scsi_sg_count(srb)); - RTS51X_DEBUGP("Data direction: %s\n", - (srb->sc_data_direction == - DMA_TO_DEVICE) ? "write" : "read"); - - buf = (u8 *) scsi_sglist(srb); - - retval = xd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - log_blk = start_sector >> xd_card->block_shift; - start_page = (u8) start_sector & xd_card->page_off; - zone_no = (int)(log_blk / 1000); - log_off = (u16) (log_blk % 1000); - - RTS51X_DEBUGP("log_blk = 0x%x\n", log_blk); - - if (xd_card->zone[zone_no].build_flag == 0) { - retval = xd_build_l2p_tbl(chip, zone_no); - if (retval != STATUS_SUCCESS) { - chip->card_fail |= XD_CARD; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, retval); - } - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - if (delay_write->delay_write_flag && - (delay_write->logblock == log_blk) && - (start_page > delay_write->pageoff)) { - delay_write->delay_write_flag = 0; - if (delay_write->old_phyblock != BLK_NOT_FOUND) { -#ifdef XD_SPEEDUP - retval = xd_auto_copy_page(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - delay_write->pageoff, start_page); -#else - retval = xd_copy_page(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - delay_write->pageoff, - start_page); -#endif - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, retval); - } - } - old_blk = delay_write->old_phyblock; - new_blk = delay_write->new_phyblock; - } else if (delay_write->delay_write_flag && - (delay_write->logblock == log_blk) && - (start_page == delay_write->pageoff)) { - delay_write->delay_write_flag = 0; - old_blk = delay_write->old_phyblock; - new_blk = delay_write->new_phyblock; - } else { - retval = xd_delay_write(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, retval); - } - old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); - new_blk = xd_get_unused_block(chip, zone_no); - if ((old_blk == BLK_NOT_FOUND) - || (new_blk == BLK_NOT_FOUND)) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, retval); - } - - retval = - xd_prepare_write(chip, old_blk, new_blk, log_blk, - start_page); - if (retval != STATUS_SUCCESS) { - if (monitor_card_cd(chip, XD_CARD) == - CD_NOT_EXIST) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, STATUS_FAIL); - } - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, retval); - } - } - } else { - retval = xd_delay_write(chip); - if (retval != STATUS_SUCCESS) { - if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, STATUS_FAIL); - } - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, retval); - } - - old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); - if (old_blk == BLK_NOT_FOUND) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - RTS51X_DEBUGP("old_blk = 0x%x\n", old_blk); - if (srb->sc_data_direction == DMA_TO_DEVICE) - RTS51X_DEBUGP("new_blk = 0x%x\n", new_blk); - - while (total_sec_cnt) { - if ((start_page + total_sec_cnt) > (xd_card->page_off + 1)) - end_page = xd_card->page_off + 1; - else - end_page = start_page + (u8) total_sec_cnt; - page_cnt = end_page - start_page; - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - retval = xd_read_multiple_pages(chip, old_blk, log_blk, - start_page, end_page, - buf, &ptr, &offset); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - } else { - retval = - xd_write_multiple_pages(chip, old_blk, new_blk, - log_blk, start_page, - end_page, buf, &ptr, - &offset); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - total_sec_cnt -= page_cnt; - - if (total_sec_cnt == 0) - break; - - log_blk++; - zone_no = (int)(log_blk / 1000); - log_off = (u16) (log_blk % 1000); - - if (xd_card->zone[zone_no].build_flag == 0) { - retval = xd_build_l2p_tbl(chip, zone_no); - if (retval != STATUS_SUCCESS) { - chip->card_fail |= XD_CARD; - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - TRACE_RET(chip, retval); - } - } - - old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); - if (old_blk == BLK_NOT_FOUND) { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - } - TRACE_RET(chip, STATUS_FAIL); - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - new_blk = xd_get_unused_block(chip, zone_no); - if (new_blk == BLK_NOT_FOUND) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - TRACE_RET(chip, STATUS_FAIL); - } - } - - start_page = 0; - } - - if ((srb->sc_data_direction == DMA_TO_DEVICE) && - (end_page != (xd_card->page_off + 1))) { - delay_write->delay_write_flag = 1; - delay_write->old_phyblock = old_blk; - delay_write->new_phyblock = new_blk; - delay_write->logblock = log_blk; - delay_write->pageoff = end_page; - } - - scsi_set_resid(srb, 0); - - return STATUS_SUCCESS; -} - -void xd_free_l2p_tbl(struct rts51x_chip *chip) -{ - struct xd_info *xd_card = &(chip->xd_card); - int i = 0; - - if (xd_card->zone != NULL) { - for (i = 0; i < xd_card->zone_cnt; i++) { - if (xd_card->zone[i].l2p_table != NULL) { - vfree(xd_card->zone[i].l2p_table); - xd_card->zone[i].l2p_table = NULL; - } - if (xd_card->zone[i].free_table != NULL) { - vfree(xd_card->zone[i].free_table); - xd_card->zone[i].free_table = NULL; - } - } - vfree(xd_card->zone); - xd_card->zone = NULL; - } -} - -void xd_cleanup_work(struct rts51x_chip *chip) -{ - struct xd_info *xd_card = &(chip->xd_card); - - if (xd_card->delay_write.delay_write_flag) { - RTS51X_DEBUGP("xD: delay write\n"); - xd_delay_write(chip); - xd_card->counter = 0; - } -} - -int xd_power_off_card3v3(struct rts51x_chip *chip) -{ - int retval; - - rts51x_init_cmd(chip); - - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, XD_CLK_EN, 0); - - if (chip->asic_code) - xd_pull_ctl_disable(chip); - else - rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, 0xDF); - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0); - if (!chip->option.FT2_fast_mode) { - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, - POWER_OFF); - if (CHECK_PKG(chip, LQFP48) - || chip->option.rts5129_D3318_off_enable) - rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, - DV3318_AUTO_PWR_OFF, 0); - } - - retval = rts51x_send_cmd(chip, MODE_C, 100); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - return STATUS_SUCCESS; -} - -int release_xd_card(struct rts51x_chip *chip) -{ - struct xd_info *xd_card = &(chip->xd_card); - int retval; - - RTS51X_DEBUGP("elease_xd_card\n"); - - chip->card_ready &= ~XD_CARD; - chip->card_fail &= ~XD_CARD; - chip->card_wp &= ~XD_CARD; - - xd_card->delay_write.delay_write_flag = 0; - - xd_free_l2p_tbl(chip); - - rts51x_write_register(chip, SFSM_ED, HW_CMD_STOP, HW_CMD_STOP); - - retval = xd_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) - TRACE_RET(chip, retval); - - if (chip->asic_code && CHECK_PKG(chip, QFN24)) - wait_timeout(20); - - return STATUS_SUCCESS; -} diff --git a/trunk/drivers/staging/rts5139/xd.h b/trunk/drivers/staging/rts5139/xd.h deleted file mode 100644 index fa695903ba65..000000000000 --- a/trunk/drivers/staging/rts5139/xd.h +++ /dev/null @@ -1,193 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * Header file - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Author: - * wwang (wei_wang@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - * Edwin Rong (edwin_rong@realsil.com.cn) - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#ifndef __RTS51X_XD_H -#define __RTS51X_XD_H - -/* Error Codes */ -#define XD_NO_ERROR 0x00 -#define XD_NO_MEMORY 0x80 -#define XD_PRG_ERROR 0x40 -#define XD_NO_CARD 0x20 -#define XD_READ_FAIL 0x10 -#define XD_ERASE_FAIL 0x08 -#define XD_WRITE_FAIL 0x04 -#define XD_ECC_ERROR 0x02 -#define XD_TO_ERROR 0x01 - -/* XD Commands */ -#define READ1_1 0x00 -#define READ1_2 0x01 -#define READ2 0x50 -#define READ_ID 0x90 -#define RESET 0xff -#define PAGE_PRG_1 0x80 -#define PAGE_PRG_2 0x10 -#define BLK_ERASE_1 0x60 -#define BLK_ERASE_2 0xD0 -#define READ_STS 0x70 -#define READ_xD_ID 0x9A -#define COPY_BACK_512 0x8A -#define COPY_BACK_2K 0x85 -#define READ1_1_2 0x30 -#define READ1_1_3 0x35 -#define CHG_DAT_OUT_1 0x05 -#define RDM_DAT_OUT_1 0x05 -#define CHG_DAT_OUT_2 0xE0 -#define RDM_DAT_OUT_2 0xE0 -#define CHG_DAT_OUT_2 0xE0 -#define CHG_DAT_IN_1 0x85 -#define CACHE_PRG 0x15 - -/* Redundant Area Related */ -#define XD_EXTRA_SIZE 0x10 -#define XD_2K_EXTRA_SIZE 0x40 - -/* Define for XD Status */ -#define NOT_WRITE_PROTECTED 0x80 -#define READY_STATE 0x40 -#define PROGRAM_ERROR 0x01 -#define PROGRAM_ERROR_N_1 0x02 -#define INTERNAL_READY 0x20 -#define READY_FLAG 0x5F - -/* Define for device code */ -#define XD_8M_X8_512 0xE6 -#define XD_16M_X8_512 0x73 -#define XD_32M_X8_512 0x75 -#define XD_64M_X8_512 0x76 -#define XD_128M_X8_512 0x79 -#define XD_256M_X8_512 0x71 -#define XD_128M_X8_2048 0xF1 -#define XD_256M_X8_2048 0xDA -#define XD_512M_X8 0xDC -#define XD_128M_X16_2048 0xC1 -#define XD_4M_X8_512_1 0xE3 -#define XD_4M_X8_512_2 0xE5 -#define xD_1G_X8_512 0xD3 -#define xD_2G_X8_512 0xD5 - -#define XD_ID_CODE 0xB5 - -#define VENDOR_BLOCK 0xEFFF -#define CIS_BLOCK 0xDFFF - -#define BLK_NOT_FOUND 0xFFFFFFFF - -#define NO_NEW_BLK 0xFFFFFFFF - -#define PAGE_CORRECTABLE 0x0 -#define PAGE_NOTCORRECTABLE 0x1 - -#define NO_OFFSET 0x0 -#define WITH_OFFSET 0x1 - -#define Sect_Per_Page 4 -#define XD_ADDR_MODE_2C XD_ADDR_MODE_2A - -#define ZONE0_BAD_BLOCK 23 -#define NOT_ZONE0_BAD_BLOCK 24 - -/* Assign address mode */ -#define XD_RW_ADDR 0x01 -#define XD_ERASE_ADDR 0x02 - -/* Macro Definition */ -#define XD_PAGE_512(xd_card) \ - do { \ - (xd_card)->block_shift = 5; \ - (xd_card)->page_off = 0x1F; \ - } while (0) - -#define XD_SET_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag |= 0x01) -#define XD_CLR_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag &= ~0x01) -#define XD_CHK_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag & 0x01) - -#define XD_SET_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag |= 0x02) -#define XD_CLR_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag &= ~0x02) -#define XD_CHK_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag & 0x02) - -#define XD_SET_MBR_FAIL(xd_card) ((xd_card)->multi_flag |= 0x04) -#define XD_CLR_MBR_FAIL(xd_card) ((xd_card)->multi_flag &= ~0x04) -#define XD_CHK_MBR_FAIL(xd_card) ((xd_card)->multi_flag & 0x04) - -#define XD_SET_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag |= 0x08) -#define XD_CLR_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag &= ~0x08) -#define XD_CHK_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag & 0x08) - -#define XD_SET_4MB(xd_card) ((xd_card)->multi_flag |= 0x10) -#define XD_CLR_4MB(xd_card) ((xd_card)->multi_flag &= ~0x10) -#define XD_CHK_4MB(xd_card) ((xd_card)->multi_flag & 0x10) - -#define XD_SET_ECC_ERR(xd_card) ((xd_card)->multi_flag |= 0x40) -#define XD_CLR_ECC_ERR(xd_card) ((xd_card)->multi_flag &= ~0x40) -#define XD_CHK_ECC_ERR(xd_card) ((xd_card)->multi_flag & 0x40) - -/* Offset in xD redundant buffer */ -#define PAGE_STATUS 0 -#define BLOCK_STATUS 1 -#define BLOCK_ADDR1_L 2 -#define BLOCK_ADDR1_H 3 -#define BLOCK_ADDR2_L 4 -#define BLOCK_ADDR2_H 5 -#define RESERVED0 6 -#define RESERVED1 7 -#define RESERVED2 8 -#define RESERVED3 9 -#define PARITY 10 - -/* For CIS block */ -#define CIS0_0 0 -#define CIS0_1 1 -#define CIS0_2 2 -#define CIS0_3 3 -#define CIS0_4 4 -#define CIS0_5 5 -#define CIS0_6 6 -#define CIS0_7 7 -#define CIS0_8 8 -#define CIS0_9 9 -#define CIS1_0 256 -#define CIS1_1 (256 + 1) -#define CIS1_2 (256 + 2) -#define CIS1_3 (256 + 3) -#define CIS1_4 (256 + 4) -#define CIS1_5 (256 + 5) -#define CIS1_6 (256 + 6) -#define CIS1_7 (256 + 7) -#define CIS1_8 (256 + 8) -#define CIS1_9 (256 + 9) - -int reset_xd_card(struct rts51x_chip *chip); -int xd_delay_write(struct rts51x_chip *chip); -int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector, - u16 sector_cnt); -void xd_free_l2p_tbl(struct rts51x_chip *chip); -void xd_cleanup_work(struct rts51x_chip *chip); -int xd_power_off_card3v3(struct rts51x_chip *chip); -int release_xd_card(struct rts51x_chip *chip); - -#endif /* __RTS51X_XD_H */ diff --git a/trunk/drivers/staging/rts_pstor/Makefile b/trunk/drivers/staging/rts_pstor/Makefile index 42533d39c07f..61609aee0a0f 100644 --- a/trunk/drivers/staging/rts_pstor/Makefile +++ b/trunk/drivers/staging/rts_pstor/Makefile @@ -1,4 +1,4 @@ -ccflags := -Idrivers/scsi +EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_RTS_PSTOR) := rts_pstor.o diff --git a/trunk/drivers/staging/rts_pstor/rtsx_scsi.c b/trunk/drivers/staging/rts_pstor/rtsx_scsi.c index f2e5842d4c90..7de1fae443fc 100644 --- a/trunk/drivers/staging/rts_pstor/rtsx_scsi.c +++ b/trunk/drivers/staging/rts_pstor/rtsx_scsi.c @@ -2730,7 +2730,7 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) buf_len = data_len = 0x6A; } - buf = kmalloc(buf_len, GFP_KERNEL); + buf = (u8 *)kmalloc(buf_len, GFP_KERNEL); if (!buf) { TRACE_RET(chip, TRANSPORT_ERROR); } diff --git a/trunk/drivers/staging/rts_pstor/sd.c b/trunk/drivers/staging/rts_pstor/sd.c index fb62eafe4fcd..8db14ddbeb7b 100644 --- a/trunk/drivers/staging/rts_pstor/sd.c +++ b/trunk/drivers/staging/rts_pstor/sd.c @@ -4139,7 +4139,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) cmd[3] = srb->cmnd[5]; cmd[4] = srb->cmnd[6]; - buf = kmalloc(data_len, GFP_KERNEL); + buf = (u8 *)kmalloc(data_len, GFP_KERNEL); if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); } @@ -4385,7 +4385,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) u16 i; u8 *buf; - buf = kmalloc(data_len, GFP_KERNEL); + buf = (u8 *)kmalloc(data_len, GFP_KERNEL); if (buf == NULL) { TRACE_RET(chip, TRANSPORT_ERROR); } diff --git a/trunk/drivers/staging/rts_pstor/spi.c b/trunk/drivers/staging/rts_pstor/spi.c index 6b36cc532a8c..c803ba635509 100644 --- a/trunk/drivers/staging/rts_pstor/spi.c +++ b/trunk/drivers/staging/rts_pstor/spi.c @@ -463,7 +463,7 @@ int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) } if (len) { - buf = kmalloc(len, GFP_KERNEL); + buf = (u8 *)kmalloc(len, GFP_KERNEL); if (!buf) TRACE_RET(chip, STATUS_ERROR); diff --git a/trunk/drivers/staging/serqt_usb2/serqt_usb2.c b/trunk/drivers/staging/serqt_usb2/serqt_usb2.c index 2ea82c104d57..12f5eba0355c 100644 --- a/trunk/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/trunk/drivers/staging/serqt_usb2/serqt_usb2.c @@ -190,7 +190,7 @@ struct quatech_port { struct usb_serial_port *port; /* owner of this object */ struct qt_get_device_data DeviceData; - struct mutex lock; + spinlock_t lock; bool read_urb_busy; int RxHolding; int ReadBulkStopped; @@ -745,7 +745,7 @@ static int qt_startup(struct usb_serial *serial) } return -ENOMEM; } - mutex_init(&qt_port->lock); + spin_lock_init(&qt_port->lock); usb_set_serial_port_data(port, qt_port); @@ -1160,6 +1160,7 @@ static int qt_write_room(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial; struct quatech_port *qt_port; + unsigned long flags; int retval = -EINVAL; @@ -1175,7 +1176,7 @@ static int qt_write_room(struct tty_struct *tty) qt_port = qt_get_port_private(port); - mutex_lock(&qt_port->lock); + spin_lock_irqsave(&qt_port->lock, flags); dbg("%s - port %d\n", __func__, port->number); @@ -1184,7 +1185,7 @@ static int qt_write_room(struct tty_struct *tty) retval = port->bulk_out_size; } - mutex_unlock(&qt_port->lock); + spin_unlock_irqrestore(&qt_port->lock, flags); return retval; } @@ -1357,6 +1358,7 @@ static void qt_break(struct tty_struct *tty, int break_state) struct quatech_port *qt_port; u16 index, onoff; unsigned int result; + unsigned long flags; index = tty->index - serial->minor; @@ -1367,7 +1369,7 @@ static void qt_break(struct tty_struct *tty, int break_state) else onoff = 0; - mutex_lock(&qt_port->lock); + spin_lock_irqsave(&qt_port->lock, flags); dbg("%s - port %d\n", __func__, port->number); @@ -1375,7 +1377,7 @@ static void qt_break(struct tty_struct *tty, int break_state) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_BREAK_CONTROL, 0x40, onoff, index, NULL, 0, 300); - mutex_unlock(&qt_port->lock); + spin_unlock_irqrestore(&qt_port->lock, flags); } static inline int qt_real_tiocmget(struct tty_struct *tty, @@ -1464,20 +1466,21 @@ static int qt_tiocmget(struct tty_struct *tty) struct usb_serial *serial = get_usb_serial(port, __func__); struct quatech_port *qt_port = qt_get_port_private(port); int retval = -ENODEV; + unsigned long flags; dbg("In %s\n", __func__); if (!serial) return -ENODEV; - mutex_lock(&qt_port->lock); + spin_lock_irqsave(&qt_port->lock, flags); dbg("%s - port %d\n", __func__, port->number); dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding); retval = qt_real_tiocmget(tty, port, serial); - mutex_unlock(&qt_port->lock); + spin_unlock_irqrestore(&qt_port->lock, flags); return retval; } @@ -1488,6 +1491,7 @@ static int qt_tiocmset(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = get_usb_serial(port, __func__); struct quatech_port *qt_port = qt_get_port_private(port); + unsigned long flags; int retval = -ENODEV; dbg("In %s\n", __func__); @@ -1495,14 +1499,14 @@ static int qt_tiocmset(struct tty_struct *tty, if (!serial) return -ENODEV; - mutex_lock(&qt_port->lock); + spin_lock_irqsave(&qt_port->lock, flags); dbg("%s - port %d\n", __func__, port->number); dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding); retval = qt_real_tiocmset(tty, port, serial, set); - mutex_unlock(&qt_port->lock); + spin_unlock_irqrestore(&qt_port->lock, flags); return retval; } @@ -1511,6 +1515,7 @@ static void qt_throttle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = get_usb_serial(port, __func__); struct quatech_port *qt_port; + unsigned long flags; dbg("%s - port %d\n", __func__, port->number); @@ -1519,13 +1524,13 @@ static void qt_throttle(struct tty_struct *tty) qt_port = qt_get_port_private(port); - mutex_lock(&qt_port->lock); + spin_lock_irqsave(&qt_port->lock, flags); /* pass on to the driver specific version of this function */ qt_port->RxHolding = 1; dbg("%s - port->RxHolding = 1\n", __func__); - mutex_unlock(&qt_port->lock); + spin_unlock_irqrestore(&qt_port->lock, flags); return; } @@ -1534,6 +1539,7 @@ static void qt_unthrottle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = get_usb_serial(port, __func__); struct quatech_port *qt_port; + unsigned long flags; unsigned int result; if (!serial) @@ -1541,7 +1547,7 @@ static void qt_unthrottle(struct tty_struct *tty) qt_port = qt_get_port_private(port); - mutex_lock(&qt_port->lock); + spin_lock_irqsave(&qt_port->lock, flags); dbg("%s - port %d\n", __func__, port->number); @@ -1567,7 +1573,7 @@ static void qt_unthrottle(struct tty_struct *tty) __func__, result); } } - mutex_unlock(&qt_port->lock); + spin_unlock_irqrestore(&qt_port->lock, flags); return; } diff --git a/trunk/drivers/staging/spectra/ffsport.c b/trunk/drivers/staging/spectra/ffsport.c index 86d556d6cf98..506547b603e1 100644 --- a/trunk/drivers/staging/spectra/ffsport.c +++ b/trunk/drivers/staging/spectra/ffsport.c @@ -227,12 +227,19 @@ static int ioctl_write_page_data(unsigned long arg) if (copy_from_user(&info, (void __user *)arg, sizeof(info))) return -EFAULT; - buf = memdup_user((void __user *)info.data, - IdentifyDeviceData.PageDataSize); - if (IS_ERR(buf)) { + buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); + if (!buf) { + printk(KERN_ERR "ioctl_write_page_data: " + "failed to allocate memory\n"); + return -ENOMEM; + } + + if (copy_from_user(buf, (void __user *)info.data, + IdentifyDeviceData.PageDataSize)) { printk(KERN_ERR "ioctl_write_page_data: " "failed to copy user data\n"); - return PTR_ERR(buf); + kfree(buf); + return -EFAULT; } mutex_lock(&spectra_lock); diff --git a/trunk/drivers/staging/tidspbridge/gen/gh.c b/trunk/drivers/staging/tidspbridge/gen/gh.c index 60aa7b063c91..cd725033f274 100644 --- a/trunk/drivers/staging/tidspbridge/gen/gh.c +++ b/trunk/drivers/staging/tidspbridge/gen/gh.c @@ -55,7 +55,7 @@ struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size, hash_tab->match = match; hash_tab->delete = delete == NULL ? noop : delete; - hash_tab->buckets = + hash_tab->buckets = (struct element **) kzalloc(sizeof(struct element *) * max_bucket, GFP_KERNEL); if (hash_tab->buckets == NULL) { gh_delete(hash_tab); diff --git a/trunk/drivers/staging/usbip/stub.h b/trunk/drivers/staging/usbip/stub.h index d4073684eacd..132adc57ebc1 100644 --- a/trunk/drivers/staging/usbip/stub.h +++ b/trunk/drivers/staging/usbip/stub.h @@ -17,9 +17,6 @@ * USA. */ -#ifndef __USBIP_STUB_H -#define __USBIP_STUB_H - #include #include #include @@ -109,5 +106,3 @@ void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum, __u32 status); void stub_complete(struct urb *urb); int stub_tx_loop(void *data); - -#endif /* __USBIP_STUB_H */ diff --git a/trunk/drivers/staging/usbip/stub_dev.c b/trunk/drivers/staging/usbip/stub_dev.c index 77d64693b873..fce22f2bd8bf 100644 --- a/trunk/drivers/staging/usbip/stub_dev.c +++ b/trunk/drivers/staging/usbip/stub_dev.c @@ -524,11 +524,11 @@ static void stub_disconnect(struct usb_interface *interface) } } -/* +/* * Presence of pre_reset and post_reset prevents the driver from being unbound * when the device is being reset */ - + int stub_pre_reset(struct usb_interface *interface) { dev_dbg(&interface->dev, "pre_reset\n"); @@ -548,4 +548,4 @@ struct usb_driver stub_driver = { .id_table = stub_table, .pre_reset = stub_pre_reset, .post_reset = stub_post_reset, -}; + }; diff --git a/trunk/drivers/staging/usbip/stub_rx.c b/trunk/drivers/staging/usbip/stub_rx.c index 6b4e3e182de8..538fb9ee341a 100644 --- a/trunk/drivers/staging/usbip/stub_rx.c +++ b/trunk/drivers/staging/usbip/stub_rx.c @@ -175,11 +175,12 @@ static int tweak_reset_device_cmd(struct urb *urb) dev_info(&urb->dev->dev, "usb_queue_reset_device\n"); /* - * With the implementation of pre_reset and post_reset the driver no + * With the implementation of pre_reset and post_reset the driver no * longer unbinds. This allows the use of synchronous reset. */ - if (usb_lock_device_for_reset(sdev->udev, sdev->interface) < 0) { + if (usb_lock_device_for_reset(sdev->udev, sdev->interface)<0) + { dev_err(&urb->dev->dev, "could not obtain lock to reset device\n"); return 0; } diff --git a/trunk/drivers/staging/usbip/usbip_protocol.txt b/trunk/drivers/staging/usbip/usbip_protocol.txt deleted file mode 100644 index 84e353b714bb..000000000000 --- a/trunk/drivers/staging/usbip/usbip_protocol.txt +++ /dev/null @@ -1,358 +0,0 @@ -PRELIMINARY DRAFT, MAY CONTAIN MISTAKES! -28 Jun 2011 - -The USB/IP protocol follows a server/client architecture. The server exports the -USB devices and the clients imports them. The device driver for the exported -USB device runs on the client machine. - -The client may ask for the list of the exported USB devices. To get the list the -client opens a TCP/IP connection towards the server, and sends an OP_REQ_DEVLIST -packet on top of the TCP/IP connection (so the actual OP_REQ_DEVLIST may be sent -in one or more pieces at the low level transport layer). The server sends back -the OP_REP_DEVLIST packet which lists the exported USB devices. Finally the -TCP/IP connection is closed. - - virtual host controller usb host - "client" "server" - (imports USB devices) (exports USB devices) - | | - | OP_REQ_DEVLIST | - | ----------------------------------------------> | - | | - | OP_REP_DEVLIST | - | <---------------------------------------------- | - | | - -Once the client knows the list of exported USB devices it may decide to use one -of them. First the client opens a TCP/IP connection towards the server and -sends an OP_REQ_IMPORT packet. The server replies with OP_REP_IMPORT. If the -import was successful the TCP/IP connection remains open and will be used -to trasfer the URB traffic between the client and the server. The client may -send two types of packets: the USBIP_CMD_SUBMIT to submit an URB, and -USBIP_CMD_UNLINK to unlink a previously submitted URB. The answers of the -server may be USBIP_RET_SUBMIT and USBIP_RET_UNLINK respectively. - - virtual host controller usb host - "client" "server" - (imports USB devices) (exports USB devices) - | | - | OP_REQ_IMPORT | - | ----------------------------------------------> | - | | - | OP_REP_IMPORT | - | <---------------------------------------------- | - | | - | | - | USBIP_CMD_SUBMIT(seqnum = n) | - | ----------------------------------------------> | - | | - | USBIP_RET_SUBMIT(seqnum = n) | - | <---------------------------------------------- | - | . | - | : | - | | - | USBIP_CMD_SUBMIT(seqnum = m) | - | ----------------------------------------------> | - | | - | USBIP_CMD_SUBMIT(seqnum = m+1) | - | ----------------------------------------------> | - | | - | USBIP_CMD_SUBMIT(seqnum = m+2) | - | ----------------------------------------------> | - | | - | USBIP_RET_SUBMIT(seqnum = m) | - | <---------------------------------------------- | - | | - | USBIP_CMD_SUBMIT(seqnum = m+3) | - | ----------------------------------------------> | - | | - | USBIP_RET_SUBMIT(seqnum = m+1) | - | <---------------------------------------------- | - | | - | USBIP_CMD_SUBMIT(seqnum = m+4) | - | ----------------------------------------------> | - | | - | USBIP_RET_SUBMIT(seqnum = m+2) | - | <---------------------------------------------- | - | . | - | : | - | | - | USBIP_CMD_UNLINK | - | ----------------------------------------------> | - | | - | USBIP_RET_UNLINK | - | <---------------------------------------------- | - | | - -The fields are in network (big endian) byte order meaning that the most significant -byte (MSB) is stored at the lowest address. - - -OP_REQ_DEVLIST: Retrieve the list of exported USB devices. - - Offset | Length | Value | Description ------------+--------+------------+--------------------------------------------------- - 0 | 2 | 0x0100 | Binary-coded decimal USBIP version number: v1.0.0 ------------+--------+------------+--------------------------------------------------- - 2 | 2 | 0x8005 | Command code: Retrieve the list of exported USB - | | | devices. ------------+--------+------------+--------------------------------------------------- - 4 | 4 | 0x00000000 | Status: unused, shall be set to 0 - -OP_REP_DEVLIST: Reply with the list of exported USB devices. - - Offset | Length | Value | Description ------------+--------+------------+--------------------------------------------------- - 0 | 2 | 0x0100 | Binary-coded decimal USBIP version number: v1.0.0. ------------+--------+------------+--------------------------------------------------- - 2 | 2 | 0x0005 | Reply code: The list of exported USB devices. ------------+--------+------------+--------------------------------------------------- - 4 | 4 | 0x00000000 | Status: 0 for OK ------------+--------+------------+--------------------------------------------------- - 8 | 4 | n | Number of exported devices: 0 means no exported - | | | devices. ------------+--------+------------+--------------------------------------------------- - 0x0C | | | From now on the exported n devices are described, - | | | if any. If no devices are exported the message - | | | ends with the previous "number of exported - | | | devices" field. ------------+--------+------------+--------------------------------------------------- - | 256 | | path: Path of the device on the host exporting the - | | | USB device, string closed with zero byte, e.g. - | | | "/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2" - | | | The unused bytes shall be filled with zero - | | | bytes. ------------+--------+------------+--------------------------------------------------- - 0x10C | 32 | | busid: Bus ID of the exported device, string - | | | closed with zero byte, e.g. "3-2". The unused - | | | bytes shall be filled with zero bytes. ------------+--------+------------+--------------------------------------------------- - 0x12C | 4 | | busnum ------------+--------+------------+--------------------------------------------------- - 0x130 | 4 | | devnum ------------+--------+------------+--------------------------------------------------- - 0x134 | 4 | | speed ------------+--------+------------+--------------------------------------------------- - 0x138 | 2 | | idVendor ------------+--------+------------+--------------------------------------------------- - 0x13A | 2 | | idProduct ------------+--------+------------+--------------------------------------------------- - 0x13C | 2 | | bcdDevice ------------+--------+------------+--------------------------------------------------- - 0x13E | 1 | | bDeviceClass ------------+--------+------------+--------------------------------------------------- - 0x13F | 1 | | bDeviceSubClass ------------+--------+------------+--------------------------------------------------- - 0x140 | 1 | | bDeviceProtocol ------------+--------+------------+--------------------------------------------------- - 0x141 | 1 | | bConfigurationValue ------------+--------+------------+--------------------------------------------------- - 0x142 | 1 | | bNumConfigurations ------------+--------+------------+--------------------------------------------------- - 0x143 | 1 | | bNumInterfaces ------------+--------+------------+--------------------------------------------------- - 0x144 | | m_0 | From now on each interface is described, all - | | | together bNumInterfaces times, with the - | | | the following 4 fields: ------------+--------+------------+--------------------------------------------------- - | 1 | | bInterfaceClass ------------+--------+------------+--------------------------------------------------- - 0x145 | 1 | | bInterfaceSubClass ------------+--------+------------+--------------------------------------------------- - 0x146 | 1 | | bInterfaceProtocol ------------+--------+------------+--------------------------------------------------- - 0x147 | 1 | | padding byte for alignment, shall be set to zero ------------+--------+------------+--------------------------------------------------- - 0xC + | | | The second exported USB device starts at i=1 - i*0x138 + | | | with the busid field. - m_(i-1)*4 | | | - -OP_REQ_IMPORT: Request to import (attach) a remote USB device. - - Offset | Length | Value | Description ------------+--------+------------+--------------------------------------------------- - 0 | 2 | 0x0100 | Binary-coded decimal USBIP version number: v1.0.0 ------------+--------+------------+--------------------------------------------------- - 2 | 2 | 0x8003 | Command code: import a remote USB device. ------------+--------+------------+--------------------------------------------------- - 4 | 4 | 0x00000000 | Status: unused, shall be set to 0 ------------+--------+------------+--------------------------------------------------- - 8 | 32 | | busid: the busid of the exported device on the - | | | remote host. The possible values are taken - | | | from the message field OP_REP_DEVLIST.busid. - | | | A string closed with zero, the unused bytes - | | | shall be filled with zeros. ------------+--------+------------+--------------------------------------------------- - -OP_REP_IMPORT: Reply to import (attach) a remote USB device. - - Offset | Length | Value | Description ------------+--------+------------+--------------------------------------------------- - 0 | 2 | 0x0100 | Binary-coded decimal USBIP version number: v1.0.0 ------------+--------+------------+--------------------------------------------------- - 2 | 2 | 0x0003 | Reply code: Reply to import. ------------+--------+------------+--------------------------------------------------- - 4 | 4 | 0x00000000 | Status: 0 for OK - | | | 1 for error ------------+--------+------------+--------------------------------------------------- - 8 | | | From now on comes the details of the imported - | | | device, if the previous status field was OK (0), - | | | otherwise the reply ends with the status field. ------------+--------+------------+--------------------------------------------------- - | 256 | | path: Path of the device on the host exporting the - | | | USB device, string closed with zero byte, e.g. - | | | "/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2" - | | | The unused bytes shall be filled with zero - | | | bytes. ------------+--------+------------+--------------------------------------------------- - 0x108 | 32 | | busid: Bus ID of the exported device, string - | | | closed with zero byte, e.g. "3-2". The unused - | | | bytes shall be filled with zero bytes. ------------+--------+------------+--------------------------------------------------- - 0x128 | 4 | | busnum ------------+--------+------------+--------------------------------------------------- - 0x12C | 4 | | devnum ------------+--------+------------+--------------------------------------------------- - 0x130 | 4 | | speed ------------+--------+------------+--------------------------------------------------- - 0x134 | 2 | | idVendor ------------+--------+------------+--------------------------------------------------- - 0x136 | 2 | | idProduct ------------+--------+------------+--------------------------------------------------- - 0x138 | 2 | | bcdDevice ------------+--------+------------+--------------------------------------------------- - 0x139 | 1 | | bDeviceClass ------------+--------+------------+--------------------------------------------------- - 0x13A | 1 | | bDeviceSubClass ------------+--------+------------+--------------------------------------------------- - 0x13B | 1 | | bDeviceProtocol ------------+--------+------------+--------------------------------------------------- - 0x13C | 1 | | bConfigurationValue ------------+--------+------------+--------------------------------------------------- - 0x13D | 1 | | bNumConfigurations ------------+--------+------------+--------------------------------------------------- - 0x13E | 1 | | bNumInterfaces - -USBIP_CMD_SUBMIT: Submit an URB - - Offset | Length | Value | Description ------------+--------+------------+--------------------------------------------------- - 0 | 4 | 0x00000001 | command: Submit an URB ------------+--------+------------+--------------------------------------------------- - 4 | 4 | | seqnum: the sequence number of the URB to submit ------------+--------+------------+--------------------------------------------------- - 8 | 4 | | devid ------------+--------+------------+--------------------------------------------------- - 0xC | 4 | | direction: 0: USBIP_DIR_IN - | | | 1: USBIP_DIR_OUT ------------+--------+------------+--------------------------------------------------- - 0x10 | 4 | | ep: endpoint number, possible values are: 0...15 ------------+--------+------------+--------------------------------------------------- - 0x14 | 4 | | transfer_flags: possible values depend on the - | | | URB transfer type, see below ------------+--------+------------+--------------------------------------------------- - 0x18 | 4 | | transfer_buffer_length ------------+--------+------------+--------------------------------------------------- - 0x1C | 4 | | start_frame: specify the selected frame to - | | | transmit an ISO frame, ignored if URB_ISO_ASAP - | | | is specified at transfer_flags ------------+--------+------------+--------------------------------------------------- - 0x20 | 4 | | number_of_packets: number of ISO packets ------------+--------+------------+--------------------------------------------------- - 0x24 | 4 | | interval: maximum time for the request on the - | | | server-side host controller ------------+--------+------------+--------------------------------------------------- - 0x28 | 8 | | setup: data bytes for USB setup, filled with - | | | zeros if not used ------------+--------+------------+--------------------------------------------------- - 0x30 | | | URB data. For ISO transfers the padding between - | | | each ISO packets is not transmitted. - - - Allowed transfer_flags | value | control | interrupt | bulk | isochronous - -------------------------+------------+---------+-----------+----------+------------- - URB_SHORT_NOT_OK | 0x00000001 | only in | only in | only in | no - URB_ISO_ASAP | 0x00000002 | no | no | no | yes - URB_NO_TRANSFER_DMA_MAP | 0x00000004 | yes | yes | yes | yes - URB_NO_FSBR | 0x00000020 | yes | no | no | no - URB_ZERO_PACKET | 0x00000040 | no | no | only out | no - URB_NO_INTERRUPT | 0x00000080 | yes | yes | yes | yes - URB_FREE_BUFFER | 0x00000100 | yes | yes | yes | yes - URB_DIR_MASK | 0x00000200 | yes | yes | yes | yes - - -USBIP_RET_SUBMIT: Reply for submitting an URB - - Offset | Length | Value | Description ------------+--------+------------+--------------------------------------------------- - 0 | 4 | 0x00000002 | command ------------+--------+------------+--------------------------------------------------- - 4 | 4 | | seqnum: URB sequence number ------------+--------+------------+--------------------------------------------------- - 8 | 4 | | devid ------------+--------+------------+--------------------------------------------------- - 0xC | 4 | | direction: 0: USBIP_DIR_IN - | | | 1: USBIP_DIR_OUT ------------+--------+------------+--------------------------------------------------- - 0x10 | 4 | | ep: endpoint number ------------+--------+------------+--------------------------------------------------- - 0x14 | 4 | | status: zero for successful URB transaction, - | | | otherwise some kind of error happened. ------------+--------+------------+--------------------------------------------------- - 0x18 | 4 | n | actual_length: number of URB data bytes ------------+--------+------------+--------------------------------------------------- - 0x1C | 4 | | start_frame: for an ISO frame the actually - | | | selected frame for transmit. ------------+--------+------------+--------------------------------------------------- - 0x20 | 4 | | number_of_packets ------------+--------+------------+--------------------------------------------------- - 0x24 | 4 | | error_count ------------+--------+------------+--------------------------------------------------- - 0x28 | 8 | | setup: data bytes for USB setup, filled with - | | | zeros if not used ------------+--------+------------+--------------------------------------------------- - 0x30 | n | | URB data bytes. For ISO transfers the padding - | | | between each ISO packets is not transmitted. - -USBIP_CMD_UNLINK: Unlink an URB - - Offset | Length | Value | Description ------------+--------+------------+--------------------------------------------------- - 0 | 4 | 0x00000003 | command: URB unlink command ------------+--------+------------+--------------------------------------------------- - 4 | 4 | | seqnum: URB sequence number to unlink: FIXME: is this so? ------------+--------+------------+--------------------------------------------------- - 8 | 4 | | devid ------------+--------+------------+--------------------------------------------------- - 0xC | 4 | | direction: 0: USBIP_DIR_IN - | | | 1: USBIP_DIR_OUT ------------+--------+------------+--------------------------------------------------- - 0x10 | 4 | | ep: endpoint number: zero ------------+--------+------------+--------------------------------------------------- - 0x14 | 4 | | seqnum: the URB sequence number given previously - | | | at USBIP_CMD_SUBMIT.seqnum field ------------+--------+------------+--------------------------------------------------- - 0x30 | n | | URB data bytes. For ISO transfers the padding - | | | between each ISO packets is not transmitted. - -USBIP_RET_UNLINK: Reply for URB unlink - - Offset | Length | Value | Description ------------+--------+------------+--------------------------------------------------- - 0 | 4 | 0x00000004 | command: reply for the URB unlink command ------------+--------+------------+--------------------------------------------------- - 4 | 4 | | seqnum: the unlinked URB sequence number ------------+--------+------------+--------------------------------------------------- - 8 | 4 | | devid ------------+--------+------------+--------------------------------------------------- - 0xC | 4 | | direction: 0: USBIP_DIR_IN - | | | 1: USBIP_DIR_OUT ------------+--------+------------+--------------------------------------------------- - 0x10 | 4 | | ep: endpoint number ------------+--------+------------+--------------------------------------------------- - 0x14 | 4 | | status: This is the value contained in the - | | | urb->status in the URB completition handler. - | | | FIXME: a better explanation needed. ------------+--------+------------+--------------------------------------------------- - 0x30 | n | | URB data bytes. For ISO transfers the padding - | | | between each ISO packets is not transmitted. diff --git a/trunk/drivers/staging/usbip/userspace/libsrc/vhci_driver.c b/trunk/drivers/staging/usbip/userspace/libsrc/vhci_driver.c index 269787751b20..abbc285f4339 100644 --- a/trunk/drivers/staging/usbip/userspace/libsrc/vhci_driver.c +++ b/trunk/drivers/staging/usbip/userspace/libsrc/vhci_driver.c @@ -133,7 +133,7 @@ static int check_usbip_device(struct sysfs_class_device *cdev) strlen(vhci_driver->hc_device->path))) { /* found usbip device */ usbip_cdev = calloc(1, sizeof(*usbip_cdev)); - if (!usbip_cdev) { + if (!cdev) { dbg("calloc failed"); return -1; } diff --git a/trunk/drivers/staging/usbip/userspace/src/usbip_attach.c b/trunk/drivers/staging/usbip/userspace/src/usbip_attach.c index bdf61c0fe699..b7885a202757 100644 --- a/trunk/drivers/staging/usbip/userspace/src/usbip_attach.c +++ b/trunk/drivers/staging/usbip/userspace/src/usbip_attach.c @@ -51,9 +51,7 @@ static int record_connection(char *host, char *port, char *busid, int rhport) char buff[MAX_BUFF+1]; int ret; - ret = mkdir(VHCI_STATE_PATH, 0700); - if (ret < 0) - return -1; + mkdir(VHCI_STATE_PATH, 0700); snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport); diff --git a/trunk/drivers/staging/usbip/vhci.h b/trunk/drivers/staging/usbip/vhci.h index 88b32981cf1f..71a586e00fd7 100644 --- a/trunk/drivers/staging/usbip/vhci.h +++ b/trunk/drivers/staging/usbip/vhci.h @@ -8,9 +8,6 @@ * */ -#ifndef __USBIP_VHCI_H -#define __USBIP_VHCI_H - #include #include #include @@ -132,5 +129,3 @@ static inline struct device *vhci_dev(struct vhci_hcd *vhci) { return vhci_to_hcd(vhci)->self.controller; } - -#endif /* __USBIP_VHCI_H */ diff --git a/trunk/drivers/staging/vme/bridges/vme_ca91cx42.c b/trunk/drivers/staging/vme/bridges/vme_ca91cx42.c index 0e4feac138eb..5122c13a9563 100644 --- a/trunk/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/trunk/drivers/staging/vme/bridges/vme_ca91cx42.c @@ -1500,28 +1500,6 @@ static int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) } -void *ca91cx42_alloc_consistent(struct device *parent, size_t size, - dma_addr_t *dma) -{ - struct pci_dev *pdev; - - /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); - - return pci_alloc_consistent(pdev, size, dma); -} - -void ca91cx42_free_consistent(struct device *parent, size_t size, void *vaddr, - dma_addr_t dma) -{ - struct pci_dev *pdev; - - /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); - - pci_free_consistent(pdev, size, vaddr, dma); -} - static int __init ca91cx42_init(void) { return pci_register_driver(&ca91cx42_driver); @@ -1791,8 +1769,6 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; ca91cx42_bridge->slot_get = ca91cx42_slot_get; - ca91cx42_bridge->alloc_consistent = ca91cx42_alloc_consistent; - ca91cx42_bridge->free_consistent = ca91cx42_free_consistent; data = ioread32(ca91cx42_device->base + MISC_CTL); dev_info(&pdev->dev, "Board is%s the VME system controller\n", diff --git a/trunk/drivers/staging/vme/bridges/vme_tsi148.c b/trunk/drivers/staging/vme/bridges/vme_tsi148.c index 6c1167c2bea9..9c539513c74b 100644 --- a/trunk/drivers/staging/vme/bridges/vme_tsi148.c +++ b/trunk/drivers/staging/vme/bridges/vme_tsi148.c @@ -2114,28 +2114,6 @@ static int tsi148_slot_get(struct vme_bridge *tsi148_bridge) return (int)slot; } -void *tsi148_alloc_consistent(struct device *parent, size_t size, - dma_addr_t *dma) -{ - struct pci_dev *pdev; - - /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); - - return pci_alloc_consistent(pdev, size, dma); -} - -void tsi148_free_consistent(struct device *parent, size_t size, void *vaddr, - dma_addr_t dma) -{ - struct pci_dev *pdev; - - /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); - - pci_free_consistent(pdev, size, vaddr, dma); -} - static int __init tsi148_init(void) { return pci_register_driver(&tsi148_driver); @@ -2465,8 +2443,6 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) tsi148_bridge->lm_attach = tsi148_lm_attach; tsi148_bridge->lm_detach = tsi148_lm_detach; tsi148_bridge->slot_get = tsi148_slot_get; - tsi148_bridge->alloc_consistent = tsi148_alloc_consistent; - tsi148_bridge->free_consistent = tsi148_free_consistent; data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); dev_info(&pdev->dev, "Board is%s the VME system controller\n", diff --git a/trunk/drivers/staging/vme/devices/vme_user.c b/trunk/drivers/staging/vme/devices/vme_user.c index 3cbeb2ada418..91d2cc7bb4c3 100644 --- a/trunk/drivers/staging/vme/devices/vme_user.c +++ b/trunk/drivers/staging/vme/devices/vme_user.c @@ -651,7 +651,7 @@ static int __init vme_user_init(void) /* Dynamically create the bind table based on module parameters */ - ids = kzalloc(sizeof(struct vme_device_id) * (bus_num + 1), GFP_KERNEL); + ids = kmalloc(sizeof(struct vme_device_id) * (bus_num + 1), GFP_KERNEL); if (ids == NULL) { printk(KERN_ERR "%s: Unable to allocate ID table\n", driver_name); @@ -659,6 +659,8 @@ static int __init vme_user_init(void) goto err_id; } + memset(ids, 0, (sizeof(struct vme_device_id) * (bus_num + 1))); + for (i = 0; i < bus_num; i++) { ids[i].bus = bus[i]; /* diff --git a/trunk/drivers/staging/vme/vme.c b/trunk/drivers/staging/vme/vme.c index b2968f8588ff..c078ce369df9 100644 --- a/trunk/drivers/staging/vme/vme.c +++ b/trunk/drivers/staging/vme/vme.c @@ -34,10 +34,9 @@ #include "vme.h" #include "vme_bridge.h" -/* Bitmask and list of registered buses both protected by common mutex */ +/* Bitmask and mutex to keep track of bridge numbers */ static unsigned int vme_bus_numbers; -static LIST_HEAD(vme_bus_list); -static DEFINE_MUTEX(vme_buses_lock); +static DEFINE_MUTEX(vme_bus_num_mtx); static void __exit vme_exit(void); static int __init vme_init(void); @@ -84,11 +83,15 @@ static struct vme_bridge *find_bridge(struct vme_resource *resource) /* * Allocate a contiguous block of memory for use by the driver. This is used to * create the buffers for the slave windows. + * + * XXX VME bridges could be available on buses other than PCI. At the momment + * this framework only supports PCI devices. */ void *vme_alloc_consistent(struct vme_resource *resource, size_t size, dma_addr_t *dma) { struct vme_bridge *bridge; + struct pci_dev *pdev; if (resource == NULL) { printk(KERN_ERR "No resource\n"); @@ -101,29 +104,28 @@ void *vme_alloc_consistent(struct vme_resource *resource, size_t size, return NULL; } + /* Find pci_dev container of dev */ if (bridge->parent == NULL) { - printk(KERN_ERR "Dev entry NULL for" - " bridge %s\n", bridge->name); - return NULL; - } - - if (bridge->alloc_consistent == NULL) { - printk(KERN_ERR "alloc_consistent not supported by" - " bridge %s\n", bridge->name); + printk(KERN_ERR "Dev entry NULL\n"); return NULL; } + pdev = container_of(bridge->parent, struct pci_dev, dev); - return bridge->alloc_consistent(bridge->parent, size, dma); + return pci_alloc_consistent(pdev, size, dma); } EXPORT_SYMBOL(vme_alloc_consistent); /* * Free previously allocated contiguous block of memory. + * + * XXX VME bridges could be available on buses other than PCI. At the momment + * this framework only supports PCI devices. */ void vme_free_consistent(struct vme_resource *resource, size_t size, void *vaddr, dma_addr_t dma) { struct vme_bridge *bridge; + struct pci_dev *pdev; if (resource == NULL) { printk(KERN_ERR "No resource\n"); @@ -136,19 +138,10 @@ void vme_free_consistent(struct vme_resource *resource, size_t size, return; } - if (bridge->parent == NULL) { - printk(KERN_ERR "Dev entry NULL for" - " bridge %s\n", bridge->name); - return; - } - - if (bridge->free_consistent == NULL) { - printk(KERN_ERR "free_consistent not supported by" - " bridge %s\n", bridge->name); - return; - } + /* Find pci_dev container of dev */ + pdev = container_of(bridge->parent, struct pci_dev, dev); - bridge->free_consistent(bridge->parent, size, vaddr, dma); + pci_free_consistent(pdev, size, vaddr, dma); } EXPORT_SYMBOL(vme_free_consistent); @@ -1310,32 +1303,27 @@ EXPORT_SYMBOL(vme_slot_get); /* - Bridge Registration --------------------------------------------------- */ -static int vme_add_bus(struct vme_bridge *bridge) +static int vme_alloc_bus_num(void) { int i; - int ret = -1; - mutex_lock(&vme_buses_lock); + mutex_lock(&vme_bus_num_mtx); for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) { - if ((vme_bus_numbers & (1 << i)) == 0) { - vme_bus_numbers |= (1 << i); - bridge->num = i; - list_add_tail(&bridge->bus_list, &vme_bus_list); - ret = 0; + if (((vme_bus_numbers >> i) & 0x1) == 0) { + vme_bus_numbers |= (0x1 << i); break; } } - mutex_unlock(&vme_buses_lock); + mutex_unlock(&vme_bus_num_mtx); - return ret; + return i; } -static void vme_remove_bus(struct vme_bridge *bridge) +static void vme_free_bus_num(int bus) { - mutex_lock(&vme_buses_lock); - vme_bus_numbers &= ~(1 << bridge->num); - list_del(&bridge->bus_list); - mutex_unlock(&vme_buses_lock); + mutex_lock(&vme_bus_num_mtx); + vme_bus_numbers &= ~(0x1 << bus); + mutex_unlock(&vme_bus_num_mtx); } int vme_register_bridge(struct vme_bridge *bridge) @@ -1344,9 +1332,7 @@ int vme_register_bridge(struct vme_bridge *bridge) int retval; int i; - retval = vme_add_bus(bridge); - if (retval) - return retval; + bridge->num = vme_alloc_bus_num(); /* This creates 32 vme "slot" devices. This equates to a slot for each * ID available in a system conforming to the ANSI/VITA 1-1994 @@ -1378,7 +1364,7 @@ int vme_register_bridge(struct vme_bridge *bridge) dev = &bridge->dev[i]; device_unregister(dev); } - vme_remove_bus(bridge); + vme_free_bus_num(bridge->num); return retval; } EXPORT_SYMBOL(vme_register_bridge); @@ -1393,7 +1379,7 @@ void vme_unregister_bridge(struct vme_bridge *bridge) dev = &bridge->dev[i]; device_unregister(dev); } - vme_remove_bus(bridge); + vme_free_bus_num(bridge->num); } EXPORT_SYMBOL(vme_unregister_bridge); diff --git a/trunk/drivers/staging/vme/vme_bridge.h b/trunk/drivers/staging/vme/vme_bridge.h index 895967058297..4c6ec31b01db 100644 --- a/trunk/drivers/staging/vme/vme_bridge.h +++ b/trunk/drivers/staging/vme/vme_bridge.h @@ -98,6 +98,8 @@ struct vme_irq { /* This structure stores all the information about one bridge * The structure should be dynamically allocated by the driver and one instance * of the structure should be present for each VME chip present in the system. + * + * Currently we assume that all chips are PCI-based */ struct vme_bridge { char name[VMENAMSIZ]; @@ -110,9 +112,8 @@ struct vme_bridge { struct list_head vme_errors; /* List for errors generated on VME */ /* Bridge Info - XXX Move to private structure? */ - struct device *parent; /* Parent device (eg. pdev->dev for PCI) */ + struct device *parent; /* Generic device struct (pdev->dev for PCI) */ void *driver_priv; /* Private pointer for the bridge driver */ - struct list_head bus_list; /* list of VME buses */ struct device dev[VME_SLOTS_MAX]; /* Device registered with * device model on VME bus @@ -164,12 +165,6 @@ struct vme_bridge { /* CR/CSR space functions */ int (*slot_get) (struct vme_bridge *); - - /* Bridge parent interface */ - void *(*alloc_consistent)(struct device *dev, size_t size, - dma_addr_t *dma); - void (*free_consistent)(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma); }; void vme_irq_handler(struct vme_bridge *, int, int); diff --git a/trunk/drivers/staging/vt6655/IEEE11h.c b/trunk/drivers/staging/vt6655/IEEE11h.c index cf7364d65263..e07ebd578d44 100644 --- a/trunk/drivers/staging/vt6655/IEEE11h.c +++ b/trunk/drivers/staging/vt6655/IEEE11h.c @@ -41,52 +41,52 @@ #include "channel.h" /*--------------------- Static Definitions -------------------------*/ -static int msglevel = MSG_LEVEL_INFO; +static int msglevel =MSG_LEVEL_INFO; #pragma pack(1) typedef struct _WLAN_FRAME_ACTION { - WLAN_80211HDR_A3 Header; - unsigned char byCategory; - unsigned char byAction; - unsigned char abyVars[1]; + WLAN_80211HDR_A3 Header; + unsigned char byCategory; + unsigned char byAction; + unsigned char abyVars[1]; } WLAN_FRAME_ACTION, *PWLAN_FRAME_ACTION; typedef struct _WLAN_FRAME_MSRREQ { - WLAN_80211HDR_A3 Header; - unsigned char byCategory; - unsigned char byAction; - unsigned char byDialogToken; - WLAN_IE_MEASURE_REQ sMSRReqEIDs[1]; + WLAN_80211HDR_A3 Header; + unsigned char byCategory; + unsigned char byAction; + unsigned char byDialogToken; + WLAN_IE_MEASURE_REQ sMSRReqEIDs[1]; } WLAN_FRAME_MSRREQ, *PWLAN_FRAME_MSRREQ; typedef struct _WLAN_FRAME_MSRREP { - WLAN_80211HDR_A3 Header; - unsigned char byCategory; - unsigned char byAction; - unsigned char byDialogToken; - WLAN_IE_MEASURE_REP sMSRRepEIDs[1]; + WLAN_80211HDR_A3 Header; + unsigned char byCategory; + unsigned char byAction; + unsigned char byDialogToken; + WLAN_IE_MEASURE_REP sMSRRepEIDs[1]; } WLAN_FRAME_MSRREP, *PWLAN_FRAME_MSRREP; typedef struct _WLAN_FRAME_TPCREQ { - WLAN_80211HDR_A3 Header; - unsigned char byCategory; - unsigned char byAction; - unsigned char byDialogToken; - WLAN_IE_TPC_REQ sTPCReqEIDs; + WLAN_80211HDR_A3 Header; + unsigned char byCategory; + unsigned char byAction; + unsigned char byDialogToken; + WLAN_IE_TPC_REQ sTPCReqEIDs; } WLAN_FRAME_TPCREQ, *PWLAN_FRAME_TPCREQ; typedef struct _WLAN_FRAME_TPCREP { - WLAN_80211HDR_A3 Header; - unsigned char byCategory; - unsigned char byAction; - unsigned char byDialogToken; - WLAN_IE_TPC_REP sTPCRepEIDs; + WLAN_80211HDR_A3 Header; + unsigned char byCategory; + unsigned char byAction; + unsigned char byDialogToken; + WLAN_IE_TPC_REP sTPCRepEIDs; } WLAN_FRAME_TPCREP, *PWLAN_FRAME_TPCREP; #pragma pack() -/* action field reference ieee 802.11h Table 20e */ +// action field reference ieee 802.11h Table 20e #define ACTION_MSRREQ 0 #define ACTION_MSRREP 1 #define ACTION_TPCREQ 2 @@ -101,100 +101,84 @@ typedef struct _WLAN_FRAME_TPCREP { static bool s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq, unsigned int uLength) { - size_t uNumOfEIDs = 0; - bool bResult = true; - - if (uLength <= WLAN_A3FR_MAXLEN) - memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength); - uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ, - sMSRReqEIDs))/ - (sizeof(WLAN_IE_MEASURE_REQ))); - pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP) - (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]); - pMgmt->uLengthOfRepEIDs = 0; - bResult = CARDbStartMeasure(pMgmt->pAdapter, - ((PWLAN_FRAME_MSRREQ) - (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs, - uNumOfEIDs - ); - return bResult; + size_t uNumOfEIDs = 0; + bool bResult = true; + + if (uLength <= WLAN_A3FR_MAXLEN) { + memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength); + } + uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ, sMSRReqEIDs))/ (sizeof(WLAN_IE_MEASURE_REQ))); + pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]); + pMgmt->uLengthOfRepEIDs = 0; + bResult = CARDbStartMeasure(pMgmt->pAdapter, + ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs, + uNumOfEIDs + ); + return (bResult); } -static bool s_bRxTPCReq(PSMgmtObject pMgmt, - PWLAN_FRAME_TPCREQ pTPCReq, - unsigned char byRate, - unsigned char byRSSI) +static bool s_bRxTPCReq(PSMgmtObject pMgmt, PWLAN_FRAME_TPCREQ pTPCReq, unsigned char byRate, unsigned char byRSSI) { - PWLAN_FRAME_TPCREP pFrame; - PSTxMgmtPacket pTxPacket = NULL; - - pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; - memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + -sizeof(STxMgmtPacket)); - - pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket + -sizeof(STxMgmtPacket)); - - pFrame->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | - WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION) - ); - - memcpy(pFrame->Header.abyAddr1, - pTPCReq->Header.abyAddr2, - WLAN_ADDR_LEN); - memcpy(pFrame->Header.abyAddr2, - CARDpGetCurrentAddress(pMgmt->pAdapter), - WLAN_ADDR_LEN); - memcpy(pFrame->Header.abyAddr3, - pMgmt->abyCurrBSSID, - WLAN_BSSID_LEN); - - pFrame->byCategory = 0; - pFrame->byAction = 3; - pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ) -(pMgmt->abyCurrentMSRReq))->byDialogToken; - - pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP; - pFrame->sTPCRepEIDs.len = 2; - pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter); - switch (byRate) { - case RATE_54M: - pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI; - break; - case RATE_48M: - pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI; - break; - case RATE_36M: - pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI; - break; - case RATE_24M: - pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI; - break; - case RATE_18M: - pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI; - break; - case RATE_12M: - pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI; - break; - case RATE_9M: - pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI; - break; - case RATE_6M: - default: - pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI; - break; -} - - pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP); - pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) - -WLAN_HDR_ADDR3_LEN; - if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING) - return false; - return true; -/* return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG, -sizeof(WLAN_FRAME_TPCREP))); */ + PWLAN_FRAME_TPCREP pFrame; + PSTxMgmtPacket pTxPacket = NULL; + + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); + + pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); + + pFrame->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION) + ); + + memcpy( pFrame->Header.abyAddr1, pTPCReq->Header.abyAddr2, WLAN_ADDR_LEN); + memcpy( pFrame->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN); + memcpy( pFrame->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + pFrame->byCategory = 0; + pFrame->byAction = 3; + pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken; + + pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP; + pFrame->sTPCRepEIDs.len = 2; + pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter); + switch (byRate) { + case RATE_54M: + pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI; + break; + case RATE_48M: + pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI; + break; + case RATE_36M: + pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI; + break; + case RATE_24M: + pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI; + break; + case RATE_18M: + pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI; + break; + case RATE_12M: + pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI; + break; + case RATE_9M: + pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI; + break; + case RATE_6M: + default: + pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI; + break; + } + + pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP); + pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) - WLAN_HDR_ADDR3_LEN; + if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING) + return (false); + return (true); +// return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG, sizeof(WLAN_FRAME_TPCREP))); } @@ -220,110 +204,102 @@ sizeof(WLAN_FRAME_TPCREP))); */ * -*/ bool -IEEE11hbMgrRxAction(void *pMgmtHandle, void *pRxPacket) +IEEE11hbMgrRxAction ( + void *pMgmtHandle, + void *pRxPacket + ) { - PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; - PWLAN_FRAME_ACTION pAction = NULL; - unsigned int uLength = 0; - PWLAN_IE_CH_SW pChannelSwitch = NULL; - - /* decode the frame */ - uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen; - if (uLength > WLAN_A3FR_MAXLEN) - return false; - - pAction = (PWLAN_FRAME_ACTION) -(((PSRxMgmtPacket)pRxPacket)->p80211Header); - - if (pAction->byCategory == 0) { - switch (pAction->byAction) { - case ACTION_MSRREQ: - return s_bRxMSRReq(pMgmt, - (PWLAN_FRAME_MSRREQ) - pAction, - uLength); - break; - case ACTION_MSRREP: - break; - case ACTION_TPCREQ: - return s_bRxTPCReq(pMgmt, - (PWLAN_FRAME_TPCREQ) pAction, - ((PSRxMgmtPacket)pRxPacket)->byRxRate, - (unsigned char) - ((PSRxMgmtPacket)pRxPacket)->uRSSI); - break; - case ACTION_TPCREP: - break; - case ACTION_CHSW: - pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars); - if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH) - && (pChannelSwitch->len == 3)) { - /* valid element id */ - CARDbChannelSwitch(pMgmt->pAdapter, - pChannelSwitch->byMode, - get_channel_mapping(pMgmt->pAdapter, - pChannelSwitch->byChannel, - pMgmt->eCurrentPHYMode), - pChannelSwitch->byCount); - } - break; - default: - DBG_PRT(MSG_LEVEL_DEBUG, - KERN_INFO"Unknown Action = %d\n", - pAction->byAction); - break; - } - } else { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n", -pAction->byCategory); - pAction->byCategory |= 0x80; - - /*return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG, -uLength));*/ - return true; - } - return true; + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; + PWLAN_FRAME_ACTION pAction = NULL; + unsigned int uLength = 0; + PWLAN_IE_CH_SW pChannelSwitch = NULL; + + + // decode the frame + uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen; + if (uLength > WLAN_A3FR_MAXLEN) { + return (false); + } + + + pAction = (PWLAN_FRAME_ACTION) (((PSRxMgmtPacket)pRxPacket)->p80211Header); + + if (pAction->byCategory == 0) { + switch (pAction->byAction) { + case ACTION_MSRREQ: + return (s_bRxMSRReq(pMgmt, (PWLAN_FRAME_MSRREQ) pAction, uLength)); + break; + case ACTION_MSRREP: + break; + case ACTION_TPCREQ: + return (s_bRxTPCReq(pMgmt, + (PWLAN_FRAME_TPCREQ) pAction, + ((PSRxMgmtPacket)pRxPacket)->byRxRate, + (unsigned char) ((PSRxMgmtPacket)pRxPacket)->uRSSI)); + break; + case ACTION_TPCREP: + break; + case ACTION_CHSW: + pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars); + if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH) && + (pChannelSwitch->len == 3)) { + // valid element id + CARDbChannelSwitch( pMgmt->pAdapter, + pChannelSwitch->byMode, + get_channel_mapping(pMgmt->pAdapter, pChannelSwitch->byChannel, pMgmt->eCurrentPHYMode), + pChannelSwitch->byCount + ); + } + break; + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Action = %d\n", pAction->byAction); + break; + } + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n", pAction->byCategory); + pAction->byCategory |= 0x80; + + //return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG, uLength)); + return (true); + } + return (true); } -bool IEEE11hbMSRRepTx(void *pMgmtHandle) +bool IEEE11hbMSRRepTx ( + void *pMgmtHandle + ) { - PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; - PWLAN_FRAME_MSRREP pMSRRep = (PWLAN_FRAME_MSRREP) -(pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket)); - size_t uLength = 0; - PSTxMgmtPacket pTxPacket = NULL; - - pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep; - memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); - pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + -sizeof(STxMgmtPacket)); - - pMSRRep->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | - WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION) - ); - - memcpy(pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ) - (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN); - memcpy(pMSRRep->Header.abyAddr2, - CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN); - memcpy(pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); - - pMSRRep->byCategory = 0; - pMSRRep->byAction = 1; - pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ) - (pMgmt->abyCurrentMSRReq))->byDialogToken; - - uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP, - sMSRRepEIDs); - - pTxPacket->cbMPDULen = uLength; - pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN; - if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING) - return false; - return true; -/* return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG, -uLength)); */ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; + PWLAN_FRAME_MSRREP pMSRRep = (PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket)); + size_t uLength = 0; + PSTxMgmtPacket pTxPacket = NULL; + + pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket)); + + + pMSRRep->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION) + ); + + memcpy( pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN); + memcpy( pMSRRep->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN); + memcpy( pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + pMSRRep->byCategory = 0; + pMSRRep->byAction = 1; + pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken; + + uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP, sMSRRepEIDs); + + pTxPacket->cbMPDULen = uLength; + pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN; + if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING) + return (false); + return (true); +// return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG, uLength)); } diff --git a/trunk/drivers/staging/vt6655/device_main.c b/trunk/drivers/staging/vt6655/device_main.c index 567df434318a..3d2a9ba16b15 100644 --- a/trunk/drivers/staging/vt6655/device_main.c +++ b/trunk/drivers/staging/vt6655/device_main.c @@ -815,8 +815,14 @@ else CARDbRadioPowerOn(pDevice); pMgmt->eScanType = WMAC_SCAN_PASSIVE; // get Permanent network address SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n", - pDevice->abyCurrentNetAddr); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %02x-%02x-%02x=%02x-%02x-%02x\n", + pDevice->abyCurrentNetAddr[0], + pDevice->abyCurrentNetAddr[1], + pDevice->abyCurrentNetAddr[2], + pDevice->abyCurrentNetAddr[3], + pDevice->abyCurrentNetAddr[4], + pDevice->abyCurrentNetAddr[5]); + // reset Tx pointer CARDvSafeResetRx(pDevice); diff --git a/trunk/drivers/staging/vt6655/dpc.c b/trunk/drivers/staging/vt6655/dpc.c index c0fab4bc8702..cf0deacd9da7 100644 --- a/trunk/drivers/staging/vt6655/dpc.c +++ b/trunk/drivers/staging/vt6655/dpc.c @@ -1107,12 +1107,30 @@ static bool s_bAPModeRxCtl ( &Status ); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n", - p802_11Header->abyAddr3); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n", - p802_11Header->abyAddr2); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n", - p802_11Header->abyAddr1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%02x-%02x-%02x=%02x-%02x-%02x \n", + p802_11Header->abyAddr3[0], + p802_11Header->abyAddr3[1], + p802_11Header->abyAddr3[2], + p802_11Header->abyAddr3[3], + p802_11Header->abyAddr3[4], + p802_11Header->abyAddr3[5] + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%02x-%02x-%02x=%02x-%02x-%02x \n", + p802_11Header->abyAddr2[0], + p802_11Header->abyAddr2[1], + p802_11Header->abyAddr2[2], + p802_11Header->abyAddr2[3], + p802_11Header->abyAddr2[4], + p802_11Header->abyAddr2[5] + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%02x-%02x-%02x=%02x-%02x-%02x \n", + p802_11Header->abyAddr1[0], + p802_11Header->abyAddr1[1], + p802_11Header->abyAddr1[2], + p802_11Header->abyAddr1[3], + p802_11Header->abyAddr1[4], + p802_11Header->abyAddr1[5] + ); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: wFrameCtl= %x\n", p802_11Header->wFrameCtl ); VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode)); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc:pDevice->byRxMode = %x\n", pDevice->byRxMode ); diff --git a/trunk/drivers/staging/vt6655/wmgr.c b/trunk/drivers/staging/vt6655/wmgr.c index c46d51908ac0..ab289c30edb4 100644 --- a/trunk/drivers/staging/vt6655/wmgr.c +++ b/trunk/drivers/staging/vt6655/wmgr.c @@ -2521,8 +2521,14 @@ vMgrCreateOwnIBSS( if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { // AP mode BSSID = MAC addr memcpy(pMgmt->abyCurrBSSID, pMgmt->abyMACAddr, WLAN_ADDR_LEN); - DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:%pM\n", - pMgmt->abyCurrBSSID); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:%02x-%02x-%02x-%02x-%02x-%02x \n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5] + ); } if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { @@ -2544,8 +2550,14 @@ vMgrCreateOwnIBSS( pMgmt->abyCurrBSSID[0] |= IEEE_ADDR_UNIVERSAL; - DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:%pM\n", - pMgmt->abyCurrBSSID); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:%02x-%02x-%02x-%02x-%02x-%02x \n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5] + ); } // Set Capability Info @@ -2875,8 +2887,14 @@ vMgrJoinBSSBegin( // pDevice->bLinkPass = true; // memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%pM\n", - pMgmt->abyCurrBSSID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%02x-%02x-%02x-%02x-%02x-%02x \n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5] + ); // Preamble type auto-switch: if AP can receive short-preamble cap, // and if registry setting is short preamble we can turn on too. @@ -2966,8 +2984,13 @@ s_vMgrSynchBSS ( MACvReadBSSIDAddress(pDevice->PortOffset, pMgmt->abyCurrBSSID); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = " - "%pM\n", pMgmt->abyCurrBSSID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = %02x-%02x-%02x=%02x-%02x-%02x\n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5]); if (pCurr->eNetworkTypeInUse == PHY_TYPE_11A) { if ((pMgmt->eConfigPHYMode == PHY_TYPE_11A) || @@ -4439,8 +4462,14 @@ s_vMgrRxProbeRequest( sFrame.pBuf = (unsigned char *)pRxPacket->p80211Header; vMgrDecodeProbeRequest(&sFrame); /* - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%pM\n", - sFrame.pHdr->sA3.abyAddr2); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%02x-%02x-%02x=%02x-%02x-%02x \n", + sFrame.pHdr->sA3.abyAddr2[0], + sFrame.pHdr->sA3.abyAddr2[1], + sFrame.pHdr->sA3.abyAddr2[2], + sFrame.pHdr->sA3.abyAddr2[3], + sFrame.pHdr->sA3.abyAddr2[4], + sFrame.pHdr->sA3.abyAddr2[5] + ); */ if (sFrame.pSSID->len != 0) { if (sFrame.pSSID->len != ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) diff --git a/trunk/drivers/staging/vt6656/dpc.c b/trunk/drivers/staging/vt6656/dpc.c index c0edf97535dc..cb817ced5184 100644 --- a/trunk/drivers/staging/vt6656/dpc.c +++ b/trunk/drivers/staging/vt6656/dpc.c @@ -1109,12 +1109,30 @@ static BOOL s_bAPModeRxCtl ( &Status ); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n", - p802_11Header->abyAddr3); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n", - p802_11Header->abyAddr2); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n", - p802_11Header->abyAddr1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%02x-%02x-%02x=%02x-%02x-%02x \n", + p802_11Header->abyAddr3[0], + p802_11Header->abyAddr3[1], + p802_11Header->abyAddr3[2], + p802_11Header->abyAddr3[3], + p802_11Header->abyAddr3[4], + p802_11Header->abyAddr3[5] + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%02x-%02x-%02x=%02x-%02x-%02x \n", + p802_11Header->abyAddr2[0], + p802_11Header->abyAddr2[1], + p802_11Header->abyAddr2[2], + p802_11Header->abyAddr2[3], + p802_11Header->abyAddr2[4], + p802_11Header->abyAddr2[5] + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%02x-%02x-%02x=%02x-%02x-%02x \n", + p802_11Header->abyAddr1[0], + p802_11Header->abyAddr1[1], + p802_11Header->abyAddr1[2], + p802_11Header->abyAddr1[3], + p802_11Header->abyAddr1[4], + p802_11Header->abyAddr1[5] + ); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: wFrameCtl= %x\n", p802_11Header->wFrameCtl ); return TRUE; } diff --git a/trunk/drivers/staging/vt6656/main_usb.c b/trunk/drivers/staging/vt6656/main_usb.c index 73a083819100..e18efd43e3e0 100644 --- a/trunk/drivers/staging/vt6656/main_usb.c +++ b/trunk/drivers/staging/vt6656/main_usb.c @@ -611,10 +611,17 @@ static BOOL device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) // if exist SW network address, use SW network address. - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n", - pDevice->abyCurrentNetAddr); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %02x-%02x-%02x=%02x-%02x-%02x\n", + pDevice->abyCurrentNetAddr[0], + pDevice->abyCurrentNetAddr[1], + pDevice->abyCurrentNetAddr[2], + pDevice->abyCurrentNetAddr[3], + pDevice->abyCurrentNetAddr[4], + pDevice->abyCurrentNetAddr[5]); } + + // Set BB and packet type at the same time. // Set Short Slot Time, xIFS, and RSPINF. if (pDevice->byBBType == BB_TYPE_11A) { diff --git a/trunk/drivers/staging/vt6656/wmgr.c b/trunk/drivers/staging/vt6656/wmgr.c index f08e2d15c7b3..d67748f90b14 100644 --- a/trunk/drivers/staging/vt6656/wmgr.c +++ b/trunk/drivers/staging/vt6656/wmgr.c @@ -2477,8 +2477,14 @@ void vMgrCreateOwnIBSS(void *hDeviceContext, if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { // AP mode BSSID = MAC addr memcpy(pMgmt->abyCurrBSSID, pMgmt->abyMACAddr, WLAN_ADDR_LEN); - DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:" - "%pM\n", pMgmt->abyCurrBSSID); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:%02x-%02x-%02x-%02x-%02x-%02x \n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5] + ); } if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { @@ -2500,8 +2506,14 @@ void vMgrCreateOwnIBSS(void *hDeviceContext, pMgmt->abyCurrBSSID[0] |= IEEE_ADDR_UNIVERSAL; - DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:" - "%pM\n", pMgmt->abyCurrBSSID); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:%02x-%02x-%02x-%02x-%02x-%02x \n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5] + ); } // set BSSID filter @@ -2866,8 +2878,14 @@ void vMgrJoinBSSBegin(void *hDeviceContext, PCMD_STATUS pStatus) ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%pM\n", - pMgmt->abyCurrBSSID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%02x-%02x-%02x-%02x-%02x-%02x \n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5] + ); // Preamble type auto-switch: if AP can receive short-preamble cap, // and if registry setting is short preamble we can turn on too. @@ -2965,8 +2983,13 @@ s_vMgrSynchBSS ( memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, 6); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = " - "%pM\n", pMgmt->abyCurrBSSID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = %02x-%02x-%02x=%02x-%02x-%02x\n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5]); if (pCurr->eNetworkTypeInUse == PHY_TYPE_11A) { if ((pDevice->eConfigPHYMode == PHY_TYPE_11A) || @@ -4311,8 +4334,14 @@ s_vMgrRxProbeRequest( sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; vMgrDecodeProbeRequest(&sFrame); /* - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%pM\n", - sFrame.pHdr->sA3.abyAddr2); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%02x-%02x-%02x=%02x-%02x-%02x \n", + sFrame.pHdr->sA3.abyAddr2[0], + sFrame.pHdr->sA3.abyAddr2[1], + sFrame.pHdr->sA3.abyAddr2[2], + sFrame.pHdr->sA3.abyAddr2[3], + sFrame.pHdr->sA3.abyAddr2[4], + sFrame.pHdr->sA3.abyAddr2[5] + ); */ if (sFrame.pSSID->len != 0) { if (sFrame.pSSID->len != ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) diff --git a/trunk/drivers/staging/winbond/phy_calibration.c b/trunk/drivers/staging/winbond/phy_calibration.c index 77a3fff708c6..c5a07fbe10ae 100644 --- a/trunk/drivers/staging/winbond/phy_calibration.c +++ b/trunk/drivers/staging/winbond/phy_calibration.c @@ -24,7 +24,7 @@ #define AG_CONST 0.6072529350 #define FIXED(X) ((s32)((X) * 32768.0)) -#define DEG2RAD(X) (0.017453 * (X)) +#define DEG2RAD(X) 0.017453 * (X) static const s32 Angles[] = { FIXED(DEG2RAD(45.0)), FIXED(DEG2RAD(26.565)), FIXED(DEG2RAD(14.0362)), @@ -51,7 +51,7 @@ s32 _s13_to_s32(u32 data) if ((data & BIT(12)) != 0) val |= 0xFFFFF000; - return (s32) val; + return ((s32) val); } u32 _s32_to_s13(s32 data) @@ -184,7 +184,7 @@ s32 _floor(s32 n) else n -= 5; - return n/10; + return (n/10); } /****************************************************************************/ @@ -455,7 +455,7 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6); /* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */ phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A); - /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ + /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C); /* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */ phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); @@ -577,7 +577,7 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6); /* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */ phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A); - /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ + /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C); /* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */ phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); @@ -974,7 +974,7 @@ void _tx_iq_calibration_winbond(struct hw_data *phw_data) phy_set_rf_data(phw_data, 11, (11<<24)|0x19BDD6); /* 20060612.1.a 0x1905D6); */ /* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */ phy_set_rf_data(phw_data, 5, (5<<24)|0x24C60A); /* 0x24C60A (high temperature) */ - /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ + /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ phy_set_rf_data(phw_data, 6, (6<<24)|0x34880C); /* 20060612.1.a 0x06890C); */ /* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */ phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); diff --git a/trunk/drivers/staging/xgifb/XGI_main.h b/trunk/drivers/staging/xgifb/XGI_main.h index 59f741136cfc..f6cd22d79630 100644 --- a/trunk/drivers/staging/xgifb/XGI_main.h +++ b/trunk/drivers/staging/xgifb/XGI_main.h @@ -11,6 +11,12 @@ #define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while (0) +#define VER_MAJOR 0 +#define VER_MINOR 8 +#define VER_LEVEL 1 + +#define DRIVER_DESC "XGI Volari Frame Buffer Module Version 0.8.1" + #ifndef PCI_VENDOR_ID_XG #define PCI_VENDOR_ID_XG 0x18CA #endif @@ -31,6 +37,12 @@ #define PCI_DEVICE_ID_XG_27 0x027 #endif + + +#define XGI_IOTYPE1 void __iomem +#define XGI_IOTYPE2 __iomem +#define XGIINITSTATIC static + static DEFINE_PCI_DEVICE_TABLE(xgifb_pci_table) = { {PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, @@ -46,11 +58,31 @@ static DEFINE_PCI_DEVICE_TABLE(xgifb_pci_table) = { MODULE_DEVICE_TABLE(pci, xgifb_pci_table); /* To be included in fb.h */ +#ifndef FB_ACCEL_XGI_GLAMOUR_2 +#define FB_ACCEL_XGI_GLAMOUR_2 40 /* XGI 315, 650, 740 */ +#endif #ifndef FB_ACCEL_XGI_XABRE #define FB_ACCEL_XGI_XABRE 41 /* XGI 330 ("Xabre") */ #endif +#define MAX_ROM_SCAN 0x10000 + +#define SEQ_ADR 0x14 #define SEQ_DATA 0x15 +#define DAC_ADR 0x18 +#define DAC_DATA 0x19 +#define CRTC_ADR 0x24 +#define CRTC_DATA 0x25 +#define DAC2_ADR (0x16-0x30) +#define DAC2_DATA (0x17-0x30) +#define VB_PART1_ADR (0x04-0x30) +#define VB_PART1_DATA (0x05-0x30) +#define VB_PART2_ADR (0x10-0x30) +#define VB_PART2_DATA (0x11-0x30) +#define VB_PART3_ADR (0x12-0x30) +#define VB_PART3_DATA (0x13-0x30) +#define VB_PART4_ADR (0x14-0x30) +#define VB_PART4_DATA (0x15-0x30) #define XGISR XGI_Pr.P3c4 #define XGICR XGI_Pr.P3d4 @@ -63,12 +95,24 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table); #define XGIPART5 XGI_Pr.Part5Port #define XGIDAC2A XGIPART5 #define XGIDAC2D (XGIPART5 + 1) +#define XGIMISCR (XGI_Pr.RelIO + 0x1c) +#define XGIINPSTAT (XGI_Pr.RelIO + 0x2a) #define IND_XGI_PASSWORD 0x05 /* SRs */ +#define IND_XGI_COLOR_MODE 0x06 #define IND_XGI_RAMDAC_CONTROL 0x07 #define IND_XGI_DRAM_SIZE 0x14 +#define IND_XGI_SCRATCH_REG_16 0x16 +#define IND_XGI_SCRATCH_REG_17 0x17 +#define IND_XGI_SCRATCH_REG_1A 0x1A #define IND_XGI_MODULE_ENABLE 0x1E #define IND_XGI_PCI_ADDRESS_SET 0x20 +#define IND_XGI_TURBOQUEUE_ADR 0x26 +#define IND_XGI_TURBOQUEUE_SET 0x27 +#define IND_XGI_POWER_ON_TRAP 0x38 +#define IND_XGI_POWER_ON_TRAP2 0x39 +#define IND_XGI_CMDQUEUE_SET 0x26 +#define IND_XGI_CMDQUEUE_THRESHOLD 0x27 #define IND_XGI_SCRATCH_REG_CR30 0x30 /* CRs */ #define IND_XGI_SCRATCH_REG_CR31 0x31 @@ -76,10 +120,23 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table); #define IND_XGI_SCRATCH_REG_CR33 0x33 #define IND_XGI_LCD_PANEL 0x36 #define IND_XGI_SCRATCH_REG_CR37 0x37 +#define IND_XGI_AGP_IO_PAD 0x48 + +#define IND_BRI_DRAM_STATUS 0x63 /* PCI config memory size offset */ +#define MMIO_QUEUE_PHYBASE 0x85C0 +#define MMIO_QUEUE_WRITEPORT 0x85C4 +#define MMIO_QUEUE_READPORT 0x85C8 + +#define IND_XGI_CRT2_WRITE_ENABLE_300 0x24 #define IND_XGI_CRT2_WRITE_ENABLE_315 0x2F #define XGI_PASSWORD 0x86 /* SR05 */ +#define XGI_INTERLACED_MODE 0x20 /* SR06 */ +#define XGI_8BPP_COLOR_MODE 0x0 +#define XGI_15BPP_COLOR_MODE 0x1 +#define XGI_16BPP_COLOR_MODE 0x2 +#define XGI_32BPP_COLOR_MODE 0x4 #define XGI_DRAM_SIZE_MASK 0xF0 /*SR14 */ #define XGI_DRAM_SIZE_1MB 0x00 @@ -91,6 +148,27 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table); #define XGI_DRAM_SIZE_64MB 0x06 #define XGI_DRAM_SIZE_128MB 0x07 #define XGI_DRAM_SIZE_256MB 0x08 +#define XGI_DATA_BUS_MASK 0x02 +#define XGI_DATA_BUS_64 0x00 +#define XGI_DATA_BUS_128 0x01 +#define XGI_DUAL_CHANNEL_MASK 0x0C +#define XGI_SINGLE_CHANNEL_1_RANK 0x0 +#define XGI_SINGLE_CHANNEL_2_RANK 0x1 +#define XGI_ASYM_DDR 0x02 +#define XGI_DUAL_CHANNEL_1_RANK 0x3 + +#define XGI550_DRAM_SIZE_MASK 0x3F /* 550/650/740 SR14 */ +#define XGI550_DRAM_SIZE_4MB 0x00 +#define XGI550_DRAM_SIZE_8MB 0x01 +#define XGI550_DRAM_SIZE_16MB 0x03 +#define XGI550_DRAM_SIZE_24MB 0x05 +#define XGI550_DRAM_SIZE_32MB 0x07 +#define XGI550_DRAM_SIZE_64MB 0x0F +#define XGI550_DRAM_SIZE_96MB 0x17 +#define XGI550_DRAM_SIZE_128MB 0x1F +#define XGI550_DRAM_SIZE_256MB 0x3F + +#define XGI_SCRATCH_REG_1A_MASK 0x10 #define XGI_ENABLE_2D 0x40 /* SR1E */ @@ -98,6 +176,7 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table); #define XGI_PCI_ADDR_ENABLE 0x80 #define XGI_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */ +#define XGI_MODE_SELECT_CRT2 0x02 #define XGI_VB_OUTPUT_COMPOSITE 0x04 #define XGI_VB_OUTPUT_SVIDEO 0x08 #define XGI_VB_OUTPUT_SCART 0x10 @@ -120,14 +199,35 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table); XGI_VB_SCART | XGI_VB_HIVISION|XGI_VB_YPBPR) #define XGI_EXTERNAL_CHIP_MASK 0x0E /* CR37 */ +#define XGI_EXTERNAL_CHIP_XGI301 0x01 /* in CR37 << 1 ! */ +#define XGI_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */ +#define XGI_EXTERNAL_CHIP_TRUMPION 0x03 /* in CR37 << 1 ! */ +#define XGI_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04 /* in CR37 << 1 ! */ +#define XGI_EXTERNAL_CHIP_CHRONTEL 0x05 /* in CR37 << 1 ! */ #define XGI310_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */ #define XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03 /* in CR37 << 1 ! */ +#define XGI_AGP_2X 0x20 /* CR48 */ + +#define BRI_DRAM_SIZE_MASK 0x70 /* PCI bridge config data */ +#define BRI_DRAM_SIZE_2MB 0x00 +#define BRI_DRAM_SIZE_4MB 0x01 +#define BRI_DRAM_SIZE_8MB 0x02 +#define BRI_DRAM_SIZE_16MB 0x03 +#define BRI_DRAM_SIZE_32MB 0x04 +#define BRI_DRAM_SIZE_64MB 0x05 + +#define SR_BUFFER_SIZE 5 +#define CR_BUFFER_SIZE 5 + /* ------------------- Global Variables ----------------------------- */ /* Fbcon variables */ static struct fb_info *fb_info; + +static int video_type = FB_TYPE_PACKED_PIXELS; + static struct fb_var_screeninfo default_var = { .xres = 0, .yres = 0, @@ -163,30 +263,39 @@ static struct fb_fix_screeninfo XGIfb_fix = { .xpanstep = 1, .ypanstep = 1, }; +static char myid[20]; static u32 pseudo_palette[17]; /* display status */ -static int XGIfb_off; -static int XGIfb_crt1off; +static int XGIfb_off = 0; +static int XGIfb_crt1off = 0; static int XGIfb_forcecrt1 = -1; -static int XGIfb_userom ; +static int XGIfb_userom = 0; /*static int XGIfb_useoem = -1; */ /* global flags */ -static int XGIfb_tvmode; -static int XGIfb_pdc; -static int enable_dstn; +static int XGIfb_registered; +static int XGIfb_tvmode = 0; +static int XGIfb_pdc = 0; +static int enable_dstn = 0; static int XGIfb_ypan = -1; -static int XGIfb_CRT2_write_enable; +static int XGIfb_CRT2_write_enable = 0; /* TW: CRT2 type (for overriding autodetection) */ static int XGIfb_crt2type = -1; /* PR: Tv plug type (for overriding autodetection) */ static int XGIfb_tvplug = -1; +static unsigned char XGIfb_detectedpdc = 0; + +static unsigned char XGIfb_detectedlcda = 0xff; + + + + /* TW: For ioctl XGIFB_GET_INFO */ /* XGIfb_info XGIfbinfo; */ @@ -315,6 +424,7 @@ static struct _XGIbios_mode { MD_XGI315}, {"1280x768x32", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_XGI315}, +#define MODEINDEX_1280x960 48 {"1280x960x8", 0x7C, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60, MD_XGI300|MD_XGI315}, /* TW: Modenumbers being patched */ {"1280x960x16", 0x7D, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, @@ -373,8 +483,8 @@ static int xgifb_mode_idx = 1; static int xgifb_mode_idx = -1; /* Use a default mode if we are inside the kernel */ #endif -static u8 XGIfb_mode_no; -static u8 XGIfb_rate_idx; +static u8 XGIfb_mode_no = 0; +static u8 XGIfb_rate_idx = 0; /* TW: CR36 evaluation */ static const unsigned short XGI300paneltype[] = { diff --git a/trunk/drivers/staging/xgifb/XGI_main_26.c b/trunk/drivers/staging/xgifb/XGI_main_26.c index 7b36b7ea4640..4403e5f80597 100644 --- a/trunk/drivers/staging/xgifb/XGI_main_26.c +++ b/trunk/drivers/staging/xgifb/XGI_main_26.c @@ -28,6 +28,10 @@ #include #include +#ifndef XGIFB_PAN +#define XGIFB_PAN +#endif + #include #ifdef CONFIG_MTRR #include @@ -41,9 +45,11 @@ #include "vb_setmode.h" #define Index_CR_GPIO_Reg1 0x48 +#define Index_CR_GPIO_Reg2 0x49 #define Index_CR_GPIO_Reg3 0x4a #define GPIOG_EN (1<<6) +#define GPIOG_WRITE (1<<6) #define GPIOG_READ (1<<1) #define XGIFB_ROM_SIZE 65536 @@ -390,8 +396,8 @@ static unsigned char XGIfb_query_VGA_config_space( struct xgi_hw_device_info *pXGIhw_ext, unsigned long offset, unsigned long set, unsigned long *value) { - static struct pci_dev *pdev; - static unsigned char init, valid_pdev; + static struct pci_dev *pdev = NULL; + static unsigned char init = 0, valid_pdev = 0; if (!set) DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset); @@ -1357,6 +1363,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, return 0; } +#ifdef XGIFB_PAN static int XGIfb_pan_var(struct fb_var_screeninfo *var) { unsigned int base; @@ -1409,6 +1416,7 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var) /* printk("End of pan_var"); */ return 0; } +#endif static int XGIfb_open(struct fb_info *info, int user) { @@ -1481,19 +1489,23 @@ static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con, DEBUGPRN("inside get_fix"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id, myid); + fix->smem_start = xgi_video_info.video_base; fix->smem_len = xgi_video_info.video_size; - fix->type = FB_TYPE_PACKED_PIXELS; + fix->type = video_type; fix->type_aux = 0; if (xgi_video_info.video_bpp == 8) fix->visual = FB_VISUAL_PSEUDOCOLOR; else fix->visual = FB_VISUAL_DIRECTCOLOR; fix->xpanstep = 0; +#ifdef XGIFB_PAN if (XGIfb_ypan) fix->ypanstep = 1; +#endif fix->ywrapstep = 0; fix->line_length = xgi_video_info.video_linelength; fix->mmio_start = xgi_video_info.mmio_base; @@ -1661,6 +1673,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) return 0; } +#ifdef XGIFB_PAN static int XGIfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { @@ -1697,6 +1710,7 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var, /* printk("End of pan_display\n"); */ return 0; } +#endif static int XGIfb_blank(int blank, struct fb_info *info) { @@ -1722,7 +1736,9 @@ static struct fb_ops XGIfb_ops = { .fb_check_var = XGIfb_check_var, .fb_set_par = XGIfb_set_par, .fb_setcolreg = XGIfb_setcolreg, +#ifdef XGIFB_PAN .fb_pan_display = XGIfb_pan_display, +#endif .fb_blank = XGIfb_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, @@ -1933,7 +1949,7 @@ static void XGIfb_get_VB_type(void) } } -static int __init XGIfb_setup(char *options) +XGIINITSTATIC int __init XGIfb_setup(char *options) { char *this_opt; @@ -2044,6 +2060,8 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, if (XGIfb_off) return -ENXIO; + XGIfb_registered = 0; + memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info)); fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev); if (!fb_info) @@ -2139,12 +2157,15 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, goto error; } - /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ - xgifb_reg_or(XGISR, - IND_XGI_PCI_ADDRESS_SET, - (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE)); - /* Enable 2D accelerator engine */ - xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D); + if ((xgifb_mode_idx < 0) || + ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) { + /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ + xgifb_reg_or(XGISR, + IND_XGI_PCI_ADDRESS_SET, + (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE)); + /* Enable 2D accelerator engine */ + xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D); + } XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size; @@ -2188,282 +2209,297 @@ static int __devinit xgifb_probe(struct pci_dev *pdev, xgi_video_info.mtrr = (unsigned int) 0; - xgi_video_info.hasVB = HASVB_NONE; - if ((xgi_video_info.chip == XG20) || - (xgi_video_info.chip == XG27)) { + if ((xgifb_mode_idx < 0) || + ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) { xgi_video_info.hasVB = HASVB_NONE; - } else if (xgi_video_info.chip == XG21) { - CR38 = xgifb_reg_get(XGICR, 0x38); - if ((CR38&0xE0) == 0xC0) { - xgi_video_info.disp_state = DISPTYPE_LCD; - if (!XGIfb_GetXG21LVDSData()) { - int m; - for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) { - if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) && - (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) { - xgifb_reg_set(XGI_Pr.P3d4, 0x36, m); + if ((xgi_video_info.chip == XG20) || + (xgi_video_info.chip == XG27)) { + xgi_video_info.hasVB = HASVB_NONE; + } else if (xgi_video_info.chip == XG21) { + CR38 = xgifb_reg_get(XGICR, 0x38); + if ((CR38&0xE0) == 0xC0) { + xgi_video_info.disp_state = DISPTYPE_LCD; + if (!XGIfb_GetXG21LVDSData()) { + int m; + for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) { + if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) && + (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) { + xgifb_reg_set(XGI_Pr.P3d4, 0x36, m); + } } } + } else if ((CR38&0xE0) == 0x60) { + xgi_video_info.hasVB = HASVB_CHRONTEL; + } else { + xgi_video_info.hasVB = HASVB_NONE; } - } else if ((CR38&0xE0) == 0x60) { - xgi_video_info.hasVB = HASVB_CHRONTEL; } else { - xgi_video_info.hasVB = HASVB_NONE; + XGIfb_get_VB_type(); } - } else { - XGIfb_get_VB_type(); - } - XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN; + XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN; - XGIhw_ext.ulExternalChip = 0; + XGIhw_ext.ulExternalChip = 0; - switch (xgi_video_info.hasVB) { - case HASVB_301: - reg = xgifb_reg_get(XGIPART4, 0x01); - if (reg >= 0xE0) { - XGIhw_ext.ujVBChipID = VB_CHIP_302LV; - printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg); - } else if (reg >= 0xD0) { - XGIhw_ext.ujVBChipID = VB_CHIP_301LV; - printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg); - } - /* else if (reg >= 0xB0) { - XGIhw_ext.ujVBChipID = VB_CHIP_301B; - reg1 = xgifb_reg_get(XGIPART4, 0x23); - printk("XGIfb: XGI301B bridge detected\n"); - } */ - else { - XGIhw_ext.ujVBChipID = VB_CHIP_301; - printk("XGIfb: XGI301 bridge detected\n"); + switch (xgi_video_info.hasVB) { + case HASVB_301: + reg = xgifb_reg_get(XGIPART4, 0x01); + if (reg >= 0xE0) { + XGIhw_ext.ujVBChipID = VB_CHIP_302LV; + printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg); + } else if (reg >= 0xD0) { + XGIhw_ext.ujVBChipID = VB_CHIP_301LV; + printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg); + } + /* else if (reg >= 0xB0) { + XGIhw_ext.ujVBChipID = VB_CHIP_301B; + reg1 = xgifb_reg_get(XGIPART4, 0x23); + printk("XGIfb: XGI301B bridge detected\n"); + } */ + else { + XGIhw_ext.ujVBChipID = VB_CHIP_301; + printk("XGIfb: XGI301 bridge detected\n"); + } + break; + case HASVB_302: + reg = xgifb_reg_get(XGIPART4, 0x01); + if (reg >= 0xE0) { + XGIhw_ext.ujVBChipID = VB_CHIP_302LV; + printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg); + } else if (reg >= 0xD0) { + XGIhw_ext.ujVBChipID = VB_CHIP_301LV; + printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg); + } else if (reg >= 0xB0) { + reg1 = xgifb_reg_get(XGIPART4, 0x23); + + XGIhw_ext.ujVBChipID = VB_CHIP_302B; + + } else { + XGIhw_ext.ujVBChipID = VB_CHIP_302; + printk(KERN_INFO "XGIfb: XGI302 bridge detected\n"); + } + break; + case HASVB_LVDS: + XGIhw_ext.ulExternalChip = 0x1; + printk(KERN_INFO "XGIfb: LVDS transmitter detected\n"); + break; + case HASVB_TRUMPION: + XGIhw_ext.ulExternalChip = 0x2; + printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n"); + break; + case HASVB_CHRONTEL: + XGIhw_ext.ulExternalChip = 0x4; + printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n"); + break; + case HASVB_LVDS_CHRONTEL: + XGIhw_ext.ulExternalChip = 0x5; + printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n"); + break; + default: + printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n"); + break; } - break; - case HASVB_302: - reg = xgifb_reg_get(XGIPART4, 0x01); - if (reg >= 0xE0) { - XGIhw_ext.ujVBChipID = VB_CHIP_302LV; - printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg); - } else if (reg >= 0xD0) { - XGIhw_ext.ujVBChipID = VB_CHIP_301LV; - printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg); - } else if (reg >= 0xB0) { - reg1 = xgifb_reg_get(XGIPART4, 0x23); - XGIhw_ext.ujVBChipID = VB_CHIP_302B; + if (xgi_video_info.hasVB != HASVB_NONE) + XGIfb_detect_VB(); + if (xgi_video_info.disp_state & DISPTYPE_DISP2) { + if (XGIfb_crt1off) + xgi_video_info.disp_state |= DISPMODE_SINGLE; + else + xgi_video_info.disp_state |= (DISPMODE_MIRROR | + DISPTYPE_CRT1); } else { - XGIhw_ext.ujVBChipID = VB_CHIP_302; - printk(KERN_INFO "XGIfb: XGI302 bridge detected\n"); + xgi_video_info.disp_state = DISPMODE_SINGLE | + DISPTYPE_CRT1; } - break; - case HASVB_LVDS: - XGIhw_ext.ulExternalChip = 0x1; - printk(KERN_INFO "XGIfb: LVDS transmitter detected\n"); - break; - case HASVB_TRUMPION: - XGIhw_ext.ulExternalChip = 0x2; - printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n"); - break; - case HASVB_CHRONTEL: - XGIhw_ext.ulExternalChip = 0x4; - printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n"); - break; - case HASVB_LVDS_CHRONTEL: - XGIhw_ext.ulExternalChip = 0x5; - printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n"); - break; - default: - printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n"); - break; - } - if (xgi_video_info.hasVB != HASVB_NONE) - XGIfb_detect_VB(); + if (xgi_video_info.disp_state & DISPTYPE_LCD) { + if (!enable_dstn) { + reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL); + reg &= 0x0f; + XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg]; - if (xgi_video_info.disp_state & DISPTYPE_DISP2) { - if (XGIfb_crt1off) - xgi_video_info.disp_state |= DISPMODE_SINGLE; - else - xgi_video_info.disp_state |= (DISPMODE_MIRROR | - DISPTYPE_CRT1); - } else { - xgi_video_info.disp_state = DISPMODE_SINGLE | - DISPTYPE_CRT1; - } + } else { + /* TW: FSTN/DSTN */ + XGIhw_ext.ulCRT2LCDType = LCD_320x480; + } + } - if (xgi_video_info.disp_state & DISPTYPE_LCD) { - if (!enable_dstn) { - reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL); - reg &= 0x0f; - XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg]; + XGIfb_detectedpdc = 0; - } else { - /* TW: FSTN/DSTN */ - XGIhw_ext.ulCRT2LCDType = LCD_320x480; - } - } + XGIfb_detectedlcda = 0xff; - if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) || - (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || - (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) { - int tmp; - tmp = xgifb_reg_get(XGICR, 0x34); - if (tmp <= 0x13) { - /* Currently on LCDA? - *(Some BIOSes leave CR38) */ - tmp = xgifb_reg_get(XGICR, 0x38); - if ((tmp & 0x03) == 0x03) { - /* XGI_Pr.XGI_UseLCDA = 1; */ - } else { + /* TW: Try to find about LCDA */ + + if ((XGIhw_ext.ujVBChipID == VB_CHIP_302B) || + (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || + (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) { + int tmp; + tmp = xgifb_reg_get(XGICR, 0x34); + if (tmp <= 0x13) { /* Currently on LCDA? - *(Some newer BIOSes set D0 in CR35) */ - tmp = xgifb_reg_get(XGICR, 0x35); - if (tmp & 0x01) { + *(Some BIOSes leave CR38) */ + tmp = xgifb_reg_get(XGICR, 0x38); + if ((tmp & 0x03) == 0x03) { /* XGI_Pr.XGI_UseLCDA = 1; */ } else { - tmp = xgifb_reg_get(XGICR, - 0x30); - if (tmp & 0x20) { - tmp = xgifb_reg_get( - XGIPART1, 0x13); - if (tmp & 0x04) { - /* XGI_Pr.XGI_UseLCDA = 1; */ + /* Currently on LCDA? + *(Some newer BIOSes set D0 in CR35) */ + tmp = xgifb_reg_get(XGICR, 0x35); + if (tmp & 0x01) { + /* XGI_Pr.XGI_UseLCDA = 1; */ + } else { + tmp = xgifb_reg_get(XGICR, + 0x30); + if (tmp & 0x20) { + tmp = xgifb_reg_get( + XGIPART1, 0x13); + if (tmp & 0x04) { + /* XGI_Pr.XGI_UseLCDA = 1; */ + } } } } } + + } + + if (xgifb_mode_idx >= 0) + xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx); + + if (xgifb_mode_idx < 0) { + switch (xgi_video_info.disp_state & DISPTYPE_DISP2) { + case DISPTYPE_LCD: + xgifb_mode_idx = DEFAULT_LCDMODE; + if (xgi_video_info.chip == XG21) + xgifb_mode_idx = + XGIfb_GetXG21DefaultLVDSModeIdx(); + break; + case DISPTYPE_TV: + xgifb_mode_idx = DEFAULT_TVMODE; + break; + default: + xgifb_mode_idx = DEFAULT_MODE; + break; + } } - } + XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no; - if (xgifb_mode_idx >= 0) - xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx); + /* yilin set default refresh rate */ + if (xgi_video_info.refresh_rate == 0) + xgi_video_info.refresh_rate = 60; + if (XGIfb_search_refresh_rate( + xgi_video_info.refresh_rate) == 0) { + XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx; + xgi_video_info.refresh_rate = 60; + } - if (xgifb_mode_idx < 0) { - switch (xgi_video_info.disp_state & DISPTYPE_DISP2) { - case DISPTYPE_LCD: - xgifb_mode_idx = DEFAULT_LCDMODE; - if (xgi_video_info.chip == XG21) - xgifb_mode_idx = - XGIfb_GetXG21DefaultLVDSModeIdx(); + xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp; + xgi_video_info.video_vwidth = + xgi_video_info.video_width = + XGIbios_mode[xgifb_mode_idx].xres; + xgi_video_info.video_vheight = + xgi_video_info.video_height = + XGIbios_mode[xgifb_mode_idx].yres; + xgi_video_info.org_x = xgi_video_info.org_y = 0; + xgi_video_info.video_linelength = + xgi_video_info.video_width * + (xgi_video_info.video_bpp >> 3); + switch (xgi_video_info.video_bpp) { + case 8: + xgi_video_info.DstColor = 0x0000; + xgi_video_info.XGI310_AccelDepth = 0x00000000; + xgi_video_info.video_cmap_len = 256; break; - case DISPTYPE_TV: - xgifb_mode_idx = DEFAULT_TVMODE; + case 16: + xgi_video_info.DstColor = 0x8000; + xgi_video_info.XGI310_AccelDepth = 0x00010000; + xgi_video_info.video_cmap_len = 16; + break; + case 32: + xgi_video_info.DstColor = 0xC000; + xgi_video_info.XGI310_AccelDepth = 0x00020000; + xgi_video_info.video_cmap_len = 16; break; default: - xgifb_mode_idx = DEFAULT_MODE; + xgi_video_info.video_cmap_len = 16; + printk(KERN_INFO "XGIfb: Unsupported depth %d", + xgi_video_info.video_bpp); break; } - } - - XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no; - - /* yilin set default refresh rate */ - if (xgi_video_info.refresh_rate == 0) - xgi_video_info.refresh_rate = 60; - if (XGIfb_search_refresh_rate( - xgi_video_info.refresh_rate) == 0) { - XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx; - xgi_video_info.refresh_rate = 60; - } - xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp; - xgi_video_info.video_vwidth = - xgi_video_info.video_width = - XGIbios_mode[xgifb_mode_idx].xres; - xgi_video_info.video_vheight = - xgi_video_info.video_height = - XGIbios_mode[xgifb_mode_idx].yres; - xgi_video_info.org_x = xgi_video_info.org_y = 0; - xgi_video_info.video_linelength = - xgi_video_info.video_width * - (xgi_video_info.video_bpp >> 3); - switch (xgi_video_info.video_bpp) { - case 8: - xgi_video_info.DstColor = 0x0000; - xgi_video_info.XGI310_AccelDepth = 0x00000000; - xgi_video_info.video_cmap_len = 256; - break; - case 16: - xgi_video_info.DstColor = 0x8000; - xgi_video_info.XGI310_AccelDepth = 0x00010000; - xgi_video_info.video_cmap_len = 16; - break; - case 32: - xgi_video_info.DstColor = 0xC000; - xgi_video_info.XGI310_AccelDepth = 0x00020000; - xgi_video_info.video_cmap_len = 16; - break; - default: - xgi_video_info.video_cmap_len = 16; - printk(KERN_INFO "XGIfb: Unsupported depth %d", - xgi_video_info.video_bpp); - break; - } - - printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n", - xgi_video_info.video_width, - xgi_video_info.video_height, - xgi_video_info.video_bpp, - xgi_video_info.refresh_rate); + printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n", + xgi_video_info.video_width, + xgi_video_info.video_height, + xgi_video_info.video_bpp, + xgi_video_info.refresh_rate); + + default_var.xres = + default_var.xres_virtual = + xgi_video_info.video_width; + default_var.yres = + default_var.yres_virtual = + xgi_video_info.video_height; + default_var.bits_per_pixel = xgi_video_info.video_bpp; + + XGIfb_bpp_to_var(&default_var); + + default_var.pixclock = (u32) (1000000000 / + XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext, + XGIfb_mode_no, XGIfb_rate_idx)); + + if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext, + XGIfb_mode_no, XGIfb_rate_idx, + &default_var.left_margin, &default_var.right_margin, + &default_var.upper_margin, &default_var.lower_margin, + &default_var.hsync_len, &default_var.vsync_len, + &default_var.sync, &default_var.vmode)) { + + if ((default_var.vmode & FB_VMODE_MASK) == + FB_VMODE_INTERLACED) { + default_var.yres <<= 1; + default_var.yres_virtual <<= 1; + } else if ((default_var.vmode & FB_VMODE_MASK) == + FB_VMODE_DOUBLE) { + default_var.pixclock >>= 1; + default_var.yres >>= 1; + default_var.yres_virtual >>= 1; + } - default_var.xres = - default_var.xres_virtual = - xgi_video_info.video_width; - default_var.yres = - default_var.yres_virtual = - xgi_video_info.video_height; - default_var.bits_per_pixel = xgi_video_info.video_bpp; - - XGIfb_bpp_to_var(&default_var); - - default_var.pixclock = (u32) (1000000000 / - XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext, - XGIfb_mode_no, XGIfb_rate_idx)); - - if (XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext, - XGIfb_mode_no, XGIfb_rate_idx, - &default_var.left_margin, &default_var.right_margin, - &default_var.upper_margin, &default_var.lower_margin, - &default_var.hsync_len, &default_var.vsync_len, - &default_var.sync, &default_var.vmode)) { - - if ((default_var.vmode & FB_VMODE_MASK) == - FB_VMODE_INTERLACED) { - default_var.yres <<= 1; - default_var.yres_virtual <<= 1; - } else if ((default_var.vmode & FB_VMODE_MASK) == - FB_VMODE_DOUBLE) { - default_var.pixclock >>= 1; - default_var.yres >>= 1; - default_var.yres_virtual >>= 1; } - } - - fb_info->flags = FBINFO_FLAG_DEFAULT; - fb_info->var = default_var; - fb_info->fix = XGIfb_fix; - fb_info->par = &xgi_video_info; - fb_info->screen_base = xgi_video_info.video_vbase; - fb_info->fbops = &XGIfb_ops; - XGIfb_get_fix(&fb_info->fix, -1, fb_info); - fb_info->pseudo_palette = pseudo_palette; + fb_info->flags = FBINFO_FLAG_DEFAULT; + fb_info->var = default_var; + fb_info->fix = XGIfb_fix; + fb_info->par = &xgi_video_info; + fb_info->screen_base = xgi_video_info.video_vbase; + fb_info->fbops = &XGIfb_ops; + XGIfb_get_fix(&fb_info->fix, -1, fb_info); + fb_info->pseudo_palette = pseudo_palette; - fb_alloc_cmap(&fb_info->cmap, 256 , 0); + fb_alloc_cmap(&fb_info->cmap, 256 , 0); #ifdef CONFIG_MTRR - xgi_video_info.mtrr = mtrr_add( - (unsigned int) xgi_video_info.video_base, - (unsigned int) xgi_video_info.video_size, - MTRR_TYPE_WRCOMB, 1); - if (xgi_video_info.mtrr) - printk(KERN_INFO "XGIfb: Added MTRRs\n"); + xgi_video_info.mtrr = mtrr_add( + (unsigned int) xgi_video_info.video_base, + (unsigned int) xgi_video_info.video_size, + MTRR_TYPE_WRCOMB, 1); + if (xgi_video_info.mtrr) + printk(KERN_INFO "XGIfb: Added MTRRs\n"); #endif - if (register_framebuffer(fb_info) < 0) { - ret = -EINVAL; - goto error_1; + if (register_framebuffer(fb_info) < 0) { + ret = -EINVAL; + goto error_1; + } + + XGIfb_registered = 1; + + printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n", + fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL); + } dumpVGAReg(); @@ -2507,7 +2543,7 @@ static struct pci_driver xgifb_driver = { .remove = __devexit_p(xgifb_remove) }; -static int __init xgifb_init(void) +XGIINITSTATIC int __init xgifb_init(void) { char *option = NULL; @@ -2528,26 +2564,26 @@ module_init(xgifb_init); #ifdef MODULE -static char *mode; -static int vesa; -static unsigned int rate; -static unsigned int mem; -static char *forcecrt2type; +static char *mode = NULL; +static int vesa = 0; +static unsigned int rate = 0; +static unsigned int mem = 0; +static char *forcecrt2type = NULL; static int forcecrt1 = -1; static int pdc = -1; static int pdc1 = -1; static int noypan = -1; static int userom = -1; static int useoem = -1; -static char *tvstandard; -static int nocrt2rate; +static char *tvstandard = NULL; +static int nocrt2rate = 0; static int scalelcd = -1; -static char *specialtiming; +static char *specialtiming = NULL; static int lvdshl = -1; -static int tvxposoffset, tvyposoffset; +static int tvxposoffset = 0, tvyposoffset = 0; #if !defined(__i386__) && !defined(__x86_64__) -static int resetcard; -static int videoram; +static int resetcard = 0; +static int videoram = 0; #endif MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver"); diff --git a/trunk/drivers/staging/xgifb/XGIfb.h b/trunk/drivers/staging/xgifb/XGIfb.h index 5d81cb69e63c..45b6015d160c 100644 --- a/trunk/drivers/staging/xgifb/XGIfb.h +++ b/trunk/drivers/staging/xgifb/XGIfb.h @@ -7,9 +7,11 @@ #define DISPTYPE_CRT2 0x00000004L #define DISPTYPE_LCD 0x00000002L #define DISPTYPE_TV 0x00000001L +#define DISPTYPE_DISP1 DISPTYPE_CRT1 #define DISPTYPE_DISP2 (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV) #define DISPMODE_SINGLE 0x00000020L #define DISPMODE_MIRROR 0x00000010L +#define DISPMODE_DUALVIEW 0x00000040L #define HASVB_NONE 0x00 #define HASVB_301 0x01 @@ -17,8 +19,13 @@ #define HASVB_TRUMPION 0x04 #define HASVB_LVDS_CHRONTEL 0x10 #define HASVB_302 0x20 +#define HASVB_303 0x40 #define HASVB_CHRONTEL 0x80 +#ifndef XGIFB_ID +#define XGIFB_ID 0x53495346 /* Identify myself with 'XGIF' */ +#endif + enum XGI_CHIP_TYPE { XG40 = 32, XG41, @@ -40,6 +47,11 @@ enum xgi_tvtype { }; enum xgi_tv_plug { /* vicki@030226 */ +/* TVPLUG_Legacy = 0, */ +/* TVPLUG_COMPOSITE, */ +/* TVPLUG_SVIDEO, */ +/* TVPLUG_SCART, */ +/* TVPLUG_TOTAL */ TVPLUG_UNKNOWN = 0, TVPLUG_COMPOSITE = 1, TVPLUG_SVIDEO = 2, diff --git a/trunk/drivers/staging/xgifb/vb_def.h b/trunk/drivers/staging/xgifb/vb_def.h index 06846868e9f1..339c071854f0 100644 --- a/trunk/drivers/staging/xgifb/vb_def.h +++ b/trunk/drivers/staging/xgifb/vb_def.h @@ -3,48 +3,261 @@ #ifndef _INITDEF_ #define _INITDEF_ +#ifndef NewScratch +#define NewScratch +#endif +/* shampoo */ + +#define SEQ_ADDRESS_PORT 0x0014 +#define SEQ_DATA_PORT 0x0015 +#define MISC_OUTPUT_REG_READ_PORT 0x001C +#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 +#define GRAPH_DATA_PORT 0x1F +#define GRAPH_ADDRESS_PORT 0x1E +#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */ +#define CRTC_ADDRESS_PORT_COLOR 0x0024 +#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 +#define PCI_COMMAND 0x04 + +/* ~shampoo */ + + +#define VB_XGI301 0x0001 /*301b*/ +#define VB_XGI301B 0x0002 +#define VB_XGI302B 0x0004 +#define VB_XGI301LV 0x0008 /*301lv*/ +#define VB_XGI302LV 0x0010 #define VB_XGI301C 0x0020 /* for 301C */ +#define VB_NoLCD 0x8000 /*end 301b*/ +#define VB_YPbPrInfo 0x07 /*301lv*/ +#define VB_YPbPr525i 0x00 #define VB_YPbPr525p 0x01 #define VB_YPbPr750p 0x02 #define VB_YPbPr1080i 0x03 +/* #define CRT1Len 17 */ #define LVDSCRT1Len 15 - +#define CHTVRegDataLen 5 + +/* #define ModeInfoFlag 0x07 */ +/* #define IsTextMode 0x07 */ +/* #define ModeText 0x00 */ +/* #define ModeCGA 0x01 */ +/* #define ModeEGA 0x02 */ +/* #define ModeVGA 0x03 */ +/* #define Mode15Bpp 0x04 */ +/* #define Mode16Bpp 0x05 */ +/* #define Mode24Bpp 0x06 */ +/* #define Mode32Bpp 0x07 */ + +/* #define DACInfoFlag 0x18 */ +/* #define MemoryInfoFlag 0x1E0 */ +/* #define MemorySizeShift 0x05 */ + +#define Charx8Dot 0x0200 +#define LineCompareOff 0x0400 +#define CRT2Mode 0x0800 +#define HalfDCLK 0x1000 +#define NoSupportSimuTV 0x2000 +#define DoubleScanMode 0x8000 + +#define SupportAllCRT2 0x0078 +#define SupportTV 0x0008 +#define SupportHiVisionTV 0x0010 +#define SupportLCD 0x0020 +#define SupportRAMDAC2 0x0040 +#define NoSupportTV 0x0070 +#define NoSupportHiVisionTV 0x0060 +#define NoSupportLCD 0x0058 #define SupportCHTV 0x0800 #define SupportCRT2in301C 0x0100 /* for 301C */ +#define SupportTV1024 0x0800 /*301b*/ +#define SupportYPbPr 0x1000 /*301lv*/ +#define InterlaceMode 0x0080 +#define SyncPP 0x0000 +#define SyncPN 0x4000 +#define SyncNP 0x8000 +/* #define SyncNN 0xc000 */ +#define ECLKindex0 0x0000 +#define ECLKindex1 0x0100 +#define ECLKindex2 0x0200 +#define ECLKindex3 0x0300 +#define ECLKindex4 0x0400 + +#define SetSimuScanMode 0x0001 +#define SwitchToCRT2 0x0002 +/* #define SetCRT2ToTV 0x009C */ +#define SetCRT2ToAVIDEO 0x0004 +#define SetCRT2ToSVIDEO 0x0008 +#define SetCRT2ToSCART 0x0010 +#define SetCRT2ToLCD 0x0020 +#define SetCRT2ToRAMDAC 0x0040 +#define SetCRT2ToHiVisionTV 0x0080 +#define SetNTSCTV 0x0000 +/* #define SetPALTV 0x0100 */ +#define SetInSlaveMode 0x0200 +#define SetNotSimuMode 0x0400 +#define SetNotSimuTVMode 0x0400 +#define SetDispDevSwitch 0x0800 +#define LoadDACFlag 0x1000 +#define DisableCRT2Display 0x2000 +#define DriverMode 0x4000 +#define HotKeySwitch 0x8000 #define SetCHTVOverScan 0x8000 +/* #define SetCRT2ToLCDA 0x8000 301b */ #define PanelRGB18Bit 0x0100 #define PanelRGB24Bit 0x0000 +#define TVOverScan 0x10 +#define TVOverScanShift 4 +#define ClearBufferFlag 0x20 +#define EnableDualEdge 0x01 /*301b*/ +#define SetToLCDA 0x02 + +#define YPbPrModeInfo 0x38 +/* #define YPbPrMode525i 0x00 */ +/* #define YPbPrMode525p 0x08 */ +/* #define YPbPrMode750p 0x10 */ +/* #define YPbPrMode1080i 0x18 */ + +#define SetSCARTOutput 0x01 +#define BoardTVType 0x02 +#define EnablePALMN 0x40 +/* #define ProgrammingCRT2 0x01 */ +/* #define TVSimuMode 0x02 */ +/* #define RPLLDIV2XO 0x04 */ +/* #define LCDVESATiming 0x08 */ +/* #define EnableLVDSDDA 0x10 */ +#define SetDispDevSwitchFlag 0x20 +#define CheckWinDos 0x40 +#define SetJDOSMode 0x80 + #define Panel320x480 0x07 /*fstn*/ /* [ycchen] 02/12/03 Modify for Multi-Sync. LCD Support */ #define PanelResInfo 0x1F /* CR36 Panel Type/LCDResInfo */ +#define PanelRefInfo 0x60 #define Panel800x600 0x01 #define Panel1024x768 0x02 #define Panel1024x768x75 0x22 #define Panel1280x1024 0x03 #define Panel1280x1024x75 0x23 #define Panel640x480 0x04 +#define Panel1024x600 0x05 +#define Panel1152x864 0x06 #define Panel1280x960 0x07 +#define Panel1152x768 0x08 #define Panel1400x1050 0x09 +#define Panel1280x768 0x0A #define Panel1600x1200 0x0B #define PanelRef60Hz 0x00 #define PanelRef75Hz 0x20 +#define LCDRGB18Bit 0x01 + +#define ExtChipTrumpion 0x06 +#define ExtChipCH7005 0x08 +#define ExtChipMitacTV 0x0a +#define LCDNonExpanding 0x10 +#define LCDNonExpandingShift 4 +#define LCDSync 0x20 +#define LCDSyncBit 0xe0 +#define LCDSyncShift 6 + +/* #define DDC2DelayTime 300 */ #define CRT2DisplayFlag 0x2000 +/* #define LCDDataLen 8 */ +/* #define HiTVDataLen 12 */ +/* #define TVDataLen 16 */ +/* #define SetPALTV 0x0100 */ +#define HalfDCLK 0x1000 +#define NTSCHT 1716 +#define NTSCVT 525 +#define PALHT 1728 +#define PALVT 625 +#define StHiTVHT 892 +#define StHiTVVT 1126 +#define StHiTextTVHT 1000 +#define StHiTextTVVT 1126 +#define ExtHiTVHT 2100 +#define ExtHiTVVT 1125 + +#define St750pTVHT 1716 +#define St750pTVVT 525 +#define Ext750pTVHT 1716 +#define Ext750pTVVT 525 +#define St525pTVHT 1716 +#define St525pTVVT 525 +#define Ext525pTVHT 1716 +#define Ext525pTVVT 525 +#define St525iTVHT 1716 +#define St525iTVVT 525 +#define Ext525iTVHT 1716 +#define Ext525iTVVT 525 + +#define VCLKStartFreq 25 +#define SoftDramType 0x80 +#define VCLK40 0x04 + +#define VCLK162 0x21 + +#define LCDRGB18Bit 0x01 +#define LoadDACFlag 0x1000 +#define AfterLockCRT2 0x4000 +#define SetCRT2ToAVIDEO 0x0004 +#define SetCRT2ToSCART 0x0010 +#define Ext2StructSize 5 + #define YPbPr525iVCLK 0x03B #define YPbPr525iVCLK_2 0x03A +#define SwitchToCRT2 0x0002 +/* #define LCDVESATiming 0x08 */ +#define SetSCARTOutput 0x01 +#define AVIDEOSense 0x01 +#define SVIDEOSense 0x02 +#define SCARTSense 0x04 +#define LCDSense 0x08 +#define Monitor1Sense 0x20 +#define Monitor2Sense 0x10 +#define HiTVSense 0x40 +#define BoardTVType 0x02 +#define HotPlugFunction 0x08 +#define StStructSize 0x06 + + #define XGI_CRT2_PORT_00 (0x00 - 0x030) #define XGI_CRT2_PORT_04 (0x04 - 0x030) #define XGI_CRT2_PORT_10 (0x10 - 0x30) #define XGI_CRT2_PORT_12 (0x12 - 0x30) #define XGI_CRT2_PORT_14 (0x14 - 0x30) + +#define LCDNonExpanding 0x10 +#define ADR_CRT2PtrData 0x20E +#define offset_Zurac 0x210 +#define ADR_LVDSDesPtrData 0x212 +#define ADR_LVDSCRT1DataPtr 0x214 +#define ADR_CHTVVCLKPtr 0x216 +#define ADR_CHTVRegDataPtr 0x218 + +#define LVDSDataLen 6 +/* #define EnableLVDSDDA 0x10 */ +/* #define LVDSDesDataLen 3 */ +#define ActiveNonExpanding 0x40 +#define ActiveNonExpandingShift 6 +/* #define ActivePAL 0x20 */ +#define ActivePALShift 5 +/* #define ModeSwitchStatus 0x0F */ +#define SoftTVType 0x40 +#define SoftSettingAddr 0x52 +#define ModeSettingAddr 0x53 + +/* #define SelectCRT1Rate 0x4 */ + #define _PanelType00 0x00 #define _PanelType01 0x08 #define _PanelType02 0x10 @@ -62,26 +275,173 @@ #define _PanelType0E 0x70 #define _PanelType0F 0x78 +/* 1: XGI is primary vga 0:XGI is secondary vga */ +#define PRIMARY_VGA 0 +#define BIOSIDCodeAddr 0x235 +#define OEMUtilIDCodeAddr 0x237 +#define VBModeIDTableAddr 0x239 +#define OEMTVPtrAddr 0x241 +#define PhaseTableAddr 0x243 +#define NTSCFilterTableAddr 0x245 +#define PALFilterTableAddr 0x247 +#define OEMLCDPtr_1Addr 0x249 +#define OEMLCDPtr_2Addr 0x24B +#define LCDHPosTable_1Addr 0x24D +#define LCDHPosTable_2Addr 0x24F +#define LCDVPosTable_1Addr 0x251 +#define LCDVPosTable_2Addr 0x253 +#define OEMLCDPIDTableAddr 0x255 + +#define VBModeStructSize 5 +#define PhaseTableSize 4 +#define FilterTableSize 4 +#define LCDHPosTableSize 7 +#define LCDVPosTableSize 5 +#define OEMLVDSPIDTableSize 4 +#define LVDSHPosTableSize 4 +#define LVDSVPosTableSize 6 + +#define VB_ModeID 0 +#define VB_TVTableIndex 1 +#define VB_LCDTableIndex 2 +#define VB_LCDHIndex 3 +#define VB_LCDVIndex 4 + +#define OEMLCDEnable 0x0001 +#define OEMLCDDelayEnable 0x0002 +#define OEMLCDPOSEnable 0x0004 +#define OEMTVEnable 0x0100 +#define OEMTVDelayEnable 0x0200 +#define OEMTVFlickerEnable 0x0400 +#define OEMTVPhaseEnable 0x0800 +#define OEMTVFilterEnable 0x1000 + +#define OEMLCDPanelIDSupport 0x0080 + +/* #define LCDVESATiming 0x0001 //LCD Info CR37 */ +/* #define EnableLVDSDDA 0x0002 */ +#define EnableScalingLCD 0x0008 +#define SetPWDEnable 0x0004 +#define SetLCDtoNonExpanding 0x0010 +/* #define SetLCDPolarity 0x00E0 */ +#define SetLCDDualLink 0x0100 +#define SetLCDLowResolution 0x0200 +#define SetLCDStdMode 0x0400 +#define SetTVStdMode 0x0200 +#define SetTVLowResolution 0x0400 /* ============================================================= for 310 ============================================================== */ +#define SoftDRAMType 0x80 +#define SoftSetting_OFFSET 0x52 +#define SR07_OFFSET 0x7C +#define SR15_OFFSET 0x7D +#define SR16_OFFSET 0x81 +#define SR17_OFFSET 0x85 +#define SR19_OFFSET 0x8D +#define SR1F_OFFSET 0x99 +#define SR21_OFFSET 0x9A +#define SR22_OFFSET 0x9B +#define SR23_OFFSET 0x9C +#define SR24_OFFSET 0x9D +#define SR25_OFFSET 0x9E +#define SR31_OFFSET 0x9F +#define SR32_OFFSET 0xA0 +#define SR33_OFFSET 0xA1 + +#define CR40_OFFSET 0xA2 +#define SR25_1_OFFSET 0xF6 +#define CR49_OFFSET 0xF7 + +#define VB310Data_1_2_Offset 0xB6 +#define VB310Data_4_D_Offset 0xB7 +#define VB310Data_4_E_Offset 0xB8 +#define VB310Data_4_10_Offset 0xBB + +#define RGBSenseDataOffset 0xBD +#define YCSenseDataOffset 0xBF +#define VideoSenseDataOffset 0xC1 +#define OutputSelectOffset 0xF3 + +#define ECLK_MCLK_DISTANCE 0x14 +#define VBIOSTablePointerStart 0x200 +#define StandTablePtrOffset (VBIOSTablePointerStart+0x02) +#define EModeIDTablePtrOffset (VBIOSTablePointerStart+0x04) +#define CRT1TablePtrOffset (VBIOSTablePointerStart+0x06) +#define ScreenOffsetPtrOffset (VBIOSTablePointerStart+0x08) +#define VCLKDataPtrOffset (VBIOSTablePointerStart+0x0A) +#define MCLKDataPtrOffset (VBIOSTablePointerStart+0x0E) +#define CRT2PtrDataPtrOffset (VBIOSTablePointerStart+0x10) +#define TVAntiFlickPtrOffset (VBIOSTablePointerStart+0x12) +#define TVDelayPtr1Offset (VBIOSTablePointerStart+0x14) +#define TVPhaseIncrPtr1Offset (VBIOSTablePointerStart+0x16) +#define TVYFilterPtr1Offset (VBIOSTablePointerStart+0x18) +#define LCDDelayPtr1Offset (VBIOSTablePointerStart+0x20) +#define TVEdgePtr1Offset (VBIOSTablePointerStart+0x24) +#define CRT2Delay1Offset (VBIOSTablePointerStart+0x28) +#define LCDDataDesOffset (VBIOSTablePointerStart-0x02) +#define LCDDataPtrOffset (VBIOSTablePointerStart+0x2A) +#define LCDDesDataPtrOffset (VBIOSTablePointerStart+0x2C) /* add LCDDataList for GetLCDPtr */ #define LCDDataList (VBIOSTablePointerStart+0x22) +/* add TVDataList for GetTVPtr */ +#define TVDataList (VBIOSTablePointerStart+0x36) /* */ /* Modify from 310.inc */ /* */ /* */ + +#define ShowMsgFlag 0x20 /* SoftSetting */ +#define ShowVESAFlag 0x10 +#define HotPlugFunction 0x08 #define ModeSoftSetting 0x04 +#define TVSoftSetting 0x02 +#define LCDSoftSetting 0x01 +#define GatingCRTinLCDA 0x10 +#define SetHiTVOutput 0x08 +#define SetYPbPrOutput 0x04 #define BoardTVType 0x02 +#define SetSCARTOutput 0x01 + +/* TVModeSetting, Others as same as CR30 */ +#define ModeSettingYPbPr 0x02 + +/* TVModeSetting same as CR35 */ + +/* LCDModeSetting same as CR37 */ + +#define EnableNewTVFont 0x10 /* MiscCapability */ + +#define EnableLCDOutput 0x80 /* LCDCfgSetting */ #define SoftDRAMType 0x80 /* DRAMSetting */ +#define SoftDRAMConfig 0x40 +#define MosSelDRAMType 0x20 +#define SDRAM 000h +#define SGRAM 0x01 +#define ESDRAM 0x02 + +#define EnableAGPCfgSetting 0x01 /* AGPCfgSetting */ /* ---------------- SetMode Stack */ #define CRT1Len 15 #define VCLKLen 4 +#define DefThreshold 0x0100 +#define ExtRegsSize ((57+8+37+70+63+28+768+1)/64+1) + +#define VGA_XGI315 0x0001 /* VGA Type Info */ +#define VGA_SNewis315e 0x0002 /* 315 series */ +#define VGA_XGI550 0x0004 +#define VGA_XGI640 0x0008 +#define VGA_XGI740 0x0010 +#define VGA_XGI650 0x0020 +#define VGA_XGI650M 0x0040 +#define VGA_XGI651 0x0080 #define VGA_XGI340 0x0001 /* 340 series */ +#define VGA_XGI330 0x0001 /* 330 series */ +#define VGA_XGI660 0x0001 /* 660 series */ #define VB_XGI301 0x0001 /* VB Type Info */ #define VB_XGI301B 0x0002 /* 301 series */ @@ -92,16 +452,32 @@ #define VB_LVDS_NS 0x0001 /* 3rd party chip */ #define VB_CH7017 0x0002 #define VB_CH7007 0x0080 /* [Billy] 07/05/03 */ +/* #define VB_LVDS_SI 0x0004 */ #define ModeInfoFlag 0x0007 +#define IsTextMode 0x0007 #define ModeText 0x0000 +#define ModeCGA 0x0001 #define ModeEGA 0x0002 /* 16 colors mode */ #define ModeVGA 0x0003 /* 256 colors mode */ +#define Mode15Bpp 0x0004 /* 15 Bpp Color Mode */ +#define Mode16Bpp 0x0005 /* 16 Bpp Color Mode */ +#define Mode24Bpp 0x0006 /* 24 Bpp Color Mode */ +#define Mode32Bpp 0x0007 /* 32 Bpp Color Mode */ #define DACInfoFlag 0x0018 +#define MONODAC 0x0000 +#define CGADAC 0x0008 +#define EGADAC 0x0010 +#define VGADAC 0x0018 #define MemoryInfoFlag 0x01e0 #define MemorySizeShift 5 +#define Need1MSize 0x0000 +#define Need2MSize 0x0020 +#define Need4MSize 0x0060 +#define Need8MSize 0x00e0 +#define Need16MSize 0x01e0 #define Charx8Dot 0x0200 #define LineCompareOff 0x0400 @@ -111,7 +487,11 @@ #define DoubleScanMode 0x8000 /* -------------- Ext_InfoFlag */ +#define SupportModeInfo 0x0007 +#define Support256 0x0003 +#define Support15Bpp 0x0004 #define Support16Bpp 0x0005 +#define Support24Bpp 0x0006 #define Support32Bpp 0x0007 #define SupportAllCRT2 0x0078 @@ -133,6 +513,7 @@ /* -------------- SetMode Stack/Scratch */ #define SetSimuScanMode 0x0001 /* VBInfo/CR30 & CR31 */ #define SwitchToCRT2 0x0002 +#define SetCRT2ToTV1 0x009C #define SetCRT2ToTV 0x089C #define SetCRT2ToAVIDEO 0x0004 #define SetCRT2ToSVIDEO 0x0008 @@ -143,16 +524,23 @@ #define SetCRT2ToLCDA 0x0100 #define SetInSlaveMode 0x0200 #define SetNotSimuMode 0x0400 +#define HKEventMode 0x0800 #define SetCRT2ToYPbPr 0x0800 #define LoadDACFlag 0x1000 #define DisableCRT2Display 0x2000 #define DriverMode 0x4000 #define SetCRT2ToDualEdge 0x8000 +#define HotKeySwitch 0x8000 #define ProgrammingCRT2 0x0001 /* Set Flag */ #define EnableVCMode 0x0002 +#define SetHKEventMode 0x0004 #define ReserveTVOption 0x0008 +#define DisableRelocateIO 0x0010 #define Win9xDOSMode 0x0020 +#define JDOSMode 0x0040 +/* #define SetWin9xforJap 0x0080 // not used now */ +/* #define SetWin9xforKorea 0x0100 // not used now */ #define GatingCRT 0x0800 #define DisableChB 0x1000 #define EnableChB 0x2000 @@ -164,11 +552,15 @@ #define SetNTSCJ 0x0002 #define SetPALMTV 0x0004 #define SetPALNTV 0x0008 +#define SetCHTVUnderScan 0x0000 +/* #define SetCHTVOverScan 0x0010 */ #define SetYPbPrMode525i 0x0020 #define SetYPbPrMode525p 0x0040 #define SetYPbPrMode750p 0x0080 #define SetYPbPrMode1080i 0x0100 +#define SetTVStdMode 0x0200 #define SetTVLowResolution 0x0400 +#define SetTVSimuMode 0x0800 #define TVSimuMode 0x0800 #define RPLLDIV2XO 0x1000 #define NTSC1024x768 0x2000 @@ -179,20 +571,38 @@ #define EnableScalingLCD 0x0008 #define SetPWDEnable 0x0004 #define SetLCDtoNonExpanding 0x0010 +#define SetLCDPolarity 0x00e0 #define SetLCDDualLink 0x0100 #define SetLCDLowResolution 0x0200 #define SetLCDStdMode 0x0400 /* LCD Capability shampoo */ #define DefaultLCDCap 0x80ea +#define RLVDSDHL00 0x0000 +#define RLVDSDHL01 0x0001 +#define RLVDSDHL10 0x0002 /* default */ +#define RLVDSDHL11 0x0003 #define EnableLCD24bpp 0x0004 /* default */ #define DisableLCD24bpp 0x0000 +#define RLVDSClkSFT0 0x0000 +#define RLVDSClkSFT1 0x0008 /* default */ +#define EnableLVDSDCBal 0x0010 +#define DisableLVDSDCBal 0x0000 /* default */ +#define SinglePolarity 0x0020 /* default */ +#define MultiPolarity 0x0000 #define LCDPolarity 0x00c0 /* default: SyncNN */ +#define LCDSingleLink 0x0000 /* default */ #define LCDDualLink 0x0100 #define EnableSpectrum 0x0200 +#define DisableSpectrum 0x0000 /* default */ #define PWDEnable 0x0400 +#define PWDDisable 0x0000 /* default */ +#define PWMEnable 0x0800 +#define PWMDisable 0x0000 /* default */ #define EnableVBCLKDRVLOW 0x4000 +#define EnableVBCLKDRVHigh 0x0000 /* default */ #define EnablePLLSPLOW 0x8000 +#define EnablePLLSPHigh 0x0000 /* default */ #define LCDBToA 0x20 /* LCD SetFlag */ #define StLCDBToA 0x40 @@ -206,51 +616,187 @@ #define Monitor1Sense 0x20 #define HiTVSense 0x40 +#ifdef NewScratch #define YPbPrSense 0x80 /* NEW SCRATCH */ +#endif #define TVSense 0xc7 #define TVOverScan 0x10 /* CR35 */ +#define TVOverScanShift 4 +#ifdef NewScratch +#define NTSCMode 0x00 +#define PALMode 0x00 +#define NTSCJMode 0x02 +#define PALMNMode 0x0c #define YPbPrMode 0xe0 #define YPbPrMode525i 0x00 #define YPbPrMode525p 0x20 #define YPbPrMode750p 0x40 #define YPbPrMode1080i 0x60 +#else /* Old Scratch */ +#define ClearBufferFlag 0x20 +#endif #define LCDRGB18Bit 0x01 /* CR37 */ #define LCDNonExpanding 0x10 +#define LCDNonExpandingShift 4 #define LCDSync 0x20 #define LCDSyncBit 0xe0 /* H/V polarity & sync ID */ +#define LCDSyncShift 6 +#ifdef NewScratch #define ScalingLCD 0x08 +#else /* Old Scratch */ +#define ExtChipType 0x0e +#define ExtChip301 0x02 +#define ExtChipLVDS 0x04 +#define ExtChipCH7019 0x06 +#define ScalingLCD 0x10 +#endif #define EnableDualEdge 0x01 /* CR38 */ #define SetToLCDA 0x02 +#ifdef NewScratch #define SetYPbPr 0x04 +#define DisableChannelA 0x08 +#define DisableChannelB 0x10 +#define ExtChipType 0xe0 +#define ExtChip301 0x20 +#define ExtChipLVDS 0x40 +#define ExtChipCH7019 0x60 +#else /* Old Scratch */ +#define YPbPrSense 0x04 +#define SetYPbPr 0x08 +#define YPbPrMode 0x30 +#define YPbPrMode525i 0x00 +#define YPbPrMode525p 0x10 +#define YPbPrMode750p 0x20 +#define YPbPrMode1080i 0x30 +#define PALMNMode 0xc0 +#endif +#define BacklightControlBit 0x01 /* CR3A */ +#define Win9xforJap 0x40 +#define Win9xforKorea 0x80 + +#define ForceMDBits 0x07 /* CR3B */ +#define ForceMD_JDOS 0x00 +#define ForceMD_640x400T 0x01 +#define ForceMD_640x350T 0x02 +#define ForceMD_720x400T 0x03 +#define ForceMD_640x480E 0x04 +#define ForceMD_640x400E 0x05 +#define ForceP1Bit 0x10 +#define ForceP2Bit 0x20 +#define EnableForceMDinBIOS 0x40 +#define EnableForceMDinDrv 0x80 + +#ifdef NewScratch /* New Scratch */ /* ---------------------- VUMA Information */ +#define LCDSettingFromCMOS 0x04 /* CR3C */ +#define TVSettingFromCMOS 0x08 #define DisplayDeviceFromCMOS 0x10 +#define HKSupportInSBIOS 0x20 +#define OSDSupportInSBIOS 0x40 +#define DisableLogo 0x80 /* ---------------------- HK Evnet Definition */ +#define HKEvent 0x0f /* CR3D */ +#define HK_ModeSwitch 0x01 +#define HK_Expanding 0x02 +#define HK_OverScan 0x03 +#define HK_Brightness 0x04 +#define HK_Contrast 0x05 +#define HK_Mute 0x06 +#define HK_Volume 0x07 #define ModeSwitchStatus 0xf0 #define ActiveCRT1 0x10 #define ActiveLCD 0x0020 #define ActiveTV 0x40 #define ActiveCRT2 0x80 +#define TVSwitchStatus 0x1f /* CR3E */ #define ActiveAVideo 0x01 #define ActiveSVideo 0x02 #define ActiveSCART 0x04 #define ActiveHiTV 0x08 #define ActiveYPbPr 0x10 +#define EnableHKEvent 0x01 /* CR3F */ +#define EnableOSDEvent 0x02 +#define StartOSDEvent 0x04 +#define IgnoreHKEvent 0x08 +#define IgnoreOSDEvent 0x10 +#else /* Old Scratch */ +#define OSD_SBIOS 0x02 /* SR17 */ +#define DisableLogo 0x04 +#define SelectKDOS 0x08 +#define KorWinMode 0x10 +#define KorMode3Bit 0x0020 +#define PSCCtrlBit 0x40 +#define NPSCCtrlBitShift 6 +#define BlueScreenBit 0x80 + +#define HKEvent 0x0f /* CR79 */ +#define HK_ModeSwitch 0x01 +#define HK_Expanding 0x02 +#define HK_OverScan 0x03 +#define HK_Brightness 0x04 +#define HK_Contrast 0x05 +#define HK_Mute 0x06 +#define HK_Volume 0x07 +#define ActivePAL 0x0020 +#define ActivePALShift 5 +#define ActiveNonExpanding 0x40 +#define ActiveNonExpandingShift 6 +#define ActiveOverScan 0x80 +#define ActiveOverScanShift 7 + +#define ModeSwitchStatus 0x0b /* SR15 */ +#define ActiveCRT1 0x01 +#define ActiveLCD 0x02 +#define ActiveCRT2 0x08 + +#define TVSwitchStatus 0xf0 /* SR16 */ +#define TVConfigShift 3 +#define ActiveTV 0x01 +#define ActiveYPbPr 0x04 +#define ActiveAVideo 0x10 +#define ActiveSVideo 0x0020 +#define ActiveSCART 0x40 +#define ActiveHiTV 0x80 + +#define EnableHKEvent 0x01 /* CR7A */ +#define EnableOSDEvent 0x02 +#define StartOSDEvent 0x04 +#define CMOSSupport 0x08 +#define HotKeySupport 0x10 +#define IngoreHKOSDEvent 0x20 +#endif + +/* //------------- Misc. Definition */ +#define SelectCRT1Rate 00h +/* #define SelectCRT2Rate 04h */ + +#define DDC1DelayTime 1000 +#ifdef TRUMPION +#define DDC2DelayTime 15 +#else +#define DDC2DelayTime 150 +#endif + +#define R_FACTOR 04Dh +#define G_FACTOR 097h +#define B_FACTOR 01Ch /* --------------------------------------------------------- */ /* translated from asm code 301def.h */ /* */ /* --------------------------------------------------------- */ #define LCDDataLen 8 +#define HiTVDataLen 12 #define TVDataLen 12 #define LVDSCRT1Len_H 8 #define LVDSCRT1Len_V 7 @@ -260,6 +806,7 @@ #define LVDSDesDataLen2 8 #define LCDDesDataLen2 8 #define CHTVRegLen 16 +#define CHLVRegLen 12 #define StHiTVHT 892 #define StHiTVVT 1126 @@ -270,6 +817,7 @@ #define NTSCHT 1716 #define NTSCVT 525 #define NTSC1024x768HT 1908 +#define NTSC1024x768VT 525 #define PALHT 1728 #define PALVT 625 @@ -280,6 +828,8 @@ #define YPbPrTV750pHT 1650 #define YPbPrTV750pVT 750 +#define CRT2VCLKSel 0xc0 + #define CRT2Delay1 0x04 /* XGI301 */ #define CRT2Delay2 0x0A /* 301B,302 */ @@ -296,41 +846,57 @@ #define VCLK52_406 0x09 #define VCLK56_25 0x0A #define VCLK65 0x0B +#define VCLK67_765 0x0C #define VCLK68_179 0x0D #define VCLK72_852 0x0E #define VCLK75 0x0F +#define VCLK75_8 0x10 #define VCLK78_75 0x11 #define VCLK79_411 0x12 #define VCLK83_95 0x13 +#define VCLK84_8 0x14 #define VCLK86_6 0x15 #define VCLK94_5 0x16 +#define VCLK104_998 0x17 +#define VCLK105_882 0x18 #define VCLK108_2 0x19 +#define VCLK109_175 0x1A #define VCLK113_309 0x1B #define VCLK116_406 0x1C +#define VCLK132_258 0x1D #define VCLK135_5 0x1E #define VCLK139_054 0x1F #define VCLK157_5 0x20 #define VCLK162 0x21 #define VCLK175 0x22 #define VCLK189 0x23 +#define VCLK194_4 0x24 #define VCLK202_5 0x25 #define VCLK229_5 0x26 #define VCLK234 0x27 +#define VCLK252_699 0x28 #define VCLK254_817 0x29 +#define VCLK265_728 0x2A #define VCLK266_952 0x2B #define VCLK269_655 0x2C +#define VCLK272_042 0x2D #define VCLK277_015 0x2E +#define VCLK286_359 0x2F #define VCLK291_132 0x30 #define VCLK291_766 0x31 +#define VCLK309_789 0x32 #define VCLK315_195 0x33 #define VCLK323_586 0x34 #define VCLK330_615 0x35 +#define VCLK332_177 0x36 #define VCLK340_477 0x37 #define VCLK375_847 0x38 #define VCLK388_631 0x39 #define VCLK125_999 0x51 #define VCLK148_5 0x52 +#define VCLK178_992 0x54 #define VCLK217_325 0x55 +#define VCLK299_505 0x56 #define YPbPr750pVCLK 0x57 #define TVVCLKDIV2 0x3A @@ -340,13 +906,34 @@ #define HiTVSimuVCLK 0x3E #define HiTVTextVCLK 0x3F #define VCLK39_77 0x40 +/* #define YPbPr750pVCLK 0x0F */ #define YPbPr525pVCLK 0x3A +/* #define ;;YPbPr525iVCLK 0x3B */ +/* #define ;;YPbPr525iVCLK_2 0x3A */ #define NTSC1024VCLK 0x41 +#define VCLK25_175_41 0x42 /* ; ScaleLCD */ +#define VCLK25_175_42 0x43 +#define VCLK28_322_43 0x44 +#define VCLK40_44 0x45 +#define VCLKQVGA_1 0x46 /* ; QVGA */ +#define VCLKQVGA_2 0x47 +#define VCLKQVGA_3 0x48 #define VCLK35_2 0x49 /* ; 800x480 */ #define VCLK122_61 0x4A #define VCLK80_350 0x4B #define VCLK107_385 0x4C +#define CHTVVCLK30_2 0x50 /* ;;CHTV */ +#define CHTVVCLK28_1 0x51 +#define CHTVVCLK43_6 0x52 +#define CHTVVCLK26_4 0x53 +#define CHTVVCLK24_6 0x54 +#define CHTVVCLK47_8 0x55 +#define CHTVVCLK31_5 0x56 +#define CHTVVCLK26_2 0x57 +#define CHTVVCLK39 0x58 +#define CHTVVCLK36 0x59 + #define CH7007TVVCLK30_2 0x00 /* [Billy] 2007/05/18 For CH7007 */ #define CH7007TVVCLK28_1 0x01 #define CH7007TVVCLK43_6 0x02 @@ -431,4 +1018,5 @@ #define RES1280x960x85 0x46 #define RES1280x960x120 0x47 +#define LFBDRAMTrap 0x30 #endif diff --git a/trunk/drivers/staging/xgifb/vb_ext.h b/trunk/drivers/staging/xgifb/vb_ext.h index 0b1f55b4242f..814a446b70c8 100644 --- a/trunk/drivers/staging/xgifb/vb_ext.h +++ b/trunk/drivers/staging/xgifb/vb_ext.h @@ -1,6 +1,26 @@ #ifndef _VBEXT_ #define _VBEXT_ +struct DWORDREGS { + unsigned long Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp; +}; + +struct WORDREGS { + unsigned short ax, hi_ax, bx, hi_bx, cx, hi_cx, dx, hi_dx, si, + hi_si, di, hi_di, bp, hi_bp; +}; + +struct BYTEREGS { + unsigned char al, ah, hi_al, hi_ah, bl, bh, hi_bl, hi_bh, cl, ch, + hi_cl, hi_ch, dl, dh, hi_dl, hi_dh; +}; + +typedef union _X86_REGS { + struct DWORDREGS e; + struct WORDREGS x; + struct BYTEREGS h; +} X86_REGS, *PX86_REGS; + extern void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo); extern unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *, diff --git a/trunk/drivers/staging/xgifb/vb_setmode.c b/trunk/drivers/staging/xgifb/vb_setmode.c index 845e036bd788..dc4d6e6fc9b3 100644 --- a/trunk/drivers/staging/xgifb/vb_setmode.c +++ b/trunk/drivers/staging/xgifb/vb_setmode.c @@ -14,6 +14,9 @@ #define IndexMask 0xff +#ifndef XGI_MASK_DUAL_CHIP +#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */ +#endif static unsigned short XGINew_MDA_DAC[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/trunk/drivers/staging/xgifb/vb_struct.h b/trunk/drivers/staging/xgifb/vb_struct.h index 3ef79e08857e..377d27c0c332 100644 --- a/trunk/drivers/staging/xgifb/vb_struct.h +++ b/trunk/drivers/staging/xgifb/vb_struct.h @@ -1,6 +1,16 @@ #ifndef _VB_STRUCT_ #define _VB_STRUCT_ +#ifdef _INITNEW_ +#define EXTERN +#else +#define EXTERN extern +#endif + +struct XGI_PanelDelayTblStruct { + unsigned char timer[2]; +}; + struct XGI_LCDDataStruct { unsigned short RVBHCMAX; unsigned short RVBHCFACT; @@ -35,6 +45,24 @@ struct XGI_TVDataStruct { unsigned char RY4COE; }; +struct XGI_LVDSDataStruct { + unsigned short VGAHT; + unsigned short VGAVT; + unsigned short LCDHT; + unsigned short LCDVT; +}; + +struct XGI_LVDSDesStruct { + unsigned short LCDHDES; + unsigned short LCDVDES; +}; + +struct XGI_LVDSCRT1DataStruct { + unsigned char CR[15]; +}; + +/*add for LCDA*/ + struct XGI_StStruct { unsigned char St_ModeID; unsigned short St_ModeFlag; @@ -118,6 +146,10 @@ struct XGI_ModeResInfoStruct { unsigned char YChar; }; +struct XGI_LCDNBDesStruct { + unsigned char NB[12]; +}; + /*add for new UNIVGABIOS*/ struct XGI_LCDDesStruct { unsigned short LCDHDES; @@ -133,6 +165,12 @@ struct XGI_LCDDataTablStruct { unsigned short DATAPTR; }; +struct XGI_TVTablDataStruct { + unsigned short MASK; + unsigned short CAP; + unsigned short DATAPTR; +}; + struct XGI330_LCDDataDesStruct { unsigned short LCDHDES; unsigned short LCDHRS; @@ -220,6 +258,10 @@ struct XGI_XG21CRT1Struct { unsigned char ModeID, CR02, CR03, CR15, CR16; }; +struct XGI330_CHTVRegDataStruct { + unsigned char Reg[16]; +}; + struct XGI330_LCDCapStruct { unsigned char LCD_ID; unsigned short LCD_Capability; @@ -282,6 +324,18 @@ struct XGI301C_Tap4TimingStruct { unsigned char Reg[64]; /* C0-FF */ }; +struct XGI_New_StandTableStruct { + unsigned char CRT_COLS; + unsigned char ROWS; + unsigned char CHAR_HEIGHT; + unsigned short CRT_LEN; + unsigned char SR[4]; + unsigned char MISC; + unsigned char CRTC[0x19]; + unsigned char ATTR[0x14]; + unsigned char GRC[9]; +}; + struct vb_device_info { unsigned char ISXPDOS; unsigned long P3c4, P3d4, P3c0, P3ce, P3c2, P3cc; @@ -408,4 +462,21 @@ struct vb_device_info { struct XGI_XG21CRT1Struct *UpdateCRT1; }; /* _struct vb_device_info */ + +struct TimingInfo { + unsigned short Horizontal_ACTIVE; + unsigned short Horizontal_FP; + unsigned short Horizontal_SYNC; + unsigned short Horizontal_BP; + unsigned short Vertical_ACTIVE; + unsigned short Vertical_FP; + unsigned short Vertical_SYNC; + unsigned short Vertical_BP; + double DCLK; + unsigned char FrameRate; + unsigned char Interlace; + unsigned short Margin; +}; + +#define _VB_STRUCT_ #endif /* _VB_STRUCT_ */ diff --git a/trunk/drivers/staging/xgifb/vb_table.h b/trunk/drivers/staging/xgifb/vb_table.h index 0184292fc7eb..d10de4888dc3 100644 --- a/trunk/drivers/staging/xgifb/vb_table.h +++ b/trunk/drivers/staging/xgifb/vb_table.h @@ -173,6 +173,37 @@ static unsigned char XGI340_AGPReg[12] = { static unsigned char XGI340_SR16[4] = {0x03, 0x83, 0x03, 0x83}; +#if 0 +static unsigned char XGI330_SR15_1[8][8] = { + {0x0, 0x0, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00}, + {0x5, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00}, + {0xba, 0xba, 0xba, 0xba, 0xBA, 0xBA, 0x00, 0x00}, + {0x55, 0x57, 0x57, 0xAB, 0xAB, 0xAB, 0x00, 0x00}, + {0x60, 0x34, 0x34, 0x34, 0x34, 0x34, 0x00, 0x00}, + {0x0, 0x80, 0x80, 0x80, 0x83, 0x83, 0x00, 0x00}, + {0x50, 0x50, 0x50, 0x3C, 0x3C, 0x3C, 0x00, 0x00}, + {0x0, 0xa5, 0xfb, 0xf6, 0xF6, 0xF6, 0x00, 0x00} +}; + +static unsigned char XGI330_cr40_1[15][8] = { + {0x66, 0x40, 0x40, 0x28, 0x24, 0x24, 0x00, 0x00}, + {0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, + {0x00, 0xf0, 0xf0, 0xf0, 0xF0, 0xF0, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x88, 0x88, 0x88, 0xAA, 0xAC, 0xAC, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0xA2, 0x00, 0x00, 0xA2, 0xA2, 0x00, 0x00}, +}; +#endif + static unsigned char XGI330_sr25[] = {0x00, 0x0}; static unsigned char XGI330_sr31 = 0xc0; static unsigned char XGI330_sr32 = 0x11; @@ -976,6 +1007,112 @@ static struct XGI_CRT1TableStruct XGI_CRT1Table[] = { 0x03, 0xDE, 0xC0, 0x84, 0xBF, 0x04, 0x90} } /* 0x47 */ }; +#if 0 +static struct XGI330_CHTVRegDataStruct XGI_CHTVRegUNTSC[] = { + /* Index: 000h, 001h, 002h, 004h, 003h, 005h, 006h, 007h, + 008h, 015h, 01Fh, 00Ch, 00Dh, 00Eh, 00Fh, 010h */ + /* 00 (640x200,640x400) */ + { {0x4A, 0x77, 0xBB, 0x94, 0x84, 0x48, 0xFE, 0x50, + 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 } }, + /* 01 (640x350) */ + { {0x4A, 0x77, 0xBB, 0x94, 0x84, 0x48, 0xFE, 0x50, + 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 } }, + /* 02 (720x400) */ + { {0x4A, 0x77, 0xBB, 0x94, 0x84, 0x48, 0xFE, 0x50, + 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 } }, + /* 03 (720x350) */ + { {0x4A, 0x77, 0xBB, 0x94, 0x84, 0x48, 0xFE, 0x50, + 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 } }, + /* 04 (640x480) ;;5/6/02 */ + { {0x6A, 0x77, 0xBB, 0x6E, 0x84, 0x2E, 0x02, 0x5A, + 0x04, 0x00, 0x80, 0x20, 0x7E, 0x80, 0x97, 0x00 } }, + /* 05 (800x600) ;;1/12/02 */ + { {0xCF, 0x77, 0xB7, 0xC8, 0x84, 0x3B, 0x02, 0x5A, + 0x04, 0x00, 0x80, 0x19, 0x88, 0xAE, 0xA3, 0x00 } }, + /* 06 (1024x768) ;;5/6/02 */ + { {0xEE, 0x77, 0xBB, 0x66, 0x87, 0x32, 0x01, 0x5A, + 0x04, 0x00, 0x80, 0x1B, 0xD4, 0x2F, 0x6F, 0x00 } } +}; + +static struct XGI330_CHTVRegDataStruct XGI_CHTVRegONTSC[] = { + /* Index: 000h, 001h, 002h, 004h, 003h, 005h, 006h, 007h, + 008h, 015h, 01Fh, 00Ch, 00Dh, 00Eh, 00Fh, 010h */ + /* 00 (640x200,640x400) */ + { {0x49, 0x77, 0xBB, 0x7B, 0x84, 0x34, 0x00, 0x50, + 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* 01 (640x350) */ + { {0x49, 0x77, 0xBB, 0x7B, 0x84, 0x34, 0x00 , 0x50, + 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* 02 (720x400) */ + { {0x49, 0x77, 0xBB, 0x7B, 0x84, 0x34, 0x00 , 0x50, + 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* 03 (720x350) */ + { {0x49, 0x77, 0xBB, 0x7B, 0x84, 0x34, 0x00 , 0x50, + 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* 04 (640x480) ;;5/6/02 */ + { {0x69, 0x77, 0xBB, 0x6E, 0x84, 0x1E, 0x00 , 0x5A, + 0x04, 0x00, 0x80, 0x25, 0x1A, 0x80, 0x26, 0x00} }, + /* 05 (800x600) ;;5/6/02 */ + { {0xCE, 0x77, 0xB7, 0xB6, 0x83, 0x2C, 0x02 , 0x5A, + 0x04, 0x00, 0x80, 0x1C, 0x00, 0x82, 0x97, 0x00} }, + /* 06 (1024x768) ;;5/6/02 */ + { {0xED, 0x77, 0xBB, 0x66, 0x8C, 0x21, 0x02 , 0x5A, + 0x04, 0x00, 0x80, 0x1F, 0xA0, 0x7E, 0x73, 0x00} } +}; + +static struct XGI330_CHTVRegDataStruct XGI_CHTVRegUPAL[] = { + /* Index: 000h, 001h, 002h, 004h, 003h, 005h, 006h, 007h, + 008h, 015h, 01Fh, 00Ch, 00Dh, 00Eh, 00Fh, 010h */ + /* ; 00 (640x200,640x400) */ + { {0x41, 0x7F, 0xB7, 0x34, 0xAD, 0x50, 0x34, 0x83, + 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* ; 01 (640x350) */ + { {0x41, 0x7F, 0xB7, 0x80, 0x85, 0x50, 0x00, 0x83, + 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* ; 02 (720x400) */ + { {0x41, 0x7F, 0xB7, 0x34, 0xAD, 0x50, 0x34, 0x83, + 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* ; 03 (720x350) */ + { {0x41, 0x7F, 0xB7, 0x12, 0x85, 0x50, 0x00, 0x83, + 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* ; 04 (640x480) */ + { {0x61, 0x7F, 0xB7, 0x99, 0x84, 0x35, 0x04, 0x5A, + 0x05, 0x00, 0x80, 0x26, 0x2A, 0x55, 0x5D, 0x00} }, + /* ; 05 (800x600) ;;1/12/02 */ + { {0xC3, 0x7F, 0xB7, 0x7A, 0x84, 0x40, 0x02, 0x5A, + 0x05, 0x00, 0x80, 0x1F, 0x84, 0x3D, 0x28, 0x00} }, + /* ; 06 (1024x768) ;;1/12/02 */ + { {0xE5, 0x7F, 0xB7, 0x1D, 0xA7, 0x3E, 0x04, 0x5A, + 0x05, 0x00, 0x80, 0x20, 0x3E, 0xE4, 0x22, 0x00} } +}; + +static struct XGI330_CHTVRegDataStruct XGI_CHTVRegOPAL[] = { + /* Index: 000, 0x01, 0x02, 0x04, 0x03, 0x05, 0x06, 0x07, + 0x08, 0x15, 0x1F, 0x0C, 0x0D, 0x0E, 0x0F, 0x10h */ + /* 00 (640x200,640x400) */ + { {0x41, 0x7F, 0xB7, 0x36, 0xAD, 0x50, 0x34, 0x83, + 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* 01 (640x350) */ + { {0x41, 0x7F, 0xB7, 0x86, 0x85, 0x50, 0x00, 0x83, + 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* 02 (720x400) */ + { {0x41, 0x7F, 0xB7, 0x36, 0xAD, 0x50, 0x34, 0x83, + 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* 03 (720x350) */ + { {0x41, 0x7F, 0xB7, 0x86, 0x85, 0x50, 0x00, 0x83, + 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01} }, + /* 04 (640x480) */ + { {0x61, 0x7F, 0xB7, 0x99, 0x84, 0x35, 0x04, 0x5A, + 0x05, 0x00, 0x80, 0x26, 0x2A, 0x55, 0x5D, 0x00} }, + /* 05 (800x600) ;;1/12/02 */ + { {0xC1, 0x7F, 0xB7, 0x4D, 0x8C, 0x1E, 0x31, 0x5A, + 0x05, 0x00, 0x80, 0x26, 0x78, 0x19, 0x34, 0x00} }, + /* 06 (1024x768) ;;1/12/02 */ + { {0xE4, 0x7F, 0xB7, 0x1E, 0xAF, 0x29, 0x37, 0x5A, + 0x05, 0x00, 0x80, 0x25, 0x8C, 0xB2, 0x2A, 0x00} } +}; +#endif + static unsigned char XGI_CH7017LV1024x768[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xED, 0xA3, 0xC8, 0xC7, 0xAC, 0xE0, 0x02}; @@ -1014,6 +1151,16 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1024x768Data[] = { {1, 1, 1344, 806, 1344, 806} }; +/*struct XGI330_LCDDataStruct XGI_St2LCD1024x768Data[] = { + {62, 25, 800, 546, 1344, 806}, + {32, 15, 930, 546, 1344, 806}, + {62, 25, 800, 546, 1344, 806}, + {104, 45, 945, 496, 1344, 806}, + {62, 25, 800, 546, 1344, 806}, + {31, 18, 1008, 624, 1344, 806}, + {1, 1, 1344, 806, 1344, 806} +};*/ + static struct XGI330_LCDDataStruct XGI_CetLCD1024x768Data[] = { {1, 1, 1344, 806, 1344, 806}, /* ; 00 (320x200,320x400, 640x200,640x400) */ @@ -1047,6 +1194,19 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1280x1024Data[] = { {1, 1, 1688, 1066, 1688, 1066} }; +#if 0 +static struct XGI330_LCDDataStruct XGI_St2LCD1280x1024Data[] = { + {22, 5, 800, 510, 1650, 1088}, + {22, 5, 800, 510, 1650, 1088}, + {176, 45, 900, 510, 1650, 1088}, + {176, 45, 900, 510, 1650, 1088}, + {22, 5, 800, 510, 1650, 1088}, + {13, 5, 1024, 675, 1560, 1152}, + {16, 9, 1266, 804, 1688, 1072}, + {1, 1, 1688, 1066, 1688, 1066} +}; +#endif + static struct XGI330_LCDDataStruct XGI_CetLCD1280x1024Data[] = { {1, 1, 1688, 1066, 1688, 1066}, /* 00 (320x200,320x400, 640x200,640x400) */ @@ -1155,6 +1315,19 @@ static struct XGI330_LCDDataStruct XGI_ExtLCD1024x768x75Data[] = { {1, 1, 1312, 800, 1312, 800} /* ; 06 (1024x768x75Hz) */ }; +#if 0 +static struct XGI330_LCDDataStruct XGI_StLCD1024x768x75Data[] = { + {42, 25, 1536, 419, 1344, 806}, /* ; 00 (320x200,320x400, + 640x200,640x400) */ + {48, 25, 1536, 369, 1344, 806}, /* ; 01 (320x350,640x350) */ + {42, 25, 1536, 419, 1344, 806}, /* ; 02 (360x400,720x400) */ + {48, 25, 1536, 369, 1344, 806}, /* ; 03 (720x350) */ + {8, 5, 1312, 500, 1312, 800}, /* ; 04 (640x480x75Hz) */ + {41, 25, 1024, 625, 1312, 800}, /* ; 05 (800x600x75Hz) */ + {1, 1, 1312, 800, 1312, 800} /* ; 06 (1024x768x75Hz) */ +}; +#endif + static struct XGI330_LCDDataStruct XGI_CetLCD1024x768x75Data[] = { {1, 1, 1312, 800, 1312, 800}, /* ; 00 (320x200,320x400, 640x200,640x400) */ @@ -1868,6 +2041,63 @@ static unsigned char XGI330_Ren750pGroup3[] = { 0x18, 0x1D, 0x23, 0x28, 0x4C, 0xAA, 0x01 }; +#if 0 +static struct XGI_PanelDelayTblStruct XGI330_PanelDelayTbl[] = { + { {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} } +}; + +static struct XGI330_LVDSDataStruct XGI330_LVDS320x480Data_1[] = { + {848, 433, 400, 525}, + {848, 389, 400, 525}, + {848, 433, 400, 525}, + {848, 389, 400, 525}, + {848, 518, 400, 525}, + {1056, 628, 400, 525}, + {400, 525, 400, 525}, + {800, 449, 1000, 644}, + {800, 525, 1000, 635} +}; + +static struct XGI330_LVDSDataStruct XGI330_LVDS800x600Data_1[] = { + {848, 433, 1060, 629}, + {848, 389, 1060, 629}, + {848, 433, 1060, 629}, + {848, 389, 1060, 629}, + {848, 518, 1060, 629}, + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628}, + {800, 449, 1000, 644}, + {800, 525, 1000, 635} +}; + +static struct XGI330_LVDSDataStruct XGI330_LVDS800x600Data_2[] = { + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628}, + {800, 449, 1000, 644}, + {800, 525, 1000, 635} +}; +#endif + static struct XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1[] = { { 960, 438, 1344, 806}, /* 00 (320x200,320x400,640x200,640x400) */ { 960, 388, 1344, 806}, /* 01 (320x350,640x350) */ @@ -1913,7 +2143,79 @@ static struct XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2[] = { {800, 449, 1280, 801}, {800, 525, 1280, 813} }; +/* +struct XGI330_LVDSDataStruct XGI_LVDS1280x768Data_1[] = { + {768, 438, 1408, 806}, + {768, 388, 1408, 806}, + {768, 438, 1408, 806}, + {768, 388, 1408, 806}, + {768, 518, 1408, 806}, + {928, 638, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806} +}; + +struct XGI330_LVDSDataStruct XGI_LVDS1280x768Data_2[] = { + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806} +}; + +struct XGI330_LVDSDataStruct XGI_LVDS1280x768NData_1[] = { + {704, 438, 1344, 806}, + {704, 388, 1344, 806}, + {704, 438, 1344, 806}, + {704, 388, 1344, 806}, + {704, 518, 1344, 806}, + {864, 638, 1344, 806}, + {1088, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806} +}; +struct XGI330_LVDSDataStruct XGI_LVDS1280x768NData_2[] = { + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806}, + {1344, 806, 1344, 806} +}; + +struct XGI330_LVDSDataStruct XGI_LVDS1280x768SData_1[] = { + {1048, 438, 1688, 806}, + {1048, 388, 1688, 806}, + {1148, 438, 1688, 806}, + {1148, 388, 1688, 806}, + {1048, 518, 1688, 806}, + {1208, 638, 1688, 806}, + {1432, 806, 1688, 806}, + {1688, 806, 1688, 806}, + {1688, 806, 1688, 806} +}; + +struct XGI330_LVDSDataStruct XGI_LVDS1280x768SData_2[] = { + {1688, 806, 1688, 806}, + {1688, 806, 1688, 806}, + {1688, 806, 1688, 806}, + {1688, 806, 1688, 806}, + {1688, 806, 1688, 806}, + {1688, 806, 1688, 806}, + {1688, 806, 1688, 806}, + {1688, 806, 1688, 806}, + {1688, 806, 1688, 806} +}; +*/ static struct XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_1[] = { {928, 416, 1688, 1066}, {928, 366, 1688, 1066}, @@ -2200,6 +2502,20 @@ static struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = { {0, 1328, 0, 771, 112, 6} /* ; 0A (1280x768x75Hz) */ }; +#if 0 +static struct XGI330_LVDSDataStruct XGI330_LVDS640x480Data_1[] = { + { 800, 449, 800, 449}, + { 800, 449, 800, 449}, + { 800, 449, 800, 449}, + { 800, 449, 800, 449}, + { 800, 525, 800, 525}, + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628}, + {1056, 628, 1056, 628} +}; +#endif + static struct XGI330_CHTVDataStruct XGI_CHTVUNTSCData[] = { { 840, 600, 840, 600}, { 840, 600, 840, 600}, @@ -2489,6 +2805,68 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[] = { { {0x28, 0x5A, 0x13, 0x87, 0xFF, 0x29, 0xA9} } /* ; 05 (x1024) */ }; +#if 0 +static struct XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UNTSC[] = { + { {0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e, + 0xe8, 0x84, 0x8f, 0x57, 0x20, 0x00, 0x01, 0x00 } }, + { {0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e, + 0xd0, 0x82, 0x5d, 0x57, 0x00, 0x00, 0x01, 0x00 } }, + { {0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e, + 0xe8, 0x84, 0x8f, 0x57, 0x20, 0x00, 0x01, 0x00 } }, + { {0x64, 0x4f, 0x88, 0x56, 0x9f, 0x56, 0x3e, + 0xd0, 0x82, 0x5d, 0x57, 0x00, 0x00, 0x01, 0x00 } }, + { {0x5d, 0x4f, 0x81, 0x53, 0x9c, 0x56, 0xba, + 0x18, 0x84, 0xdf, 0x57, 0x00, 0x00, 0x01, 0x00 } }, + { {0x80, 0x63, 0x84, 0x6c, 0x17, 0xec, 0xf0, + x90, 0x8c, 0x57, 0xed, 0x20, 0x00, 0x06, 0x01 } } +}; + +static struct XGI_LVDSCRT1DataStruct XGI_CHTVCRT1ONTSC[] = { + { {0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e, + 0xc0, 0x84, 0x8f, 0x0c, 0x20, 0x00, 0x01, 0x00 } }, + { {0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e, + 0xb0, 0x8d, 0x5d, 0x0c, 0x00, 0x00, 0x01, 0x00 } }, + { {0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e, + 0xc0, 0x84, 0x8f, 0x0c, 0x20, 0x00, 0x01, 0x00 } }, + { {0x64, 0x4f, 0x88, 0x5a, 0x9f, 0x0b, 0x3e, + 0xb0, 0x8d, 0x5d, 0x0c, 0x00, 0x00, 0x01, 0x00 } }, + { {0x5d, 0x4f, 0x81, 0x56, 0x9c, 0x0b, 0x3e, + 0xe8, 0x84, 0xdf, 0x0c, 0x00, 0x00, 0x01, 0x00 } }, + { {0x7d, 0x63, 0x81, 0x6a, 0x16, 0xba, 0xf0, + x7f, 0x86, 0x57, 0xbb, 0x00, 0x00, 0x06, 0x01 } } +}; + +static struct XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UPAL[] = { + { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e, + 0xf8, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05, 0x00 } }, + { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e, + 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05, 0x00 } }, + { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e, + 0xf8, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05, 0x00 } }, + { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e, + 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05, 0x00 } }, + { {0x64, 0x4f, 0x88, 0x55, 0x80, 0xec, 0xba, + 0x50, 0x84, 0xdf, 0xed, 0x00, 0x00, 0x05, 0x00 } }, + { {0x70, 0x63, 0x94, 0x68, 0x8d, 0x42, 0xf1, + xc8, 0x8c, 0x57, 0xe9, 0x20, 0x00, 0x05, 0x01 } } +}; + +static struct XGI_LVDSCRT1DataStruct XGI_CHTVCRT1OPAL[] = { + { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e, + 0xf0, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05, 0x00 } }, + { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e, + 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05, 0x00 } }, + { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e, + 0xf0, 0x83, 0x8f, 0x70, 0x20, 0x00, 0x05, 0x00 } }, + { {0x79, 0x4f, 0x9d, 0x5a, 0x90, 0x6f, 0x3e, + 0xde, 0x81, 0x5d, 0x70, 0x00, 0x00, 0x05, 0x00 } }, + { {0x64, 0x4f, 0x88, 0x55, 0x80, 0x6f, 0xba, + 0x20, 0x83, 0xdf, 0x70, 0x00, 0x00, 0x05, 0x00 } }, + { {0x73, 0x63, 0x97, 0x69, 0x8e, 0xec, 0xf0, + x90, 0x8c, 0x57, 0xed, 0x20, 0x00, 0x05, 0x01 } } +}; +#endif + /*add for new UNIVGABIOS*/ static struct XGI330_LCDDataTablStruct XGI_LCDDataTable[] = { {Panel1024x768, 0x0019, 0x0001, 0}, /* XGI_ExtLCD1024x768Data */ @@ -2629,6 +3007,19 @@ static struct XGI330_TVDataTablStruct XGI_TVDataTable[] = { {0xffff, 0x0000, 12} /* END */ }; +#if 0 +static unsigned short TVLenList[] = { + LVDSCRT1Len_H, + LVDSCRT1Len_V, + LVDSDataLen, + 0, + TVDataLen, + 0, + 0, + CHTVRegLen +}; +#endif + /* Chrontel 7017 TV CRT1 Timing List */ static struct XGI330_TVDataTablStruct XGI_EPLCHTVCRT1Ptr[] = { {0x0011, 0x0000, 0}, /* XGI_CHTVCRT1UNTSC */ @@ -2669,6 +3060,44 @@ static unsigned short LCDLenList[] = { 0 }; +#if 0 +/* 660, Dual link */ +static struct XGI330_LCDCapStruct XGI660_LCDDLCapList[] = { +/* LCDCap1024x768 */ + {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024 */ + {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, + 0x053, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1400x1050 */ + {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, + 0x053, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1600x1200 */ + {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, + 0x053, 0xC0, 0x03, VCLK162, + 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1024x768x75 */ + {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75, + 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024x75 */ + {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, + 0x053, 0x90, 0x03, VCLK135_5, + 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCapDefault */ + {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} +}; +#endif + /* Dual link only */ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = { /* LCDCap1024x768 */ @@ -2705,6 +3134,40 @@ static struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = { 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} }; +#if 0 +static struct XGI330_LCDCapStruct XGI660_LCDCapList[] = { +/* LCDCap1024x768 */ + {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024 */ + {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1400x1050 */ + {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1600x1200 */ + {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162, + 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1024x768x75 */ + {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75, + 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024x75 */ + {Panel1280x1024x75, + DefaultLCDCap, StLCDBToA, + 0x053, 0x90, 0x03, VCLK135_5, + 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCapDefault */ + {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} +}; +#endif + static struct XGI330_LCDCapStruct XGI_LCDCapList[] = { /* LCDCap1024x768 */ {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, @@ -2921,6 +3384,169 @@ static struct XGI_Ext2Struct XGI330_RefIndex[] = { 0x30, 0x47, 0x37, 1024, 768},/* 48 1024x768x160Hz */ }; + +#if 0 +static struct XGI330_VCLKDataStruct XGI330_VCLKData[] = { + {0x1b, 0xe1, 25}, /* 0x0 */ + {0x4e, 0xe4, 28}, /* 0x1 */ + {0x57, 0xe4, 31}, /* 0x2 */ + {0xc3, 0xc8, 36}, /* 0x3 */ + {0x42, 0xe2, 40}, /* 0x4 */ + {0xfe, 0xcd, 43}, /* 0x5 */ + {0x5d, 0xc4, 44}, /* 0x6 */ + {0x52, 0xe2, 49}, /* 0x7 */ + {0x53, 0xe2, 50}, /* 0x8 */ + {0x74, 0x67, 52}, /* 0x9 */ + {0x6d, 0x66, 56}, /* 0xa */ + {0x6c, 0xc3, 65}, /* 0xb */ + {0x46, 0x44, 67}, /* 0xc */ + {0xb1, 0x46, 68}, /* 0xd */ + {0xd3, 0x4a, 72}, /* 0xe */ + {0x29, 0x61, 75}, /* 0xf */ + {0x6e, 0x46, 76}, /* 0x10 */ + {0x2b, 0x61, 78}, /* 0x11 */ + {0x31, 0x42, 79}, /* 0x12 */ + {0xab, 0x44, 83}, /* 0x13 */ + {0x46, 0x25, 84}, /* 0x14 */ + {0x78, 0x29, 86}, /* 0x15 */ + {0x62, 0x44, 94}, /* 0x16 */ + {0x2b, 0x41, 104}, /* 0x17 */ + {0x3a, 0x23, 105}, /* 0x18 */ + {0x70, 0x44, 108}, /* 0x19 */ + {0x3c, 0x23, 109}, /* 0x1a */ + {0x5e, 0x43, 113}, /* 0x1b */ + {0xbc, 0x44, 116}, /* 0x1c */ + {0xe0, 0x46, 132}, /* 0x1d */ + {0x54, 0x42, 135}, /* 0x1e */ + {0xea, 0x2a, 139}, /* 0x1f */ + {0x41, 0x22, 157}, /* 0x20 */ + {0x70, 0x24, 162}, /* 0x21 */ + {0x30, 0x21, 175}, /* 0x22 */ + {0x4e, 0x22, 189}, /* 0x23 */ + {0xde, 0x26, 194}, /* 0x24 */ + {0x62, 0x06, 202}, /* 0x25 */ + {0x3f, 0x03, 229}, /* 0x26 */ + {0xb8, 0x06, 234}, /* 0x27 */ + {0x34, 0x02, 253}, /* 0x28 */ + {0x58, 0x04, 255}, /* 0x29 */ + {0x24, 0x01, 265}, /* 0x2a */ + {0x9b, 0x02, 267}, /* 0x2b */ + {0x70, 0x05, 270}, /* 0x2c */ + {0x25, 0x01, 272}, /* 0x2d */ + {0x9c, 0x02, 277}, /* 0x2e */ + {0x27, 0x01, 286}, /* 0x2f */ + {0x3c, 0x02, 291}, /* 0x30 */ + {0xef, 0x0a, 292}, /* 0x31 */ + {0xf6, 0x0a, 310}, /* 0x32 */ + {0x95, 0x01, 315}, /* 0x33 */ + {0xf0, 0x09, 324}, /* 0x34 */ + {0xfe, 0x0a, 331}, /* 0x35 */ + {0xf3, 0x09, 332}, /* 0x36 */ + {0xea, 0x08, 340}, /* 0x37 */ + {0xe8, 0x07, 376}, /* 0x38 */ + {0xde, 0x06, 389}, /* 0x39 */ + {0x52, 0x2a, 54}, /* 0x3a */ + {0x52, 0x6a, 27}, /* 0x3b */ + {0x62, 0x24, 70}, /* 0x3c */ + {0x62, 0x64, 70}, /* 0x3d */ + {0xa8, 0x4c, 30}, /* 0x3e */ + {0x20, 0x26, 33}, /* 0x3f */ + {0x31, 0xc2, 39}, /* 0x40 */ + {0x60, 0x36, 30}, /* 0x41 */ + {0x40, 0x4A, 28}, /* 0x42 */ + {0x9F, 0x46, 44}, /* 0x43 */ + {0x97, 0x2C, 26}, /* 0x44 */ + {0x44, 0xE4, 25}, /* 0x45 */ + {0x7E, 0x32, 47}, /* 0x46 */ + {0x08, 0x24, 31}, /* 0x47 */ + {0x97, 0x2c, 26}, /* 0x48 */ + {0xCE, 0x3c, 39}, /* 0x49 */ + {0x52, 0x4A, 36}, /* 0x4a */ + {0x2C, 0x61, 95}, /* 0x4b */ + {0x78, 0x27, 108}, /* 0x4c */ + {0x66, 0x43, 123}, /* 0x4d */ + {0x2c, 0x61, 80}, /* 0x4e */ + {0x3b, 0x61, 108} /* 0x4f */ +}; + +static struct XGI_VBVCLKDataStruct XGI330_VBVCLKData[] = { + {0x1b, 0xe1, 25}, /* 0x0 */ + {0x4e, 0xe4, 28}, /* 0x1 */ + {0x57, 0xe4, 31}, /* 0x2 */ + {0xc3, 0xc8, 36}, /* 0x3 */ + {0x42, 0x47, 40}, /* 0x4 */ + {0xfe, 0xcd, 43}, /* 0x5 */ + {0x5d, 0xc4, 44}, /* 0x6 */ + {0x52, 0x47, 49}, /* 0x7 */ + {0x53, 0x47, 50}, /* 0x8 */ + {0x74, 0x67, 52}, /* 0x9 */ + {0x6d, 0x66, 56}, /* 0xa */ + {0x5a, 0x64, 65}, /* 0xb */ + {0x46, 0x44, 67}, /* 0xc */ + {0xb1, 0x46, 68}, /* 0xd */ + {0xd3, 0x4a, 72}, /* 0xe */ + {0x29, 0x61, 75}, /* 0xf */ + {0x6d, 0x46, 75}, /* 0x10 */ + {0x41, 0x43, 78}, /* 0x11 */ + {0x31, 0x42, 79}, /* 0x12 */ + {0xab, 0x44, 83}, /* 0x13 */ + {0x46, 0x25, 84}, /* 0x14 */ + {0x78, 0x29, 86}, /* 0x15 */ + {0x62, 0x44, 94}, /* 0x16 */ + {0x2b, 0x22, 104}, /* 0x17 */ + {0x49, 0x24, 105}, /* 0x18 */ + {0xf8, 0x2f, 108}, /* 0x19 */ + {0x3c, 0x23, 109}, /* 0x1a */ + {0x5e, 0x43, 113}, /* 0x1b */ + {0xbc, 0x44, 116}, /* 0x1c */ + {0xe0, 0x46, 132}, /* 0x1d */ + {0xd4, 0x28, 135}, /* 0x1e */ + {0xea, 0x2a, 139}, /* 0x1f */ + {0x41, 0x22, 157}, /* 0x20 */ + {0x70, 0x24, 162}, /* 0x21 */ + {0x30, 0x21, 175}, /* 0x22 */ + {0x4e, 0x22, 189}, /* 0x23 */ + {0xde, 0x26, 194}, /* 0x24 */ + {0x70, 0x07, 202}, /* 0x25 */ + {0x3f, 0x03, 229}, /* 0x26 */ + {0xb8, 0x06, 234}, /* 0x27 */ + {0x34, 0x02, 253}, /* 0x28 */ + {0x58, 0x04, 255}, /* 0x29 */ + {0x24, 0x01, 265}, /* 0x2a */ + {0x9b, 0x02, 267}, /* 0x2b */ + {0x70, 0x05, 270}, /* 0x2c */ + {0x25, 0x01, 272}, /* 0x2d */ + {0x9c, 0x02, 277}, /* 0x2e */ + {0x27, 0x01, 286}, /* 0x2f */ + {0x3c, 0x02, 291}, /* 0x30 */ + {0xef, 0x0a, 292}, /* 0x31 */ + {0xf6, 0x0a, 310}, /* 0x32 */ + {0x95, 0x01, 315}, /* 0x33 */ + {0xf0, 0x09, 324}, /* 0x34 */ + {0xfe, 0x0a, 331}, /* 0x35 */ + {0xf3, 0x09, 332}, /* 0x36 */ + {0xea, 0x08, 340}, /* 0x37 */ + {0xe8, 0x07, 376}, /* 0x38 */ + {0xde, 0x06, 389}, /* 0x39 */ + {0x52, 0x2a, 54}, /* 0x3a */ + {0x52, 0x6a, 27}, /* 0x3b */ + {0x62, 0x24, 70}, /* 0x3c */ + {0x62, 0x64, 70}, /* 0x3d */ + {0xa8, 0x4c, 30}, /* 0x3e */ + {0x20, 0x26, 33}, /* 0x3f */ + {0x31, 0xc2, 39}, /* 0x40 */ + {0x2e, 0x48, 25}, /* 0x41 */ + {0x24, 0x46, 25}, /* 0x42 */ + {0x26, 0x64, 28}, /* 0x43 */ + {0x37, 0x64, 40}, /* 0x44 */ + {0xa1, 0x42, 108}, /* 0x45 */ + {0x37, 0x61, 100}, /* 0x46 */ + {0x78, 0x27, 108}, /* 0x47 */ + {0x5e, 0x64, 68}, /* 0x48 chiawen for fuj1280x768*/ + {0x70, 0x44, 108}, /* 0x49 chiawen for 1400x1050*/ +}; +#endif + static unsigned char XGI330_ScreenOffset[] = { 0x14, 0x19, 0x20, 0x28, 0x32, 0x40, 0x50, 0x64, 0x78, 0x80, 0x2d, 0x35, @@ -2965,13 +3591,46 @@ static unsigned char XGI330_OutputSelect = 0x40; static unsigned char XGI330_SoftSetting = 0x30; static unsigned char XGI330_SR07 = 0x18; +#if 0 +static unsigned char XGI330New_SR15[8][8] = { + { 0x0, 0x4, 0x60, 0x60}, + { 0xf, 0xf, 0xf, 0xf}, + {0xba, 0xba, 0xba, 0xba}, + {0xa9, 0xa9, 0xac, 0xac}, + {0xa0, 0xa0, 0xa0, 0xa8}, + { 0x0, 0x0, 0x2, 0x2}, + {0x30, 0x30, 0x40, 0x40}, + { 0x0, 0xa5, 0xfb, 0xf6} +}; + +static unsigned char XGI330New_CR40[5][8] = { + {0x77, 0x77, 0x44, 0x44}, + {0x77, 0x77, 0x44, 0x44}, + { 0x0, 0x0, 0x0, 0x0}, + {0x5b, 0x5b, 0xab, 0xab}, + { 0x0, 0x0, 0xf0, 0xf8} +}; +#endif + static unsigned char XGI330_CR49[] = {0xaa, 0x88}; static unsigned char XGI330_SR1F = 0x0; static unsigned char XGI330_SR21 = 0xa3; +#if 0 +static unsigned char XGI330_650_SR21 = 0xa7; +#endif static unsigned char XGI330_SR22 = 0xfb; static unsigned char XGI330_SR23 = 0xf6; static unsigned char XGI330_SR24 = 0xd; +#if 0 +static unsigned char XGI660_SR21 = 0xa3;/* 2003.0312 */ +static unsigned char XGI660_SR22 = 0xf3;/* 2003.0312 */ + +static unsigned char XGI330_LVDS_SR32 = 0x00; /* ynlai for 650 LVDS */ +static unsigned char XGI330_LVDS_SR33 = 0x00; /* chiawen for 650 LVDS */ +static unsigned char XGI330_650_SR31 = 0x40; +static unsigned char XGI330_650_SR33 = 0x04; +#endif static unsigned char XGI330_CRT2Data_1_2 = 0x0; static unsigned char XGI330_CRT2Data_4_D = 0x0; static unsigned char XGI330_CRT2Data_4_E = 0x0; @@ -2982,6 +3641,14 @@ static unsigned short XGI330_YCSenseData = 0xb3; static unsigned short XGI330_RGBSenseData2 = 0x0190; /*301b*/ static unsigned short XGI330_VideoSenseData2 = 0x0110; static unsigned short XGI330_YCSenseData2 = 0x016B; +#if 0 +static unsigned char XGI330_NTSCPhase[] = {0x21, 0xed, 0x8a, 0x8}; +static unsigned char XGI330_PALPhase[] = {0x2a, 0x5, 0xd3, 0x0}; +static unsigned char XGI330_NTSCPhase2[] = {0x21, 0xF0, 0x7B, 0xD6};/*301b*/ +static unsigned char XGI330_PALPhase2[] = {0x2a, 0x09, 0x86, 0xe9}; +static unsigned char XGI330_PALMPhase[] = {0x21, 0xE4, 0x2E, 0x9B}; /*palmn*/ +static unsigned char XGI330_PALNPhase[] = {0x21, 0xF4, 0x3E, 0xBA}; +#endif static unsigned char XG40_I2CDefinition = 0x00 ; static unsigned char XG20_CR97 = 0x10 ; @@ -3138,6 +3805,21 @@ static struct XGI330_VCLKDataStruct XGI_VCLKData[] = { {0x66, 0x43, 123}, /* 4A (122.61Mhz) */ {0x2C, 0x61, 80}, /* 4B (80.350Mhz) */ {0x3B, 0x61, 108}, /* 4C (107.385Mhz) */ +/* + {0x60, 0x36, 30},// 4D (30.200MHz) }// No use + {0x60, 0x36, 30},// 4E (30.200MHz) }// No use + {0x60, 0x36, 30},// 4F (30.200MHz) }// No use + {0x60, 0x36, 30},// 50 (30.200MHz) }// CHTV + {0x40, 0x4A, 28},// 51 (28.190MHz) + {0x9F, 0x46, 44},// 52 (43.600MHz) + {0x97, 0x2C, 26},// 53 (26.400MHz) + {0x44, 0xE4, 25},// 54 (24.600MHz) + {0x7E, 0x32, 47},// 55 (47.832MHz) + {0x8A, 0x24, 31},// 56 (31.500MHz) + {0x97, 0x2C, 26},// 57 (26.200MHz) + {0xCE, 0x3C, 39},// 58 (39.000MHz) + {0x52, 0x4A, 36},// 59 (36.000MHz) +*/ {0x69, 0x61, 191}, /* 4D (190.96MHz ) */ {0x4F, 0x22, 192}, /* 4E (192.069MHz) */ {0x28, 0x26, 322}, /* 4F (322.273MHz) */ @@ -3230,6 +3912,21 @@ static struct XGI330_VCLKDataStruct XGI_VBVCLKData[] = { {0x66, 0x43, 123}, /* 4A (122.61Mhz) */ {0x2C, 0x61, 80 }, /* 4B (80.350Mhz) */ {0x3B, 0x61, 108}, /* 4C (107.385Mhz) */ +/* + {0x60, 0x36, 30}, // 4D (30.200MHz) }// No use + {0x60, 0x36, 30}, // 4E (30.200MHz) }// No use + {0x60, 0x36, 30}, // 4F (30.200MHz) }// No use + {0x60, 0x36, 30}, // 50 (30.200MHz) }// CHTV + {0x40, 0x4A, 28}, // 51 (28.190MHz) + {0x9F, 0x46, 44}, // 52 (43.600MHz) + {0x97, 0x2C, 26}, // 53 (26.400MHz) + {0x44, 0xE4, 25}, // 54 (24.600MHz) + {0x7E, 0x32, 47}, // 55 (47.832MHz) + {0x8A, 0x24, 31}, // 56 (31.500MHz) + {0x97, 0x2C, 26}, // 57 (26.200MHz) + {0xCE, 0x3C, 39}, // 58 (39.000MHz) + {0x52, 0x4A, 36}, // 59 (36.000MHz) +*/ {0x69, 0x61, 191}, /* 4D (190.96MHz ) */ {0x4F, 0x22, 192}, /* 4E (192.069MHz) */ {0x28, 0x26, 322}, /* 4F (322.273MHz) */ @@ -3244,6 +3941,38 @@ static struct XGI330_VCLKDataStruct XGI_VBVCLKData[] = { {0xFF, 0x00, 0} /* End mark */ }; +#if 0 +static unsigned char XGI660_TVDelayList[] = { + 0x44, /* ; 0 ExtNTSCDelay */ + 0x44, /* ; 1 StNTSCDelay */ + 0x44, /* ; 2 ExtPALDelay */ + 0x44, /* ; 3 StPALDelay */ + 0x44, /* ; 4 ExtHiTVDelay(1080i) */ + 0x44, /* ; 5 StHiTVDelay(1080i) */ + 0x44, /* ; 6 ExtYPbPrDelay(525i) */ + 0x44, /* ; 7 StYPbPrDealy(525i) */ + 0x44, /* ; 8 ExtYPbPrDelay(525p) */ + 0x44, /* ; 9 StYPbPrDealy(525p) */ + 0x44, /* ; A ExtYPbPrDelay(750p) */ + 0x44 /* ; B StYPbPrDealy(750p) */ +}; + +static unsigned char XGI660_TVDelayList2[] = { + 0x44, /* ; 0 ExtNTSCDelay */ + 0x44, /* ; 1 StNTSCDelay */ + 0x44, /* ; 2 ExtPALDelay */ + 0x44, /* ; 3 StPALDelay */ + 0x44, /* ; 4 ExtHiTVDelay */ + 0x44, /* ; 5 StHiTVDelay */ + 0x44, /* ; 6 ExtYPbPrDelay(525i) */ + 0x44, /* ; 7 StYPbPrDealy(525i) */ + 0x44, /* ; 8 ExtYPbPrDelay(525p) */ + 0x44, /* ; 9 StYPbPrDealy(525p) */ + 0x44, /* ; A ExtYPbPrDelay(750p) */ + 0x44 /* ; B StYPbPrDealy(750p) */ +}; +#endif + static unsigned char XGI301TVDelayList[] = { 0x22, /* ; 0 ExtNTSCDelay */ 0x22, /* ; 1 StNTSCDelay */ diff --git a/trunk/drivers/staging/xgifb/vgatypes.h b/trunk/drivers/staging/xgifb/vgatypes.h index 7f911f1ac32d..5aeb3a4d66fb 100644 --- a/trunk/drivers/staging/xgifb/vgatypes.h +++ b/trunk/drivers/staging/xgifb/vgatypes.h @@ -47,6 +47,11 @@ enum XGI_LCD_TYPE { }; #endif +struct XGI_DSReg { + unsigned char jIdx; + unsigned char jVal; +}; + struct xgi_hw_device_info { unsigned long ulExternalChip; /* NO VB or other video bridge*/ /* if ujVBChipID = VB_CHIP_UNKNOWN, */ diff --git a/trunk/drivers/staging/zcache/zcache-main.c b/trunk/drivers/staging/zcache/zcache-main.c index 6c0f001c3586..855a5bb56a47 100644 --- a/trunk/drivers/staging/zcache/zcache-main.c +++ b/trunk/drivers/staging/zcache/zcache-main.c @@ -651,7 +651,7 @@ static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7; /* * byte count defining poor *mean* compression; pages with greater zsize * will be rejected until sufficient better-compressed pages are accepted - * driving the mean below this threshold + * driving the man below this threshold */ static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; @@ -1668,7 +1668,7 @@ static int zcache_new_pool(uint16_t cli_id, uint32_t flags) if (cli == NULL) goto out; atomic_inc(&cli->refcount); - pool = kmalloc(sizeof(struct tmem_pool), GFP_ATOMIC); + pool = kmalloc(sizeof(struct tmem_pool), GFP_KERNEL); if (pool == NULL) { pr_info("zcache: pool creation failed: out of memory\n"); goto out; @@ -1993,7 +1993,7 @@ static int __init zcache_init(void) pr_info("zcache: frontswap enabled using kernel " "transcendent memory and xvmalloc\n"); if (old_ops.init != NULL) - pr_warning("zcache: frontswap_ops overridden"); + pr_warning("ktmem: frontswap_ops overridden"); } #endif out: diff --git a/trunk/drivers/staging/zram/zram_drv.c b/trunk/drivers/staging/zram/zram_drv.c index ec66b0a5873b..d70ec1ad10de 100644 --- a/trunk/drivers/staging/zram/zram_drv.c +++ b/trunk/drivers/staging/zram/zram_drv.c @@ -37,10 +37,10 @@ /* Globals */ static int zram_major; -struct zram *zram_devices; +struct zram *devices; /* Module params (documentation at end) */ -unsigned int zram_num_devices; +unsigned int num_devices; static void zram_stat_inc(u32 *v) { @@ -780,9 +780,9 @@ static int __init zram_init(void) { int ret, dev_id; - if (zram_num_devices > max_num_devices) { + if (num_devices > max_num_devices) { pr_warning("Invalid value for num_devices: %u\n", - zram_num_devices); + num_devices); ret = -EINVAL; goto out; } @@ -794,21 +794,21 @@ static int __init zram_init(void) goto out; } - if (!zram_num_devices) { + if (!num_devices) { pr_info("num_devices not specified. Using default: 1\n"); - zram_num_devices = 1; + num_devices = 1; } /* Allocate the device array and initialize each one */ - pr_info("Creating %u devices ...\n", zram_num_devices); - zram_devices = kzalloc(zram_num_devices * sizeof(struct zram), GFP_KERNEL); - if (!zram_devices) { + pr_info("Creating %u devices ...\n", num_devices); + devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL); + if (!devices) { ret = -ENOMEM; goto unregister; } - for (dev_id = 0; dev_id < zram_num_devices; dev_id++) { - ret = create_device(&zram_devices[dev_id], dev_id); + for (dev_id = 0; dev_id < num_devices; dev_id++) { + ret = create_device(&devices[dev_id], dev_id); if (ret) goto free_devices; } @@ -817,8 +817,8 @@ static int __init zram_init(void) free_devices: while (dev_id) - destroy_device(&zram_devices[--dev_id]); - kfree(zram_devices); + destroy_device(&devices[--dev_id]); + kfree(devices); unregister: unregister_blkdev(zram_major, "zram"); out: @@ -830,8 +830,8 @@ static void __exit zram_exit(void) int i; struct zram *zram; - for (i = 0; i < zram_num_devices; i++) { - zram = &zram_devices[i]; + for (i = 0; i < num_devices; i++) { + zram = &devices[i]; destroy_device(zram); if (zram->init_done) @@ -840,12 +840,12 @@ static void __exit zram_exit(void) unregister_blkdev(zram_major, "zram"); - kfree(zram_devices); + kfree(devices); pr_debug("Cleanup done!\n"); } -module_param(zram_num_devices, uint, 0); -MODULE_PARM_DESC(zram_num_devices, "Number of zram devices"); +module_param(num_devices, uint, 0); +MODULE_PARM_DESC(num_devices, "Number of zram devices"); module_init(zram_init); module_exit(zram_exit); diff --git a/trunk/drivers/staging/zram/zram_drv.h b/trunk/drivers/staging/zram/zram_drv.h index 59b01d602f44..abe5221c100d 100644 --- a/trunk/drivers/staging/zram/zram_drv.h +++ b/trunk/drivers/staging/zram/zram_drv.h @@ -123,8 +123,8 @@ struct zram { struct zram_stats stats; }; -extern struct zram *zram_devices; -extern unsigned int zram_num_devices; +extern struct zram *devices; +extern unsigned int num_devices; #ifdef CONFIG_SYSFS extern struct attribute_group zram_disk_attr_group; #endif diff --git a/trunk/drivers/staging/zram/zram_sysfs.c b/trunk/drivers/staging/zram/zram_sysfs.c index df1f9dc4269c..a70cc010d18d 100644 --- a/trunk/drivers/staging/zram/zram_sysfs.c +++ b/trunk/drivers/staging/zram/zram_sysfs.c @@ -34,8 +34,8 @@ static struct zram *dev_to_zram(struct device *dev) int i; struct zram *zram = NULL; - for (i = 0; i < zram_num_devices; i++) { - zram = &zram_devices[i]; + for (i = 0; i < num_devices; i++) { + zram = &devices[i]; if (disk_to_dev(zram->disk) == dev) break; }