aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-07-11 14:55:48 +0100
committerDavid Woodhouse <dwmw2@infradead.org>2007-07-11 14:55:48 +0100
commitdb1b39d8b860e3716620c225bc86e0ec41764e34 (patch)
tree8739074db733ef767400ea92cfbfed9352ddb92d /drivers
parenta6bc432e296dfa1f05d4b586ca5ca3085a2d42d7 (diff)
parent4eb6bf6bfb580afaf1e1a1d30cba17a078530cf4 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acorn/block/fd1772.c2
-rw-r--r--drivers/acorn/block/mfmhd.c13
-rw-r--r--drivers/ata/ahci.c159
-rw-r--r--drivers/ata/ata_generic.c4
-rw-r--r--drivers/ata/ata_piix.c35
-rw-r--r--drivers/ata/libata-acpi.c914
-rw-r--r--drivers/ata/libata-core.c105
-rw-r--r--drivers/ata/libata-eh.c11
-rw-r--r--drivers/ata/libata-scsi.c2
-rw-r--r--drivers/ata/libata.h18
-rw-r--r--drivers/ata/pata_ali.c22
-rw-r--r--drivers/ata/pata_amd.c38
-rw-r--r--drivers/ata/pata_artop.c6
-rw-r--r--drivers/ata/pata_atiixp.c3
-rw-r--r--drivers/ata/pata_cmd640.c2
-rw-r--r--drivers/ata/pata_cmd64x.c12
-rw-r--r--drivers/ata/pata_cs5520.c4
-rw-r--r--drivers/ata/pata_cs5530.c8
-rw-r--r--drivers/ata/pata_cs5535.c4
-rw-r--r--drivers/ata/pata_cypress.c2
-rw-r--r--drivers/ata/pata_efar.c2
-rw-r--r--drivers/ata/pata_hpt366.c4
-rw-r--r--drivers/ata/pata_hpt37x.c20
-rw-r--r--drivers/ata/pata_hpt3x2n.c4
-rw-r--r--drivers/ata/pata_hpt3x3.c2
-rw-r--r--drivers/ata/pata_icside.c2
-rw-r--r--drivers/ata/pata_it8213.c4
-rw-r--r--drivers/ata/pata_it821x.c6
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c76
-rw-r--r--drivers/ata/pata_jmicron.c4
-rw-r--r--drivers/ata/pata_marvell.c8
-rw-r--r--drivers/ata/pata_netcell.c4
-rw-r--r--drivers/ata/pata_ns87410.c2
-rw-r--r--drivers/ata/pata_oldpiix.c2
-rw-r--r--drivers/ata/pata_opti.c2
-rw-r--r--drivers/ata/pata_optidma.c4
-rw-r--r--drivers/ata/pata_pdc202xx_old.c6
-rw-r--r--drivers/ata/pata_platform.c6
-rw-r--r--drivers/ata/pata_radisys.c2
-rw-r--r--drivers/ata/pata_rz1000.c2
-rw-r--r--drivers/ata/pata_sc1200.c6
-rw-r--r--drivers/ata/pata_serverworks.c12
-rw-r--r--drivers/ata/pata_sil680.c21
-rw-r--r--drivers/ata/pata_sis.c14
-rw-r--r--drivers/ata/pata_sl82c105.c4
-rw-r--r--drivers/ata/pata_triflex.c2
-rw-r--r--drivers/ata/pata_via.c8
-rw-r--r--drivers/ata/pdc_adma.c20
-rw-r--r--drivers/ata/sata_inic162x.c6
-rw-r--r--drivers/ata/sata_mv.c31
-rw-r--r--drivers/ata/sata_promise.c78
-rw-r--r--drivers/ata/sata_qstor.c2
-rw-r--r--drivers/ata/sata_sil.c13
-rw-r--r--drivers/ata/sata_sil24.c8
-rw-r--r--drivers/ata/sata_sis.c2
-rw-r--r--drivers/ata/sata_svw.c15
-rw-r--r--drivers/ata/sata_sx4.c168
-rw-r--r--drivers/ata/sata_uli.c2
-rw-r--r--drivers/ata/sata_via.c10
-rw-r--r--drivers/ata/sata_vsc.c2
-rw-r--r--drivers/atm/firestream.c2
-rw-r--r--drivers/block/Kconfig44
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/acsi.c1825
-rw-r--r--drivers/block/amiflop.c2
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/block/loop.c64
-rw-r--r--drivers/block/nbd.c2
-rw-r--r--drivers/cdrom/Kconfig213
-rw-r--r--drivers/cdrom/Makefile10
-rw-r--r--drivers/cdrom/aztcd.c2492
-rw-r--r--drivers/cdrom/aztcd.h162
-rw-r--r--drivers/cdrom/cdrom.c216
-rw-r--r--drivers/cdrom/cdu31a.c3251
-rw-r--r--drivers/cdrom/cdu31a.h411
-rw-r--r--drivers/cdrom/cm206.c1594
-rw-r--r--drivers/cdrom/cm206.h171
-rw-r--r--drivers/cdrom/gscd.c1029
-rw-r--r--drivers/cdrom/gscd.h108
-rw-r--r--drivers/cdrom/isp16.c374
-rw-r--r--drivers/cdrom/isp16.h72
-rw-r--r--drivers/cdrom/mcdx.c1943
-rw-r--r--drivers/cdrom/mcdx.h185
-rw-r--r--drivers/cdrom/optcd.c2105
-rw-r--r--drivers/cdrom/optcd.h52
-rw-r--r--drivers/cdrom/sbpcd.c5966
-rw-r--r--drivers/cdrom/sbpcd.h839
-rw-r--r--drivers/cdrom/sjcd.c1815
-rw-r--r--drivers/cdrom/sjcd.h181
-rw-r--r--drivers/cdrom/sonycd535.c1689
-rw-r--r--drivers/cdrom/sonycd535.h183
-rw-r--r--drivers/char/keyboard.c4
-rw-r--r--drivers/char/mem.c9
-rw-r--r--drivers/char/sx.c4
-rw-r--r--drivers/firewire/fw-card.c7
-rw-r--r--drivers/firewire/fw-cdev.c2
-rw-r--r--drivers/firewire/fw-device.c38
-rw-r--r--drivers/firewire/fw-device.h1
-rw-r--r--drivers/firewire/fw-ohci.c6
-rw-r--r--drivers/firewire/fw-sbp2.c117
-rw-r--r--drivers/firewire/fw-topology.c66
-rw-r--r--drivers/firewire/fw-topology.h25
-rw-r--r--drivers/firewire/fw-transaction.h3
-rw-r--r--drivers/hid/Kconfig10
-rw-r--r--drivers/hid/hid-core.c93
-rw-r--r--drivers/hid/hid-debug.c15
-rw-r--r--drivers/hid/hid-input.c125
-rw-r--r--drivers/hid/usbhid/hid-core.c111
-rw-r--r--drivers/hid/usbhid/hid-lgff.c10
-rw-r--r--drivers/hid/usbhid/hid-pidff.c1
-rw-r--r--drivers/hid/usbhid/hid-quirks.c185
-rw-r--r--drivers/hid/usbhid/hid-tmff.c2
-rw-r--r--drivers/hid/usbhid/hid-zpff.c8
-rw-r--r--drivers/hid/usbhid/hiddev.c2
-rw-r--r--drivers/hid/usbhid/usbkbd.c6
-rw-r--r--drivers/ide/arm/icside.c16
-rw-r--r--drivers/ide/cris/ide-cris.c2
-rw-r--r--drivers/ide/ide-cd.c6
-rw-r--r--drivers/ide/ide-cd.h2
-rw-r--r--drivers/ide/ide-disk.c8
-rw-r--r--drivers/ide/ide-dma.c110
-rw-r--r--drivers/ide/ide-io.c4
-rw-r--r--drivers/ide/ide-iops.c8
-rw-r--r--drivers/ide/ide-probe.c10
-rw-r--r--drivers/ide/ide-proc.c34
-rw-r--r--drivers/ide/ide-timing.h56
-rw-r--r--drivers/ide/ide.c33
-rw-r--r--drivers/ide/legacy/hd.c5
-rw-r--r--drivers/ide/legacy/macide.c14
-rw-r--r--drivers/ide/legacy/qd65xx.c3
-rw-r--r--drivers/ide/mips/au1xxx-ide.c24
-rw-r--r--drivers/ide/pci/aec62xx.c119
-rw-r--r--drivers/ide/pci/alim15x3.c78
-rw-r--r--drivers/ide/pci/amd74xx.c127
-rw-r--r--drivers/ide/pci/atiixp.c5
-rw-r--r--drivers/ide/pci/cmd64x.c130
-rw-r--r--drivers/ide/pci/cs5535.c6
-rw-r--r--drivers/ide/pci/hpt366.c170
-rw-r--r--drivers/ide/pci/it8213.c8
-rw-r--r--drivers/ide/pci/it821x.c9
-rw-r--r--drivers/ide/pci/jmicron.c20
-rw-r--r--drivers/ide/pci/pdc202xx_new.c9
-rw-r--r--drivers/ide/pci/pdc202xx_old.c35
-rw-r--r--drivers/ide/pci/piix.c45
-rw-r--r--drivers/ide/pci/scc_pata.c2
-rw-r--r--drivers/ide/pci/serverworks.c103
-rw-r--r--drivers/ide/pci/sgiioc4.c20
-rw-r--r--drivers/ide/pci/siimage.c18
-rw-r--r--drivers/ide/pci/sis5513.c35
-rw-r--r--drivers/ide/pci/sl82c105.c20
-rw-r--r--drivers/ide/pci/slc90e66.c5
-rw-r--r--drivers/ide/pci/tc86c001.c4
-rw-r--r--drivers/ide/pci/via82cxxx.c175
-rw-r--r--drivers/ide/ppc/pmac.c42
-rw-r--r--drivers/ieee1394/dv1394.c8
-rw-r--r--drivers/ieee1394/eth1394.c4
-rw-r--r--drivers/ieee1394/highlevel.c45
-rw-r--r--drivers/ieee1394/highlevel.h16
-rw-r--r--drivers/ieee1394/hosts.c11
-rw-r--r--drivers/ieee1394/hosts.h10
-rw-r--r--drivers/ieee1394/ieee1394_core.c8
-rw-r--r--drivers/ieee1394/ieee1394_core.h15
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c30
-rw-r--r--drivers/ieee1394/ieee1394_transactions.h2
-rw-r--r--drivers/ieee1394/nodemgr.c185
-rw-r--r--drivers/ieee1394/nodemgr.h4
-rw-r--r--drivers/ieee1394/ohci1394.c272
-rw-r--r--drivers/ieee1394/ohci1394.h14
-rw-r--r--drivers/ieee1394/pcilynx.c16
-rw-r--r--drivers/ieee1394/raw1394-private.h5
-rw-r--r--drivers/ieee1394/raw1394.c364
-rw-r--r--drivers/ieee1394/raw1394.h4
-rw-r--r--drivers/ieee1394/sbp2.c15
-rw-r--r--drivers/ieee1394/sbp2.h2
-rw-r--r--drivers/ieee1394/video1394.c10
-rw-r--r--drivers/input/evdev.c84
-rw-r--r--drivers/input/input.c136
-rw-r--r--drivers/input/joydev.c84
-rw-r--r--drivers/input/joystick/Kconfig7
-rw-r--r--drivers/input/joystick/grip_mp.c4
-rw-r--r--drivers/input/joystick/xpad.c281
-rw-r--r--drivers/input/keyboard/atkbd.c51
-rw-r--r--drivers/input/keyboard/pxa27x_keyboard.c2
-rw-r--r--drivers/input/misc/Kconfig6
-rw-r--r--drivers/input/misc/wistron_btns.c359
-rw-r--r--drivers/input/mouse/Kconfig16
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/gpio_mouse.c196
-rw-r--r--drivers/input/mouse/psmouse-base.c29
-rw-r--r--drivers/input/mouse/psmouse.h1
-rw-r--r--drivers/input/mousedev.c242
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h11
-rw-r--r--drivers/input/serio/serio.c2
-rw-r--r--drivers/input/serio/serio_raw.c2
-rw-r--r--drivers/input/tablet/aiptek.c991
-rw-r--r--drivers/input/tablet/wacom.h8
-rw-r--r--drivers/input/tablet/wacom_sys.c6
-rw-r--r--drivers/input/tablet/wacom_wac.c47
-rw-r--r--drivers/input/tablet/wacom_wac.h1
-rw-r--r--drivers/input/touchscreen/Kconfig6
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c33
-rw-r--r--drivers/input/tsdev.c90
-rw-r--r--drivers/misc/Kconfig14
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/blink.c45
-rw-r--r--drivers/misc/eeprom_93cx6.c241
-rw-r--r--drivers/mmc/card/Kconfig18
-rw-r--r--drivers/mmc/card/block.c7
-rw-r--r--drivers/mmc/card/queue.c191
-rw-r--r--drivers/mmc/card/queue.h7
-rw-r--r--drivers/mmc/core/Makefile3
-rw-r--r--drivers/mmc/core/bus.c253
-rw-r--r--drivers/mmc/core/bus.h22
-rw-r--r--drivers/mmc/core/core.c147
-rw-r--r--drivers/mmc/core/core.h8
-rw-r--r--drivers/mmc/core/host.c156
-rw-r--r--drivers/mmc/core/host.h18
-rw-r--r--drivers/mmc/core/mmc.c65
-rw-r--r--drivers/mmc/core/sd.c63
-rw-r--r--drivers/mmc/core/sysfs.c347
-rw-r--r--drivers/mmc/core/sysfs.h19
-rw-r--r--drivers/mmc/host/at91_mci.c217
-rw-r--r--drivers/mmc/host/sdhci.c10
-rw-r--r--drivers/mtd/devices/docprobe.c2
-rw-r--r--drivers/mtd/maps/Kconfig6
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/lasat.c103
-rw-r--r--drivers/mtd/nand/diskonchip.c2
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139cp.c11
-rw-r--r--drivers/net/8390.h11
-rw-r--r--drivers/net/Kconfig292
-rw-r--r--drivers/net/Makefile5
-rw-r--r--drivers/net/acenic.c4
-rw-r--r--drivers/net/arm/Kconfig12
-rw-r--r--drivers/net/arm/am79c961a.c2
-rw-r--r--drivers/net/atari_pamsnet.c62
-rw-r--r--drivers/net/atl1/atl1_main.c3
-rw-r--r--drivers/net/ax88796.c952
-rw-r--r--drivers/net/b44.c56
-rw-r--r--drivers/net/b44.h2
-rw-r--r--drivers/net/bonding/bond_main.c16
-rw-r--r--drivers/net/bonding/bonding.h2
-rw-r--r--drivers/net/cxgb3/adapter.h38
-rw-r--r--drivers/net/cxgb3/common.h28
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c48
-rw-r--r--drivers/net/cxgb3/regs.h11
-rw-r--r--drivers/net/cxgb3/sge.c423
-rw-r--r--drivers/net/cxgb3/t3_hw.c128
-rw-r--r--drivers/net/cxgb3/version.h2
-rw-r--r--drivers/net/e100.c12
-rw-r--r--drivers/net/ehea/ehea.h20
-rw-r--r--drivers/net/ehea/ehea_hw.h24
-rw-r--r--drivers/net/ehea/ehea_main.c55
-rw-r--r--drivers/net/ehea/ehea_qmr.c56
-rw-r--r--drivers/net/fec_8xx/Kconfig2
-rw-r--r--drivers/net/fs_enet/Kconfig2
-rw-r--r--drivers/net/gianfar.c27
-rw-r--r--drivers/net/gianfar.h6
-rw-r--r--drivers/net/gianfar_mii.c55
-rw-r--r--drivers/net/ioc3-eth.c41
-rw-r--r--drivers/net/ixp2000/ixpdev.c2
-rw-r--r--drivers/net/lasi_82596.c1460
-rw-r--r--drivers/net/lib82596.c1434
-rw-r--r--drivers/net/macmace.c2
-rw-r--r--drivers/net/mlx4/qp.c3
-rw-r--r--drivers/net/myri10ge/myri10ge.c3
-rw-r--r--drivers/net/netxen/netxen_nic.h103
-rw-r--r--drivers/net/netxen/netxen_nic_main.c97
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c6
-rw-r--r--drivers/net/pasemi_mac.c2
-rw-r--r--drivers/net/pcmcia/axnet_cs.c7
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c23
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c11
-rw-r--r--drivers/net/phy/Kconfig5
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/icplus.c134
-rw-r--r--drivers/net/phy/marvell.c139
-rw-r--r--drivers/net/ps3_gelic_net.c1576
-rw-r--r--drivers/net/ps3_gelic_net.h239
-rwxr-xr-xdrivers/net/qla3xxx.c33
-rw-r--r--drivers/net/r8169.c944
-rw-r--r--drivers/net/rrunner.c2
-rw-r--r--drivers/net/s2io.c116
-rw-r--r--drivers/net/s2io.h6
-rw-r--r--drivers/net/sb1250-mac.c2
-rw-r--r--drivers/net/sis900.c2
-rw-r--r--drivers/net/sk98lin/Makefile87
-rw-r--r--drivers/net/sk98lin/h/lm80.h179
-rw-r--r--drivers/net/sk98lin/h/skaddr.h285
-rw-r--r--drivers/net/sk98lin/h/skcsum.h213
-rw-r--r--drivers/net/sk98lin/h/skdebug.h74
-rw-r--r--drivers/net/sk98lin/h/skdrv1st.h188
-rw-r--r--drivers/net/sk98lin/h/skdrv2nd.h447
-rw-r--r--drivers/net/sk98lin/h/skerror.h55
-rw-r--r--drivers/net/sk98lin/h/skgedrv.h51
-rw-r--r--drivers/net/sk98lin/h/skgehw.h2126
-rw-r--r--drivers/net/sk98lin/h/skgehwt.h48
-rw-r--r--drivers/net/sk98lin/h/skgei2c.h210
-rw-r--r--drivers/net/sk98lin/h/skgeinit.h797
-rw-r--r--drivers/net/sk98lin/h/skgepnm2.h334
-rw-r--r--drivers/net/sk98lin/h/skgepnmi.h962
-rw-r--r--drivers/net/sk98lin/h/skgesirq.h110
-rw-r--r--drivers/net/sk98lin/h/ski2c.h174
-rw-r--r--drivers/net/sk98lin/h/skqueue.h94
-rw-r--r--drivers/net/sk98lin/h/skrlmt.h438
-rw-r--r--drivers/net/sk98lin/h/sktimer.h63
-rw-r--r--drivers/net/sk98lin/h/sktypes.h69
-rw-r--r--drivers/net/sk98lin/h/skversion.h38
-rw-r--r--drivers/net/sk98lin/h/skvpd.h248
-rw-r--r--drivers/net/sk98lin/h/xmac_ii.h1579
-rw-r--r--drivers/net/sk98lin/skaddr.c1788
-rw-r--r--drivers/net/sk98lin/skdim.c742
-rw-r--r--drivers/net/sk98lin/skethtool.c628
-rw-r--r--drivers/net/sk98lin/skge.c5211
-rw-r--r--drivers/net/sk98lin/skgehwt.c171
-rw-r--r--drivers/net/sk98lin/skgeinit.c2005
-rw-r--r--drivers/net/sk98lin/skgemib.c1075
-rw-r--r--drivers/net/sk98lin/skgepnmi.c8210
-rw-r--r--drivers/net/sk98lin/skgesirq.c2229
-rw-r--r--drivers/net/sk98lin/ski2c.c1296
-rw-r--r--drivers/net/sk98lin/sklm80.c141
-rw-r--r--drivers/net/sk98lin/skqueue.c179
-rw-r--r--drivers/net/sk98lin/skrlmt.c3257
-rw-r--r--drivers/net/sk98lin/sktimer.c250
-rw-r--r--drivers/net/sk98lin/skvpd.c1091
-rw-r--r--drivers/net/sk98lin/skxmac2.c4160
-rw-r--r--drivers/net/sky2.c665
-rw-r--r--drivers/net/sky2.h167
-rw-r--r--drivers/net/sni_82596.c185
-rw-r--r--drivers/net/spider_net.c243
-rw-r--r--drivers/net/spider_net.h21
-rw-r--r--drivers/net/sunhme.c2
-rw-r--r--drivers/net/tc35815.c50
-rw-r--r--drivers/net/tokenring/3c359.c2
-rw-r--r--drivers/net/tulip/Kconfig27
-rw-r--r--drivers/net/tulip/de2104x.c1
-rw-r--r--drivers/net/tulip/de4x5.c98
-rw-r--r--drivers/net/tulip/de4x5.h9
-rw-r--r--drivers/net/ucc_geth.c2
-rw-r--r--drivers/net/usb/usbnet.c78
-rw-r--r--drivers/net/usb/usbnet.h10
-rw-r--r--drivers/net/wireless/Kconfig12
-rw-r--r--drivers/net/wireless/Makefile3
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c34
-rw-r--r--drivers/net/wireless/hostap/hostap_config.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c5
-rw-r--r--drivers/net/wireless/hostap/hostap_plx.c5
-rw-r--r--drivers/net/wireless/rtl8187.h145
-rw-r--r--drivers/net/wireless/rtl8187_dev.c731
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.c745
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.h44
-rw-r--r--drivers/net/wireless/rtl818x.h226
-rw-r--r--drivers/net/wireless/zd1211rw/Makefile2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.c21
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.h28
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al2230.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al7230b.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_uw2453.c534
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c1
-rw-r--r--drivers/pnp/quirks.c63
-rw-r--r--drivers/power/Kconfig51
-rw-r--r--drivers/power/Makefile22
-rw-r--r--drivers/power/apm_power.c243
-rw-r--r--drivers/power/ds2760_battery.c470
-rw-r--r--drivers/power/olpc_battery.c352
-rw-r--r--drivers/power/pda_power.c261
-rw-r--r--drivers/power/pmu_battery.c215
-rw-r--r--drivers/power/power_supply.h42
-rw-r--r--drivers/power/power_supply_core.c168
-rw-r--r--drivers/power/power_supply_leds.c176
-rw-r--r--drivers/power/power_supply_sysfs.c299
-rw-r--r--drivers/s390/block/dasd_proc.c4
-rw-r--r--drivers/s390/char/sclp.h12
-rw-r--r--drivers/s390/char/sclp_chp.c4
-rw-r--r--drivers/s390/char/sclp_info.c117
-rw-r--r--drivers/s390/char/vmcp.c13
-rw-r--r--drivers/s390/char/vmlogrdr.c4
-rw-r--r--drivers/s390/char/zcore.c2
-rw-r--r--drivers/s390/cio/device_id.c22
-rw-r--r--drivers/s390/crypto/ap_bus.c98
-rw-r--r--drivers/s390/crypto/ap_bus.h11
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c27
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c27
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.c27
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c40
-rw-r--r--drivers/serial/serial_cs.c4
-rw-r--r--drivers/tc/zs.c6
-rw-r--r--drivers/usb/misc/uss720.c2
-rw-r--r--drivers/w1/slaves/Kconfig13
-rw-r--r--drivers/w1/slaves/Makefile1
-rw-r--r--drivers/w1/slaves/w1_ds2760.c213
-rw-r--r--drivers/w1/slaves/w1_ds2760.h50
-rw-r--r--drivers/w1/w1_family.h1
402 files changed, 18260 insertions, 76012 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 050323fd79e..7916f4b86d2 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -24,8 +24,6 @@ source "drivers/scsi/Kconfig"
source "drivers/ata/Kconfig"
-source "drivers/cdrom/Kconfig"
-
source "drivers/md/Kconfig"
source "drivers/message/fusion/Kconfig"
@@ -54,6 +52,8 @@ source "drivers/spi/Kconfig"
source "drivers/w1/Kconfig"
+source "drivers/power/Kconfig"
+
source "drivers/hwmon/Kconfig"
source "drivers/mfd/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index adad2f3d438..503d8256944 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_RTC_LIB) += rtc/
obj-y += i2c/
obj-$(CONFIG_W1) += w1/
+obj-$(CONFIG_POWER_SUPPLY) += power/
obj-$(CONFIG_HWMON) += hwmon/
obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_MD) += md/
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 674bf81c6e6..423ed08fb6f 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1246,7 +1246,7 @@ repeat:
del_timer(&motor_off_timer);
ReqCnt = 0;
- ReqCmd = CURRENT->cmd;
+ ReqCmd = rq_data_dir(CURRENT);
ReqBlock = CURRENT->sector;
ReqBuffer = CURRENT->buffer;
setup_req_params(drive);
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 689a4c3542b..d85520f78e6 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -439,7 +439,7 @@ static void mfm_rw_intr(void)
a choice of command end or some data which is ready to be collected */
/* I think we have to transfer data while the interrupt line is on and its
not any other type of interrupt */
- if (CURRENT->cmd == WRITE) {
+ if (rq_data_dir(CURRENT) == WRITE) {
extern void hdc63463_writedma(void);
if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
@@ -799,7 +799,7 @@ static void issue_request(unsigned int block, unsigned int nsect,
raw_cmd.head = start_head;
raw_cmd.cylinder = track / p->heads;
raw_cmd.cmdtype = CURRENT->cmd;
- raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
+ raw_cmd.cmdcode = rq_data_dir(CURRENT) == WRITE ? CMD_WD : CMD_RD;
raw_cmd.cmddata[0] = dev + 1; /* DAG: +1 to get US */
raw_cmd.cmddata[1] = raw_cmd.head;
raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;
@@ -830,7 +830,7 @@ static void issue_request(unsigned int block, unsigned int nsect,
hdc63463_dataleft = nsect * 256; /* Better way? */
DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
- raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ",
+ raw_cmd.dev + 'a', rq_data_dir(CURRENT) == READ ? "read" : "writ",
raw_cmd.cylinder,
raw_cmd.head,
raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);
@@ -917,13 +917,6 @@ static void mfm_request(void)
DBG("mfm_request: block after offset=%d\n", block);
- if (CURRENT->cmd != READ && CURRENT->cmd != WRITE) {
- printk("unknown mfm-command %d\n", CURRENT->cmd);
- end_request(CURRENT, 0);
- Busy = 0;
- printk("mfm: continue 4\n");
- continue;
- }
issue_request(block, nsect, CURRENT);
break;
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index ca5229d24d8..11e4eb9f304 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -46,7 +46,7 @@
#include <linux/libata.h>
#define DRV_NAME "ahci"
-#define DRV_VERSION "2.2"
+#define DRV_VERSION "2.3"
enum {
@@ -54,7 +54,7 @@ enum {
AHCI_MAX_PORTS = 32,
AHCI_MAX_SG = 168, /* hardware max is 64K */
AHCI_DMA_BOUNDARY = 0xffffffff,
- AHCI_USE_CLUSTERING = 0,
+ AHCI_USE_CLUSTERING = 1,
AHCI_MAX_CMDS = 32,
AHCI_CMD_SZ = 32,
AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
@@ -81,6 +81,7 @@ enum {
board_ahci_vt8251 = 2,
board_ahci_ign_iferr = 3,
board_ahci_sb600 = 4,
+ board_ahci_mv = 5,
/* global controller registers */
HOST_CAP = 0x00, /* host capabilities */
@@ -171,6 +172,8 @@ enum {
AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */
AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */
+ AHCI_FLAG_MV_PATA = (1 << 29), /* PATA port */
+ AHCI_FLAG_NO_MSI = (1 << 30), /* no PCI MSI */
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
@@ -228,9 +231,12 @@ static void ahci_thaw(struct ata_port *ap);
static void ahci_error_handler(struct ata_port *ap);
static void ahci_vt8251_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+static int ahci_port_resume(struct ata_port *ap);
+static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+ u32 opts);
#ifdef CONFIG_PM
static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
-static int ahci_port_resume(struct ata_port *ap);
static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int ahci_pci_device_resume(struct pci_dev *pdev);
#endif
@@ -327,14 +333,14 @@ static const struct ata_port_info ahci_port_info[] = {
{
.flags = AHCI_FLAG_COMMON,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_pi */
{
.flags = AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_vt8251 */
@@ -342,14 +348,14 @@ static const struct ata_port_info ahci_port_info[] = {
.flags = AHCI_FLAG_COMMON | ATA_FLAG_HRST_TO_RESUME |
AHCI_FLAG_NO_NCQ,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_vt8251_ops,
},
/* board_ahci_ign_iferr */
{
.flags = AHCI_FLAG_COMMON | AHCI_FLAG_IGN_IRQ_IF_ERR,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_sb600 */
@@ -358,7 +364,19 @@ static const struct ata_port_info ahci_port_info[] = {
AHCI_FLAG_IGN_SERR_INTERNAL |
AHCI_FLAG_32BIT_ONLY,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+ },
+ /* board_ahci_mv */
+ {
+ .sht = &ahci_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI |
+ AHCI_FLAG_NO_NCQ | AHCI_FLAG_NO_MSI |
+ AHCI_FLAG_MV_PATA,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
};
@@ -456,6 +474,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */
{ PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
+ /* Marvell */
+ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
+
/* Generic, PCI class code for AHCI */
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -481,11 +502,17 @@ static inline int ahci_nr_ports(u32 cap)
return (cap & 0x1f) + 1;
}
-static inline void __iomem *ahci_port_base(struct ata_port *ap)
+static inline void __iomem *__ahci_port_base(struct ata_host *host,
+ unsigned int port_no)
{
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
+
+ return mmio + 0x100 + (port_no * 0x80);
+}
- return mmio + 0x100 + (ap->port_no * 0x80);
+static inline void __iomem *ahci_port_base(struct ata_port *ap)
+{
+ return __ahci_port_base(ap->host, ap->port_no);
}
/**
@@ -535,6 +562,20 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
hpriv->saved_port_map = port_map;
}
+ /*
+ * Temporary Marvell 6145 hack: PATA port presence
+ * is asserted through the standard AHCI port
+ * presence register, as bit 4 (counting from 0)
+ */
+ if (pi->flags & AHCI_FLAG_MV_PATA) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "MV_AHCI HACK: port_map %x -> %x\n",
+ hpriv->port_map,
+ hpriv->port_map & 0xf);
+
+ port_map &= 0xf;
+ }
+
/* cross check port_map and cap.n_ports */
if (pi->flags & AHCI_FLAG_HONOR_PI) {
u32 tmp_port_map = port_map;
@@ -740,7 +781,7 @@ static void ahci_power_down(struct ata_port *ap)
}
#endif
-static void ahci_init_port(struct ata_port *ap)
+static void ahci_start_port(struct ata_port *ap)
{
/* enable FIS reception */
ahci_start_fis_rx(ap);
@@ -814,39 +855,62 @@ static int ahci_reset_controller(struct ata_host *host)
return 0;
}
+static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
+ int port_no, void __iomem *mmio,
+ void __iomem *port_mmio)
+{
+ const char *emsg = NULL;
+ int rc;
+ u32 tmp;
+
+ /* make sure port is not active */
+ rc = ahci_deinit_port(ap, &emsg);
+ if (rc)
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "%s (%d)\n", emsg, rc);
+
+ /* clear SError */
+ tmp = readl(port_mmio + PORT_SCR_ERR);
+ VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
+ writel(tmp, port_mmio + PORT_SCR_ERR);
+
+ /* clear port IRQ */
+ tmp = readl(port_mmio + PORT_IRQ_STAT);
+ VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
+ if (tmp)
+ writel(tmp, port_mmio + PORT_IRQ_STAT);
+
+ writel(1 << port_no, mmio + HOST_IRQ_STAT);
+}
+
static void ahci_init_controller(struct ata_host *host)
{
struct pci_dev *pdev = to_pci_dev(host->dev);
void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
- int i, rc;
+ int i;
+ void __iomem *port_mmio;
u32 tmp;
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- void __iomem *port_mmio = ahci_port_base(ap);
- const char *emsg = NULL;
-
- if (ata_port_is_dummy(ap))
- continue;
-
- /* make sure port is not active */
- rc = ahci_deinit_port(ap, &emsg);
- if (rc)
- dev_printk(KERN_WARNING, &pdev->dev,
- "%s (%d)\n", emsg, rc);
+ if (host->ports[0]->flags & AHCI_FLAG_MV_PATA) {
+ port_mmio = __ahci_port_base(host, 4);
- /* clear SError */
- tmp = readl(port_mmio + PORT_SCR_ERR);
- VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
- writel(tmp, port_mmio + PORT_SCR_ERR);
+ writel(0, port_mmio + PORT_IRQ_MASK);
/* clear port IRQ */
tmp = readl(port_mmio + PORT_IRQ_STAT);
VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
if (tmp)
writel(tmp, port_mmio + PORT_IRQ_STAT);
+ }
- writel(1 << i, mmio + HOST_IRQ_STAT);
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ port_mmio = ahci_port_base(ap);
+ if (ata_port_is_dummy(ap))
+ continue;
+
+ ahci_port_init(pdev, ap, i, mmio, port_mmio);
}
tmp = readl(mmio + HOST_CTL);
@@ -1232,7 +1296,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
ata_port_abort(ap);
}
-static void ahci_host_intr(struct ata_port *ap)
+static void ahci_port_intr(struct ata_port *ap)
{
void __iomem *port_mmio = ap->ioaddr.cmd_addr;
struct ata_eh_info *ehi = &ap->eh_info;
@@ -1358,7 +1422,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
ap = host->ports[i];
if (ap) {
- ahci_host_intr(ap);
+ ahci_port_intr(ap);
VPRINTK("port %u\n", i);
} else {
VPRINTK("port %u (no irq)\n", i);
@@ -1466,7 +1530,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
ahci_power_down(ap);
else {
ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
- ahci_init_port(ap);
+ ahci_start_port(ap);
}
return rc;
@@ -1475,7 +1539,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
static int ahci_port_resume(struct ata_port *ap)
{
ahci_power_up(ap);
- ahci_init_port(ap);
+ ahci_start_port(ap);
return 0;
}
@@ -1573,13 +1637,8 @@ static int ahci_port_start(struct ata_port *ap)
ap->private_data = pp;
- /* power up port */
- ahci_power_up(ap);
-
- /* initialize port */
- ahci_init_port(ap);
-
- return 0;
+ /* engage engines, captain */
+ return ahci_port_resume(ap);
}
static void ahci_port_stop(struct ata_port *ap)
@@ -1724,7 +1783,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;
- if (pci_enable_msi(pdev))
+ if ((pi.flags & AHCI_FLAG_NO_MSI) || pci_enable_msi(pdev))
pci_intx(pdev, 1);
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
@@ -1745,14 +1804,18 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
host->private_data = hpriv;
for (i = 0; i < host->n_ports; i++) {
- if (hpriv->port_map & (1 << i)) {
- struct ata_port *ap = host->ports[i];
- void __iomem *port_mmio = ahci_port_base(ap);
+ struct ata_port *ap = host->ports[i];
+ void __iomem *port_mmio = ahci_port_base(ap);
+ /* standard SATA port setup */
+ if (hpriv->port_map & (1 << i)) {
ap->ioaddr.cmd_addr = port_mmio;
ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
- } else
- host->ports[i]->ops = &ata_dummy_port_ops;
+ }
+
+ /* disabled/not-implemented port */
+ else
+ ap->ops = &ata_dummy_port_ops;
}
/* initialize adapter */
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 4c6e95c95e4..430fcf4f9ef 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -143,10 +143,10 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
u16 command;
static const struct ata_port_info info = {
.sht = &generic_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &generic_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 9c07b88631b..6a3bfef58e1 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -200,6 +200,8 @@ static const struct pci_device_id piix_pci_tbl[] = {
/* ICH7/7-R (i945, i975) UDMA 100*/
{ 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 },
{ 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* ICH8 Mobile PATA Controller */
+ { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* NOTE: The following PCI ids must be kept in sync with the
* list in drivers/pci/quirks.c.
@@ -495,7 +497,7 @@ static struct ata_port_info piix_port_info[] = {
.flags = PIIX_SATA_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -505,7 +507,7 @@ static struct ata_port_info piix_port_info[] = {
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -516,7 +518,7 @@ static struct ata_port_info piix_port_info[] = {
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -527,7 +529,7 @@ static struct ata_port_info piix_port_info[] = {
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -538,7 +540,7 @@ static struct ata_port_info piix_port_info[] = {
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -685,8 +687,14 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
if (adev->class == ATA_DEV_ATA)
control |= 4; /* PPE enable */
+ /* PIO configuration clears DTE unconditionally. It will be
+ * programmed in set_dmamode which is guaranteed to be called
+ * after set_piomode if any DMA mode is available.
+ */
pci_read_config_word(dev, master_port, &master_data);
if (is_slave) {
+ /* clear TIME1|IE1|PPE1|DTE1 */
+ master_data &= 0xff0f;
/* Enable SITRE (seperate slave timing register) */
master_data |= 0x4000;
/* enable PPE1, IE1 and TIME1 as needed */
@@ -694,12 +702,14 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
pci_read_config_byte(dev, slave_port, &slave_data);
slave_data &= (ap->port_no ? 0x0f : 0xf0);
/* Load the timing nibble for this slave */
- slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1])
+ << (ap->port_no ? 4 : 0);
} else {
- /* Master keeps the bits in a different format */
- master_data &= 0xccf8;
+ /* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */
+ master_data &= 0xccf0;
/* Enable PPE, IE and TIME as appropriate */
master_data |= control;
+ /* load ISP and RCT */
master_data |=
(timings[pio][0] << 12) |
(timings[pio][1] << 8);
@@ -816,7 +826,7 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i
master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */
master_data |= control << 4;
pci_read_config_byte(dev, 0x44, &slave_data);
- slave_data &= (0x0F + 0xE1 * ap->port_no);
+ slave_data &= (ap->port_no ? 0x0f : 0xf0);
/* Load the matching timing */
slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
pci_write_config_byte(dev, 0x44, slave_data);
@@ -828,8 +838,11 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i
(timings[pio][0] << 12) |
(timings[pio][1] << 8);
}
- udma_enable &= ~(1 << devid);
- pci_write_config_word(dev, master_port, master_data);
+
+ if (ap->udma_mask) {
+ udma_enable &= ~(1 << devid);
+ pci_write_config_word(dev, master_port, master_data);
+ }
}
/* Don't scribble on 0x48 if the controller does not support UDMA */
if (ap->udma_mask)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 02236739b40..c059f78ad94 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -24,15 +24,13 @@
#include <acpi/acmacros.h>
#include <acpi/actypes.h>
-#define SATA_ROOT_PORT(x) (((x) >> 16) & 0xffff)
-#define SATA_PORT_NUMBER(x) ((x) & 0xffff) /* or NO_PORT_MULT */
#define NO_PORT_MULT 0xffff
-#define SATA_ADR_RSVD 0xffffffff
+#define SATA_ADR(root,pmp) (((root) << 16) | (pmp))
#define REGS_PER_GTF 7
-struct taskfile_array {
- u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */
-};
+struct ata_acpi_gtf {
+ u8 tf[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */
+} __packed;
/*
* Helper - belongs in the PCI layer somewhere eventually
@@ -42,237 +40,173 @@ static int is_pci_dev(struct device *dev)
return (dev->bus == &pci_bus_type);
}
+static void ata_acpi_associate_sata_port(struct ata_port *ap)
+{
+ acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
+
+ ap->device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr);
+}
+
+static void ata_acpi_associate_ide_port(struct ata_port *ap)
+{
+ int max_devices, i;
+
+ ap->acpi_handle = acpi_get_child(ap->host->acpi_handle, ap->port_no);
+ if (!ap->acpi_handle)
+ return;
+
+ max_devices = 1;
+ if (ap->flags & ATA_FLAG_SLAVE_POSS)
+ max_devices++;
+
+ for (i = 0; i < max_devices; i++) {
+ struct ata_device *dev = &ap->device[i];
+
+ dev->acpi_handle = acpi_get_child(ap->acpi_handle, i);
+ }
+}
+
/**
- * sata_get_dev_handle - finds acpi_handle and PCI device.function
- * @dev: device to locate
- * @handle: returned acpi_handle for @dev
- * @pcidevfn: return PCI device.func for @dev
+ * ata_acpi_associate - associate ATA host with ACPI objects
+ * @host: target ATA host
+ *
+ * Look up ACPI objects associated with @host and initialize
+ * acpi_handle fields of @host, its ports and devices accordingly.
*
- * This function is somewhat SATA-specific. Or at least the
- * PATA & SATA versions of this function are different,
- * so it's not entirely generic code.
+ * LOCKING:
+ * EH context.
*
- * Returns 0 on success, <0 on error.
+ * RETURNS:
+ * 0 on success, -errno on failure.
*/
-static int sata_get_dev_handle(struct device *dev, acpi_handle *handle,
- acpi_integer *pcidevfn)
+void ata_acpi_associate(struct ata_host *host)
{
- struct pci_dev *pci_dev;
- acpi_integer addr;
-
- if (!is_pci_dev(dev))
- return -ENODEV;
-
- pci_dev = to_pci_dev(dev); /* NOTE: PCI-specific */
- /* Please refer to the ACPI spec for the syntax of _ADR. */
- addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
- *pcidevfn = addr;
- *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
- if (!*handle)
- return -ENODEV;
- return 0;
+ int i;
+
+ if (!is_pci_dev(host->dev) || libata_noacpi)
+ return;
+
+ host->acpi_handle = DEVICE_ACPI_HANDLE(host->dev);
+ if (!host->acpi_handle)
+ return;
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (host->ports[0]->flags & ATA_FLAG_ACPI_SATA)
+ ata_acpi_associate_sata_port(ap);
+ else
+ ata_acpi_associate_ide_port(ap);
+ }
}
/**
- * pata_get_dev_handle - finds acpi_handle and PCI device.function
- * @dev: device to locate
- * @handle: returned acpi_handle for @dev
- * @pcidevfn: return PCI device.func for @dev
+ * ata_acpi_gtm - execute _GTM
+ * @ap: target ATA port
+ * @gtm: out parameter for _GTM result
+ *
+ * Evaluate _GTM and store the result in @gtm.
*
- * The PATA and SATA versions of this function are different.
+ * LOCKING:
+ * EH context.
*
- * Returns 0 on success, <0 on error.
+ * RETURNS:
+ * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
*/
-static int pata_get_dev_handle(struct device *dev, acpi_handle *handle,
- acpi_integer *pcidevfn)
+static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm)
{
- unsigned int bus, devnum, func;
- acpi_integer addr;
- acpi_handle dev_handle, parent_handle;
- struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER,
- .pointer = NULL};
+ struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
+ union acpi_object *out_obj;
acpi_status status;
- struct acpi_device_info *dinfo = NULL;
- int ret = -ENODEV;
- struct pci_dev *pdev;
-
- if (!is_pci_dev(dev))
- return -ENODEV;
-
- pdev = to_pci_dev(dev);
-
- bus = pdev->bus->number;
- devnum = PCI_SLOT(pdev->devfn);
- func = PCI_FUNC(pdev->devfn);
-
- dev_handle = DEVICE_ACPI_HANDLE(dev);
- parent_handle = DEVICE_ACPI_HANDLE(dev->parent);
-
- status = acpi_get_object_info(parent_handle, &buffer);
- if (ACPI_FAILURE(status))
- goto err;
-
- dinfo = buffer.pointer;
- if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
- dinfo->address == bus) {
- /* ACPI spec for _ADR for PCI bus: */
- addr = (acpi_integer)(devnum << 16 | func);
- *pcidevfn = addr;
- *handle = dev_handle;
- } else {
- goto err;
+ int rc = 0;
+
+ status = acpi_evaluate_object(ap->acpi_handle, "_GTM", NULL, &output);
+
+ rc = -ENOENT;
+ if (status == AE_NOT_FOUND)
+ goto out_free;
+
+ rc = -EINVAL;
+ if (ACPI_FAILURE(status)) {
+ ata_port_printk(ap, KERN_ERR,
+ "ACPI get timing mode failed (AE 0x%x)\n",
+ status);
+ goto out_free;
}
- if (!*handle)
- goto err;
- ret = 0;
-err:
- kfree(dinfo);
- return ret;
-}
+ out_obj = output.pointer;
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
+ ata_port_printk(ap, KERN_WARNING,
+ "_GTM returned unexpected object type 0x%x\n",
+ out_obj->type);
-struct walk_info { /* can be trimmed some */
- struct device *dev;
- struct acpi_device *adev;
- acpi_handle handle;
- acpi_integer pcidevfn;
- unsigned int drivenum;
- acpi_handle obj_handle;
- struct ata_port *ataport;
- struct ata_device *atadev;
- u32 sata_adr;
- int status;
- char basepath[ACPI_PATHNAME_MAX];
- int basepath_len;
-};
-
-static acpi_status get_devices(acpi_handle handle,
- u32 level, void *context, void **return_value)
-{
- acpi_status status;
- struct walk_info *winfo = context;
- struct acpi_buffer namebuf = {ACPI_ALLOCATE_BUFFER, NULL};
- char *pathname;
- struct acpi_buffer buffer;
- struct acpi_device_info *dinfo;
-
- status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf);
- if (status)
- goto ret;
- pathname = namebuf.pointer;
-
- buffer.length = ACPI_ALLOCATE_BUFFER;
- buffer.pointer = NULL;
- status = acpi_get_object_info(handle, &buffer);
- if (ACPI_FAILURE(status))
- goto out2;
-
- dinfo = buffer.pointer;
-
- /* find full device path name for pcidevfn */
- if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
- dinfo->address == winfo->pcidevfn) {
- if (ata_msg_probe(winfo->ataport))
- ata_dev_printk(winfo->atadev, KERN_DEBUG,
- ":%s: matches pcidevfn (0x%llx)\n",
- pathname, winfo->pcidevfn);
- strlcpy(winfo->basepath, pathname,
- sizeof(winfo->basepath));
- winfo->basepath_len = strlen(pathname);
- goto out;
+ goto out_free;
}
- /* if basepath is not yet known, ignore this object */
- if (!winfo->basepath_len)
- goto out;
-
- /* if this object is in scope of basepath, maybe use it */
- if (strncmp(pathname, winfo->basepath,
- winfo->basepath_len) == 0) {
- if (!(dinfo->valid & ACPI_VALID_ADR))
- goto out;
- if (ata_msg_probe(winfo->ataport))
- ata_dev_printk(winfo->atadev, KERN_DEBUG,
- "GOT ONE: (%s) root_port = 0x%llx,"
- " port_num = 0x%llx\n", pathname,
- SATA_ROOT_PORT(dinfo->address),
- SATA_PORT_NUMBER(dinfo->address));
- /* heuristics: */
- if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
- if (ata_msg_probe(winfo->ataport))
- ata_dev_printk(winfo->atadev,
- KERN_DEBUG, "warning: don't"
- " know how to handle SATA port"
- " multiplier\n");
- if (SATA_ROOT_PORT(dinfo->address) ==
- winfo->ataport->port_no &&
- SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
- if (ata_msg_probe(winfo->ataport))
- ata_dev_printk(winfo->atadev,
- KERN_DEBUG,
- "THIS ^^^^^ is the requested"
- " SATA drive (handle = 0x%p)\n",
- handle);
- winfo->sata_adr = dinfo->address;
- winfo->obj_handle = handle;
- }
+ if (out_obj->buffer.length != sizeof(struct ata_acpi_gtm)) {
+ ata_port_printk(ap, KERN_ERR,
+ "_GTM returned invalid length %d\n",
+ out_obj->buffer.length);
+ goto out_free;
}
-out:
- kfree(dinfo);
-out2:
- kfree(pathname);
-ret:
- return status;
+ memcpy(gtm, out_obj->buffer.pointer, sizeof(struct ata_acpi_gtm));
+ rc = 0;
+ out_free:
+ kfree(output.pointer);
+ return rc;
}
-/* Get the SATA drive _ADR object. */
-static int get_sata_adr(struct device *dev, acpi_handle handle,
- acpi_integer pcidevfn, unsigned int drive,
- struct ata_port *ap,
- struct ata_device *atadev, u32 *dev_adr)
+/**
+ * ata_acpi_stm - execute _STM
+ * @ap: target ATA port
+ * @stm: timing parameter to _STM
+ *
+ * Evaluate _STM with timing parameter @stm.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure.
+ */
+static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
{
- acpi_status status;
- struct walk_info *winfo;
- int err = -ENOMEM;
-
- winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
- if (!winfo)
- goto out;
-
- winfo->dev = dev;
- winfo->atadev = atadev;
- winfo->ataport = ap;
- if (acpi_bus_get_device(handle, &winfo->adev) < 0)
- if (ata_msg_probe(ap))
- ata_dev_printk(winfo->atadev, KERN_DEBUG,
- "acpi_bus_get_device failed\n");
- winfo->handle = handle;
- winfo->pcidevfn = pcidevfn;
- winfo->drivenum = drive;
+ acpi_status status;
+ struct acpi_object_list input;
+ union acpi_object in_params[3];
- status = acpi_get_devices(NULL, get_devices, winfo, NULL);
+ in_params[0].type = ACPI_TYPE_BUFFER;
+ in_params[0].buffer.length = sizeof(struct ata_acpi_gtm);
+ in_params[0].buffer.pointer = (u8 *)stm;
+ /* Buffers for id may need byteswapping ? */
+ in_params[1].type = ACPI_TYPE_BUFFER;
+ in_params[1].buffer.length = 512;
+ in_params[1].buffer.pointer = (u8 *)ap->device[0].id;
+ in_params[2].type = ACPI_TYPE_BUFFER;
+ in_params[2].buffer.length = 512;
+ in_params[2].buffer.pointer = (u8 *)ap->device[1].id;
+
+ input.count = 3;
+ input.pointer = in_params;
+
+ status = acpi_evaluate_object(ap->acpi_handle, "_STM", &input, NULL);
+
+ if (status == AE_NOT_FOUND)
+ return -ENOENT;
if (ACPI_FAILURE(status)) {
- if (ata_msg_probe(ap))
- ata_dev_printk(winfo->atadev, KERN_DEBUG,
- "%s: acpi_get_devices failed\n",
- __FUNCTION__);
- err = -ENODEV;
- } else {
- *dev_adr = winfo->sata_adr;
- atadev->obj_handle = winfo->obj_handle;
- err = 0;
+ ata_port_printk(ap, KERN_ERR,
+ "ACPI set timing mode failed (status=0x%x)\n", status);
+ return -EINVAL;
}
- kfree(winfo);
-out:
- return err;
+ return 0;
}
/**
- * do_drive_get_GTF - get the drive bootup default taskfile settings
+ * ata_dev_get_GTF - get the drive bootup default taskfile settings
* @dev: target ATA device
- * @gtf_length: number of bytes of _GTF data returned at @gtf_address
- * @gtf_address: buffer containing _GTF taskfile arrays
+ * @gtf: output parameter for buffer containing _GTF taskfile arrays
+ * @ptr_to_free: pointer which should be freed
*
* This applies to both PATA and SATA drives.
*
@@ -282,121 +216,41 @@ out:
* The <variable number> is not known in advance, so have ACPI-CA
* allocate the buffer as needed and return it, then free it later.
*
- * The returned @gtf_length and @gtf_address are only valid if the
- * function return value is 0.
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't
+ * contain valid data. -errno on other errors.
*/
-static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
- unsigned long *gtf_address, unsigned long *obj_loc)
+static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
+ void **ptr_to_free)
{
struct ata_port *ap = dev->ap;
acpi_status status;
- acpi_handle dev_handle = NULL;
- acpi_handle chan_handle, drive_handle;
- acpi_integer pcidevfn = 0;
- u32 dev_adr;
struct acpi_buffer output;
union acpi_object *out_obj;
- struct device *gdev = ap->host->dev;
- int err = -ENODEV;
+ int rc = 0;
- *gtf_length = 0;
- *gtf_address = 0UL;
- *obj_loc = 0UL;
-
- if (libata_noacpi)
- return 0;
+ /* set up output buffer */
+ output.length = ACPI_ALLOCATE_BUFFER;
+ output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
__FUNCTION__, ap->port_no);
- if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED)) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: ERR: "
- "ata_dev_present: %d, PORT_DISABLED: %lu\n",
- __FUNCTION__, ata_dev_enabled(dev),
- ap->flags & ATA_FLAG_DISABLED);
- goto out;
- }
-
- /* Don't continue if device has no _ADR method.
- * _GTF is intended for known motherboard devices. */
- if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
- err = pata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
- if (err < 0) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: pata_get_dev_handle failed (%d)\n",
- __FUNCTION__, err);
- goto out;
- }
- } else {
- err = sata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
- if (err < 0) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: sata_get_dev_handle failed (%d\n",
- __FUNCTION__, err);
- goto out;
- }
- }
-
- /* Get this drive's _ADR info. if not already known. */
- if (!dev->obj_handle) {
- if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
- /* get child objects of dev_handle == channel objects,
- * + _their_ children == drive objects */
- /* channel is ap->port_no */
- chan_handle = acpi_get_child(dev_handle,
- ap->port_no);
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: chan adr=%d: chan_handle=0x%p\n",
- __FUNCTION__, ap->port_no,
- chan_handle);
- if (!chan_handle) {
- err = -ENODEV;
- goto out;
- }
- /* TBD: could also check ACPI object VALID bits */
- drive_handle = acpi_get_child(chan_handle, dev->devno);
- if (!drive_handle) {
- err = -ENODEV;
- goto out;
- }
- dev_adr = dev->devno;
- dev->obj_handle = drive_handle;
- } else { /* for SATA mode */
- dev_adr = SATA_ADR_RSVD;
- err = get_sata_adr(gdev, dev_handle, pcidevfn, 0,
- ap, dev, &dev_adr);
- }
- if (err < 0 || dev_adr == SATA_ADR_RSVD ||
- !dev->obj_handle) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: get_sata/pata_adr failed: "
- "err=%d, dev_adr=%u, obj_handle=0x%p\n",
- __FUNCTION__, err, dev_adr,
- dev->obj_handle);
- goto out;
- }
- }
-
- /* Setting up output buffer */
- output.length = ACPI_ALLOCATE_BUFFER;
- output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
-
/* _GTF has no input parameters */
- err = -EIO;
- status = acpi_evaluate_object(dev->obj_handle, "_GTF",
- NULL, &output);
+ status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
+
if (ACPI_FAILURE(status)) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: Run _GTF error: status = 0x%x\n",
- __FUNCTION__, status);
- goto out;
+ if (status != AE_NOT_FOUND) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "_GTF evaluation failed (AE 0x%x)\n",
+ status);
+ rc = -EIO;
+ }
+ goto out_free;
}
if (!output.length || !output.pointer) {
@@ -406,43 +260,39 @@ static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
__FUNCTION__,
(unsigned long long)output.length,
output.pointer);
- kfree(output.pointer);
- goto out;
+ goto out_free;
}
out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) {
- kfree(output.pointer);
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: "
- "error: expected object type of "
- " ACPI_TYPE_BUFFER, got 0x%x\n",
- __FUNCTION__, out_obj->type);
- err = -ENOENT;
- goto out;
+ ata_dev_printk(dev, KERN_WARNING,
+ "_GTF unexpected object type 0x%x\n",
+ out_obj->type);
+ rc = -EINVAL;
+ goto out_free;
}
- if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
- out_obj->buffer.length % REGS_PER_GTF) {
- if (ata_msg_drv(ap))
- ata_dev_printk(dev, KERN_ERR,
- "%s: unexpected GTF length (%d) or addr (0x%p)\n",
- __FUNCTION__, out_obj->buffer.length,
- out_obj->buffer.pointer);
- err = -ENOENT;
- goto out;
+ if (out_obj->buffer.length % REGS_PER_GTF) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "unexpected _GTF length (%d)\n",
+ out_obj->buffer.length);
+ rc = -EINVAL;
+ goto out_free;
}
- *gtf_length = out_obj->buffer.length;
- *gtf_address = (unsigned long)out_obj->buffer.pointer;
- *obj_loc = (unsigned long)out_obj;
+ *ptr_to_free = out_obj;
+ *gtf = (void *)out_obj->buffer.pointer;
+ rc = out_obj->buffer.length / REGS_PER_GTF;
+
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: returning "
- "gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n",
- __FUNCTION__, *gtf_length, *gtf_address, *obj_loc);
- err = 0;
-out:
- return err;
+ "gtf=%p, gtf_count=%d, ptr_to_free=%p\n",
+ __FUNCTION__, *gtf, rc, *ptr_to_free);
+ return rc;
+
+ out_free:
+ kfree(output.pointer);
+ return rc;
}
/**
@@ -461,154 +311,99 @@ out:
* function also waits for idle after writing control and before
* writing the remaining registers.
*
- * LOCKING: TBD:
- * Inherited from caller.
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
*/
-static void taskfile_load_raw(struct ata_device *dev,
- const struct taskfile_array *gtf)
+static int taskfile_load_raw(struct ata_device *dev,
+ const struct ata_acpi_gtf *gtf)
{
struct ata_port *ap = dev->ap;
- struct ata_taskfile tf;
- unsigned int err;
+ struct ata_taskfile tf, rtf;
+ unsigned int err_mask;
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: "
- "%02x %02x %02x %02x %02x %02x %02x\n",
- __FUNCTION__,
- gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
- gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
-
- if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0)
- && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0)
- && (gtf->tfa[6] == 0))
- return;
+ if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0)
+ && (gtf->tf[3] == 0) && (gtf->tf[4] == 0) && (gtf->tf[5] == 0)
+ && (gtf->tf[6] == 0))
+ return 0;
ata_tf_init(dev, &tf);
/* convert gtf to tf */
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
tf.protocol = ATA_PROT_NODATA;
- tf.feature = gtf->tfa[0]; /* 0x1f1 */
- tf.nsect = gtf->tfa[1]; /* 0x1f2 */
- tf.lbal = gtf->tfa[2]; /* 0x1f3 */
- tf.lbam = gtf->tfa[3]; /* 0x1f4 */
- tf.lbah = gtf->tfa[4]; /* 0x1f5 */
- tf.device = gtf->tfa[5]; /* 0x1f6 */
- tf.command = gtf->tfa[6]; /* 0x1f7 */
-
- err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
- if (err && ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_ERR,
- "%s: ata_exec_internal failed: %u\n",
- __FUNCTION__, err);
-}
-
-/**
- * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
- * @dev: target ATA device
- * @gtf_length: total number of bytes of _GTF taskfiles
- * @gtf_address: location of _GTF taskfile arrays
- *
- * This applies to both PATA and SATA drives.
- *
- * Write {gtf_address, length gtf_length} in groups of
- * REGS_PER_GTF bytes.
- */
-static int do_drive_set_taskfiles(struct ata_device *dev,
- unsigned int gtf_length,
- unsigned long gtf_address)
-{
- struct ata_port *ap = dev->ap;
- int err = -ENODEV;
- int gtf_count = gtf_length / REGS_PER_GTF;
- int ix;
- struct taskfile_array *gtf;
+ tf.feature = gtf->tf[0]; /* 0x1f1 */
+ tf.nsect = gtf->tf[1]; /* 0x1f2 */
+ tf.lbal = gtf->tf[2]; /* 0x1f3 */
+ tf.lbam = gtf->tf[3]; /* 0x1f4 */
+ tf.lbah = gtf->tf[4]; /* 0x1f5 */
+ tf.device = gtf->tf[5]; /* 0x1f6 */
+ tf.command = gtf->tf[6]; /* 0x1f7 */
if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
- __FUNCTION__, ap->port_no);
-
- if (libata_noacpi || !(ap->flags & ATA_FLAG_ACPI_SATA))
- return 0;
-
- if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED))
- goto out;
- if (!gtf_count) /* shouldn't be here */
- goto out;
-
- if (gtf_length % REGS_PER_GTF) {
- if (ata_msg_drv(ap))
- ata_dev_printk(dev, KERN_ERR,
- "%s: unexpected GTF length (%d)\n",
- __FUNCTION__, gtf_length);
- goto out;
- }
-
- for (ix = 0; ix < gtf_count; ix++) {
- gtf = (struct taskfile_array *)
- (gtf_address + ix * REGS_PER_GTF);
-
- /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
- taskfile_load_raw(dev, gtf);
+ ata_dev_printk(dev, KERN_DEBUG, "executing ACPI cmd "
+ "%02x/%02x:%02x:%02x:%02x:%02x:%02x\n",
+ tf.command, tf.feature, tf.nsect,
+ tf.lbal, tf.lbam, tf.lbah, tf.device);
+
+ rtf = tf;
+ err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0);
+ if (err_mask) {
+ ata_dev_printk(dev, KERN_ERR,
+ "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed "
+ "(Emask=0x%x Stat=0x%02x Err=0x%02x)\n",
+ tf.command, tf.feature, tf.nsect, tf.lbal, tf.lbam,
+ tf.lbah, tf.device, err_mask, rtf.command, rtf.feature);
+ return -EIO;
}
- err = 0;
-out:
- return err;
+ return 0;
}
/**
* ata_acpi_exec_tfs - get then write drive taskfile settings
- * @ap: the ata_port for the drive
+ * @dev: target ATA device
*
- * This applies to both PATA and SATA drives.
+ * Evaluate _GTF and excute returned taskfiles.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Number of executed taskfiles on success, 0 if _GTF doesn't exist or
+ * doesn't contain valid data. -errno on other errors.
*/
-int ata_acpi_exec_tfs(struct ata_port *ap)
+static int ata_acpi_exec_tfs(struct ata_device *dev)
{
- int ix;
- int ret = 0;
- unsigned int gtf_length;
- unsigned long gtf_address;
- unsigned long obj_loc;
-
- if (libata_noacpi)
- return 0;
- /*
- * TBD - implement PATA support. For now,
- * we should not run GTF on PATA devices since some
- * PATA require execution of GTM/STM before GTF.
- */
- if (!(ap->flags & ATA_FLAG_ACPI_SATA))
- return 0;
-
- for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
- struct ata_device *dev = &ap->device[ix];
-
- if (!ata_dev_enabled(dev))
- continue;
-
- ret = do_drive_get_GTF(dev, &gtf_length, &gtf_address,
- &obj_loc);
- if (ret < 0) {
- if (ata_msg_probe(ap))
- ata_port_printk(ap, KERN_DEBUG,
- "%s: get_GTF error (%d)\n",
- __FUNCTION__, ret);
- break;
- }
-
- ret = do_drive_set_taskfiles(dev, gtf_length, gtf_address);
- kfree((void *)obj_loc);
- if (ret < 0) {
- if (ata_msg_probe(ap))
- ata_port_printk(ap, KERN_DEBUG,
- "%s: set_taskfiles error (%d)\n",
- __FUNCTION__, ret);
- break;
- }
+ struct ata_acpi_gtf *gtf = NULL;
+ void *ptr_to_free = NULL;
+ int gtf_count, i, rc;
+
+ /* get taskfiles */
+ rc = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
+ if (rc < 0)
+ return rc;
+ gtf_count = rc;
+
+ /* execute them */
+ for (i = 0, rc = 0; i < gtf_count; i++) {
+ int tmp;
+
+ /* ACPI errors are eventually ignored. Run till the
+ * end even after errors.
+ */
+ tmp = taskfile_load_raw(dev, gtf++);
+ if (!rc)
+ rc = tmp;
}
- return ret;
+ kfree(ptr_to_free);
+
+ if (rc == 0)
+ return gtf_count;
+ return rc;
}
/**
@@ -620,62 +415,25 @@ int ata_acpi_exec_tfs(struct ata_port *ap)
* ATM this function never returns a failure. It is an optional
* method and if it fails for whatever reason, we should still
* just keep going.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
*/
-int ata_acpi_push_id(struct ata_device *dev)
+static int ata_acpi_push_id(struct ata_device *dev)
{
struct ata_port *ap = dev->ap;
- acpi_handle handle;
- acpi_integer pcidevfn;
int err;
- struct device *gdev = ap->host->dev;
- u32 dev_adr;
acpi_status status;
struct acpi_object_list input;
union acpi_object in_params[1];
- if (libata_noacpi)
- return 0;
-
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
__FUNCTION__, dev->devno, ap->port_no);
- /* Don't continue if not a SATA device. */
- if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: Not a SATA device\n", __FUNCTION__);
- goto out;
- }
-
- /* Don't continue if device has no _ADR method.
- * _SDD is intended for known motherboard devices. */
- err = sata_get_dev_handle(gdev, &handle, &pcidevfn);
- if (err < 0) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: sata_get_dev_handle failed (%d\n",
- __FUNCTION__, err);
- goto out;
- }
-
- /* Get this drive's _ADR info, if not already known */
- if (!dev->obj_handle) {
- dev_adr = SATA_ADR_RSVD;
- err = get_sata_adr(gdev, handle, pcidevfn, dev->devno, ap, dev,
- &dev_adr);
- if (err < 0 || dev_adr == SATA_ADR_RSVD ||
- !dev->obj_handle) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: get_sata_adr failed: "
- "err=%d, dev_adr=%u, obj_handle=0x%p\n",
- __FUNCTION__, err, dev_adr,
- dev->obj_handle);
- goto out;
- }
- }
-
/* Give the drive Identify data to the drive via the _SDD method */
/* _SDD: set up input parameters */
input.count = 1;
@@ -687,20 +445,150 @@ int ata_acpi_push_id(struct ata_device *dev)
/* It's OK for _SDD to be missing too. */
swap_buf_le16(dev->id, ATA_ID_WORDS);
- status = acpi_evaluate_object(dev->obj_handle, "_SDD", &input, NULL);
+ status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL);
swap_buf_le16(dev->id, ATA_ID_WORDS);
err = ACPI_FAILURE(status) ? -EIO : 0;
- if (err < 0) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s _SDD error: status = 0x%x\n",
- __FUNCTION__, status);
+ if (err < 0)
+ ata_dev_printk(dev, KERN_WARNING,
+ "ACPI _SDD failed (AE 0x%x)\n", status);
+
+ return err;
+}
+
+/**
+ * ata_acpi_on_suspend - ATA ACPI hook called on suspend
+ * @ap: target ATA port
+ *
+ * This function is called when @ap is about to be suspended. All
+ * devices are already put to sleep but the port_suspend() callback
+ * hasn't been executed yet. Error return from this function aborts
+ * suspend.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int ata_acpi_on_suspend(struct ata_port *ap)
+{
+ unsigned long flags;
+ int rc;
+
+ /* proceed iff per-port acpi_handle is valid */
+ if (!ap->acpi_handle)
+ return 0;
+ BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA);
+
+ /* store timing parameters */
+ rc = ata_acpi_gtm(ap, &ap->acpi_gtm);
+
+ spin_lock_irqsave(ap->lock, flags);
+ if (rc == 0)
+ ap->pflags |= ATA_PFLAG_GTM_VALID;
+ else
+ ap->pflags &= ~ATA_PFLAG_GTM_VALID;
+ spin_unlock_irqrestore(ap->lock, flags);
+
+ if (rc == -ENOENT)
+ rc = 0;
+ return rc;
+}
+
+/**
+ * ata_acpi_on_resume - ATA ACPI hook called on resume
+ * @ap: target ATA port
+ *
+ * This function is called when @ap is resumed - right after port
+ * itself is resumed but before any EH action is taken.
+ *
+ * LOCKING:
+ * EH context.
+ */
+void ata_acpi_on_resume(struct ata_port *ap)
+{
+ int i;
+
+ if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) {
+ BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA);
+
+ /* restore timing parameters */
+ ata_acpi_stm(ap, &ap->acpi_gtm);
}
- /* always return success */
-out:
- return 0;
+ /* schedule _GTF */
+ for (i = 0; i < ATA_MAX_DEVICES; i++)
+ ap->device[i].flags |= ATA_DFLAG_ACPI_PENDING;
}
+/**
+ * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
+ * @dev: target ATA device
+ *
+ * This function is called when @dev is about to be configured.
+ * IDENTIFY data might have been modified after this hook is run.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Positive number if IDENTIFY data needs to be refreshed, 0 if not,
+ * -errno on failure.
+ */
+int ata_acpi_on_devcfg(struct ata_device *dev)
+{
+ struct ata_port *ap = dev->ap;
+ struct ata_eh_context *ehc = &ap->eh_context;
+ int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA;
+ int rc;
+
+ if (!dev->acpi_handle)
+ return 0;
+
+ /* do we need to do _GTF? */
+ if (!(dev->flags & ATA_DFLAG_ACPI_PENDING) &&
+ !(acpi_sata && (ehc->i.flags & ATA_EHI_DID_HARDRESET)))
+ return 0;
+
+ /* do _SDD if SATA */
+ if (acpi_sata) {
+ rc = ata_acpi_push_id(dev);
+ if (rc)
+ goto acpi_err;
+ }
+
+ /* do _GTF */
+ rc = ata_acpi_exec_tfs(dev);
+ if (rc < 0)
+ goto acpi_err;
+
+ dev->flags &= ~ATA_DFLAG_ACPI_PENDING;
+
+ /* refresh IDENTIFY page if any _GTF command has been executed */
+ if (rc > 0) {
+ rc = ata_dev_reread_id(dev, 0);
+ if (rc < 0) {
+ ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY "
+ "after ACPI commands\n");
+ return rc;
+ }
+ }
+ return 0;
+
+ acpi_err:
+ /* let EH retry on the first failure, disable ACPI on the second */
+ if (dev->flags & ATA_DFLAG_ACPI_FAILED) {
+ ata_dev_printk(dev, KERN_WARNING, "ACPI on devcfg failed the "
+ "second time, disabling (errno=%d)\n", rc);
+
+ dev->acpi_handle = NULL;
+
+ /* if port is working, request IDENTIFY reload and continue */
+ if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ rc = 1;
+ }
+ dev->flags |= ATA_DFLAG_ACPI_FAILED;
+ return rc;
+}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 981b397cb46..5b25311ba88 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1845,7 +1845,8 @@ static void ata_dev_config_ncq(struct ata_device *dev,
int ata_dev_configure(struct ata_device *dev)
{
struct ata_port *ap = dev->ap;
- int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO;
+ struct ata_eh_context *ehc = &ap->eh_context;
+ int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
const u16 *id = dev->id;
unsigned int xfer_mask;
char revbuf[7]; /* XYZ-99\0 */
@@ -1862,15 +1863,10 @@ int ata_dev_configure(struct ata_device *dev)
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
- /* set _SDD */
- rc = ata_acpi_push_id(dev);
- if (rc) {
- ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n",
- rc);
- }
-
- /* retrieve and execute the ATA task file of _GTF */
- ata_acpi_exec_tfs(ap);
+ /* let ACPI work its magic */
+ rc = ata_acpi_on_devcfg(dev);
+ if (rc)
+ return rc;
/* print device capabilities */
if (ata_msg_probe(ap))
@@ -3359,7 +3355,7 @@ int ata_std_prereset(struct ata_port *ap, unsigned long deadline)
return 0;
/* if SATA, resume phy */
- if (ap->cbl == ATA_CBL_SATA) {
+ if (ap->flags & ATA_FLAG_SATA) {
rc = sata_phy_resume(ap, timing, deadline);
/* whine about phy resume failure but proceed */
if (rc && rc != -EOPNOTSUPP)
@@ -4107,6 +4103,68 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
}
/**
+ * ata_fill_sg_dumb - Fill PCI IDE PRD table
+ * @qc: Metadata associated with taskfile to be transferred
+ *
+ * Fill PCI IDE PRD (scatter-gather) table with segments
+ * associated with the current disk command. Perform the fill
+ * so that we avoid writing any length 64K records for
+ * controllers that don't follow the spec.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ *
+ */
+static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct scatterlist *sg;
+ unsigned int idx;
+
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+ idx = 0;
+ ata_for_each_sg(sg, qc) {
+ u32 addr, offset;
+ u32 sg_len, len, blen;
+
+ /* determine if physical DMA addr spans 64K boundary.
+ * Note h/w doesn't support 64-bit, so we unconditionally
+ * truncate dma_addr_t to u32.
+ */
+ addr = (u32) sg_dma_address(sg);
+ sg_len = sg_dma_len(sg);
+
+ while (sg_len) {
+ offset = addr & 0xffff;
+ len = sg_len;
+ if ((offset + sg_len) > 0x10000)
+ len = 0x10000 - offset;
+
+ blen = len & 0xffff;
+ ap->prd[idx].addr = cpu_to_le32(addr);
+ if (blen == 0) {
+ /* Some PATA chipsets like the CS5530 can't
+ cope with 0x0000 meaning 64K as the spec says */
+ ap->prd[idx].flags_len = cpu_to_le32(0x8000);
+ blen = 0x8000;
+ ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
+ }
+ ap->prd[idx].flags_len = cpu_to_le32(blen);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+
+ idx++;
+ sg_len -= len;
+ addr += len;
+ }
+ }
+
+ if (idx)
+ ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+}
+
+/**
* ata_check_atapi_dma - Check whether ATAPI DMA can be supported
* @qc: Metadata associated with taskfile to check
*
@@ -4153,6 +4211,23 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
ata_fill_sg(qc);
}
+/**
+ * ata_dumb_qc_prep - Prepare taskfile for submission
+ * @qc: Metadata associated with taskfile to be prepared
+ *
+ * Prepare ATA taskfile for submission.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
+{
+ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+ return;
+
+ ata_fill_sg_dumb(qc);
+}
+
void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
/**
@@ -5660,7 +5735,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance)
*/
int sata_scr_valid(struct ata_port *ap)
{
- return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
+ return (ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read;
}
/**
@@ -6293,6 +6368,9 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
if (rc)
return rc;
+ /* associate with ACPI nodes */
+ ata_acpi_associate(host);
+
/* set cable, sata_spd_limit and report */
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
@@ -6324,7 +6402,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
if (!ata_port_is_dummy(ap))
ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%p "
"ctl 0x%p bmdma 0x%p irq %d\n",
- ap->cbl == ATA_CBL_SATA ? 'S' : 'P',
+ (ap->flags & ATA_FLAG_SATA) ? 'S' : 'P',
ata_mode_string(xfer_mask),
ap->ioaddr.cmd_addr,
ap->ioaddr.ctl_addr,
@@ -6822,6 +6900,7 @@ EXPORT_SYMBOL_GPL(ata_do_set_mode);
EXPORT_SYMBOL_GPL(ata_data_xfer);
EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
EXPORT_SYMBOL_GPL(ata_qc_prep);
+EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup);
EXPORT_SYMBOL_GPL(ata_bmdma_start);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index f7582c9c320..9ee0a8c08d9 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2154,19 +2154,25 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
+ /* tell ACPI we're suspending */
+ rc = ata_acpi_on_suspend(ap);
+ if (rc)
+ goto out;
+
/* suspend */
ata_eh_freeze_port(ap);
if (ap->ops->port_suspend)
rc = ap->ops->port_suspend(ap, ap->pm_mesg);
+ out:
/* report result */
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~ATA_PFLAG_PM_PENDING;
if (rc == 0)
ap->pflags |= ATA_PFLAG_SUSPENDED;
- else
+ else if (ap->pflags & ATA_PFLAG_FROZEN)
ata_port_schedule_eh(ap);
if (ap->pm_result) {
@@ -2207,6 +2213,9 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
if (ap->ops->port_resume)
rc = ap->ops->port_resume(ap);
+ /* tell ACPI that we're resuming */
+ ata_acpi_on_resume(ap);
+
/* report result */
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 4ddf00c8c5f..cfde22da07a 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2620,7 +2620,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
ata_dev_printk(dev, KERN_WARNING,
"invalid multi_count %u ignored\n",
multi_count);
- }
+ }
/* READ/WRITE LONG use a non-standard sect_size */
qc->sect_size = ATA_SECT_SIZE;
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 5e246665842..ba17fc5f2e9 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -98,17 +98,15 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host);
/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
-extern int ata_acpi_exec_tfs(struct ata_port *ap);
-extern int ata_acpi_push_id(struct ata_device *dev);
+extern void ata_acpi_associate(struct ata_host *host);
+extern int ata_acpi_on_suspend(struct ata_port *ap);
+extern void ata_acpi_on_resume(struct ata_port *ap);
+extern int ata_acpi_on_devcfg(struct ata_device *adev);
#else
-static inline int ata_acpi_exec_tfs(struct ata_port *ap)
-{
- return 0;
-}
-static inline int ata_acpi_push_id(struct ata_device *dev)
-{
- return 0;
-}
+static inline void ata_acpi_associate(struct ata_host *host) { }
+static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
+static inline void ata_acpi_on_resume(struct ata_port *ap) { }
+static inline int ata_acpi_on_devcfg(struct ata_device *adev) { return 0; }
#endif
/* libata-scsi.c */
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 75e95bdbe02..30c4276ec88 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -520,14 +520,14 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info_early = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &ali_early_port_ops
};
/* Revision 0x20 added DMA */
static const struct ata_port_info info_20 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &ali_20_port_ops
@@ -535,7 +535,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Revision 0x20 with support logic added UDMA */
static const struct ata_port_info info_20_udma = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07, /* UDMA33 */
@@ -544,37 +544,37 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Revision 0xC2 adds UDMA66 */
static const struct ata_port_info info_c2 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &ali_c2_port_ops
};
/* Revision 0xC3 is UDMA66 for now */
static const struct ata_port_info info_c3 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &ali_c2_port_ops
};
/* Revision 0xC4 is UDMA100 */
static const struct ata_port_info info_c4 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &ali_c2_port_ops
};
/* Revision 0xC5 is UDMA133 with LBA48 DMA */
static const struct ata_port_info info_c5 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &ali_c5_port_ops
};
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index a16f629b7b3..b9c44c575ce 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -541,7 +541,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct ata_port_info info[10] = {
{ /* 0: AMD 7401 */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07, /* No SWDMA */
.udma_mask = 0x07, /* UDMA 33 */
@@ -549,74 +549,74 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
},
{ /* 1: Early AMD7409 - no swdma */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f, /* UDMA 66 */
+ .udma_mask = ATA_UDMA4, /* UDMA 66 */
.port_ops = &amd66_port_ops
},
{ /* 2: AMD 7409, no swdma errata */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f, /* UDMA 66 */
+ .udma_mask = ATA_UDMA4, /* UDMA 66 */
.port_ops = &amd66_port_ops
},
{ /* 3: AMD 7411 */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA5, /* UDMA 100 */
.port_ops = &amd100_port_ops
},
{ /* 4: AMD 7441 */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA5, /* UDMA 100 */
.port_ops = &amd100_port_ops
},
{ /* 5: AMD 8111*/
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f, /* UDMA 133, no swdma */
+ .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */
.port_ops = &amd133_port_ops
},
{ /* 6: AMD 8111 UDMA 100 (Serenade) */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100, no swdma */
+ .udma_mask = ATA_UDMA5, /* UDMA 100, no swdma */
.port_ops = &amd133_port_ops
},
{ /* 7: Nvidia Nforce */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA5, /* UDMA 100 */
.port_ops = &nv100_port_ops
},
{ /* 8: Nvidia Nforce2 and later */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f, /* UDMA 133, no swdma */
+ .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */
.port_ops = &nv133_port_ops
},
{ /* 9: AMD CS5536 (Geode companion) */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA5, /* UDMA 100 */
.port_ops = &amd100_port_ops
}
};
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 03b6ddd2abd..ce589d96ca4 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -416,7 +416,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
static int printed_version;
static const struct ata_port_info info_6210 = {
.sht = &artop_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA2,
@@ -424,7 +424,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
};
static const struct ata_port_info info_626x = {
.sht = &artop_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA4,
@@ -432,7 +432,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
};
static const struct ata_port_info info_626x_fast = {
.sht = &artop_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5,
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 844914681a2..80509be49e7 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -270,7 +270,7 @@ static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &atiixp_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x06, /* No MWDMA0 support */
.udma_mask = 0x3F,
@@ -285,6 +285,7 @@ static const struct pci_device_id atiixp[] = {
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), },
+ { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), },
{ },
};
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index 31cbf8daa29..0feb5ae8c48 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -251,7 +251,7 @@ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &cmd640_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &cmd640_port_ops
};
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 320a5b10aa9..dc443e7dc37 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -380,21 +380,21 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct ata_port_info cmd_info[6] = {
{ /* CMD 643 - no UDMA */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &cmd64x_port_ops
},
{ /* CMD 646 with broken UDMA */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &cmd64x_port_ops
},
{ /* CMD 646 with working UDMA */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA1,
@@ -402,14 +402,14 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
},
{ /* CMD 646 rev 1 */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &cmd646r1_port_ops
},
{ /* CMD 648 */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA2,
@@ -417,7 +417,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
},
{ /* CMD 649 */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA3,
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 00cf0134079..6bf037d82b5 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -146,7 +146,7 @@ static struct scsi_host_template cs5520_sht = {
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -178,7 +178,7 @@ static struct ata_port_operations cs5520_port_ops = {
.bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
+ .qc_prep = ata_dumb_qc_prep,
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_data_xfer,
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 848f0309bf0..3fca5898642 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -167,7 +167,7 @@ static struct scsi_host_template cs5530_sht = {
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -201,7 +201,7 @@ static struct ata_port_operations cs5530_port_ops = {
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = ata_cable_40wire,
- .qc_prep = ata_qc_prep,
+ .qc_prep = ata_dumb_qc_prep,
.qc_issue = cs5530_qc_issue_prot,
.data_xfer = ata_data_xfer,
@@ -337,7 +337,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &cs5530_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07,
@@ -346,7 +346,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* The docking connector doesn't do UDMA, and it seems not MWDMA */
static const struct ata_port_info info_palmax_secondary = {
.sht = &cs5530_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &cs5530_port_ops
};
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index aa3256fb9f7..360b6f32e17 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -225,10 +225,10 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &cs5535_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &cs5535_port_ops
};
const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index d41a7691dd8..6cbc8778bf4 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -167,7 +167,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i
{
static const struct ata_port_info info = {
.sht = &cy82c693_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &cy82c693_port_ops
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index 079248a9b46..c8ba59c5611 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -303,7 +303,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int printed_version;
static const struct ata_port_info info = {
.sht = &efar_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma1-2 */
.udma_mask = 0x0f, /* UDMA 66 */
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 0c9cb609071..6f7d34ad19e 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -393,10 +393,10 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info_hpt366 = {
.sht = &hpt36x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &hpt366_port_ops
};
struct ata_port_info info = info_hpt366;
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index a8c0cbeca39..b0af65aadde 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -889,25 +889,25 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT370 - UDMA100 */
static const struct ata_port_info info_hpt370 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &hpt370_port_ops
};
/* HPT370A - UDMA100 */
static const struct ata_port_info info_hpt370a = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &hpt370a_port_ops
};
/* HPT370 - UDMA100 */
static const struct ata_port_info info_hpt370_33 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x0f,
@@ -916,7 +916,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT370A - UDMA100 */
static const struct ata_port_info info_hpt370a_33 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x0f,
@@ -925,19 +925,19 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT371, 372 and friends - UDMA133 */
static const struct ata_port_info info_hpt372 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &hpt372_port_ops
};
/* HPT374 - UDMA100 */
static const struct ata_port_info info_hpt374 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &hpt374_port_ops
};
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index e947433cb37..aa29cde09f8 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -490,10 +490,10 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT372N and friends - UDMA133 */
static const struct ata_port_info info = {
.sht = &hpt3x2n_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &hpt3x2n_port_ops
};
struct ata_port_info port = info;
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 8ce5e23a5f7..d928c910503 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -173,7 +173,7 @@ static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &hpt3x3_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07,
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index c791a46df46..321d98b0bed 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -530,7 +530,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
ap->pio_mask = 0x1f;
ap->mwdma_mask = info->mwdma_mask;
- ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ops = &pata_icside_port_ops;
pata_icside_setup_ioaddr(&ap->ioaddr, info->base, info->port[i]);
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index 95b0bb61788..b8af55e8915 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -313,10 +313,10 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
static int printed_version;
static const struct ata_port_info info = {
.sht = &it8213_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x1f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA4, /* FIXME: want UDMA 100? */
.port_ops = &it8213_ops,
};
/* Current IT8213 stuff is single port */
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 12c6e08cc4d..b67bbf6516b 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -714,17 +714,17 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct ata_port_info info_smart = {
.sht = &it821x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &it821x_smart_port_ops
};
static const struct ata_port_info info_passthru = {
.sht = &it821x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &it821x_passthru_port_ops
};
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index 8d2bc1e9e87..4ca7fd6118d 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -1,13 +1,14 @@
/*
* ixp4xx PATA/Compact Flash driver
- * Copyright (c) 2006 Tower Technologies
+ * Copyright (C) 2006-07 Tower Technologies
* Author: Alessandro Zummo <a.zummo@towertech.it>
*
* An ATA driver to handle a Compact Flash connected
* to the ixp4xx expansion bus in TrueIDE mode. The CF
* must have it chip selects connected to two CS lines
- * on the ixp4xx. The interrupt line is optional, if not
- * specified the driver will run in polling mode.
+ * on the ixp4xx. In the irq is not available, you might
+ * want to modify both this driver and libata to run in
+ * polling mode.
*
* 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
@@ -23,7 +24,7 @@
#include <scsi/scsi_host.h>
#define DRV_NAME "pata_ixp4xx_cf"
-#define DRV_VERSION "0.1.3"
+#define DRV_VERSION "0.2"
static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error)
{
@@ -42,13 +43,6 @@ static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error)
return 0;
}
-static void ixp4xx_phy_reset(struct ata_port *ap)
-{
- ap->cbl = ATA_CBL_PATA40;
- ata_port_probe(ap);
- ata_bus_reset(ap);
-}
-
static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data)
{
@@ -56,7 +50,7 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int words = buflen >> 1;
u16 *buf16 = (u16 *) buf;
struct ata_port *ap = adev->ap;
- void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+ void __iomem *mmio = ap->ioaddr.data_addr;
struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
/* set the expansion bus in 16bit mode and restore
@@ -92,10 +86,6 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
*data->cs0_cfg |= 0x01;
}
-static void ixp4xx_irq_clear(struct ata_port *ap)
-{
-}
-
static struct scsi_host_template ixp4xx_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
@@ -115,29 +105,32 @@ static struct scsi_host_template ixp4xx_sht = {
};
static struct ata_port_operations ixp4xx_port_ops = {
- .set_mode = ixp4xx_set_mode,
- .mode_filter = ata_pci_default_filter,
-
- .port_disable = ata_port_disable,
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = ata_exec_command,
- .dev_select = ata_std_dev_select,
-
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .eng_timeout = ata_eng_timeout,
- .data_xfer = ixp4xx_mmio_data_xfer,
- .cable_detect = ata_cable_40wire,
-
- .irq_clear = ixp4xx_irq_clear,
- .irq_on = ata_irq_on,
- .irq_ack = ata_irq_ack,
-
- .port_start = ata_port_start,
-
- .phy_reset = ixp4xx_phy_reset,
+ .set_mode = ixp4xx_set_mode,
+ .mode_filter = ata_pci_default_filter,
+
+ .port_disable = ata_port_disable,
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .exec_command = ata_exec_command,
+ .check_status = ata_check_status,
+ .dev_select = ata_std_dev_select,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ata_bmdma_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .data_xfer = ixp4xx_mmio_data_xfer,
+ .cable_detect = ata_cable_40wire,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+ .irq_on = ata_irq_on,
+ .irq_ack = ata_dummy_irq_ack,
+
+ .port_start = ata_port_start,
};
static void ixp4xx_setup_port(struct ata_ioports *ioaddr,
@@ -178,7 +171,6 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
struct ata_host *host;
struct ata_port *ap;
struct ixp4xx_pata_data *data = pdev->dev.platform_data;
- int rc;
cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -211,10 +203,6 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
ap->pio_mask = 0x1f; /* PIO4 */
ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
- /* run in polling mode if no irq has been assigned */
- if (!irq)
- ap->flags |= ATA_FLAG_PIO_POLLING;
-
ixp4xx_setup_port(&ap->ioaddr, data);
dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 2af7ff8256c..4d67f238eee 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -193,11 +193,11 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
{
static const struct ata_port_info info = {
.sht = &jmicron_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &jmicron_ops,
};
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index edbfe0dbbf7..87594c04d3a 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -163,22 +163,22 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
{
static const struct ata_port_info info = {
.sht = &marvell_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &marvell_ops,
};
static const struct ata_port_info info_sata = {
.sht = &marvell_sht,
/* Slave possible as its magically mapped not real */
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &marvell_ops,
};
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 81f56345866..40eb574828b 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -94,12 +94,12 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
static const struct ata_port_info info = {
.sht = &netcell_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
/* Actually we don't really care about these as the
firmware deals with it */
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* UDMA 133 */
+ .udma_mask = ATA_UDMA5, /* UDMA 133 */
.port_ops = &netcell_ops,
};
const struct ata_port_info *port_info[] = { &info, NULL };
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index ea70ec74487..2f5d714ebfc 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -193,7 +193,7 @@ static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &ns87410_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x0F,
.port_ops = &ns87410_port_ops
};
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 29c23ddd655..091a70a0ef1 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -291,7 +291,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
static const struct ata_port_info info = {
.sht = &oldpiix_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma1-2 */
.port_ops = &oldpiix_pata_ops,
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index 1c44653e1e0..458bf67f766 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -218,7 +218,7 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &opti_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &opti_port_ops
};
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 3093b02286c..f89bdfde16d 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -484,14 +484,14 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info_82c700 = {
.sht = &optidma_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &optidma_port_ops
};
static const struct ata_port_info info_82c700_udma = {
.sht = &optidma_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07,
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index d277246b733..92447bed5e7 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -320,7 +320,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
static const struct ata_port_info info[3] = {
{
.sht = &pdc202xx_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA2,
@@ -328,7 +328,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
},
{
.sht = &pdc202xx_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA4,
@@ -336,7 +336,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
},
{
.sht = &pdc202xx_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA5,
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index cbb7866940d..79f841bca59 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -139,6 +139,7 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
struct resource *io_res, *ctl_res;
struct ata_host *host;
struct ata_port *ap;
+ struct pata_platform_info *pp_info;
unsigned int mmio;
/*
@@ -208,11 +209,12 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
- pata_platform_setup_port(&ap->ioaddr, pdev->dev.platform_data);
+ pp_info = (struct pata_platform_info *)(pdev->dev.platform_data);
+ pata_platform_setup_port(&ap->ioaddr, pp_info);
/* activate */
return ata_host_activate(host, platform_get_irq(pdev, 0), ata_interrupt,
- 0, &pata_platform_sht);
+ pp_info->irq_flags, &pata_platform_sht);
}
/**
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index ba96b54f5b8..7d1aabed422 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -257,7 +257,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
static const struct ata_port_info info = {
.sht = &radisys_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma1-2 */
.udma_mask = 0x14, /* UDMA33/66 only */
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index a3488b41ad2..7632fcb070c 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -133,7 +133,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
static int printed_version;
static const struct ata_port_info info = {
.sht = &rz1000_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &rz1000_port_ops
};
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 1233063ab9a..b8b2d11e418 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -185,7 +185,7 @@ static struct scsi_host_template sc1200_sht = {
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -219,7 +219,7 @@ static struct ata_port_operations sc1200_port_ops = {
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
+ .qc_prep = ata_dumb_qc_prep,
.qc_issue = sc1200_qc_issue_prot,
.data_xfer = ata_data_xfer,
@@ -245,7 +245,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &sc1200_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07,
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 1e8f421963c..0231aba51ca 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -478,31 +478,31 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
static const struct ata_port_info info[4] = {
{ /* OSB4 */
.sht = &serverworks_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07,
.port_ops = &serverworks_osb4_port_ops
}, { /* OSB4 no UDMA */
.sht = &serverworks_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x00,
.port_ops = &serverworks_osb4_port_ops
}, { /* CSB5 */
.sht = &serverworks_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &serverworks_csb_port_ops
}, { /* CSB5 - later revisions*/
.sht = &serverworks_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &serverworks_csb_port_ops
}
};
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 440e2cb6ee7..b0cd52d6e3f 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -35,6 +35,8 @@
#define DRV_NAME "pata_sil680"
#define DRV_VERSION "0.4.6"
+#define SIL680_MMIO_BAR 5
+
/**
* sil680_selreg - return register base
* @hwif: interface
@@ -293,8 +295,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev)
pci_read_config_byte(pdev, 0x8A, &tmpbyte);
- printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
- tmpbyte & 1, tmpbyte & 0x30);
+ dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
+ tmpbyte & 1, tmpbyte & 0x30);
switch(tmpbyte & 0x30) {
case 0x00:
@@ -315,8 +317,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev)
}
pci_read_config_byte(pdev, 0x8A, &tmpbyte);
- printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
- tmpbyte & 1, tmpbyte & 0x30);
+ dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
+ tmpbyte & 1, tmpbyte & 0x30);
pci_write_config_byte(pdev, 0xA1, 0x72);
pci_write_config_word(pdev, 0xA2, 0x328A);
@@ -339,22 +341,23 @@ static u8 sil680_init_chip(struct pci_dev *pdev)
return tmpbyte & 0x30;
}
-static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit sil680_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &sil680_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &sil680_port_ops
};
static const struct ata_port_info info_slow = {
.sht = &sil680_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil680_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index cfe4ec6eb3d..2b4508206a6 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -732,7 +732,7 @@ static const struct ata_port_operations sis_old_ops = {
static const struct ata_port_info sis_info = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07,
.udma_mask = 0,
@@ -740,7 +740,7 @@ static const struct ata_port_info sis_info = {
};
static const struct ata_port_info sis_info33 = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA2, /* UDMA 33 */
@@ -748,28 +748,28 @@ static const struct ata_port_info sis_info33 = {
};
static const struct ata_port_info sis_info66 = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA4, /* UDMA 66 */
.port_ops = &sis_66_ops,
};
static const struct ata_port_info sis_info100 = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA5,
.port_ops = &sis_100_ops,
};
static const struct ata_port_info sis_info100_early = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.udma_mask = ATA_UDMA5,
.pio_mask = 0x1f, /* pio0-4 */
.port_ops = &sis_66_ops,
};
static const struct ata_port_info sis_info133 = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &sis_133_ops,
@@ -783,7 +783,7 @@ const struct ata_port_info sis_info133_for_sata = {
};
static const struct ata_port_info sis_info133_early = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &sis_133_early_ops,
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index e5aaec43694..bde73418962 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -303,14 +303,14 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
{
static const struct ata_port_info info_dma = {
.sht = &sl82c105_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &sl82c105_port_ops
};
static const struct ata_port_info info_early = {
.sht = &sl82c105_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &sl82c105_port_ops
};
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index b1d3076dfe5..af21f443db6 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -235,7 +235,7 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &triflex_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &triflex_port_ops
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 63eca299c62..f0cadbe6aa1 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -471,7 +471,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7,
+ .udma_mask = ATA_UDMA2,
.port_ops = &via_port_ops
};
/* VIA UDMA 66 devices */
@@ -480,7 +480,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &via_port_ops
};
/* VIA UDMA 100 devices */
@@ -489,7 +489,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &via_port_ops
};
/* UDMA133 with bad AST (All current 133) */
@@ -498,7 +498,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f, /* FIXME: should check north bridge */
+ .udma_mask = ATA_UDMA6, /* FIXME: should check north bridge */
.port_ops = &via_port_ops
};
struct ata_port_info type;
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index f12c2b6ac08..bec1de594de 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -145,32 +145,32 @@ static struct scsi_host_template adma_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
+ .slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
+ .bios_param = ata_std_bios_param,
+ .proc_name = DRV_NAME,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
+ .dma_boundary = ADMA_DMA_BOUNDARY,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
- .emulated = ATA_SHT_EMULATED,
.use_clustering = ENABLE_CLUSTERING,
- .proc_name = DRV_NAME,
- .dma_boundary = ADMA_DMA_BOUNDARY,
- .slave_configure = ata_scsi_slave_config,
- .slave_destroy = ata_scsi_slave_destroy,
- .bios_param = ata_std_bios_param,
+ .emulated = ATA_SHT_EMULATED,
};
static const struct ata_port_operations adma_ata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .check_atapi_dma = adma_check_atapi_dma,
.exec_command = ata_exec_command,
+ .check_status = ata_check_status,
.dev_select = ata_std_dev_select,
.phy_reset = adma_phy_reset,
+ .check_atapi_dma = adma_check_atapi_dma,
+ .data_xfer = ata_data_xfer,
.qc_prep = adma_qc_prep,
.qc_issue = adma_qc_issue,
.eng_timeout = adma_eng_timeout,
- .data_xfer = ata_data_xfer,
.irq_clear = adma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -188,7 +188,7 @@ static struct ata_port_info adma_port_info[] = {
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
ATA_FLAG_PIO_POLLING,
.pio_mask = 0x10, /* pio4 */
- .udma_mask = 0x1f, /* udma0-4 */
+ .udma_mask = ATA_UDMA4,
.port_ops = &adma_ata_ops,
},
};
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index dc3bbce0467..3de183461c3 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -192,7 +192,7 @@ static void inic_reset_port(void __iomem *port_base)
static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg)
{
- void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+ void __iomem *scr_addr = ap->ioaddr.scr_addr;
void __iomem *addr;
u32 val;
@@ -210,7 +210,7 @@ static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg)
static void inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
{
- void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+ void __iomem *scr_addr = ap->ioaddr.scr_addr;
void __iomem *addr;
if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
@@ -594,7 +594,7 @@ static struct ata_port_info inic_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &inic_port_ops
};
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 590f2f92b4e..3873b29c80d 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -526,44 +526,44 @@ static const struct ata_port_info mv_port_info[] = {
{ /* chip_504x */
.flags = MV_COMMON_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv5_ops,
},
{ /* chip_508x */
.flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv5_ops,
},
{ /* chip_5080 */
.flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv5_ops,
},
{ /* chip_604x */
.flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv6_ops,
},
{ /* chip_608x */
.flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
MV_FLAG_DUAL_HC),
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv6_ops,
},
{ /* chip_6042 */
.flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv_iie_ops,
},
{ /* chip_7042 */
.flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv_iie_ops,
},
};
@@ -2338,7 +2338,7 @@ static void mv_print_info(struct ata_host *host)
struct pci_dev *pdev = to_pci_dev(host->dev);
struct mv_host_priv *hpriv = host->private_data;
u8 rev_id, scc;
- const char *scc_s;
+ const char *scc_s, *gen;
/* Use this to determine the HW stepping of the chip so we know
* what errata to workaround
@@ -2351,11 +2351,20 @@ static void mv_print_info(struct ata_host *host)
else if (scc == 0x01)
scc_s = "RAID";
else
- scc_s = "unknown";
+ scc_s = "?";
+
+ if (IS_GEN_I(hpriv))
+ gen = "I";
+ else if (IS_GEN_II(hpriv))
+ gen = "II";
+ else if (IS_GEN_IIE(hpriv))
+ gen = "IIE";
+ else
+ gen = "?";
dev_printk(KERN_INFO, &pdev->dev,
- "%u slots %u ports %s mode IRQ via %s\n",
- (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
+ "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
+ gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
}
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 6dc0b011a6b..2ad5872fe90 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -45,8 +45,7 @@
#include "sata_promise.h"
#define DRV_NAME "sata_promise"
-#define DRV_VERSION "2.07"
-
+#define DRV_VERSION "2.08"
enum {
PDC_MAX_PORTS = 4,
@@ -94,7 +93,7 @@ enum {
board_20319 = 2, /* FastTrak S150 TX4 */
board_20619 = 3, /* FastTrak TX4000 */
board_2057x = 4, /* SATAII150 Tx2plus */
- board_2057x_pata = 5, /* SATAII150 Tx2plus */
+ board_2057x_pata = 5, /* SATAII150 Tx2plus PATA port */
board_40518 = 6, /* SATAII150 Tx4 */
PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */
@@ -124,7 +123,6 @@ enum {
PDC_FLAG_4_PORTS = (1 << 26), /* 4 ports */
};
-
struct pdc_port_priv {
u8 *pkt;
dma_addr_t pkt_dma;
@@ -252,7 +250,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_SATA_PATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_old_sata_ops,
},
@@ -261,7 +259,7 @@ static const struct ata_port_info pdc_port_info[] = {
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_pata_ops,
},
@@ -271,7 +269,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_4_PORTS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_old_sata_ops,
},
@@ -281,7 +279,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_4_PORTS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_pata_ops,
},
@@ -291,7 +289,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_sata_ops,
},
@@ -301,7 +299,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_GEN_II,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_pata_ops,
},
@@ -311,7 +309,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_sata_ops,
},
};
@@ -340,7 +338,6 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
{ } /* terminate list */
};
-
static struct pci_driver pdc_ata_pci_driver = {
.name = DRV_NAME,
.id_table = pdc_ata_pci_tbl,
@@ -348,7 +345,6 @@ static struct pci_driver pdc_ata_pci_driver = {
.remove = ata_pci_remove_one,
};
-
static int pdc_common_port_start(struct ata_port *ap)
{
struct device *dev = ap->host->dev;
@@ -382,7 +378,7 @@ static int pdc_sata_port_start(struct ata_port *ap)
/* fix up PHYMODE4 align timing */
if (ap->flags & PDC_FLAG_GEN_II) {
- void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr;
+ void __iomem *mmio = ap->ioaddr.scr_addr;
unsigned int tmp;
tmp = readl(mmio + 0x014);
@@ -418,7 +414,7 @@ static void pdc_reset_port(struct ata_port *ap)
static int pdc_pata_cable_detect(struct ata_port *ap)
{
u8 tmp;
- void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
+ void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
tmp = readb(mmio);
if (tmp & 0x01)
@@ -438,7 +434,6 @@ static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
-
static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
u32 val)
{
@@ -573,7 +568,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
static void pdc_freeze(struct ata_port *ap)
{
- void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+ void __iomem *mmio = ap->ioaddr.cmd_addr;
u32 tmp;
tmp = readl(mmio + PDC_CTLSTAT);
@@ -585,7 +580,7 @@ static void pdc_freeze(struct ata_port *ap)
static void pdc_thaw(struct ata_port *ap)
{
- void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+ void __iomem *mmio = ap->ioaddr.cmd_addr;
u32 tmp;
/* clear IRQ */
@@ -657,8 +652,8 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc,
ata_port_abort(ap);
}
-static inline unsigned int pdc_host_intr( struct ata_port *ap,
- struct ata_queued_cmd *qc)
+static inline unsigned int pdc_host_intr(struct ata_port *ap,
+ struct ata_queued_cmd *qc)
{
unsigned int handled = 0;
void __iomem *port_mmio = ap->ioaddr.cmd_addr;
@@ -685,10 +680,10 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
handled = 1;
break;
- default:
+ default:
ap->stats.idle_irq++;
break;
- }
+ }
return handled;
}
@@ -701,6 +696,18 @@ static void pdc_irq_clear(struct ata_port *ap)
readl(mmio + PDC_INT_SEQMASK);
}
+static inline int pdc_is_sataii_tx4(unsigned long flags)
+{
+ const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
+ return (flags & mask) == mask;
+}
+
+static inline unsigned int pdc_port_no_to_ata_no(unsigned int port_no, int is_sataii_tx4)
+{
+ static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
+ return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
+}
+
static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
@@ -807,7 +814,6 @@ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
ata_tf_load(ap, tf);
}
-
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
@@ -867,7 +873,6 @@ static void pdc_ata_setup_port(struct ata_port *ap,
ap->ioaddr.scr_addr = scr_addr;
}
-
static void pdc_host_init(struct ata_host *host)
{
void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
@@ -955,10 +960,8 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
if (pi->flags & PDC_FLAG_SATA_PATA) {
u8 tmp = readb(base + PDC_FLASH_CTL+1);
- if (!(tmp & 0x80)) {
+ if (!(tmp & 0x80))
ppi[n_ports++] = pi + 1;
- dev_printk(KERN_INFO, &pdev->dev, "PATA port found\n");
- }
}
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
@@ -968,22 +971,12 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
}
host->iomap = pcim_iomap_table(pdev);
- is_sataii_tx4 = 0;
- if ((pi->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) == (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) {
- is_sataii_tx4 = 1;
- dev_printk(KERN_INFO, &pdev->dev, "applying SATAII TX4 port numbering workaround\n");
- }
+ is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags);
for (i = 0; i < host->n_ports; i++) {
- static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
- int ata_nr;
-
- ata_nr = i;
- if (is_sataii_tx4)
- ata_nr = sataii_tx4_port_remap[i];
-
+ unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
pdc_ata_setup_port(host->ports[i],
- base + 0x200 + ata_nr * 0x80,
- base + 0x400 + ata_nr * 0x100);
+ base + 0x200 + ata_no * 0x80,
+ base + 0x400 + ata_no * 0x100);
}
/* initialize adapter */
@@ -1002,19 +995,16 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
&pdc_ata_sht);
}
-
static int __init pdc_ata_init(void)
{
return pci_register_driver(&pdc_ata_pci_driver);
}
-
static void __exit pdc_ata_exit(void)
{
pci_unregister_driver(&pdc_ata_pci_driver);
}
-
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 6688ccb6632..9ab554da89b 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -176,7 +176,7 @@ static const struct ata_port_info qs_port_info[] = {
//FIXME ATA_FLAG_SRST |
ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
.pio_mask = 0x10, /* pio4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &qs_ata_ops,
},
};
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index a3b339bcf3c..2a86dc4598d 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -218,7 +218,7 @@ static const struct ata_port_info sil_port_info[] = {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
/* sil_3112_no_sata_irq */
@@ -227,7 +227,7 @@ static const struct ata_port_info sil_port_info[] = {
SIL_FLAG_NO_SATA_IRQ,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
/* sil_3512 */
@@ -235,7 +235,7 @@ static const struct ata_port_info sil_port_info[] = {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
/* sil_3114 */
@@ -243,7 +243,7 @@ static const struct ata_port_info sil_port_info[] = {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
};
@@ -262,8 +262,9 @@ static const struct {
unsigned long sfis_cfg; /* SATA FIS reception config register */
} sil_port[] = {
/* port 0 ... */
- { 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
- { 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
+ /* tf ctl bmdma bmdma2 fifo scr sien mode sfis */
+ { 0x80, 0x8A, 0x0, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
+ { 0xC0, 0xCA, 0x8, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
{ 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
{ 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
/* ... port 3 */
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 0ddfae9911c..ac43a30ebe2 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -426,7 +426,7 @@ static const struct ata_port_info sil24_port_info[] = {
SIL24_FLAG_PCIX_IRQ_WOC,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
.port_ops = &sil24_ops,
},
/* sil_3132 */
@@ -434,7 +434,7 @@ static const struct ata_port_info sil24_port_info[] = {
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
.port_ops = &sil24_ops,
},
/* sil_3131/sil_3531 */
@@ -442,7 +442,7 @@ static const struct ata_port_info sil24_port_info[] = {
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
.port_ops = &sil24_ops,
},
};
@@ -888,7 +888,7 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance)
if (status & (1 << i)) {
struct ata_port *ap = host->ports[i];
if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
- sil24_host_intr(host->ports[i]);
+ sil24_host_intr(ap);
handled++;
} else
printk(KERN_ERR DRV_NAME
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index f111c984a35..fd80bcf1b23 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -133,7 +133,7 @@ static const struct ata_port_info sis_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x7,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &sis_ops,
};
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index bcb2cd8b063..63fe99afd59 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -107,7 +107,7 @@ static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
- return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -116,7 +116,7 @@ static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
{
if (sc_reg > SCR_CONTROL)
return;
- writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -197,7 +197,8 @@ static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 dmactl;
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+ void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
/* load PRD table addr. */
mb(); /* make sure PRD table writes are visible to controller */
writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
@@ -225,7 +226,7 @@ static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+ void __iomem *mmio = ap->ioaddr.bmdma_addr;
u8 dmactl;
/* start host DMA transaction */
@@ -253,7 +254,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
static u8 k2_stat_check_status(struct ata_port *ap)
{
- return readl((void __iomem *) ap->ioaddr.status_addr);
+ return readl(ap->ioaddr.status_addr);
}
#ifdef CONFIG_PPC_OF
@@ -360,7 +361,7 @@ static const struct ata_port_info k2_port_info[] = {
ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
/* board_svw8 */
@@ -370,7 +371,7 @@ static const struct ata_port_info k2_port_info[] = {
K2_FLAG_SATA_8_PORTS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
};
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 2d14f3d56d9..5193bd8647b 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -30,6 +30,54 @@
*
*/
+/*
+ Theory of operation
+ -------------------
+
+ The SX4 (PDC20621) chip features a single Host DMA (HDMA) copy
+ engine, DIMM memory, and four ATA engines (one per SATA port).
+ Data is copied to/from DIMM memory by the HDMA engine, before
+ handing off to one (or more) of the ATA engines. The ATA
+ engines operate solely on DIMM memory.
+
+ The SX4 behaves like a PATA chip, with no SATA controls or
+ knowledge whatsoever, leading to the presumption that
+ PATA<->SATA bridges exist on SX4 boards, external to the
+ PDC20621 chip itself.
+
+ The chip is quite capable, supporting an XOR engine and linked
+ hardware commands (permits a string to transactions to be
+ submitted and waited-on as a single unit), and an optional
+ microprocessor.
+
+ The limiting factor is largely software. This Linux driver was
+ written to multiplex the single HDMA engine to copy disk
+ transactions into a fixed DIMM memory space, from where an ATA
+ engine takes over. As a result, each WRITE looks like this:
+
+ submit HDMA packet to hardware
+ hardware copies data from system memory to DIMM
+ hardware raises interrupt
+
+ submit ATA packet to hardware
+ hardware executes ATA WRITE command, w/ data in DIMM
+ hardware raises interrupt
+
+ and each READ looks like this:
+
+ submit ATA packet to hardware
+ hardware executes ATA READ command, w/ data in DIMM
+ hardware raises interrupt
+
+ submit HDMA packet to hardware
+ hardware copies data from DIMM to system memory
+ hardware raises interrupt
+
+ This is a very slow, lock-step way of doing things that can
+ certainly be improved by motivated kernel hackers.
+
+ */
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -58,6 +106,8 @@ enum {
PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */
PDC_HDMA_CTLSTAT = 0x12C, /* Host DMA control / status */
+ PDC_CTLSTAT = 0x60, /* IDEn control / status */
+
PDC_20621_SEQCTL = 0x400,
PDC_20621_SEQMASK = 0x480,
PDC_20621_GENERAL_CTL = 0x484,
@@ -87,48 +137,60 @@ enum {
board_20621 = 0, /* FastTrak S150 SX4 */
- PDC_RESET = (1 << 11), /* HDMA reset */
+ PDC_MASK_INT = (1 << 10), /* HDMA/ATA mask int */
+ PDC_RESET = (1 << 11), /* HDMA/ATA reset */
+ PDC_DMA_ENABLE = (1 << 7), /* DMA start/stop */
PDC_MAX_HDMA = 32,
PDC_HDMA_Q_MASK = (PDC_MAX_HDMA - 1),
- PDC_DIMM0_SPD_DEV_ADDRESS = 0x50,
- PDC_DIMM1_SPD_DEV_ADDRESS = 0x51,
- PDC_MAX_DIMM_MODULE = 0x02,
- PDC_I2C_CONTROL_OFFSET = 0x48,
- PDC_I2C_ADDR_DATA_OFFSET = 0x4C,
- PDC_DIMM0_CONTROL_OFFSET = 0x80,
- PDC_DIMM1_CONTROL_OFFSET = 0x84,
- PDC_SDRAM_CONTROL_OFFSET = 0x88,
- PDC_I2C_WRITE = 0x00000000,
- PDC_I2C_READ = 0x00000040,
- PDC_I2C_START = 0x00000080,
- PDC_I2C_MASK_INT = 0x00000020,
- PDC_I2C_COMPLETE = 0x00010000,
- PDC_I2C_NO_ACK = 0x00100000,
- PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
- PDC_DIMM_SPD_SUBADDRESS_END = 0x7F,
- PDC_DIMM_SPD_ROW_NUM = 3,
- PDC_DIMM_SPD_COLUMN_NUM = 4,
- PDC_DIMM_SPD_MODULE_ROW = 5,
- PDC_DIMM_SPD_TYPE = 11,
- PDC_DIMM_SPD_FRESH_RATE = 12,
- PDC_DIMM_SPD_BANK_NUM = 17,
- PDC_DIMM_SPD_CAS_LATENCY = 18,
- PDC_DIMM_SPD_ATTRIBUTE = 21,
- PDC_DIMM_SPD_ROW_PRE_CHARGE = 27,
- PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
- PDC_DIMM_SPD_RAS_CAS_DELAY = 29,
- PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
- PDC_DIMM_SPD_SYSTEM_FREQ = 126,
- PDC_CTL_STATUS = 0x08,
- PDC_DIMM_WINDOW_CTLR = 0x0C,
- PDC_TIME_CONTROL = 0x3C,
- PDC_TIME_PERIOD = 0x40,
- PDC_TIME_COUNTER = 0x44,
- PDC_GENERAL_CTLR = 0x484,
- PCI_PLL_INIT = 0x8A531824,
- PCI_X_TCOUNT = 0xEE1E5CFF
+ PDC_DIMM0_SPD_DEV_ADDRESS = 0x50,
+ PDC_DIMM1_SPD_DEV_ADDRESS = 0x51,
+ PDC_I2C_CONTROL = 0x48,
+ PDC_I2C_ADDR_DATA = 0x4C,
+ PDC_DIMM0_CONTROL = 0x80,
+ PDC_DIMM1_CONTROL = 0x84,
+ PDC_SDRAM_CONTROL = 0x88,
+ PDC_I2C_WRITE = 0, /* master -> slave */
+ PDC_I2C_READ = (1 << 6), /* master <- slave */
+ PDC_I2C_START = (1 << 7), /* start I2C proto */
+ PDC_I2C_MASK_INT = (1 << 5), /* mask I2C interrupt */
+ PDC_I2C_COMPLETE = (1 << 16), /* I2C normal compl. */
+ PDC_I2C_NO_ACK = (1 << 20), /* slave no-ack addr */
+ PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
+ PDC_DIMM_SPD_SUBADDRESS_END = 0x7F,
+ PDC_DIMM_SPD_ROW_NUM = 3,
+ PDC_DIMM_SPD_COLUMN_NUM = 4,
+ PDC_DIMM_SPD_MODULE_ROW = 5,
+ PDC_DIMM_SPD_TYPE = 11,
+ PDC_DIMM_SPD_FRESH_RATE = 12,
+ PDC_DIMM_SPD_BANK_NUM = 17,
+ PDC_DIMM_SPD_CAS_LATENCY = 18,
+ PDC_DIMM_SPD_ATTRIBUTE = 21,
+ PDC_DIMM_SPD_ROW_PRE_CHARGE = 27,
+ PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
+ PDC_DIMM_SPD_RAS_CAS_DELAY = 29,
+ PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
+ PDC_DIMM_SPD_SYSTEM_FREQ = 126,
+ PDC_CTL_STATUS = 0x08,
+ PDC_DIMM_WINDOW_CTLR = 0x0C,
+ PDC_TIME_CONTROL = 0x3C,
+ PDC_TIME_PERIOD = 0x40,
+ PDC_TIME_COUNTER = 0x44,
+ PDC_GENERAL_CTLR = 0x484,
+ PCI_PLL_INIT = 0x8A531824,
+ PCI_X_TCOUNT = 0xEE1E5CFF,
+
+ /* PDC_TIME_CONTROL bits */
+ PDC_TIMER_BUZZER = (1 << 10),
+ PDC_TIMER_MODE_PERIODIC = 0, /* bits 9:8 == 00 */
+ PDC_TIMER_MODE_ONCE = (1 << 8), /* bits 9:8 == 01 */
+ PDC_TIMER_ENABLE = (1 << 7),
+ PDC_TIMER_MASK_INT = (1 << 5),
+ PDC_TIMER_SEQ_MASK = 0x1f, /* SEQ ID for timer */
+ PDC_TIMER_DEFAULT = PDC_TIMER_MODE_ONCE |
+ PDC_TIMER_ENABLE |
+ PDC_TIMER_MASK_INT,
};
@@ -217,7 +279,7 @@ static const struct ata_port_info pdc_port_info[] = {
ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_20621_ops,
},
@@ -999,17 +1061,17 @@ static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device,
i2creg |= subaddr << 16;
/* Set the device and subaddress */
- writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET);
- readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+ writel(i2creg, mmio + PDC_I2C_ADDR_DATA);
+ readl(mmio + PDC_I2C_ADDR_DATA);
/* Write Control to perform read operation, mask int */
writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
- mmio + PDC_I2C_CONTROL_OFFSET);
+ mmio + PDC_I2C_CONTROL);
for (count = 0; count <= 1000; count ++) {
- status = readl(mmio + PDC_I2C_CONTROL_OFFSET);
+ status = readl(mmio + PDC_I2C_CONTROL);
if (status & PDC_I2C_COMPLETE) {
- status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+ status = readl(mmio + PDC_I2C_ADDR_DATA);
break;
} else if (count == 1000)
return 0;
@@ -1099,8 +1161,8 @@ static int pdc20621_prog_dimm0(struct ata_host *host)
data |= (((size / 16) - 1) << 16);
data |= (0 << 23);
data |= 8;
- writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
- readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
+ writel(data, mmio + PDC_DIMM0_CONTROL);
+ readl(mmio + PDC_DIMM0_CONTROL);
return size;
}
@@ -1122,27 +1184,27 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host)
*/
data = 0x022259F1;
- writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
- readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+ writel(data, mmio + PDC_SDRAM_CONTROL);
+ readl(mmio + PDC_SDRAM_CONTROL);
/* Turn on for ECC */
pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
data |= (0x01 << 16);
- writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
- readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+ writel(data, mmio + PDC_SDRAM_CONTROL);
+ readl(mmio + PDC_SDRAM_CONTROL);
printk(KERN_ERR "Local DIMM ECC Enabled\n");
}
/* DIMM Initialization Select/Enable (bit 18/19) */
data &= (~(1<<18));
data |= (1<<19);
- writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+ writel(data, mmio + PDC_SDRAM_CONTROL);
error = 1;
for (i = 1; i <= 10; i++) { /* polling ~5 secs */
- data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+ data = readl(mmio + PDC_SDRAM_CONTROL);
if (!(data & (1<<19))) {
error = 0;
break;
@@ -1176,7 +1238,7 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host)
VPRINTK("Time Period Register (0x40): 0x%x\n", time_period);
/* Enable timer */
- writel(0x00001a0, mmio + PDC_TIME_CONTROL);
+ writel(PDC_TIMER_DEFAULT, mmio + PDC_TIME_CONTROL);
readl(mmio + PDC_TIME_CONTROL);
/* Wait 3 seconds */
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 6815de7cca7..aca71819f6e 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -129,7 +129,7 @@ static const struct ata_port_info uli_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_IGN_SIMPLEX,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &uli_ops,
};
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index e8b90e7b42d..a4c0832033d 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -223,7 +223,7 @@ static const struct ata_port_info vt6420_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &vt6420_sata_ops,
};
@@ -231,7 +231,7 @@ static struct ata_port_info vt6421_sport_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &vt6421_sata_ops,
};
@@ -239,7 +239,7 @@ static struct ata_port_info vt6421_pport_info = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &vt6421_pata_ops,
};
@@ -303,9 +303,7 @@ static int vt6420_prereset(struct ata_port *ap, unsigned long deadline)
if (!(ap->pflags & ATA_PFLAG_LOADING))
goto skip_scr;
- /* Resume phy. This is the old resume sequence from
- * __sata_phy_reset().
- */
+ /* Resume phy. This is the old SATA resume sequence */
svia_scr_write(ap, SCR_CONTROL, 0x300);
svia_scr_read(ap, SCR_CONTROL); /* flush */
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 81330175fc8..1b5d81faa10 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -371,7 +371,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
ATA_FLAG_MMIO,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &vsc_sata_ops,
};
const struct ata_port_info *ppi[] = { &pi, NULL };
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 7f6d02ce1b5..38b688f9f6a 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -1654,7 +1654,7 @@ static void fs_poll (unsigned long data)
{
struct fs_dev *dev = (struct fs_dev *) data;
- fs_irq (0, dev, NULL);
+ fs_irq (0, dev);
dev->timer.expires = jiffies + FS_POLL_FREQ;
add_timer (&dev->timer);
}
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b4c8319138b..6e23af1ecbd 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -2,9 +2,12 @@
# Block device driver configuration
#
-if BLOCK
+menuconfig BLK_DEV
+ bool "Block devices"
+ depends on BLOCK
+ default y
-menu "Block devices"
+if BLK_DEV
config BLK_DEV_FD
tristate "Normal floppy disk support"
@@ -56,40 +59,9 @@ config AMIGA_Z2RAM
To compile this driver as a module, choose M here: the
module will be called z2ram.
-config ATARI_ACSI
- tristate "Atari ACSI support"
- depends on ATARI && BROKEN
- ---help---
- This enables support for the Atari ACSI interface. The driver
- supports hard disks and CD-ROMs, which have 512-byte sectors, or can
- be switched to that mode. Due to the ACSI command format, only disks
- up to 1 GB are supported. Special support for certain ACSI to SCSI
- adapters, which could relax that, isn't included yet. The ACSI
- driver is also the basis for certain other drivers for devices
- attached to the ACSI bus: Atari SLM laser printer, BioNet-100
- Ethernet, and PAMsNet Ethernet. If you want to use one of these
- devices, you need ACSI support, too.
-
- To compile this driver as a module, choose M here: the
- module will be called acsi.
-
-comment "Some devices (e.g. CD jukebox) support multiple LUNs"
- depends on ATARI && ATARI_ACSI
-
-config ACSI_MULTI_LUN
- bool "Probe all LUNs on each ACSI device"
- depends on ATARI_ACSI
- help
- If you have a ACSI device that supports more than one LUN (Logical
- Unit Number), e.g. a CD jukebox, you should say Y here so that all
- will be found by the ACSI driver. An ACSI device with multiple LUNs
- acts logically like multiple ACSI devices. The vast majority of ACSI
- devices have only one LUN, and so most people can say N here and
- should in fact do so, because it is safer.
-
config ATARI_SLM
tristate "Atari SLM laser printer support"
- depends on ATARI && ATARI_ACSI!=n
+ depends on ATARI
help
If you have an Atari SLM laser printer, say Y to include support for
it in the kernel. Otherwise, say N. This driver is also available as
@@ -453,6 +425,4 @@ config ATA_OVER_ETH
source "drivers/s390/block/Kconfig"
-endmenu
-
-endif
+endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index dd88e33c1eb..e5f98acc5d5 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
-obj-$(CONFIG_ATARI_ACSI) += acsi.o
obj-$(CONFIG_ATARI_SLM) += acsi_slm.o
obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
obj-$(CONFIG_BLK_DEV_RAM) += rd.o
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
deleted file mode 100644
index e3d9152e231..00000000000
--- a/drivers/block/acsi.c
+++ /dev/null
@@ -1,1825 +0,0 @@
-/*
- * acsi.c -- Device driver for Atari ACSI hard disks
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * Some parts are based on hd.c by Linus Torvalds
- *
- * 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.
- *
- */
-
-/*
- * Still to in this file:
- * - If a command ends with an error status (!= 0), the following
- * REQUEST SENSE commands (4 to fill the ST-DMA FIFO) are done by
- * polling the _IRQ signal (not interrupt-driven). This should be
- * avoided in future because it takes up a non-neglectible time in
- * the interrupt service routine while interrupts are disabled.
- * Maybe a timer interrupt will get lost :-(
- */
-
-/*
- * General notes:
- *
- * - All ACSI devices (disks, CD-ROMs, ...) use major number 28.
- * Minors are organized like it is with SCSI: The upper 4 bits
- * identify the device, the lower 4 bits the partition.
- * The device numbers (the upper 4 bits) are given in the same
- * order as the devices are found on the bus.
- * - Up to 8 LUNs are supported for each target (if CONFIG_ACSI_MULTI_LUN
- * is defined), but only a total of 16 devices (due to minor
- * numbers...). Note that Atari allows only a maximum of 4 targets
- * (i.e. controllers, not devices) on the ACSI bus!
- * - A optimizing scheme similar to SCSI scatter-gather is implemented.
- * - Removable media are supported. After a medium change to device
- * is reinitialized (partition check etc.). Also, if the device
- * knows the PREVENT/ALLOW MEDIUM REMOVAL command, the door should
- * be locked and unlocked when mounting the first or unmounting the
- * last filesystem on the device. The code is untested, because I
- * don't have a removable hard disk.
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/genhd.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <scsi/scsi.h> /* for SCSI_IOCTL_GET_IDLUN */
-#include <scsi/scsi_ioctl.h>
-#include <linux/hdreg.h> /* for HDIO_GETGEO */
-#include <linux/blkpg.h>
-#include <linux/buffer_head.h>
-#include <linux/blkdev.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-
-static void (*do_acsi)(void) = NULL;
-static struct request_queue *acsi_queue;
-#define QUEUE (acsi_queue)
-#define CURRENT elv_next_request(acsi_queue)
-
-#define DEBUG
-#undef DEBUG_DETECT
-#undef NO_WRITE
-
-#define MAX_ERRORS 8 /* Max read/write errors/sector */
-#define MAX_LUN 8 /* Max LUNs per target */
-#define MAX_DEV 16
-
-#define ACSI_BUFFER_SIZE (16*1024) /* "normal" ACSI buffer size */
-#define ACSI_BUFFER_MINSIZE (2048) /* min. buf size if ext. DMA */
-#define ACSI_BUFFER_SIZE_ORDER 2 /* order size for above */
-#define ACSI_BUFFER_MINSIZE_ORDER 0 /* order size for above */
-#define ACSI_BUFFER_SECTORS (ACSI_BUFFER_SIZE/512)
-
-#define ACSI_BUFFER_ORDER \
- (ATARIHW_PRESENT(EXTD_DMA) ? \
- ACSI_BUFFER_MINSIZE_ORDER : \
- ACSI_BUFFER_SIZE_ORDER)
-
-#define ACSI_TIMEOUT (4*HZ)
-
-/* minimum delay between two commands */
-
-#define COMMAND_DELAY 500
-
-typedef enum {
- NONE, HARDDISK, CDROM
-} ACSI_TYPE;
-
-struct acsi_info_struct {
- ACSI_TYPE type; /* type of device */
- unsigned target; /* target number */
- unsigned lun; /* LUN in target controller */
- unsigned removable : 1; /* Flag for removable media */
- unsigned read_only : 1; /* Flag for read only devices */
- unsigned old_atari_disk : 1; /* Is an old Atari disk */
- unsigned changed : 1; /* Medium has been changed */
- unsigned long size; /* #blocks */
- int access_count;
-} acsi_info[MAX_DEV];
-
-/*
- * SENSE KEYS
- */
-
-#define NO_SENSE 0x00
-#define RECOVERED_ERROR 0x01
-#define NOT_READY 0x02
-#define MEDIUM_ERROR 0x03
-#define HARDWARE_ERROR 0x04
-#define ILLEGAL_REQUEST 0x05
-#define UNIT_ATTENTION 0x06
-#define DATA_PROTECT 0x07
-#define BLANK_CHECK 0x08
-#define COPY_ABORTED 0x0a
-#define ABORTED_COMMAND 0x0b
-#define VOLUME_OVERFLOW 0x0d
-#define MISCOMPARE 0x0e
-
-
-/*
- * DEVICE TYPES
- */
-
-#define TYPE_DISK 0x00
-#define TYPE_TAPE 0x01
-#define TYPE_WORM 0x04
-#define TYPE_ROM 0x05
-#define TYPE_MOD 0x07
-#define TYPE_NO_LUN 0x7f
-
-/* The data returned by MODE SENSE differ between the old Atari
- * hard disks and SCSI disks connected to ACSI. In the following, both
- * formats are defined and some macros to operate on them potably.
- */
-
-typedef struct {
- unsigned long dummy[2];
- unsigned long sector_size;
- unsigned char format_code;
-#define ATARI_SENSE_FORMAT_FIX 1
-#define ATARI_SENSE_FORMAT_CHNG 2
- unsigned char cylinders_h;
- unsigned char cylinders_l;
- unsigned char heads;
- unsigned char reduced_h;
- unsigned char reduced_l;
- unsigned char precomp_h;
- unsigned char precomp_l;
- unsigned char landing_zone;
- unsigned char steprate;
- unsigned char type;
-#define ATARI_SENSE_TYPE_FIXCHNG_MASK 4
-#define ATARI_SENSE_TYPE_SOFTHARD_MASK 8
-#define ATARI_SENSE_TYPE_FIX 4
-#define ATARI_SENSE_TYPE_CHNG 0
-#define ATARI_SENSE_TYPE_SOFT 0
-#define ATARI_SENSE_TYPE_HARD 8
- unsigned char sectors;
-} ATARI_SENSE_DATA;
-
-#define ATARI_CAPACITY(sd) \
- (((int)((sd).cylinders_h<<8)|(sd).cylinders_l) * \
- (sd).heads * (sd).sectors)
-
-
-typedef struct {
- unsigned char dummy1;
- unsigned char medium_type;
- unsigned char dummy2;
- unsigned char descriptor_size;
- unsigned long block_count;
- unsigned long sector_size;
- /* Page 0 data */
- unsigned char page_code;
- unsigned char page_size;
- unsigned char page_flags;
- unsigned char qualifier;
-} SCSI_SENSE_DATA;
-
-#define SCSI_CAPACITY(sd) ((sd).block_count & 0xffffff)
-
-
-typedef union {
- ATARI_SENSE_DATA atari;
- SCSI_SENSE_DATA scsi;
-} SENSE_DATA;
-
-#define SENSE_TYPE_UNKNOWN 0
-#define SENSE_TYPE_ATARI 1
-#define SENSE_TYPE_SCSI 2
-
-#define SENSE_TYPE(sd) \
- (((sd).atari.dummy[0] == 8 && \
- ((sd).atari.format_code == 1 || \
- (sd).atari.format_code == 2)) ? SENSE_TYPE_ATARI : \
- ((sd).scsi.dummy1 >= 11) ? SENSE_TYPE_SCSI : \
- SENSE_TYPE_UNKNOWN)
-
-#define CAPACITY(sd) \
- (SENSE_TYPE(sd) == SENSE_TYPE_ATARI ? \
- ATARI_CAPACITY((sd).atari) : \
- SCSI_CAPACITY((sd).scsi))
-
-#define SECTOR_SIZE(sd) \
- (SENSE_TYPE(sd) == SENSE_TYPE_ATARI ? \
- (sd).atari.sector_size : \
- (sd).scsi.sector_size & 0xffffff)
-
-/* Default size if capacity cannot be determined (1 GByte) */
-#define DEFAULT_SIZE 0x1fffff
-
-#define CARTRCH_STAT(aip,buf) \
- (aip->old_atari_disk ? \
- (((buf)[0] & 0x7f) == 0x28) : \
- ((((buf)[0] & 0x70) == 0x70) ? \
- (((buf)[2] & 0x0f) == 0x06) : \
- (((buf)[0] & 0x0f) == 0x06))) \
-
-/* These two are also exported to other drivers that work on the ACSI bus and
- * need an ST-RAM buffer. */
-char *acsi_buffer;
-unsigned long phys_acsi_buffer;
-
-static int NDevices;
-
-static int CurrentNReq;
-static int CurrentNSect;
-static char *CurrentBuffer;
-
-static DEFINE_SPINLOCK(acsi_lock);
-
-
-#define SET_TIMER() mod_timer(&acsi_timer, jiffies + ACSI_TIMEOUT)
-#define CLEAR_TIMER() del_timer(&acsi_timer)
-
-static unsigned long STramMask;
-#define STRAM_ADDR(a) (((a) & STramMask) == 0)
-
-
-
-/* ACSI commands */
-
-static char tur_cmd[6] = { 0x00, 0, 0, 0, 0, 0 };
-static char modesense_cmd[6] = { 0x1a, 0, 0, 0, 24, 0 };
-static char modeselect_cmd[6] = { 0x15, 0, 0, 0, 12, 0 };
-static char inquiry_cmd[6] = { 0x12, 0, 0, 0,255, 0 };
-static char reqsense_cmd[6] = { 0x03, 0, 0, 0, 4, 0 };
-static char read_cmd[6] = { 0x08, 0, 0, 0, 0, 0 };
-static char write_cmd[6] = { 0x0a, 0, 0, 0, 0, 0 };
-static char pa_med_rem_cmd[6] = { 0x1e, 0, 0, 0, 0, 0 };
-
-#define CMDSET_TARG_LUN(cmd,targ,lun) \
- do { \
- cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5; \
- cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \
- } while(0)
-
-#define CMDSET_BLOCK(cmd,blk) \
- do { \
- unsigned long __blk = (blk); \
- cmd[3] = __blk; __blk >>= 8; \
- cmd[2] = __blk; __blk >>= 8; \
- cmd[1] = (cmd[1] & 0xe0) | (__blk & 0x1f); \
- } while(0)
-
-#define CMDSET_LEN(cmd,len) \
- do { \
- cmd[4] = (len); \
- } while(0)
-
-/* ACSI errors (from REQUEST SENSE); There are two tables, one for the
- * old Atari disks and one for SCSI on ACSI disks.
- */
-
-struct acsi_error {
- unsigned char code;
- const char *text;
-} atari_acsi_errors[] = {
- { 0x00, "No error (??)" },
- { 0x01, "No index pulses" },
- { 0x02, "Seek not complete" },
- { 0x03, "Write fault" },
- { 0x04, "Drive not ready" },
- { 0x06, "No Track 00 signal" },
- { 0x10, "ECC error in ID field" },
- { 0x11, "Uncorrectable data error" },
- { 0x12, "ID field address mark not found" },
- { 0x13, "Data field address mark not found" },
- { 0x14, "Record not found" },
- { 0x15, "Seek error" },
- { 0x18, "Data check in no retry mode" },
- { 0x19, "ECC error during verify" },
- { 0x1a, "Access to bad block" },
- { 0x1c, "Unformatted or bad format" },
- { 0x20, "Invalid command" },
- { 0x21, "Invalid block address" },
- { 0x23, "Volume overflow" },
- { 0x24, "Invalid argument" },
- { 0x25, "Invalid drive number" },
- { 0x26, "Byte zero parity check" },
- { 0x28, "Cartride changed" },
- { 0x2c, "Error count overflow" },
- { 0x30, "Controller selftest failed" }
-},
-
- scsi_acsi_errors[] = {
- { 0x00, "No error (??)" },
- { 0x01, "Recovered error" },
- { 0x02, "Drive not ready" },
- { 0x03, "Uncorrectable medium error" },
- { 0x04, "Hardware error" },
- { 0x05, "Illegal request" },
- { 0x06, "Unit attention (Reset or cartridge changed)" },
- { 0x07, "Data protection" },
- { 0x08, "Blank check" },
- { 0x0b, "Aborted Command" },
- { 0x0d, "Volume overflow" }
-};
-
-
-
-/***************************** Prototypes *****************************/
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int
- rwflag, int enable);
-static int acsi_reqsense( char *buffer, int targ, int lun);
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip);
-static irqreturn_t acsi_interrupt (int irq, void *data);
-static void unexpected_acsi_interrupt( void );
-static void bad_rw_intr( void );
-static void read_intr( void );
-static void write_intr( void);
-static void acsi_times_out( unsigned long dummy );
-static void copy_to_acsibuffer( void );
-static void copy_from_acsibuffer( void );
-static void do_end_requests( void );
-static void do_acsi_request( request_queue_t * );
-static void redo_acsi_request( void );
-static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int
- cmd, unsigned long arg );
-static int acsi_open( struct inode * inode, struct file * filp );
-static int acsi_release( struct inode * inode, struct file * file );
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag );
-static int acsi_change_blk_size( int target, int lun);
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
-static int acsi_revalidate (struct gendisk *disk);
-
-/************************* End of Prototypes **************************/
-
-
-DEFINE_TIMER(acsi_timer, acsi_times_out, 0, 0);
-
-
-#ifdef CONFIG_ATARI_SLM
-
-extern int attach_slm( int target, int lun );
-extern int slm_init( void );
-
-#endif
-
-
-
-/***********************************************************************
- *
- * ACSI primitives
- *
- **********************************************************************/
-
-
-/*
- * The following two functions wait for _IRQ to become Low or High,
- * resp., with a timeout. The 'timeout' parameter is in jiffies
- * (10ms).
- * If the functions are called with timer interrupts on (int level <
- * 6), the timeout is based on the 'jiffies' variable to provide exact
- * timeouts for device probing etc.
- * If interrupts are disabled, the number of tries is based on the
- * 'loops_per_jiffy' variable. A rough estimation is sufficient here...
- */
-
-#define INT_LEVEL \
- ({ unsigned __sr; \
- __asm__ __volatile__ ( "movew %/sr,%0" : "=dm" (__sr) ); \
- (__sr >> 8) & 7; \
- })
-
-int acsi_wait_for_IRQ( unsigned timeout )
-
-{
- if (INT_LEVEL < 6) {
- unsigned long maxjif = jiffies + timeout;
- while (time_before(jiffies, maxjif))
- if (!(mfp.par_dt_reg & 0x20)) return( 1 );
- }
- else {
- long tries = loops_per_jiffy / 8 * timeout;
- while( --tries >= 0 )
- if (!(mfp.par_dt_reg & 0x20)) return( 1 );
- }
- return( 0 ); /* timeout! */
-}
-
-
-int acsi_wait_for_noIRQ( unsigned timeout )
-
-{
- if (INT_LEVEL < 6) {
- unsigned long maxjif = jiffies + timeout;
- while (time_before(jiffies, maxjif))
- if (mfp.par_dt_reg & 0x20) return( 1 );
- }
- else {
- long tries = loops_per_jiffy * timeout / 8;
- while( tries-- >= 0 )
- if (mfp.par_dt_reg & 0x20) return( 1 );
- }
- return( 0 ); /* timeout! */
-}
-
-static struct timeval start_time;
-
-void
-acsi_delay_start(void)
-{
- do_gettimeofday(&start_time);
-}
-
-/* wait from acsi_delay_start to now usec (<1E6) usec */
-
-void
-acsi_delay_end(long usec)
-{
- struct timeval end_time;
- long deltau,deltas;
- do_gettimeofday(&end_time);
- deltau=end_time.tv_usec - start_time.tv_usec;
- deltas=end_time.tv_sec - start_time.tv_sec;
- if (deltas > 1 || deltas < 0)
- return;
- if (deltas > 0)
- deltau += 1000*1000;
- if (deltau >= usec)
- return;
- udelay(usec-deltau);
-}
-
-/* acsicmd_dma() sends an ACSI command and sets up the DMA to transfer
- * 'blocks' blocks of 512 bytes from/to 'buffer'.
- * Because the _IRQ signal is used for handshaking the command bytes,
- * the ACSI interrupt has to be disabled in this function. If the end
- * of the operation should be signalled by a real interrupt, it has to be
- * reenabled afterwards.
- */
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int rwflag, int enable)
-
-{ unsigned long flags, paddr;
- int i;
-
-#ifdef NO_WRITE
- if (rwflag || *cmd == 0x0a) {
- printk( "ACSI: Write commands disabled!\n" );
- return( 0 );
- }
-#endif
-
- rwflag = rwflag ? 0x100 : 0;
- paddr = virt_to_phys( buffer );
-
- acsi_delay_end(COMMAND_DELAY);
- DISABLE_IRQ();
-
- local_irq_save(flags);
- /* Low on A1 */
- dma_wd.dma_mode_status = 0x88 | rwflag;
- MFPDELAY();
-
- /* set DMA address */
- dma_wd.dma_lo = (unsigned char)paddr;
- paddr >>= 8;
- MFPDELAY();
- dma_wd.dma_md = (unsigned char)paddr;
- paddr >>= 8;
- MFPDELAY();
- if (ATARIHW_PRESENT(EXTD_DMA))
- st_dma_ext_dmahi = (unsigned short)paddr;
- else
- dma_wd.dma_hi = (unsigned char)paddr;
- MFPDELAY();
- local_irq_restore(flags);
-
- /* send the command bytes except the last */
- for( i = 0; i < 5; ++i ) {
- DMA_LONG_WRITE( *cmd++, 0x8a | rwflag );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
- }
-
- /* Clear FIFO and switch DMA to correct direction */
- dma_wd.dma_mode_status = 0x92 | (rwflag ^ 0x100);
- MFPDELAY();
- dma_wd.dma_mode_status = 0x92 | rwflag;
- MFPDELAY();
-
- /* How many sectors for DMA */
- dma_wd.fdc_acces_seccount = blocks;
- MFPDELAY();
-
- /* send last command byte */
- dma_wd.dma_mode_status = 0x8a | rwflag;
- MFPDELAY();
- DMA_LONG_WRITE( *cmd++, 0x0a | rwflag );
- if (enable)
- ENABLE_IRQ();
- udelay(80);
-
- return( 1 );
-}
-
-
-/*
- * acsicmd_nodma() sends an ACSI command that requires no DMA.
- */
-
-int acsicmd_nodma( const char *cmd, int enable)
-
-{ int i;
-
- acsi_delay_end(COMMAND_DELAY);
- DISABLE_IRQ();
-
- /* send first command byte */
- dma_wd.dma_mode_status = 0x88;
- MFPDELAY();
- DMA_LONG_WRITE( *cmd++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-
- /* send the intermediate command bytes */
- for( i = 0; i < 4; ++i ) {
- DMA_LONG_WRITE( *cmd++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
- }
-
- /* send last command byte */
- DMA_LONG_WRITE( *cmd++, 0x0a );
- if (enable)
- ENABLE_IRQ();
- udelay(80);
-
- return( 1 );
- /* Note that the ACSI interrupt is still disabled after this
- * function. If you want to get the IRQ delivered, enable it manually!
- */
-}
-
-
-static int acsi_reqsense( char *buffer, int targ, int lun)
-
-{
- CMDSET_TARG_LUN( reqsense_cmd, targ, lun);
- if (!acsicmd_dma( reqsense_cmd, buffer, 1, 0, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- dma_cache_maintenance( virt_to_phys(buffer), 16, 0 );
-
- return( 1 );
-}
-
-
-/*
- * ACSI status phase: get the status byte from the bus
- *
- * I've seen several times that a 0xff status is read, propably due to
- * a timing error. In this case, the procedure is repeated after the
- * next _IRQ edge.
- */
-
-int acsi_getstatus( void )
-
-{ int status;
-
- DISABLE_IRQ();
- for(;;) {
- if (!acsi_wait_for_IRQ( 100 )) {
- acsi_delay_start();
- return( -1 );
- }
- dma_wd.dma_mode_status = 0x8a;
- MFPDELAY();
- status = dma_wd.fdc_acces_seccount;
- if (status != 0xff) break;
-#ifdef DEBUG
- printk("ACSI: skipping 0xff status byte\n" );
-#endif
- udelay(40);
- acsi_wait_for_noIRQ( 20 );
- }
- dma_wd.dma_mode_status = 0x80;
- udelay(40);
- acsi_wait_for_noIRQ( 20 );
-
- acsi_delay_start();
- return( status & 0x1f ); /* mask of the device# */
-}
-
-
-#if (defined(CONFIG_ATARI_SLM) || defined(CONFIG_ATARI_SLM_MODULE))
-
-/* Receive data in an extended status phase. Needed by SLM printer. */
-
-int acsi_extstatus( char *buffer, int cnt )
-
-{ int status;
-
- DISABLE_IRQ();
- udelay(80);
- while( cnt-- > 0 ) {
- if (!acsi_wait_for_IRQ( 40 )) return( 0 );
- dma_wd.dma_mode_status = 0x8a;
- MFPDELAY();
- status = dma_wd.fdc_acces_seccount;
- MFPDELAY();
- *buffer++ = status & 0xff;
- udelay(40);
- }
- return( 1 );
-}
-
-
-/* Finish an extended status phase */
-
-void acsi_end_extstatus( void )
-
-{
- dma_wd.dma_mode_status = 0x80;
- udelay(40);
- acsi_wait_for_noIRQ( 20 );
- acsi_delay_start();
-}
-
-
-/* Send data in an extended command phase */
-
-int acsi_extcmd( unsigned char *buffer, int cnt )
-
-{
- while( cnt-- > 0 ) {
- DMA_LONG_WRITE( *buffer++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
- }
- return( 1 );
-}
-
-#endif
-
-
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip)
-
-{ int atari_err, i, errcode;
- struct acsi_error *arr;
-
- atari_err = aip->old_atari_disk;
- if (atari_err)
- errcode = errblk[0] & 0x7f;
- else
- if ((errblk[0] & 0x70) == 0x70)
- errcode = errblk[2] & 0x0f;
- else
- errcode = errblk[0] & 0x0f;
-
- printk( KERN_ERR "ACSI error 0x%02x", errcode );
-
- if (errblk[0] & 0x80)
- printk( " for sector %d",
- ((errblk[1] & 0x1f) << 16) |
- (errblk[2] << 8) | errblk[0] );
-
- arr = atari_err ? atari_acsi_errors : scsi_acsi_errors;
- i = atari_err ? sizeof(atari_acsi_errors)/sizeof(*atari_acsi_errors) :
- sizeof(scsi_acsi_errors)/sizeof(*scsi_acsi_errors);
-
- for( --i; i >= 0; --i )
- if (arr[i].code == errcode) break;
- if (i >= 0)
- printk( ": %s\n", arr[i].text );
-}
-
-/*******************************************************************
- *
- * ACSI interrupt routine
- * Test, if this is a ACSI interrupt and call the irq handler
- * Otherwise ignore this interrupt.
- *
- *******************************************************************/
-
-static irqreturn_t acsi_interrupt(int irq, void *data )
-
-{ void (*acsi_irq_handler)(void) = do_acsi;
-
- do_acsi = NULL;
- CLEAR_TIMER();
-
- if (!acsi_irq_handler)
- acsi_irq_handler = unexpected_acsi_interrupt;
- acsi_irq_handler();
- return IRQ_HANDLED;
-}
-
-
-/******************************************************************
- *
- * The Interrupt handlers
- *
- *******************************************************************/
-
-
-static void unexpected_acsi_interrupt( void )
-
-{
- printk( KERN_WARNING "Unexpected ACSI interrupt\n" );
-}
-
-
-/* This function is called in case of errors. Because we cannot reset
- * the ACSI bus or a single device, there is no other choice than
- * retrying several times :-(
- */
-
-static void bad_rw_intr( void )
-
-{
- if (!CURRENT)
- return;
-
- if (++CURRENT->errors >= MAX_ERRORS)
- end_request(CURRENT, 0);
- /* Otherwise just retry */
-}
-
-
-static void read_intr( void )
-
-{ int status;
-
- status = acsi_getstatus();
- if (status != 0) {
- struct gendisk *disk = CURRENT->rq_disk;
- struct acsi_info_struct *aip = disk->private_data;
- printk(KERN_ERR "%s: ", disk->disk_name);
- if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun))
- printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
- else {
- acsi_print_error(acsi_buffer, aip);
- if (CARTRCH_STAT(aip, acsi_buffer))
- aip->changed = 1;
- }
- ENABLE_IRQ();
- bad_rw_intr();
- redo_acsi_request();
- return;
- }
-
- dma_cache_maintenance( virt_to_phys(CurrentBuffer), CurrentNSect*512, 0 );
- if (CurrentBuffer == acsi_buffer)
- copy_from_acsibuffer();
-
- do_end_requests();
- redo_acsi_request();
-}
-
-
-static void write_intr(void)
-
-{ int status;
-
- status = acsi_getstatus();
- if (status != 0) {
- struct gendisk *disk = CURRENT->rq_disk;
- struct acsi_info_struct *aip = disk->private_data;
- printk( KERN_ERR "%s: ", disk->disk_name);
- if (!acsi_reqsense( acsi_buffer, aip->target, aip->lun))
- printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
- else {
- acsi_print_error(acsi_buffer, aip);
- if (CARTRCH_STAT(aip, acsi_buffer))
- aip->changed = 1;
- }
- bad_rw_intr();
- redo_acsi_request();
- return;
- }
-
- do_end_requests();
- redo_acsi_request();
-}
-
-
-static void acsi_times_out( unsigned long dummy )
-
-{
- DISABLE_IRQ();
- if (!do_acsi) return;
-
- do_acsi = NULL;
- printk( KERN_ERR "ACSI timeout\n" );
- if (!CURRENT)
- return;
- if (++CURRENT->errors >= MAX_ERRORS) {
-#ifdef DEBUG
- printk( KERN_ERR "ACSI: too many errors.\n" );
-#endif
- end_request(CURRENT, 0);
- }
-
- redo_acsi_request();
-}
-
-
-
-/***********************************************************************
- *
- * Scatter-gather utility functions
- *
- ***********************************************************************/
-
-
-static void copy_to_acsibuffer( void )
-
-{ int i;
- char *src, *dst;
- struct buffer_head *bh;
-
- src = CURRENT->buffer;
- dst = acsi_buffer;
- bh = CURRENT->bh;
-
- if (!bh)
- memcpy( dst, src, CurrentNSect*512 );
- else
- for( i = 0; i < CurrentNReq; ++i ) {
- memcpy( dst, src, bh->b_size );
- dst += bh->b_size;
- if ((bh = bh->b_reqnext))
- src = bh->b_data;
- }
-}
-
-
-static void copy_from_acsibuffer( void )
-
-{ int i;
- char *src, *dst;
- struct buffer_head *bh;
-
- dst = CURRENT->buffer;
- src = acsi_buffer;
- bh = CURRENT->bh;
-
- if (!bh)
- memcpy( dst, src, CurrentNSect*512 );
- else
- for( i = 0; i < CurrentNReq; ++i ) {
- memcpy( dst, src, bh->b_size );
- src += bh->b_size;
- if ((bh = bh->b_reqnext))
- dst = bh->b_data;
- }
-}
-
-
-static void do_end_requests( void )
-
-{ int i, n;
-
- if (!CURRENT->bh) {
- CURRENT->nr_sectors -= CurrentNSect;
- CURRENT->current_nr_sectors -= CurrentNSect;
- CURRENT->sector += CurrentNSect;
- if (CURRENT->nr_sectors == 0)
- end_request(CURRENT, 1);
- }
- else {
- for( i = 0; i < CurrentNReq; ++i ) {
- n = CURRENT->bh->b_size >> 9;
- CURRENT->nr_sectors -= n;
- CURRENT->current_nr_sectors -= n;
- CURRENT->sector += n;
- end_request(CURRENT, 1);
- }
- }
-}
-
-
-
-
-/***********************************************************************
- *
- * do_acsi_request and friends
- *
- ***********************************************************************/
-
-static void do_acsi_request( request_queue_t * q )
-
-{
- stdma_lock( acsi_interrupt, NULL );
- redo_acsi_request();
-}
-
-
-static void redo_acsi_request( void )
-{
- unsigned block, target, lun, nsect;
- char *buffer;
- unsigned long pbuffer;
- struct buffer_head *bh;
- struct gendisk *disk;
- struct acsi_info_struct *aip;
-
- repeat:
- CLEAR_TIMER();
-
- if (do_acsi)
- return;
-
- if (!CURRENT) {
- do_acsi = NULL;
- ENABLE_IRQ();
- stdma_release();
- return;
- }
-
- disk = CURRENT->rq_disk;
- aip = disk->private_data;
- if (CURRENT->bh) {
- if (!CURRENT->bh && !buffer_locked(CURRENT->bh))
- panic("ACSI: block not locked");
- }
-
- block = CURRENT->sector;
- if (block+CURRENT->nr_sectors >= get_capacity(disk)) {
-#ifdef DEBUG
- printk( "%s: attempted access for blocks %d...%ld past end of device at block %ld.\n",
- disk->disk_name,
- block, block + CURRENT->nr_sectors - 1,
- get_capacity(disk));
-#endif
- end_request(CURRENT, 0);
- goto repeat;
- }
- if (aip->changed) {
- printk( KERN_NOTICE "%s: request denied because cartridge has "
- "been changed.\n", disk->disk_name);
- end_request(CURRENT, 0);
- goto repeat;
- }
-
- target = aip->target;
- lun = aip->lun;
-
- /* Find out how many sectors should be transferred from/to
- * consecutive buffers and thus can be done with a single command.
- */
- buffer = CURRENT->buffer;
- pbuffer = virt_to_phys(buffer);
- nsect = CURRENT->current_nr_sectors;
- CurrentNReq = 1;
-
- if ((bh = CURRENT->bh) && bh != CURRENT->bhtail) {
- if (!STRAM_ADDR(pbuffer)) {
- /* If transfer is done via the ACSI buffer anyway, we can
- * assemble as much bh's as fit in the buffer.
- */
- while( (bh = bh->b_reqnext) ) {
- if (nsect + (bh->b_size>>9) > ACSI_BUFFER_SECTORS) break;
- nsect += bh->b_size >> 9;
- ++CurrentNReq;
- if (bh == CURRENT->bhtail) break;
- }
- buffer = acsi_buffer;
- pbuffer = phys_acsi_buffer;
- }
- else {
- unsigned long pendadr, pnewadr;
- pendadr = pbuffer + nsect*512;
- while( (bh = bh->b_reqnext) ) {
- pnewadr = virt_to_phys(bh->b_data);
- if (!STRAM_ADDR(pnewadr) || pendadr != pnewadr) break;
- nsect += bh->b_size >> 9;
- pendadr = pnewadr + bh->b_size;
- ++CurrentNReq;
- if (bh == CURRENT->bhtail) break;
- }
- }
- }
- else {
- if (!STRAM_ADDR(pbuffer)) {
- buffer = acsi_buffer;
- pbuffer = phys_acsi_buffer;
- if (nsect > ACSI_BUFFER_SECTORS)
- nsect = ACSI_BUFFER_SECTORS;
- }
- }
- CurrentBuffer = buffer;
- CurrentNSect = nsect;
-
- if (rq_data_dir(CURRENT) == WRITE) {
- CMDSET_TARG_LUN( write_cmd, target, lun );
- CMDSET_BLOCK( write_cmd, block );
- CMDSET_LEN( write_cmd, nsect );
- if (buffer == acsi_buffer)
- copy_to_acsibuffer();
- dma_cache_maintenance( pbuffer, nsect*512, 1 );
- do_acsi = write_intr;
- if (!acsicmd_dma( write_cmd, buffer, nsect, 1, 1)) {
- do_acsi = NULL;
- printk( KERN_ERR "ACSI (write): Timeout in command block\n" );
- bad_rw_intr();
- goto repeat;
- }
- SET_TIMER();
- return;
- }
- if (rq_data_dir(CURRENT) == READ) {
- CMDSET_TARG_LUN( read_cmd, target, lun );
- CMDSET_BLOCK( read_cmd, block );
- CMDSET_LEN( read_cmd, nsect );
- do_acsi = read_intr;
- if (!acsicmd_dma( read_cmd, buffer, nsect, 0, 1)) {
- do_acsi = NULL;
- printk( KERN_ERR "ACSI (read): Timeout in command block\n" );
- bad_rw_intr();
- goto repeat;
- }
- SET_TIMER();
- return;
- }
- panic("unknown ACSI command");
-}
-
-
-
-/***********************************************************************
- *
- * Misc functions: ioctl, open, release, check_change, ...
- *
- ***********************************************************************/
-
-static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
- struct acsi_info_struct *aip = bdev->bd_disk->private_data;
-
- /*
- * Just fake some geometry here, it's nonsense anyway
- * To make it easy, use Adaptec's usual 64/32 mapping
- */
- geo->heads = 64;
- geo->sectors = 32;
- geo->cylinders = aip->size >> 11;
- return 0;
-}
-
-static int acsi_ioctl( struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg )
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct acsi_info_struct *aip = disk->private_data;
- switch (cmd) {
- case SCSI_IOCTL_GET_IDLUN:
- /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
- put_user( aip->target | (aip->lun << 8),
- &((Scsi_Idlun *) arg)->dev_id );
- put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id );
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-
-/*
- * Open a device, check for read-only and lock the medium if it is
- * removable.
- *
- * Changes by Martin Rogge, 9th Aug 1995:
- * Check whether check_disk_change (and therefore revalidate_acsidisk)
- * was successful. They fail when there is no medium in the drive.
- *
- * The problem of media being changed during an operation can be
- * ignored because of the prevent_removal code.
- *
- * Added check for the validity of the device number.
- *
- */
-
-static int acsi_open( struct inode * inode, struct file * filp )
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct acsi_info_struct *aip = disk->private_data;
-
- if (aip->access_count == 0 && aip->removable) {
-#if 0
- aip->changed = 1; /* safety first */
-#endif
- check_disk_change( inode->i_bdev );
- if (aip->changed) /* revalidate was not successful (no medium) */
- return -ENXIO;
- acsi_prevent_removal(aip, 1);
- }
- aip->access_count++;
-
- if (filp && filp->f_mode) {
- check_disk_change( inode->i_bdev );
- if (filp->f_mode & 2) {
- if (aip->read_only) {
- acsi_release( inode, filp );
- return -EROFS;
- }
- }
- }
-
- return 0;
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-
-static int acsi_release( struct inode * inode, struct file * file )
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct acsi_info_struct *aip = disk->private_data;
- if (--aip->access_count == 0 && aip->removable)
- acsi_prevent_removal(aip, 0);
- return( 0 );
-}
-
-/*
- * Prevent or allow a media change for removable devices.
- */
-
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag)
-{
- stdma_lock( NULL, NULL );
-
- CMDSET_TARG_LUN(pa_med_rem_cmd, aip->target, aip->lun);
- CMDSET_LEN( pa_med_rem_cmd, flag );
-
- if (acsicmd_nodma(pa_med_rem_cmd, 0) && acsi_wait_for_IRQ(3*HZ))
- acsi_getstatus();
- /* Do not report errors -- some devices may not know this command. */
-
- ENABLE_IRQ();
- stdma_release();
-}
-
-static int acsi_media_change(struct gendisk *disk)
-{
- struct acsi_info_struct *aip = disk->private_data;
-
- if (!aip->removable)
- return 0;
-
- if (aip->changed)
- /* We can be sure that the medium has been changed -- REQUEST
- * SENSE has reported this earlier.
- */
- return 1;
-
- /* If the flag isn't set, make a test by reading block 0.
- * If errors happen, it seems to be better to say "changed"...
- */
- stdma_lock( NULL, NULL );
- CMDSET_TARG_LUN(read_cmd, aip->target, aip->lun);
- CMDSET_BLOCK( read_cmd, 0 );
- CMDSET_LEN( read_cmd, 1 );
- if (acsicmd_dma(read_cmd, acsi_buffer, 1, 0, 0) &&
- acsi_wait_for_IRQ(3*HZ)) {
- if (acsi_getstatus()) {
- if (acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
- if (CARTRCH_STAT(aip, acsi_buffer))
- aip->changed = 1;
- }
- else {
- printk( KERN_ERR "%s: REQUEST SENSE failed in test for "
- "medium change; assuming a change\n", disk->disk_name );
- aip->changed = 1;
- }
- }
- }
- else {
- printk( KERN_ERR "%s: Test for medium changed timed out; "
- "assuming a change\n", disk->disk_name);
- aip->changed = 1;
- }
- ENABLE_IRQ();
- stdma_release();
-
- /* Now, after reading a block, the changed status is surely valid. */
- return aip->changed;
-}
-
-
-static int acsi_change_blk_size( int target, int lun)
-
-{ int i;
-
- for (i=0; i<12; i++)
- acsi_buffer[i] = 0;
-
- acsi_buffer[3] = 8;
- acsi_buffer[10] = 2;
- CMDSET_TARG_LUN( modeselect_cmd, target, lun);
-
- if (!acsicmd_dma( modeselect_cmd, acsi_buffer, 1,1,0) ||
- !acsi_wait_for_IRQ( 3*HZ ) ||
- acsi_getstatus() != 0 ) {
- return(0);
- }
- return(1);
-}
-
-
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd )
-
-{
- int page;
-
- CMDSET_TARG_LUN( modesense_cmd, target, lun );
- for (page=0; page<4; page++) {
- modesense_cmd[2] = page;
- if (!acsicmd_dma( modesense_cmd, acsi_buffer, 1, 0, 0 ) ||
- !acsi_wait_for_IRQ( 3*HZ ) ||
- acsi_getstatus())
- continue;
-
- /* read twice to jump over the second 16-byte border! */
- udelay(300);
- if (acsi_wait_for_noIRQ( 20 ) &&
- acsicmd_nodma( modesense_cmd, 0 ) &&
- acsi_wait_for_IRQ( 3*HZ ) &&
- acsi_getstatus() == 0)
- break;
- }
- if (page == 4) {
- return(0);
- }
-
- dma_cache_maintenance( phys_acsi_buffer, sizeof(SENSE_DATA), 0 );
- *sd = *(SENSE_DATA *)acsi_buffer;
-
- /* Validity check, depending on type of data */
-
- switch( SENSE_TYPE(*sd) ) {
-
- case SENSE_TYPE_ATARI:
- if (CAPACITY(*sd) == 0)
- goto invalid_sense;
- break;
-
- case SENSE_TYPE_SCSI:
- if (sd->scsi.descriptor_size != 8)
- goto invalid_sense;
- break;
-
- case SENSE_TYPE_UNKNOWN:
-
- printk( KERN_ERR "ACSI target %d, lun %d: Cannot interpret "
- "sense data\n", target, lun );
-
- invalid_sense:
-
-#ifdef DEBUG
- { int i;
- printk( "Mode sense data for ACSI target %d, lun %d seem not valid:",
- target, lun );
- for( i = 0; i < sizeof(SENSE_DATA); ++i )
- printk( "%02x ", (unsigned char)acsi_buffer[i] );
- printk( "\n" );
- }
-#endif
- return( 0 );
- }
-
- return( 1 );
-}
-
-
-
-/*******************************************************************
- *
- * Initialization
- *
- ********************************************************************/
-
-
-extern struct block_device_operations acsi_fops;
-
-static struct gendisk *acsi_gendisk[MAX_DEV];
-
-#define MAX_SCSI_DEVICE_CODE 10
-
-static const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
-{
- "Direct-Access ",
- "Sequential-Access",
- "Printer ",
- "Processor ",
- "WORM ",
- "CD-ROM ",
- "Scanner ",
- "Optical Device ",
- "Medium Changer ",
- "Communications "
-};
-
-static void print_inquiry(unsigned char *data)
-{
- int i;
-
- printk(KERN_INFO " Vendor: ");
- for (i = 8; i < 16; i++)
- {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk(" Model: ");
- for (i = 16; i < 32; i++)
- {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk(" Rev: ");
- for (i = 32; i < 36; i++)
- {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk("\n");
-
- i = data[0] & 0x1f;
-
- printk(KERN_INFO " Type: %s ", (i < MAX_SCSI_DEVICE_CODE
- ? scsi_device_types[i]
- : "Unknown "));
- printk(" ANSI SCSI revision: %02x", data[2] & 0x07);
- if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
- printk(" CCS\n");
- else
- printk("\n");
-}
-
-
-/*
- * Changes by Martin Rogge, 9th Aug 1995:
- * acsi_devinit has been taken out of acsi_geninit, because it needs
- * to be called from revalidate_acsidisk. The result of request sense
- * is now checked for DRIVE NOT READY.
- *
- * The structure *aip is only valid when acsi_devinit returns
- * DEV_SUPPORTED.
- *
- */
-
-#define DEV_NONE 0
-#define DEV_UNKNOWN 1
-#define DEV_SUPPORTED 2
-#define DEV_SLM 3
-
-static int acsi_devinit(struct acsi_info_struct *aip)
-{
- int status, got_inquiry;
- SENSE_DATA sense;
- unsigned char reqsense, extsense;
-
- /*****************************************************************/
- /* Do a TEST UNIT READY command to test the presence of a device */
- /*****************************************************************/
-
- CMDSET_TARG_LUN(tur_cmd, aip->target, aip->lun);
- if (!acsicmd_nodma(tur_cmd, 0)) {
- /* timed out -> no device here */
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: timeout\n", aip->target, aip->lun);
-#endif
- return DEV_NONE;
- }
-
- /*************************/
- /* Read the ACSI status. */
- /*************************/
-
- status = acsi_getstatus();
- if (status) {
- if (status == 0x12) {
- /* The SLM printer should be the only device that
- * responds with the error code in the status byte. In
- * correct status bytes, bit 4 is never set.
- */
- printk( KERN_INFO "Detected SLM printer at id %d lun %d\n",
- aip->target, aip->lun);
- return DEV_SLM;
- }
- /* ignore CHECK CONDITION, since some devices send a
- UNIT ATTENTION */
- if ((status & 0x1e) != 0x2) {
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: status %d\n",
- aip->target, aip->lun, status);
-#endif
- return DEV_UNKNOWN;
- }
- }
-
- /*******************************/
- /* Do a REQUEST SENSE command. */
- /*******************************/
-
- if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
- printk( KERN_WARNING "acsi_reqsense failed\n");
- acsi_buffer[0] = 0;
- acsi_buffer[2] = UNIT_ATTENTION;
- }
- reqsense = acsi_buffer[0];
- extsense = acsi_buffer[2] & 0xf;
- if (status) {
- if ((reqsense & 0x70) == 0x70) { /* extended sense */
- if (extsense != UNIT_ATTENTION &&
- extsense != NOT_READY) {
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: extended sense %d\n",
- aip->target, aip->lun, extsense);
-#endif
- return DEV_UNKNOWN;
- }
- }
- else {
- if (reqsense & 0x7f) {
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: sense %d\n",
- aip->target, aip->lun, reqsense);
-#endif
- return DEV_UNKNOWN;
- }
- }
- }
- else
- if (reqsense == 0x4) { /* SH204 Bug workaround */
-#ifdef DEBUG_DETECT
- printk("target %d lun %d status=0 sense=4\n",
- aip->target, aip->lun);
-#endif
- return DEV_UNKNOWN;
- }
-
- /***********************************************************/
- /* Do an INQUIRY command to get more infos on this device. */
- /***********************************************************/
-
- /* Assume default values */
- aip->removable = 1;
- aip->read_only = 0;
- aip->old_atari_disk = 0;
- aip->changed = (extsense == NOT_READY); /* medium inserted? */
- aip->size = DEFAULT_SIZE;
- got_inquiry = 0;
- /* Fake inquiry result for old atari disks */
- memcpy(acsi_buffer, "\000\000\001\000 Adaptec 40xx"
- " ", 40);
- CMDSET_TARG_LUN(inquiry_cmd, aip->target, aip->lun);
- if (acsicmd_dma(inquiry_cmd, acsi_buffer, 1, 0, 0) &&
- acsi_getstatus() == 0) {
- acsicmd_nodma(inquiry_cmd, 0);
- acsi_getstatus();
- dma_cache_maintenance( phys_acsi_buffer, 256, 0 );
- got_inquiry = 1;
- aip->removable = !!(acsi_buffer[1] & 0x80);
- }
- if (aip->type == NONE) /* only at boot time */
- print_inquiry(acsi_buffer);
- switch(acsi_buffer[0]) {
- case TYPE_DISK:
- aip->type = HARDDISK;
- break;
- case TYPE_ROM:
- aip->type = CDROM;
- aip->read_only = 1;
- break;
- default:
- return DEV_UNKNOWN;
- }
- /****************************/
- /* Do a MODE SENSE command. */
- /****************************/
-
- if (!acsi_mode_sense(aip->target, aip->lun, &sense)) {
- printk( KERN_WARNING "No mode sense data.\n" );
- return DEV_UNKNOWN;
- }
- if ((SECTOR_SIZE(sense) != 512) &&
- ((aip->type != CDROM) ||
- !acsi_change_blk_size(aip->target, aip->lun) ||
- !acsi_mode_sense(aip->target, aip->lun, &sense) ||
- (SECTOR_SIZE(sense) != 512))) {
- printk( KERN_WARNING "Sector size != 512 not supported.\n" );
- return DEV_UNKNOWN;
- }
- /* There are disks out there that claim to have 0 sectors... */
- if (CAPACITY(sense))
- aip->size = CAPACITY(sense); /* else keep DEFAULT_SIZE */
- if (!got_inquiry && SENSE_TYPE(sense) == SENSE_TYPE_ATARI) {
- /* If INQUIRY failed and the sense data suggest an old
- * Atari disk (SH20x, Megafile), the disk is not removable
- */
- aip->removable = 0;
- aip->old_atari_disk = 1;
- }
-
- /******************/
- /* We've done it. */
- /******************/
-
- return DEV_SUPPORTED;
-}
-
-EXPORT_SYMBOL(acsi_delay_start);
-EXPORT_SYMBOL(acsi_delay_end);
-EXPORT_SYMBOL(acsi_wait_for_IRQ);
-EXPORT_SYMBOL(acsi_wait_for_noIRQ);
-EXPORT_SYMBOL(acsicmd_nodma);
-EXPORT_SYMBOL(acsi_getstatus);
-EXPORT_SYMBOL(acsi_buffer);
-EXPORT_SYMBOL(phys_acsi_buffer);
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-
-EXPORT_SYMBOL(acsi_extstatus);
-EXPORT_SYMBOL(acsi_end_extstatus);
-EXPORT_SYMBOL(acsi_extcmd);
-EXPORT_SYMBOL(acsi_attach_SLMs);
-
-/* to remember IDs of SLM devices, SLM module is loaded later
- * (index is target#, contents is lun#, -1 means "no SLM") */
-int SLM_devices[8];
-#endif
-
-static struct block_device_operations acsi_fops = {
- .owner = THIS_MODULE,
- .open = acsi_open,
- .release = acsi_release,
- .ioctl = acsi_ioctl,
- .getgeo = acsi_getgeo,
- .media_changed = acsi_media_change,
- .revalidate_disk= acsi_revalidate,
-};
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-/* call attach_slm() for each device that is a printer; needed for init of SLM
- * driver as a module, since it's not yet present if acsi.c is inited and thus
- * the bus gets scanned. */
-void acsi_attach_SLMs( int (*attach_func)( int, int ) )
-{
- int i, n = 0;
-
- for( i = 0; i < 8; ++i )
- if (SLM_devices[i] >= 0)
- n += (*attach_func)( i, SLM_devices[i] );
- printk( KERN_INFO "Found %d SLM printer(s) total.\n", n );
-}
-#endif /* CONFIG_ATARI_SLM_MODULE */
-
-
-int acsi_init( void )
-{
- int err = 0;
- int i, target, lun;
- struct acsi_info_struct *aip;
-#ifdef CONFIG_ATARI_SLM
- int n_slm = 0;
-#endif
- if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
- return 0;
- if (register_blkdev(ACSI_MAJOR, "ad")) {
- err = -EBUSY;
- goto out1;
- }
- if (!(acsi_buffer =
- (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) {
- err = -ENOMEM;
- printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" );
- goto out2;
- }
- phys_acsi_buffer = virt_to_phys( acsi_buffer );
- STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
-
- acsi_queue = blk_init_queue(do_acsi_request, &acsi_lock);
- if (!acsi_queue) {
- err = -ENOMEM;
- goto out2a;
- }
-#ifdef CONFIG_ATARI_SLM
- err = slm_init();
-#endif
- if (err)
- goto out3;
-
- printk( KERN_INFO "Probing ACSI devices:\n" );
- NDevices = 0;
-#ifdef CONFIG_ATARI_SLM_MODULE
- for( i = 0; i < 8; ++i )
- SLM_devices[i] = -1;
-#endif
- stdma_lock(NULL, NULL);
-
- for (target = 0; target < 8 && NDevices < MAX_DEV; ++target) {
- lun = 0;
- do {
- aip = &acsi_info[NDevices];
- aip->type = NONE;
- aip->target = target;
- aip->lun = lun;
- i = acsi_devinit(aip);
- switch (i) {
- case DEV_SUPPORTED:
- printk( KERN_INFO "Detected ");
- switch (aip->type) {
- case HARDDISK:
- printk("disk");
- break;
- case CDROM:
- printk("cdrom");
- break;
- default:
- }
- printk(" ad%c at id %d lun %d ",
- 'a' + NDevices, target, lun);
- if (aip->removable)
- printk("(removable) ");
- if (aip->read_only)
- printk("(read-only) ");
- if (aip->size == DEFAULT_SIZE)
- printk(" unkown size, using default ");
- printk("%ld MByte\n",
- (aip->size*512+1024*1024/2)/(1024*1024));
- NDevices++;
- break;
- case DEV_SLM:
-#ifdef CONFIG_ATARI_SLM
- n_slm += attach_slm( target, lun );
- break;
-#endif
-#ifdef CONFIG_ATARI_SLM_MODULE
- SLM_devices[target] = lun;
- break;
-#endif
- /* neither of the above: fall through to unknown device */
- case DEV_UNKNOWN:
- printk( KERN_INFO "Detected unsupported device at "
- "id %d lun %d\n", target, lun);
- break;
- }
- }
-#ifdef CONFIG_ACSI_MULTI_LUN
- while (i != DEV_NONE && ++lun < MAX_LUN);
-#else
- while (0);
-#endif
- }
-
- /* reenable interrupt */
- ENABLE_IRQ();
- stdma_release();
-
-#ifndef CONFIG_ATARI_SLM
- printk( KERN_INFO "Found %d ACSI device(s) total.\n", NDevices );
-#else
- printk( KERN_INFO "Found %d ACSI device(s) and %d SLM printer(s) total.\n",
- NDevices, n_slm );
-#endif
- err = -ENOMEM;
- for( i = 0; i < NDevices; ++i ) {
- acsi_gendisk[i] = alloc_disk(16);
- if (!acsi_gendisk[i])
- goto out4;
- }
-
- for( i = 0; i < NDevices; ++i ) {
- struct gendisk *disk = acsi_gendisk[i];
- sprintf(disk->disk_name, "ad%c", 'a'+i);
- aip = &acsi_info[NDevices];
- disk->major = ACSI_MAJOR;
- disk->first_minor = i << 4;
- if (acsi_info[i].type != HARDDISK)
- disk->minors = 1;
- disk->fops = &acsi_fops;
- disk->private_data = &acsi_info[i];
- set_capacity(disk, acsi_info[i].size);
- disk->queue = acsi_queue;
- add_disk(disk);
- }
- return 0;
-out4:
- while (i--)
- put_disk(acsi_gendisk[i]);
-out3:
- blk_cleanup_queue(acsi_queue);
-out2a:
- atari_stram_free( acsi_buffer );
-out2:
- unregister_blkdev( ACSI_MAJOR, "ad" );
-out1:
- return err;
-}
-
-
-#ifdef MODULE
-
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
- int err;
-
- if ((err = acsi_init()))
- return( err );
- printk( KERN_INFO "ACSI driver loaded as module.\n");
- return( 0 );
-}
-
-void cleanup_module(void)
-{
- int i;
- del_timer( &acsi_timer );
- blk_cleanup_queue(acsi_queue);
- atari_stram_free( acsi_buffer );
-
- if (unregister_blkdev( ACSI_MAJOR, "ad" ) != 0)
- printk( KERN_ERR "acsi: cleanup_module failed\n");
-
- for (i = 0; i < NDevices; i++) {
- del_gendisk(acsi_gendisk[i]);
- put_disk(acsi_gendisk[i]);
- }
-}
-#endif
-
-/*
- * This routine is called to flush all partitions and partition tables
- * for a changed scsi disk, and then re-read the new partition table.
- * If we are revalidating a disk because of a media change, then we
- * enter with usage == 0. If we are using an ioctl, we automatically have
- * usage == 1 (we need an open channel to use an ioctl :-), so this
- * is our limit.
- *
- * Changes by Martin Rogge, 9th Aug 1995:
- * got cd-roms to work by calling acsi_devinit. There are only two problems:
- * First, if there is no medium inserted, the status will remain "changed".
- * That is no problem at all, but our design of three-valued logic (medium
- * changed, medium not changed, no medium inserted).
- * Secondly the check could fail completely and the drive could deliver
- * nonsensical data, which could mess up the acsi_info[] structure. In
- * that case we try to make the entry safe.
- *
- */
-
-static int acsi_revalidate(struct gendisk *disk)
-{
- struct acsi_info_struct *aip = disk->private_data;
- stdma_lock( NULL, NULL );
- if (acsi_devinit(aip) != DEV_SUPPORTED) {
- printk( KERN_ERR "ACSI: revalidate failed for target %d lun %d\n",
- aip->target, aip->lun);
- aip->size = 0;
- aip->read_only = 1;
- aip->removable = 1;
- aip->changed = 1; /* next acsi_open will try again... */
- }
-
- ENABLE_IRQ();
- stdma_release();
- set_capacity(disk, aip->size);
- return 0;
-}
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 27a139025ce..6ce8b897e26 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1363,7 +1363,7 @@ static void redo_fd_request(void)
#ifdef DEBUG
printk("fd: sector %ld + %d requested for %s\n",
CURRENT->sector,cnt,
- (CURRENT->cmd==READ)?"read":"write");
+ (rq_data_dir(CURRENT) == READ) ? "read" : "write");
#endif
block = CURRENT->sector + cnt;
if ((int)block > floppy->blocks) {
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5acc6c44aea..0fcad430474 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -87,6 +87,7 @@ static const struct pci_device_id cciss_pci_device_id[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D},
{PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
{0,}
@@ -119,6 +120,7 @@ static struct board_type products[] = {
{0x3214103C, "Smart Array E200i", &SA5_access, 120},
{0x3215103C, "Smart Array E200i", &SA5_access, 120},
{0x3237103C, "Smart Array E500", &SA5_access, 512},
+ {0x323D103C, "Smart Array P700m", &SA5_access, 512},
{0xFFFF103C, "Unknown Smart Array", &SA5_access, 120},
};
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0ed5470d253..4503290da40 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -74,6 +74,7 @@
#include <linux/highmem.h>
#include <linux/gfp.h>
#include <linux/kthread.h>
+#include <linux/splice.h>
#include <asm/uaccess.h>
@@ -401,50 +402,73 @@ struct lo_read_data {
};
static int
-lo_read_actor(read_descriptor_t *desc, struct page *page,
- unsigned long offset, unsigned long size)
+lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+ struct splice_desc *sd)
{
- unsigned long count = desc->count;
- struct lo_read_data *p = desc->arg.data;
+ struct lo_read_data *p = sd->u.data;
struct loop_device *lo = p->lo;
+ struct page *page = buf->page;
sector_t IV;
+ size_t size;
+ int ret;
- IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
+ ret = buf->ops->confirm(pipe, buf);
+ if (unlikely(ret))
+ return ret;
- if (size > count)
- size = count;
+ IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
+ (buf->offset >> 9);
+ size = sd->len;
+ if (size > p->bsize)
+ size = p->bsize;
- if (lo_do_transfer(lo, READ, page, offset, p->page, p->offset, size, IV)) {
- size = 0;
+ if (lo_do_transfer(lo, READ, page, buf->offset, p->page, p->offset, size, IV)) {
printk(KERN_ERR "loop: transfer error block %ld\n",
page->index);
- desc->error = -EINVAL;
+ size = -EINVAL;
}
flush_dcache_page(p->page);
- desc->count = count - size;
- desc->written += size;
- p->offset += size;
+ if (size > 0)
+ p->offset += size;
+
return size;
}
static int
+lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
+{
+ return __splice_from_pipe(pipe, sd, lo_splice_actor);
+}
+
+static int
do_lo_receive(struct loop_device *lo,
struct bio_vec *bvec, int bsize, loff_t pos)
{
struct lo_read_data cookie;
+ struct splice_desc sd;
struct file *file;
- int retval;
+ long retval;
cookie.lo = lo;
cookie.page = bvec->bv_page;
cookie.offset = bvec->bv_offset;
cookie.bsize = bsize;
+
+ sd.len = 0;
+ sd.total_len = bvec->bv_len;
+ sd.flags = 0;
+ sd.pos = pos;
+ sd.u.data = &cookie;
+
file = lo->lo_backing_file;
- retval = file->f_op->sendfile(file, &pos, bvec->bv_len,
- lo_read_actor, &cookie);
- return (retval < 0)? retval: 0;
+ retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
+
+ if (retval < 0)
+ return retval;
+
+ return 0;
}
static int
@@ -679,8 +703,8 @@ static int loop_change_fd(struct loop_device *lo, struct file *lo_file,
if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
goto out_putf;
- /* new backing store needs to support loop (eg sendfile) */
- if (!inode->i_fop->sendfile)
+ /* new backing store needs to support loop (eg splice_read) */
+ if (!inode->i_fop->splice_read)
goto out_putf;
/* size of the new backing store needs to be the same */
@@ -760,7 +784,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
* If we can't read - sorry. If we only can't write - well,
* it's going to be read-only.
*/
- if (!file->f_op->sendfile)
+ if (!file->f_op->splice_read)
goto out_putf;
if (aops->prepare_write && aops->commit_write)
lo_flags |= LO_FLAGS_USE_AOPS;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 069ae39a9cd..c575fb1d585 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -416,7 +416,7 @@ static void nbd_clear_que(struct nbd_device *lo)
/*
* We always wait for result of write, for now. It would be nice to make it optional
* in future
- * if ((req->cmd == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
+ * if ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
* { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
*/
diff --git a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig
deleted file mode 100644
index 4b12e9031fb..00000000000
--- a/drivers/cdrom/Kconfig
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-# CDROM driver configuration
-#
-
-menu "Old CD-ROM drivers (not SCSI, not IDE)"
- depends on ISA && BLOCK
-
-config CD_NO_IDESCSI
- bool "Support non-SCSI/IDE/ATAPI CDROM drives"
- ---help---
- If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
- here, otherwise N. Read the CD-ROM-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about these CD-ROM drives. If you are unsure what you
- have, say Y and find out whether you have one of the following
- drives.
-
- For each of these drivers, a <file:Documentation/cdrom/{driver_name}>
- exists. Especially in cases where you do not know exactly which kind
- of drive you have you should read there. Most of these drivers use a
- file drivers/cdrom/{driver_name}.h where you can define your
- interface parameters and switch some internal goodies.
-
- To compile these CD-ROM drivers as a module, choose M instead of Y.
-
- If you want to use any of these CD-ROM drivers, you also have to
- answer Y or M to "ISO 9660 CD-ROM file system support" below (this
- answer will get "defaulted" for you if you enable any of the Linux
- CD-ROM drivers).
-
-config AZTCD
- tristate "Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- This is your driver if you have an Aztech CDA268-01A, Orchid
- CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or
- CR540 CD-ROM drive. This driver -- just like all these CD-ROM
- drivers -- is NOT for CD-ROM drives with IDE/ATAPI interfaces, such
- as Aztech CDA269-031SE. Please read the file
- <file:Documentation/cdrom/aztcd>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called aztcd.
-
-config GSCD
- tristate "Goldstar R420 CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- If this is your CD-ROM drive, say Y here. As described in the file
- <file:Documentation/cdrom/gscd>, you might have to change a setting
- in the file <file:drivers/cdrom/gscd.h> before compiling the
- kernel. Please read the file <file:Documentation/cdrom/gscd>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called gscd.
-
-config SBPCD
- tristate "Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support"
- depends on CD_NO_IDESCSI && BROKEN_ON_SMP
- ---help---
- This driver supports most of the drives which use the Panasonic or
- Sound Blaster interface. Please read the file
- <file:Documentation/cdrom/sbpcd>.
-
- The Matsushita CR-521, CR-522, CR-523, CR-562, CR-563 drives
- (sometimes labeled "Creative"), the Creative Labs CD200, the
- Longshine LCS-7260, the "IBM External ISA CD-ROM" (in fact a CR-56x
- model), the TEAC CD-55A fall under this category. Some other
- "electrically compatible" drives (Vertos, Genoa, some Funai models)
- are currently not supported; for the Sanyo H94A drive currently a
- separate driver (asked later) is responsible. Most drives have a
- uniquely shaped faceplate, with a caddyless motorized drawer, but
- without external brand markings. The older CR-52x drives have a
- caddy and manual loading/eject, but still no external markings. The
- driver is able to do an extended auto-probing for interface
- addresses and drive types; this can help to find facts in cases you
- are not sure, but can consume some time during the boot process if
- none of the supported drives gets found. Once your drive got found,
- you should enter the reported parameters into
- <file:drivers/cdrom/sbpcd.h> and set "DISTRIBUTION 0" there.
-
- This driver can support up to four CD-ROM controller cards, and each
- card can support up to four CD-ROM drives; if you say Y here, you
- will be asked how many controller cards you have. If compiled as a
- module, only one controller card (but with up to four drives) is
- usable.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called sbpcd.
-
-config MCDX
- tristate "Mitsumi CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- Use this driver if you want to be able to use your Mitsumi LU-005,
- FX-001 or FX-001D CD-ROM drive.
-
- Please read the file <file:Documentation/cdrom/mcdx>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called mcdx.
-
-config OPTCD
- tristate "Optics Storage DOLPHIN 8000AT CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- This is the driver for the 'DOLPHIN' drive with a 34-pin Sony
- compatible interface. It also works with the Lasermate CR328A. If
- you have one of those, say Y. This driver does not work for the
- Optics Storage 8001 drive; use the IDE-ATAPI CD-ROM driver for that
- one. Please read the file <file:Documentation/cdrom/optcd>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called optcd.
-
-config CM206
- tristate "Philips/LMS CM206 CDROM support"
- depends on CD_NO_IDESCSI && BROKEN_ON_SMP
- ---help---
- If you have a Philips/LMS CD-ROM drive cm206 in combination with a
- cm260 host adapter card, say Y here. Please also read the file
- <file:Documentation/cdrom/cm206>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called cm206.
-
-config SJCD
- tristate "Sanyo CDR-H94A CDROM support"
- depends on CD_NO_IDESCSI
- help
- If this is your CD-ROM drive, say Y here and read the file
- <file:Documentation/cdrom/sjcd>. You should then also say Y or M to
- "ISO 9660 CD-ROM file system support" below, because that's the
- file system used on CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called sjcd.
-
-config ISP16_CDI
- tristate "ISP16/MAD16/Mozart soft configurable cdrom interface support"
- depends on CD_NO_IDESCSI
- ---help---
- These are sound cards with built-in cdrom interfaces using the OPTi
- 82C928 or 82C929 chips. Say Y here to have them detected and
- possibly configured at boot time. In addition, You'll have to say Y
- to a driver for the particular cdrom drive you have attached to the
- card. Read <file:Documentation/cdrom/isp16> for details.
-
- To compile this driver as a module, choose M here: the
- module will be called isp16.
-
-config CDU31A
- tristate "Sony CDU31A/CDU33A CDROM support"
- depends on CD_NO_IDESCSI && BROKEN_ON_SMP
- ---help---
- These CD-ROM drives have a spring-pop-out caddyless drawer, and a
- rectangular green LED centered beneath it. NOTE: these CD-ROM
- drives will not be auto detected by the kernel at boot time; you
- have to provide the interface address as an option to the kernel at
- boot time as described in <file:Documentation/cdrom/cdu31a> or fill
- in your parameters into <file:drivers/cdrom/cdu31a.c>. Try "man
- bootparam" or see the documentation of your boot loader (lilo or
- loadlin) about how to pass options to the kernel.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called cdu31a.
-
-config CDU535
- tristate "Sony CDU535 CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM
- drives. Please read the file <file:Documentation/cdrom/sonycd535>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called sonycd535.
-
-endmenu
diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
index d1d1e5a4be7..774c180a4e1 100644
--- a/drivers/cdrom/Makefile
+++ b/drivers/cdrom/Makefile
@@ -10,14 +10,4 @@ obj-$(CONFIG_BLK_DEV_SR) += cdrom.o
obj-$(CONFIG_PARIDE_PCD) += cdrom.o
obj-$(CONFIG_CDROM_PKTCDVD) += cdrom.o
-obj-$(CONFIG_AZTCD) += aztcd.o
-obj-$(CONFIG_CDU31A) += cdu31a.o cdrom.o
-obj-$(CONFIG_CM206) += cm206.o cdrom.o
-obj-$(CONFIG_GSCD) += gscd.o
-obj-$(CONFIG_ISP16_CDI) += isp16.o
-obj-$(CONFIG_MCDX) += mcdx.o cdrom.o
-obj-$(CONFIG_OPTCD) += optcd.o
-obj-$(CONFIG_SBPCD) += sbpcd.o cdrom.o
-obj-$(CONFIG_SJCD) += sjcd.o
-obj-$(CONFIG_CDU535) += sonycd535.o
obj-$(CONFIG_VIOCD) += viocd.o cdrom.o
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
deleted file mode 100644
index 1f9fb7a9670..00000000000
--- a/drivers/cdrom/aztcd.c
+++ /dev/null
@@ -1,2492 +0,0 @@
-#define AZT_VERSION "2.60"
-
-/* $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $
- linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver
-
- Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)
-
- based on Mitsumi CDROM driver by Martin Hariss and preworks by
- Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby
- Schirmer.
-
- 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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- HISTORY
- V0.0 Adaption to Aztech CD268-01A Version 1.3
- Version is PRE_ALPHA, unresolved points:
- 1. I use busy wait instead of timer wait in STEN_LOW,DTEN_LOW
- thus driver causes CPU overhead and is very slow
- 2. could not find a way to stop the drive, when it is
- in data read mode, therefore I had to set
- msf.end.min/sec/frame to 0:0:1 (in azt_poll); so only one
- frame can be read in sequence, this is also the reason for
- 3. getting 'timeout in state 4' messages, but nevertheless
- it works
- W.Zimmermann, Oct. 31, 1994
- V0.1 Version is ALPHA, problems #2 and #3 resolved.
- W.Zimmermann, Nov. 3, 1994
- V0.2 Modification to some comments, debugging aids for partial test
- with Borland C under DOS eliminated. Timer interrupt wait
- STEN_LOW_WAIT additionally to busy wait for STEN_LOW implemented;
- use it only for the 'slow' commands (ACMD_GET_Q_CHANNEL, ACMD_
- SEEK_TO_LEAD_IN), all other commands are so 'fast', that busy
- waiting seems better to me than interrupt rescheduling.
- Besides that, when used in the wrong place, STEN_LOW_WAIT causes
- kernel panic.
- In function aztPlay command ACMD_PLAY_AUDIO added, should make
- audio functions work. The Aztech drive needs different commands
- to read data tracks and play audio tracks.
- W.Zimmermann, Nov. 8, 1994
- V0.3 Recognition of missing drive during boot up improved (speeded up).
- W.Zimmermann, Nov. 13, 1994
- V0.35 Rewrote the control mechanism in azt_poll (formerly mcd_poll)
- including removal of all 'goto' commands. :-);
- J. Nardone, Nov. 14, 1994
- V0.4 Renamed variables and constants to 'azt' instead of 'mcd'; had
- to make some "compatibility" defines in azt.h; please note,
- that the source file was renamed to azt.c, the include file to
- azt.h
- Speeded up drive recognition during init (will be a little bit
- slower than before if no drive is installed!); suggested by
- Robby Schirmer.
- read_count declared volatile and set to AZT_BUF_SIZ to make
- drive faster (now 300kB/sec, was 60kB/sec before, measured
- by 'time dd if=/dev/cdrom of=/dev/null bs=2048 count=4096';
- different AZT_BUF_SIZes were test, above 16 no further im-
- provement seems to be possible; suggested by E.Moenkeberg.
- W.Zimmermann, Nov. 18, 1994
- V0.42 Included getAztStatus command in GetQChannelInfo() to allow
- reading Q-channel info on audio disks, if drive is stopped,
- and some other bug fixes in the audio stuff, suggested by
- Robby Schirmer.
- Added more ioctls (reading data in mode 1 and mode 2).
- Completely removed the old azt_poll() routine.
- Detection of ORCHID CDS-3110 in aztcd_init implemented.
- Additional debugging aids (see the readme file).
- W.Zimmermann, Dec. 9, 1994
- V0.50 Autodetection of drives implemented.
- W.Zimmermann, Dec. 12, 1994
- V0.52 Prepared for including in the standard kernel, renamed most
- variables to contain 'azt', included autoconf.h
- W.Zimmermann, Dec. 16, 1994
- V0.6 Version for being included in the standard Linux kernel.
- Renamed source and header file to aztcd.c and aztcd.h
- W.Zimmermann, Dec. 24, 1994
- V0.7 Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case
- CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl,
- which causes kernel crashes when playing audio, changed
- include-files (config.h instead of autoconf.h, removed
- delay.h)
- W.Zimmermann, Jan. 8, 1995
- V0.72 Some more modifications for adaption to the standard kernel.
- W.Zimmermann, Jan. 16, 1995
- V0.80 aztcd is now part of the standard kernel since version 1.1.83.
- Modified the SET_TIMER and CLEAR_TIMER macros to comply with
- the new timer scheme.
- W.Zimmermann, Jan. 21, 1995
- V0.90 Included CDROMVOLCTRL, but with my Aztech drive I can only turn
- the channels on and off. If it works better with your drive,
- please mail me. Also implemented ACMD_CLOSE for CDROMSTART.
- W.Zimmermann, Jan. 24, 1995
- V1.00 Implemented close and lock tray commands. Patches supplied by
- Frank Racis
- Added support for loadable MODULEs, so aztcd can now also be
- loaded by insmod and removed by rmmod during run time
- Werner Zimmermann, Mar. 24, 95
- V1.10 Implemented soundcard configuration for Orchid CDS-3110 drives
- connected to Soundwave32 cards. Release for LST 2.1.
- (still experimental)
- Werner Zimmermann, May 8, 95
- V1.20 Implemented limited support for DOSEMU0.60's cdrom.c. Now it works, but
- sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver-
- sion needs an update of Dosemu0.60's cdrom.c, which will come with the
- next revision of Dosemu.
- Also Soundwave32 support now works.
- Werner Zimmermann, May 22, 95
- V1.30 Auto-eject feature. Inspired by Franc Racis (racis@psu.edu)
- Werner Zimmermann, July 4, 95
- V1.40 Started multisession support. Implementation copied from mcdx.c
- by Heiko Schlittermann. Not tested yet.
- Werner Zimmermann, July 15, 95
- V1.50 Implementation of ioctl CDROMRESET, continued multisession, began
- XA, but still untested. Heavy modifications to drive status de-
- tection.
- Werner Zimmermann, July 25, 95
- V1.60 XA support now should work. Speeded up drive recognition in cases,
- where no drive is installed.
- Werner Zimmermann, August 8, 1995
- V1.70 Multisession support now is completed, but there is still not
- enough testing done. If you can test it, please contact me. For
- details please read Documentation/cdrom/aztcd
- Werner Zimmermann, August 19, 1995
- V1.80 Modification to suit the new kernel boot procedure introduced
- with kernel 1.3.33. Will definitely not work with older kernels.
- Programming done by Linus himself.
- Werner Zimmermann, October 11, 1995
- V1.90 Support for Conrad TXC drives, thank's to Jochen Kunz and Olaf Kaluza.
- Werner Zimmermann, October 21, 1995
- V2.00 Changed #include "blk.h" to <linux/blk.h> as the directory
- structure was changed. README.aztcd is now /usr/src/docu-
- mentation/cdrom/aztcd
- Werner Zimmermann, November 10, 95
- V2.10 Started to modify azt_poll to prevent reading beyond end of
- tracks.
- Werner Zimmermann, December 3, 95
- V2.20 Changed some comments
- Werner Zimmermann, April 1, 96
- V2.30 Implemented support for CyCDROM CR520, CR940, Code for CR520
- delivered by H.Berger with preworks by E.Moenkeberg.
- Werner Zimmermann, April 29, 96
- V2.40 Reorganized the placement of functions in the source code file
- to reflect the layered approach; did not actually change code
- Werner Zimmermann, May 1, 96
- V2.50 Heiko Eissfeldt suggested to remove some VERIFY_READs in
- aztcd_ioctl; check_aztcd_media_change modified
- Werner Zimmermann, May 16, 96
- V2.60 Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
- Adaption to linux kernel > 2.1.0
- Werner Zimmermann, Nov 29, 97
-
- November 1999 -- Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-*/
-
-#include <linux/blkdev.h>
-#include "aztcd.h"
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/uaccess.h>
-
-/*###########################################################################
- Defines
- ###########################################################################
-*/
-
-#define MAJOR_NR AZTECH_CDROM_MAJOR
-#define QUEUE (azt_queue)
-#define CURRENT elv_next_request(azt_queue)
-#define SET_TIMER(func, jifs) delay_timer.expires = jiffies + (jifs); \
- delay_timer.function = (void *) (func); \
- add_timer(&delay_timer);
-
-#define CLEAR_TIMER del_timer(&delay_timer);
-
-#define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\
- return value;}
-#define RETURN(message) {printk("aztcd: Warning: %s failed\n",message);\
- return;}
-
-/* Macros to switch the IDE-interface to the slave device and back to the master*/
-#define SWITCH_IDE_SLAVE outb_p(0xa0,azt_port+6); \
- outb_p(0x10,azt_port+6); \
- outb_p(0x00,azt_port+7); \
- outb_p(0x10,azt_port+6);
-#define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6);
-
-
-#if 0
-#define AZT_TEST
-#define AZT_TEST1 /* <int-..> */
-#define AZT_TEST2 /* do_aztcd_request */
-#define AZT_TEST3 /* AZT_S_state */
-#define AZT_TEST4 /* QUICK_LOOP-counter */
-#define AZT_TEST5 /* port(1) state */
-#define AZT_DEBUG
-#define AZT_DEBUG_MULTISESSION
-#endif
-
-static struct request_queue *azt_queue;
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-#define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
-#define AZT_BUF_SIZ 16
-
-#define READ_TIMEOUT 3000
-
-#define azt_port aztcd /*needed for the modutils */
-
-/*##########################################################################
- Type Definitions
- ##########################################################################
-*/
-enum azt_state_e { AZT_S_IDLE, /* 0 */
- AZT_S_START, /* 1 */
- AZT_S_MODE, /* 2 */
- AZT_S_READ, /* 3 */
- AZT_S_DATA, /* 4 */
- AZT_S_STOP, /* 5 */
- AZT_S_STOPPING /* 6 */
-};
-enum azt_read_modes { AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware */
- AZT_MODE_1, /*read mode for normal CD-ROMs */
- AZT_MODE_2 /*read mode for XA CD-ROMs */
-};
-
-/*##########################################################################
- Global Variables
- ##########################################################################
-*/
-static int aztPresent = 0;
-
-static volatile int azt_transfer_is_active = 0;
-
-static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ]; /*buffer for block size conversion */
-#if AZT_PRIVATE_IOCTLS
-static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls */
-#endif
-
-static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn;
-static volatile int azt_buf_in, azt_buf_out = -1;
-static volatile int azt_error = 0;
-static int azt_open_count = 0;
-static volatile enum azt_state_e azt_state = AZT_S_IDLE;
-#ifdef AZT_TEST3
-static volatile enum azt_state_e azt_state_old = AZT_S_STOP;
-static volatile int azt_st_old = 0;
-#endif
-static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1;
-
-static int azt_mode = -1;
-static volatile int azt_read_count = 1;
-
-static int azt_port = AZT_BASE_ADDR;
-
-module_param(azt_port, int, 0);
-
-static int azt_port_auto[16] = AZT_BASE_AUTO;
-
-static char azt_cont = 0;
-static char azt_init_end = 0;
-static char azt_auto_eject = AZT_AUTO_EJECT;
-
-static int AztTimeout, AztTries;
-static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static DEFINE_TIMER(delay_timer, NULL, 0, 0);
-
-static struct azt_DiskInfo DiskInfo;
-static struct azt_Toc Toc[MAX_TRACKS];
-static struct azt_Play_msf azt_Play;
-
-static int aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-static char aztDiskChanged = 1;
-static char aztTocUpToDate = 0;
-
-static unsigned char aztIndatum;
-static unsigned long aztTimeOutCount;
-static int aztCmd = 0;
-
-static DEFINE_SPINLOCK(aztSpin);
-
-/*###########################################################################
- Function Prototypes
- ###########################################################################
-*/
-/* CDROM Drive Low Level I/O Functions */
-static void aztStatTimer(void);
-
-/* CDROM Drive Command Functions */
-static int aztGetDiskInfo(void);
-#if AZT_MULTISESSION
-static int aztGetMultiDiskInfo(void);
-#endif
-static int aztGetToc(int multi);
-
-/* Kernel Interface Functions */
-static int check_aztcd_media_change(struct gendisk *disk);
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg);
-static int aztcd_open(struct inode *ip, struct file *fp);
-static int aztcd_release(struct inode *inode, struct file *file);
-
-static struct block_device_operations azt_fops = {
- .owner = THIS_MODULE,
- .open = aztcd_open,
- .release = aztcd_release,
- .ioctl = aztcd_ioctl,
- .media_changed = check_aztcd_media_change,
-};
-
-/* Aztcd State Machine: Controls Drive Operating State */
-static void azt_poll(void);
-
-/* Miscellaneous support functions */
-static void azt_hsg2msf(long hsg, struct msf *msf);
-static long azt_msf2hsg(struct msf *mp);
-static void azt_bin2bcd(unsigned char *p);
-static int azt_bcd2bin(unsigned char bcd);
-
-/*##########################################################################
- CDROM Drive Low Level I/O Functions
- ##########################################################################
-*/
-/* Macros for the drive hardware interface handshake, these macros use
- busy waiting */
-/* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
-# define OP_OK op_ok()
-static void op_ok(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(DATA_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: Error Wait OP_OK\n");
- break;
- }
- } while (aztIndatum != AFL_OP_OK);
-}
-
-/* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
-#if 0
-# define PA_OK pa_ok()
-static void pa_ok(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(DATA_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: Error Wait PA_OK\n");
- break;
- }
- } while (aztIndatum != AFL_PA_OK);
-}
-#endif
-
-/* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
-# define STEN_LOW sten_low()
-static void sten_low(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- if (azt_init_end)
- printk
- ("aztcd: Error Wait STEN_LOW commands:%x\n",
- aztCmd);
- break;
- }
- } while (aztIndatum & AFL_STATUS);
-}
-
-/* Wait for DTEN=Low = handshake signal 'Data available'*/
-# define DTEN_LOW dten_low()
-static void dten_low(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: Error Wait DTEN_OK\n");
- break;
- }
- } while (aztIndatum & AFL_DATA);
-}
-
-/*
- * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
- * may cause kernel panic when used in the wrong place
-*/
-#define STEN_LOW_WAIT statusAzt()
-static void statusAzt(void)
-{
- AztTimeout = AZT_STATUS_DELAY;
- SET_TIMER(aztStatTimer, HZ / 100);
- sleep_on(&azt_waitq);
- if (AztTimeout <= 0)
- printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",
- aztCmd);
- return;
-}
-
-static void aztStatTimer(void)
-{
- if (!(inb(STATUS_PORT) & AFL_STATUS)) {
- wake_up(&azt_waitq);
- return;
- }
- AztTimeout--;
- if (AztTimeout <= 0) {
- wake_up(&azt_waitq);
- printk("aztcd: Error aztStatTimer: Timeout\n");
- return;
- }
- SET_TIMER(aztStatTimer, HZ / 100);
-}
-
-/*##########################################################################
- CDROM Drive Command Functions
- ##########################################################################
-*/
-/*
- * Send a single command, return -1 on error, else 0
-*/
-static int aztSendCmd(int cmd)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: Executing command %x\n", cmd);
-#endif
-
- if ((azt_port == 0x1f0) || (azt_port == 0x170))
- SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */
-
- aztCmd = cmd;
- outb(POLLED, MODE_PORT);
- do {
- if (inb(STATUS_PORT) & AFL_STATUS)
- break;
- inb(DATA_PORT); /* if status left from last command, read and */
- } while (1); /* discard it */
- do {
- if (inb(STATUS_PORT) & AFL_DATA)
- break;
- inb(DATA_PORT); /* if data left from last command, read and */
- } while (1); /* discard it */
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- outb((unsigned char) cmd, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_OP_OK) {
- return 0;
- } /*OP_OK? */
- if (data == AFL_OP_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk
- ("### Error 1 aztcd: aztSendCmd %x Error Code %x\n",
- cmd, data);
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: aztSendCmd %x \n", cmd);
- azt_error = 0xA5;
- }
- RETURNM("aztSendCmd", -1);
-}
-
-/*
- * Send a play or read command to the drive, return -1 on error, else 0
-*/
-static int sendAztCmd(int cmd, struct azt_Play_msf *params)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n",
- params->start.min, params->start.sec, params->start.frame,
- params->end.min, params->end.sec, params->end.frame);
-#endif
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- aztSendCmd(cmd);
- outb(params->start.min, CMD_PORT);
- outb(params->start.sec, CMD_PORT);
- outb(params->start.frame, CMD_PORT);
- outb(params->end.min, CMD_PORT);
- outb(params->end.sec, CMD_PORT);
- outb(params->end.frame, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_PA_OK) {
- return 0;
- } /*PA_OK ? */
- if (data == AFL_PA_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk
- ("### Error 1 aztcd: sendAztCmd %x Error Code %x\n",
- cmd, data);
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd);
- azt_error = 0xA5;
- }
- RETURNM("sendAztCmd", -1);
-}
-
-/*
- * Send a seek command to the drive, return -1 on error, else 0
-*/
-static int aztSeek(struct azt_Play_msf *params)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: aztSeek %02x:%02x:%02x\n",
- params->start.min, params->start.sec, params->start.frame);
-#endif
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- aztSendCmd(ACMD_SEEK);
- outb(params->start.min, CMD_PORT);
- outb(params->start.sec, CMD_PORT);
- outb(params->start.frame, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_PA_OK) {
- return 0;
- } /*PA_OK ? */
- if (data == AFL_PA_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk("### Error 1 aztcd: aztSeek\n");
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: aztSeek\n ");
- azt_error = 0xA5;
- }
- RETURNM("aztSeek", -1);
-}
-
-/* Send a Set Disk Type command
- does not seem to work with Aztech drives, behavior is completely indepen-
- dent on which mode is set ???
-*/
-static int aztSetDiskType(int type)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: set disk type command: type= %i\n", type);
-#endif
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- aztSendCmd(ACMD_SET_DISK_TYPE);
- outb(type, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_PA_OK) { /*PA_OK ? */
- azt_read_mode = type;
- return 0;
- }
- if (data == AFL_PA_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk
- ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",
- type, data);
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: aztSetDiskType %x\n ", type);
- azt_error = 0xA5;
- }
- RETURNM("aztSetDiskType", -1);
-}
-
-
-/* used in azt_poll to poll the status, expects another program to issue a
- * ACMD_GET_STATUS directly before
- */
-static int aztStatus(void)
-{
- int st;
-/* int i;
-
- i = inb(STATUS_PORT) & AFL_STATUS; is STEN=0? ???
- if (!i)
-*/ STEN_LOW;
- if (aztTimeOutCount < AZT_TIMEOUT) {
- st = inb(DATA_PORT) & 0xFF;
- return st;
- } else
- RETURNM("aztStatus", -1);
-}
-
-/*
- * Get the drive status
- */
-static int getAztStatus(void)
-{
- int st;
-
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURNM("getAztStatus 1", -1);
- STEN_LOW;
- st = inb(DATA_PORT) & 0xFF;
-#ifdef AZT_DEBUG
- printk("aztcd: Status = %x\n", st);
-#endif
- if ((st == 0xFF) || (st & AST_CMD_CHECK)) {
- printk
- ("aztcd: AST_CMD_CHECK error or no status available\n");
- return -1;
- }
-
- if (((st & AST_MODE_BITS) != AST_BUSY)
- && (aztAudioStatus == CDROM_AUDIO_PLAY))
- /* XXX might be an error? look at q-channel? */
- aztAudioStatus = CDROM_AUDIO_COMPLETED;
-
- if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- }
- return st;
-}
-
-
-/*
- * Send a 'Play' command and get the status. Use only from the top half.
- */
-static int aztPlay(struct azt_Play_msf *arg)
-{
- if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0)
- RETURNM("aztPlay", -1);
- return 0;
-}
-
-/*
- * Subroutines to automatically close the door (tray) and
- * lock it closed when the cd is mounted. Leave the tray
- * locking as an option
- */
-static void aztCloseDoor(void)
-{
- aztSendCmd(ACMD_CLOSE);
- STEN_LOW;
- return;
-}
-
-static void aztLockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
- aztSendCmd(ACMD_LOCK);
- STEN_LOW;
-#endif
- return;
-}
-
-static void aztUnlockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
- aztSendCmd(ACMD_UNLOCK);
- STEN_LOW;
-#endif
- return;
-}
-
-/*
- * Read a value from the drive. Should return quickly, so a busy wait
- * is used to avoid excessive rescheduling. The read command itself must
- * be issued with aztSendCmd() directly before
- */
-static int aztGetValue(unsigned char *result)
-{
- int s;
-
- STEN_LOW;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: aztGetValue timeout\n");
- return -1;
- }
- s = inb(DATA_PORT) & 0xFF;
- *result = (unsigned char) s;
- return 0;
-}
-
-/*
- * Read the current Q-channel info. Also used for reading the
- * table of contents.
- */
-static int aztGetQChannelInfo(struct azt_Toc *qp)
-{
- unsigned char notUsed;
- int st;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetQChannelInfo Time:%li\n", jiffies);
-#endif
- if ((st = getAztStatus()) == -1)
- RETURNM("aztGetQChannelInfo 1", -1);
- if (aztSendCmd(ACMD_GET_Q_CHANNEL))
- RETURNM("aztGetQChannelInfo 2", -1);
- /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */
- if (aztGetValue(&notUsed))
- RETURNM("aztGetQChannelInfo 3", -1); /*??? Nullbyte einlesen */
- if ((st & AST_MODE_BITS) == AST_INITIAL) {
- qp->ctrl_addr = 0; /* when audio stop ACMD_GET_Q_CHANNEL returns */
- qp->track = 0; /* only one byte with Aztech drives */
- qp->pointIndex = 0;
- qp->trackTime.min = 0;
- qp->trackTime.sec = 0;
- qp->trackTime.frame = 0;
- qp->diskTime.min = 0;
- qp->diskTime.sec = 0;
- qp->diskTime.frame = 0;
- return 0;
- } else {
- if (aztGetValue(&qp->ctrl_addr) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->track) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->pointIndex) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->trackTime.min) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->trackTime.sec) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->trackTime.frame) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&notUsed) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->diskTime.min) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->diskTime.sec) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->diskTime.frame) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- }
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztGetQChannelInfo Time:%li\n", jiffies);
-#endif
- return 0;
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary
- */
-static int aztUpdateToc(void)
-{
- int st;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztUpdateToc Time:%li\n", jiffies);
-#endif
- if (aztTocUpToDate)
- return 0;
-
- if (aztGetDiskInfo() < 0)
- return -EIO;
-
- if (aztGetToc(0) < 0)
- return -EIO;
-
- /*audio disk detection
- with my Aztech drive there is no audio status bit, so I use the copy
- protection bit of the first track. If this track is copy protected
- (copy bit = 0), I assume, it's an audio disk. Strange, but works ??? */
- if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
- DiskInfo.audio = 1;
- else
- DiskInfo.audio = 0;
-
- /* XA detection */
- if (!DiskInfo.audio) {
- azt_Play.start.min = 0; /*XA detection only seems to work */
- azt_Play.start.sec = 2; /*when we play a track */
- azt_Play.start.frame = 0;
- azt_Play.end.min = 0;
- azt_Play.end.sec = 0;
- azt_Play.end.frame = 1;
- if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
- return -1;
- DTEN_LOW;
- for (st = 0; st < CD_FRAMESIZE; st++)
- inb(DATA_PORT);
- }
- DiskInfo.xa = getAztStatus() & AST_MODE;
- if (DiskInfo.xa) {
- printk
- ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
- }
-
- /*multisession detection
- support for multisession CDs is done automatically with Aztech drives,
- we don't have to take care about TOC redirection; if we want the isofs
- to take care about redirection, we have to set AZT_MULTISESSION to 1 */
- DiskInfo.multi = 0;
-#if AZT_MULTISESSION
- if (DiskInfo.xa) {
- aztGetMultiDiskInfo(); /*here Disk.Info.multi is set */
- }
-#endif
- if (DiskInfo.multi) {
- DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
- DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
- DiskInfo.lastSession.frame =
- Toc[DiskInfo.next].diskTime.frame;
- printk("aztcd: Multisession support experimental\n");
- } else {
- DiskInfo.lastSession.min =
- Toc[DiskInfo.first].diskTime.min;
- DiskInfo.lastSession.sec =
- Toc[DiskInfo.first].diskTime.sec;
- DiskInfo.lastSession.frame =
- Toc[DiskInfo.first].diskTime.frame;
- }
-
- aztTocUpToDate = 1;
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztUpdateToc Time:%li\n", jiffies);
-#endif
- return 0;
-}
-
-
-/* Read the table of contents header, i.e. no. of tracks and start of first
- * track
- */
-static int aztGetDiskInfo(void)
-{
- int limit;
- unsigned char test;
- struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetDiskInfo Time:%li\n", jiffies);
-#endif
- if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
- RETURNM("aztGetDiskInfo 1", -1);
- STEN_LOW_WAIT;
- test = 0;
- for (limit = 300; limit > 0; limit--) {
- if (aztGetQChannelInfo(&qInfo) < 0)
- RETURNM("aztGetDiskInfo 2", -1);
- if (qInfo.pointIndex == 0xA0) { /*Number of FirstTrack */
- DiskInfo.first = qInfo.diskTime.min;
- DiskInfo.first = azt_bcd2bin(DiskInfo.first);
- test = test | 0x01;
- }
- if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
- DiskInfo.last = qInfo.diskTime.min;
- DiskInfo.last = azt_bcd2bin(DiskInfo.last);
- test = test | 0x02;
- }
- if (qInfo.pointIndex == 0xA2) { /*DiskLength */
- DiskInfo.diskLength.min = qInfo.diskTime.min;
- DiskInfo.diskLength.sec = qInfo.diskTime.sec;
- DiskInfo.diskLength.frame = qInfo.diskTime.frame;
- test = test | 0x04;
- }
- if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) { /*StartTime of First Track */
- DiskInfo.firstTrack.min = qInfo.diskTime.min;
- DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
- DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
- test = test | 0x08;
- }
- if (test == 0x0F)
- break;
- }
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztGetDiskInfo Time:%li\n", jiffies);
- printk
- ("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n",
- DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
- DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
- DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
- DiskInfo.firstTrack.frame);
-#endif
- if (test != 0x0F)
- return -1;
- return 0;
-}
-
-#if AZT_MULTISESSION
-/*
- * Get Multisession Disk Info
- */
-static int aztGetMultiDiskInfo(void)
-{
- int limit, k = 5;
- unsigned char test;
- struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetMultiDiskInfo\n");
-#endif
-
- do {
- azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min;
- azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec;
- azt_Play.start.frame =
- Toc[DiskInfo.last + 1].diskTime.frame;
- test = 0;
-
- for (limit = 30; limit > 0; limit--) { /*Seek for LeadIn of next session */
- if (aztSeek(&azt_Play))
- RETURNM("aztGetMultiDiskInfo 1", -1);
- if (aztGetQChannelInfo(&qInfo) < 0)
- RETURNM("aztGetMultiDiskInfo 2", -1);
- if ((qInfo.track == 0) && (qInfo.pointIndex))
- break; /*LeadIn found */
- if ((azt_Play.start.sec += 10) > 59) {
- azt_Play.start.sec = 0;
- azt_Play.start.min++;
- }
- }
- if (!limit)
- break; /*Check, if a leadin track was found, if not we're
- at the end of the disk */
-#ifdef AZT_DEBUG_MULTISESSION
- printk("leadin found track %d pointIndex %x limit %d\n",
- qInfo.track, qInfo.pointIndex, limit);
-#endif
- for (limit = 300; limit > 0; limit--) {
- if (++azt_Play.start.frame > 74) {
- azt_Play.start.frame = 0;
- if (azt_Play.start.sec > 59) {
- azt_Play.start.sec = 0;
- azt_Play.start.min++;
- }
- }
- if (aztSeek(&azt_Play))
- RETURNM("aztGetMultiDiskInfo 3", -1);
- if (aztGetQChannelInfo(&qInfo) < 0)
- RETURNM("aztGetMultiDiskInfo 4", -1);
- if (qInfo.pointIndex == 0xA0) { /*Number of NextTrack */
- DiskInfo.next = qInfo.diskTime.min;
- DiskInfo.next = azt_bcd2bin(DiskInfo.next);
- test = test | 0x01;
- }
- if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
- DiskInfo.last = qInfo.diskTime.min;
- DiskInfo.last = azt_bcd2bin(DiskInfo.last);
- test = test | 0x02;
- }
- if (qInfo.pointIndex == 0xA2) { /*DiskLength */
- DiskInfo.diskLength.min =
- qInfo.diskTime.min;
- DiskInfo.diskLength.sec =
- qInfo.diskTime.sec;
- DiskInfo.diskLength.frame =
- qInfo.diskTime.frame;
- test = test | 0x04;
- }
- if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) { /*StartTime of Next Track */
- DiskInfo.nextSession.min =
- qInfo.diskTime.min;
- DiskInfo.nextSession.sec =
- qInfo.diskTime.sec;
- DiskInfo.nextSession.frame =
- qInfo.diskTime.frame;
- test = test | 0x08;
- }
- if (test == 0x0F)
- break;
- }
-#ifdef AZT_DEBUG_MULTISESSION
- printk
- ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n",
- DiskInfo.first, DiskInfo.next, DiskInfo.last,
- DiskInfo.diskLength.min, DiskInfo.diskLength.sec,
- DiskInfo.diskLength.frame, DiskInfo.firstTrack.min,
- DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame,
- DiskInfo.nextSession.min, DiskInfo.nextSession.sec,
- DiskInfo.nextSession.frame);
-#endif
- if (test != 0x0F)
- break;
- else
- DiskInfo.multi = 1; /*found TOC of more than one session */
- aztGetToc(1);
- } while (--k);
-
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztGetMultiDiskInfo Time:%li\n", jiffies);
-#endif
- return 0;
-}
-#endif
-
-/*
- * Read the table of contents (TOC)
- */
-static int aztGetToc(int multi)
-{
- int i, px;
- int limit;
- struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetToc Time:%li\n", jiffies);
-#endif
- if (!multi) {
- for (i = 0; i < MAX_TRACKS; i++)
- Toc[i].pointIndex = 0;
- i = DiskInfo.last + 3;
- } else {
- for (i = DiskInfo.next; i < MAX_TRACKS; i++)
- Toc[i].pointIndex = 0;
- i = DiskInfo.last + 4 - DiskInfo.next;
- }
-
-/*Is there a good reason to stop motor before TOC read?
- if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
- STEN_LOW_WAIT;
-*/
-
- if (!multi) {
- azt_mode = 0x05;
- if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
- RETURNM("aztGetToc 2", -1);
- STEN_LOW_WAIT;
- }
- for (limit = 300; limit > 0; limit--) {
- if (multi) {
- if (++azt_Play.start.sec > 59) {
- azt_Play.start.sec = 0;
- azt_Play.start.min++;
- }
- if (aztSeek(&azt_Play))
- RETURNM("aztGetToc 3", -1);
- }
- if (aztGetQChannelInfo(&qInfo) < 0)
- break;
-
- px = azt_bcd2bin(qInfo.pointIndex);
-
- if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
- if (Toc[px].pointIndex == 0) {
- Toc[px] = qInfo;
- i--;
- }
-
- if (i <= 0)
- break;
- }
-
- Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
- Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;
-
-#ifdef AZT_DEBUG_MULTISESSION
- printk("aztcd: exiting aztGetToc\n");
- for (i = 1; i <= DiskInfo.last + 1; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
- for (i = 100; i < 103; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-#endif
-
- return limit > 0 ? 0 : -1;
-}
-
-
-/*##########################################################################
- Kernel Interface Functions
- ##########################################################################
-*/
-
-#ifndef MODULE
-static int __init aztcd_setup(char *str)
-{
- int ints[4];
-
- (void) get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0)
- azt_port = ints[1];
- if (ints[1] > 1)
- azt_cont = ints[2];
- return 1;
-}
-
-__setup("aztcd=", aztcd_setup);
-
-#endif /* !MODULE */
-
-/*
- * Checking if the media has been changed
-*/
-static int check_aztcd_media_change(struct gendisk *disk)
-{
- if (aztDiskChanged) { /* disk changed */
- aztDiskChanged = 0;
- return 1;
- } else
- return 0; /* no change */
-}
-
-/*
- * Kernel IO-controls
-*/
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- int i;
- struct azt_Toc qInfo;
- struct cdrom_ti ti;
- struct cdrom_tochdr tocHdr;
- struct cdrom_msf msf;
- struct cdrom_tocentry entry;
- struct azt_Toc *tocPtr;
- struct cdrom_subchnl subchnl;
- struct cdrom_volctrl volctrl;
- void __user *argp = (void __user *)arg;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n",
- cmd, jiffies);
- printk("aztcd Status %x\n", getAztStatus());
-#endif
- if (!ip)
- RETURNM("aztcd_ioctl 1", -EINVAL);
- if (getAztStatus() < 0)
- RETURNM("aztcd_ioctl 2", -EIO);
- if ((!aztTocUpToDate) || (aztDiskChanged)) {
- if ((i = aztUpdateToc()) < 0)
- RETURNM("aztcd_ioctl 3", i); /* error reading TOC */
- }
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive. Don't know, what to do,
- at least close the tray */
-#if AZT_PRIVATE_IOCTLS
- if (aztSendCmd(ACMD_CLOSE))
- RETURNM("aztcd_ioctl 4", -1);
- STEN_LOW_WAIT;
-#endif
- break;
- case CDROMSTOP: /* Spin down the drive */
- if (aztSendCmd(ACMD_STOP))
- RETURNM("aztcd_ioctl 5", -1);
- STEN_LOW_WAIT;
- /* should we do anything if it fails? */
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- break;
- case CDROMPAUSE: /* Pause the drive */
- if (aztAudioStatus != CDROM_AUDIO_PLAY)
- return -EINVAL;
-
- if (aztGetQChannelInfo(&qInfo) < 0) { /* didn't get q channel info */
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- RETURNM("aztcd_ioctl 7", 0);
- }
- azt_Play.start = qInfo.diskTime; /* remember restart point */
-
- if (aztSendCmd(ACMD_PAUSE))
- RETURNM("aztcd_ioctl 8", -1);
- STEN_LOW_WAIT;
- aztAudioStatus = CDROM_AUDIO_PAUSED;
- break;
- case CDROMRESUME: /* Play it again, Sam */
- if (aztAudioStatus != CDROM_AUDIO_PAUSED)
- return -EINVAL;
- /* restart the drive at the saved position. */
- i = aztPlay(&azt_Play);
- if (i < 0) {
- aztAudioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- aztAudioStatus = CDROM_AUDIO_PLAY;
- break;
- case CDROMMULTISESSION: /*multisession support -- experimental */
- {
- struct cdrom_multisession ms;
-#ifdef AZT_DEBUG
- printk("aztcd ioctl MULTISESSION\n");
-#endif
- if (copy_from_user(&ms, argp,
- sizeof(struct cdrom_multisession)))
- return -EFAULT;
- if (ms.addr_format == CDROM_MSF) {
- ms.addr.msf.minute =
- azt_bcd2bin(DiskInfo.lastSession.min);
- ms.addr.msf.second =
- azt_bcd2bin(DiskInfo.lastSession.sec);
- ms.addr.msf.frame =
- azt_bcd2bin(DiskInfo.lastSession.
- frame);
- } else if (ms.addr_format == CDROM_LBA)
- ms.addr.lba =
- azt_msf2hsg(&DiskInfo.lastSession);
- else
- return -EINVAL;
- ms.xa_flag = DiskInfo.xa;
- if (copy_to_user(argp, &ms,
- sizeof(struct cdrom_multisession)))
- return -EFAULT;
-#ifdef AZT_DEBUG
- if (ms.addr_format == CDROM_MSF)
- printk
- ("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
- ms.xa_flag, ms.addr.msf.minute,
- ms.addr.msf.second, ms.addr.msf.frame,
- DiskInfo.lastSession.min,
- DiskInfo.lastSession.sec,
- DiskInfo.lastSession.frame);
- else
- printk
- ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
- ms.xa_flag, ms.addr.lba,
- DiskInfo.lastSession.min,
- DiskInfo.lastSession.sec,
- DiskInfo.lastSession.frame);
-#endif
- return 0;
- }
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- if (copy_from_user(&ti, argp, sizeof ti))
- return -EFAULT;
- if (ti.cdti_trk0 < DiskInfo.first
- || ti.cdti_trk0 > DiskInfo.last
- || ti.cdti_trk1 < ti.cdti_trk0) {
- return -EINVAL;
- }
- if (ti.cdti_trk1 > DiskInfo.last)
- ti.cdti_trk1 = DiskInfo.last;
- azt_Play.start = Toc[ti.cdti_trk0].diskTime;
- azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
-#ifdef AZT_DEBUG
- printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- azt_Play.start.min, azt_Play.start.sec,
- azt_Play.start.frame, azt_Play.end.min,
- azt_Play.end.sec, azt_Play.end.frame);
-#endif
- i = aztPlay(&azt_Play);
- if (i < 0) {
- aztAudioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- aztAudioStatus = CDROM_AUDIO_PLAY;
- break;
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
-/* if (aztAudioStatus == CDROM_AUDIO_PLAY)
- { if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1);
- STEN_LOW;
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- }
-*/
- if (copy_from_user(&msf, argp, sizeof msf))
- return -EFAULT;
- /* convert to bcd */
- azt_bin2bcd(&msf.cdmsf_min0);
- azt_bin2bcd(&msf.cdmsf_sec0);
- azt_bin2bcd(&msf.cdmsf_frame0);
- azt_bin2bcd(&msf.cdmsf_min1);
- azt_bin2bcd(&msf.cdmsf_sec1);
- azt_bin2bcd(&msf.cdmsf_frame1);
- azt_Play.start.min = msf.cdmsf_min0;
- azt_Play.start.sec = msf.cdmsf_sec0;
- azt_Play.start.frame = msf.cdmsf_frame0;
- azt_Play.end.min = msf.cdmsf_min1;
- azt_Play.end.sec = msf.cdmsf_sec1;
- azt_Play.end.frame = msf.cdmsf_frame1;
-#ifdef AZT_DEBUG
- printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- azt_Play.start.min, azt_Play.start.sec,
- azt_Play.start.frame, azt_Play.end.min,
- azt_Play.end.sec, azt_Play.end.frame);
-#endif
- i = aztPlay(&azt_Play);
- if (i < 0) {
- aztAudioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- aztAudioStatus = CDROM_AUDIO_PLAY;
- break;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- tocHdr.cdth_trk0 = DiskInfo.first;
- tocHdr.cdth_trk1 = DiskInfo.last;
- if (copy_to_user(argp, &tocHdr, sizeof tocHdr))
- return -EFAULT;
- break;
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- if (copy_from_user(&entry, argp, sizeof entry))
- return -EFAULT;
- if ((!aztTocUpToDate) || aztDiskChanged)
- aztUpdateToc();
- if (entry.cdte_track == CDROM_LEADOUT)
- tocPtr = &Toc[DiskInfo.last + 1];
- else if (entry.cdte_track > DiskInfo.last
- || entry.cdte_track < DiskInfo.first) {
- return -EINVAL;
- } else
- tocPtr = &Toc[entry.cdte_track];
- entry.cdte_adr = tocPtr->ctrl_addr;
- entry.cdte_ctrl = tocPtr->ctrl_addr >> 4;
- if (entry.cdte_format == CDROM_LBA)
- entry.cdte_addr.lba =
- azt_msf2hsg(&tocPtr->diskTime);
- else if (entry.cdte_format == CDROM_MSF) {
- entry.cdte_addr.msf.minute =
- azt_bcd2bin(tocPtr->diskTime.min);
- entry.cdte_addr.msf.second =
- azt_bcd2bin(tocPtr->diskTime.sec);
- entry.cdte_addr.msf.frame =
- azt_bcd2bin(tocPtr->diskTime.frame);
- } else {
- return -EINVAL;
- }
- if (copy_to_user(argp, &entry, sizeof entry))
- return -EFAULT;
- break;
- case CDROMSUBCHNL: /* Get subchannel info */
- if (copy_from_user
- (&subchnl, argp, sizeof(struct cdrom_subchnl)))
- return -EFAULT;
- if (aztGetQChannelInfo(&qInfo) < 0) {
-#ifdef AZT_DEBUG
- printk
- ("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",
- cmd);
-#endif
- return -EIO;
- }
- subchnl.cdsc_audiostatus = aztAudioStatus;
- subchnl.cdsc_adr = qInfo.ctrl_addr;
- subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
- subchnl.cdsc_trk = azt_bcd2bin(qInfo.track);
- subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex);
- if (subchnl.cdsc_format == CDROM_LBA) {
- subchnl.cdsc_absaddr.lba =
- azt_msf2hsg(&qInfo.diskTime);
- subchnl.cdsc_reladdr.lba =
- azt_msf2hsg(&qInfo.trackTime);
- } else { /*default */
- subchnl.cdsc_format = CDROM_MSF;
- subchnl.cdsc_absaddr.msf.minute =
- azt_bcd2bin(qInfo.diskTime.min);
- subchnl.cdsc_absaddr.msf.second =
- azt_bcd2bin(qInfo.diskTime.sec);
- subchnl.cdsc_absaddr.msf.frame =
- azt_bcd2bin(qInfo.diskTime.frame);
- subchnl.cdsc_reladdr.msf.minute =
- azt_bcd2bin(qInfo.trackTime.min);
- subchnl.cdsc_reladdr.msf.second =
- azt_bcd2bin(qInfo.trackTime.sec);
- subchnl.cdsc_reladdr.msf.frame =
- azt_bcd2bin(qInfo.trackTime.frame);
- }
- if (copy_to_user(argp, &subchnl, sizeof(struct cdrom_subchnl)))
- return -EFAULT;
- break;
- case CDROMVOLCTRL: /* Volume control
- * With my Aztech CD268-01A volume control does not work, I can only
- turn the channels on (any value !=0) or off (value==0). Maybe it
- works better with your drive */
- if (copy_from_user(&volctrl, argp, sizeof(volctrl)))
- return -EFAULT;
- azt_Play.start.min = 0x21;
- azt_Play.start.sec = 0x84;
- azt_Play.start.frame = volctrl.channel0;
- azt_Play.end.min = volctrl.channel1;
- azt_Play.end.sec = volctrl.channel2;
- azt_Play.end.frame = volctrl.channel3;
- sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
- STEN_LOW_WAIT;
- break;
- case CDROMEJECT:
- aztUnlockDoor(); /* Assume user knows what they're doing */
- /* all drives can at least stop! */
- if (aztAudioStatus == CDROM_AUDIO_PLAY) {
- if (aztSendCmd(ACMD_STOP))
- RETURNM("azt_ioctl 10", -1);
- STEN_LOW_WAIT;
- }
- if (aztSendCmd(ACMD_EJECT))
- RETURNM("azt_ioctl 11", -1);
- STEN_LOW_WAIT;
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- break;
- case CDROMEJECT_SW:
- azt_auto_eject = (char) arg;
- break;
- case CDROMRESET:
- outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */
- STEN_LOW;
- if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */
- printk
- ("aztcd: AZTECH CD-ROM drive does not respond\n");
- }
- break;
-/*Take care, the following code is not compatible with other CD-ROM drivers,
- use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h,
- if you do not want to use it!
-*/
-#if AZT_PRIVATE_IOCTLS
- case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes) */
- case CDROMREADRAW: /*read data in mode 2 (2336 Bytes) */
- {
- if (copy_from_user(&msf, argp, sizeof msf))
- return -EFAULT;
- /* convert to bcd */
- azt_bin2bcd(&msf.cdmsf_min0);
- azt_bin2bcd(&msf.cdmsf_sec0);
- azt_bin2bcd(&msf.cdmsf_frame0);
- msf.cdmsf_min1 = 0;
- msf.cdmsf_sec1 = 0;
- msf.cdmsf_frame1 = 1; /*read only one frame */
- azt_Play.start.min = msf.cdmsf_min0;
- azt_Play.start.sec = msf.cdmsf_sec0;
- azt_Play.start.frame = msf.cdmsf_frame0;
- azt_Play.end.min = msf.cdmsf_min1;
- azt_Play.end.sec = msf.cdmsf_sec1;
- azt_Play.end.frame = msf.cdmsf_frame1;
- if (cmd == CDROMREADRAW) {
- if (DiskInfo.xa) {
- return -1; /*XA Disks can't be read raw */
- } else {
- if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play))
- return -1;
- DTEN_LOW;
- insb(DATA_PORT, buf, CD_FRAMESIZE_RAW);
- if (copy_to_user(argp, &buf, CD_FRAMESIZE_RAW))
- return -EFAULT;
- }
- } else
- /*CDROMREADCOOKED*/ {
- if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
- return -1;
- DTEN_LOW;
- insb(DATA_PORT, buf, CD_FRAMESIZE);
- if (copy_to_user(argp, &buf, CD_FRAMESIZE))
- return -EFAULT;
- }
- }
- break;
- case CDROMSEEK: /*seek msf address */
- if (copy_from_user(&msf, argp, sizeof msf))
- return -EFAULT;
- /* convert to bcd */
- azt_bin2bcd(&msf.cdmsf_min0);
- azt_bin2bcd(&msf.cdmsf_sec0);
- azt_bin2bcd(&msf.cdmsf_frame0);
- azt_Play.start.min = msf.cdmsf_min0;
- azt_Play.start.sec = msf.cdmsf_sec0;
- azt_Play.start.frame = msf.cdmsf_frame0;
- if (aztSeek(&azt_Play))
- return -1;
- break;
-#endif /*end of incompatible code */
- case CDROMREADMODE1: /*set read data in mode 1 */
- return aztSetDiskType(AZT_MODE_1);
- case CDROMREADMODE2: /*set read data in mode 2 */
- return aztSetDiskType(AZT_MODE_2);
- default:
- return -EINVAL;
- }
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n", cmd,
- jiffies);
-#endif
- return 0;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-static void azt_transfer(void)
-{
-#ifdef AZT_TEST
- printk("aztcd: executing azt_transfer Time:%li\n", jiffies);
-#endif
- if (!current_valid())
- return;
-
- while (CURRENT->nr_sectors) {
- int bn = CURRENT->sector / 4;
- int i;
- for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i);
- if (i < AZT_BUF_SIZ) {
- int offs = (i * 4 + (CURRENT->sector & 3)) * 512;
- int nr_sectors = 4 - (CURRENT->sector & 3);
- if (azt_buf_out != i) {
- azt_buf_out = i;
- if (azt_buf_bn[i] != bn) {
- azt_buf_out = -1;
- continue;
- }
- }
- if (nr_sectors > CURRENT->nr_sectors)
- nr_sectors = CURRENT->nr_sectors;
- memcpy(CURRENT->buffer, azt_buf + offs,
- nr_sectors * 512);
- CURRENT->nr_sectors -= nr_sectors;
- CURRENT->sector += nr_sectors;
- CURRENT->buffer += nr_sectors * 512;
- } else {
- azt_buf_out = -1;
- break;
- }
- }
-}
-
-static void do_aztcd_request(request_queue_t * q)
-{
-#ifdef AZT_TEST
- printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector,
- CURRENT->nr_sectors, jiffies);
-#endif
- if (DiskInfo.audio) {
- printk("aztcd: Error, tried to mount an Audio CD\n");
- end_request(CURRENT, 0);
- return;
- }
- azt_transfer_is_active = 1;
- while (current_valid()) {
- azt_transfer();
- if (CURRENT->nr_sectors == 0) {
- end_request(CURRENT, 1);
- } else {
- azt_buf_out = -1; /* Want to read a block not in buffer */
- if (azt_state == AZT_S_IDLE) {
- if ((!aztTocUpToDate) || aztDiskChanged) {
- if (aztUpdateToc() < 0) {
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- }
- azt_state = AZT_S_START;
- AztTries = 5;
- SET_TIMER(azt_poll, HZ / 100);
- }
- break;
- }
- }
- azt_transfer_is_active = 0;
-#ifdef AZT_TEST2
- printk
- ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n",
- azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
- printk(" do_aztcd_request ends Time:%li\n", jiffies);
-#endif
-}
-
-
-static void azt_invalidate_buffers(void)
-{
- int i;
-
-#ifdef AZT_DEBUG
- printk("aztcd: executing azt_invalidate_buffers\n");
-#endif
- for (i = 0; i < AZT_BUF_SIZ; ++i)
- azt_buf_bn[i] = -1;
- azt_buf_out = -1;
-}
-
-/*
- * Open the device special file. Check that a disk is in.
- */
-static int aztcd_open(struct inode *ip, struct file *fp)
-{
- int st;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztcd_open\n");
-#endif
-
- if (aztPresent == 0)
- return -ENXIO; /* no hardware */
-
- if (!azt_open_count && azt_state == AZT_S_IDLE) {
- azt_invalidate_buffers();
-
- st = getAztStatus(); /* check drive status */
- if (st == -1)
- goto err_out; /* drive doesn't respond */
-
- if (st & AST_DOOR_OPEN) { /* close door, then get the status again. */
- printk("aztcd: Door Open?\n");
- aztCloseDoor();
- st = getAztStatus();
- }
-
- if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) { /*no disk in drive or changed */
- printk
- ("aztcd: Disk Changed or No Disk in Drive?\n");
- aztTocUpToDate = 0;
- }
- if (aztUpdateToc())
- goto err_out;
-
- }
- ++azt_open_count;
- aztLockDoor();
-
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztcd_open\n");
-#endif
- return 0;
-
- err_out:
- return -EIO;
-}
-
-
-/*
- * On close, we flush all azt blocks from the buffer cache.
- */
-static int aztcd_release(struct inode *inode, struct file *file)
-{
-#ifdef AZT_DEBUG
- printk("aztcd: executing aztcd_release\n");
- printk("inode: %p, device: %s file: %p\n", inode,
- inode->i_bdev->bd_disk->disk_name, file);
-#endif
- if (!--azt_open_count) {
- azt_invalidate_buffers();
- aztUnlockDoor();
- if (azt_auto_eject)
- aztSendCmd(ACMD_EJECT);
- CLEAR_TIMER;
- }
- return 0;
-}
-
-static struct gendisk *azt_disk;
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- */
-
-static int __init aztcd_init(void)
-{
- long int count, max_count;
- unsigned char result[50];
- int st;
- void* status = NULL;
- int i = 0;
- int ret = 0;
-
- if (azt_port == 0) {
- printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization");
- return -EIO;
- }
-
- printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM "
- "CD-ROM Driver\n");
- printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n");
- if (azt_port == -1) {
- printk
- ("aztcd: DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",
- AZT_VERSION);
- } else
- printk
- ("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",
- AZT_VERSION, azt_port);
- printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/"
- "Documentation/cdrom/aztcd\n");
-
-
-#ifdef AZT_SW32 /*CDROM connected to Soundwave32 card */
- if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) {
- printk
- ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
- AZT_SW32_BASE_ADDR, AZT_SW32_INIT,
- AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG);
- return -EIO;
- } else {
- printk(KERN_INFO
- "aztcd: Soundwave32 card detected at %x Version %x\n",
- AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG));
- outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG);
- for (count = 0; count < 10000; count++); /*delay a bit */
- }
-#endif
-
- /* check for presence of drive */
-
- if (azt_port == -1) { /* autoprobing for proprietary interface */
- for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) {
- azt_port = azt_port_auto[i];
- printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x"
- "\n", azt_port);
- /*proprietary interfaces need 4 bytes */
- if (!request_region(azt_port, 4, "aztcd")) {
- continue;
- }
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */
-
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break;
- } while (aztIndatum & AFL_STATUS);
- if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */
- break;
- }
- else { /* Drive not found on this port - try next one */
- release_region(azt_port, 4);
- }
- }
- if ((i == 16) || (azt_port_auto[i] == 0)) {
- printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
- return -EIO;
- }
- } else { /* no autoprobing */
- if ((azt_port == 0x1f0) || (azt_port == 0x170))
- status = request_region(azt_port, 8, "aztcd"); /*IDE-interfaces need 8 bytes */
- else
- status = request_region(azt_port, 4, "aztcd"); /*proprietary interfaces need 4 bytes */
- if (!status) {
- printk(KERN_WARNING "aztcd: conflict, I/O port (%X) "
- "already used\n", azt_port);
- return -EIO;
- }
-
- if ((azt_port == 0x1f0) || (azt_port == 0x170))
- SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */
-
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */
-
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break;
- } while (aztIndatum & AFL_STATUS);
-
- if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? If not, reset and try again */
-#ifndef MODULE
- if (azt_cont != 0x79) {
- printk(KERN_WARNING "aztcd: no AZTECH CD-ROM "
- "drive found-Try boot parameter aztcd="
- "<BaseAddress>,0x79\n");
- ret = -EIO;
- goto err_out;
- }
-#else
- if (0) {
- }
-#endif
- else {
- printk(KERN_INFO "aztcd: drive reset - "
- "please wait\n");
- for (count = 0; count < 50; count++) {
- inb(STATUS_PORT); /*removing all data from earlier tries */
- inb(DATA_PORT);
- }
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- getAztStatus(); /*trap errors */
- outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */
- STEN_LOW;
- if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */
- printk(KERN_WARNING "aztcd: no AZTECH "
- "CD-ROM drive found\n");
- ret = -EIO;
- goto err_out;
- }
-
- for (count = 0; count < AZT_TIMEOUT;
- count++)
- barrier(); /* Stop gcc 2.96 being smart */
- /* use udelay(), damnit -- AV */
-
- if ((st = getAztStatus()) == -1) {
- printk(KERN_WARNING "aztcd: Drive Status"
- " Error Status=%x\n", st);
- ret = -EIO;
- goto err_out;
- }
-#ifdef AZT_DEBUG
- printk(KERN_DEBUG "aztcd: Status = %x\n", st);
-#endif
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION, CMD_PORT); /*GetVersion */
- STEN_LOW;
- OP_OK;
- }
- }
- }
-
- azt_init_end = 1;
- STEN_LOW;
- result[0] = inb(DATA_PORT); /*reading in a null byte??? */
- for (count = 1; count < 50; count++) { /*Reading version string */
- aztTimeOutCount = 0; /*here we must implement STEN_LOW differently */
- do {
- aztIndatum = inb(STATUS_PORT); /*because we want to exit by timeout */
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break;
- } while (aztIndatum & AFL_STATUS);
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break; /*all chars read? */
- result[count] = inb(DATA_PORT);
- }
- if (count > 30)
- max_count = 30; /*print max.30 chars of the version string */
- else
- max_count = count;
- printk(KERN_INFO "aztcd: FirmwareVersion=");
- for (count = 1; count < max_count; count++)
- printk("%c", result[count]);
- printk("<<>> ");
-
- if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) {
- printk("AZTECH drive detected\n");
- /*AZTECH*/}
- else if ((result[2] == 'C') && (result[3] == 'D')
- && (result[4] == 'D')) {
- printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES */
- } else if ((result[1] == 0x03) && (result[2] == '5')) {
- printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM */
- } else { /*OTHERS or none */
- printk("\nunknown drive or firmware version detected\n");
- printk
- ("aztcd may not run stable, if you want to try anyhow,\n");
- printk("boot with: aztcd=<BaseAddress>,0x79\n");
- if ((azt_cont != 0x79)) {
- printk("aztcd: FirmwareVersion=");
- for (count = 1; count < 5; count++)
- printk("%c", result[count]);
- printk("<<>> ");
- printk("Aborted\n");
- ret = -EIO;
- goto err_out;
- }
- }
- azt_disk = alloc_disk(1);
- if (!azt_disk)
- goto err_out;
-
- if (register_blkdev(MAJOR_NR, "aztcd")) {
- ret = -EIO;
- goto err_out2;
- }
-
- azt_queue = blk_init_queue(do_aztcd_request, &aztSpin);
- if (!azt_queue) {
- ret = -ENOMEM;
- goto err_out3;
- }
-
- blk_queue_hardsect_size(azt_queue, 2048);
- azt_disk->major = MAJOR_NR;
- azt_disk->first_minor = 0;
- azt_disk->fops = &azt_fops;
- sprintf(azt_disk->disk_name, "aztcd");
- azt_disk->queue = azt_queue;
- add_disk(azt_disk);
- azt_invalidate_buffers();
- aztPresent = 1;
- aztCloseDoor();
- return 0;
-err_out3:
- unregister_blkdev(MAJOR_NR, "aztcd");
-err_out2:
- put_disk(azt_disk);
-err_out:
- if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
- SWITCH_IDE_MASTER;
- release_region(azt_port, 8); /*IDE-interface */
- } else
- release_region(azt_port, 4); /*proprietary interface */
- return ret;
-
-}
-
-static void __exit aztcd_exit(void)
-{
- del_gendisk(azt_disk);
- put_disk(azt_disk);
- if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
- printk("What's that: can't unregister aztcd\n");
- return;
- }
- blk_cleanup_queue(azt_queue);
- if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
- SWITCH_IDE_MASTER;
- release_region(azt_port, 8); /*IDE-interface */
- } else
- release_region(azt_port, 4); /*proprietary interface */
- printk(KERN_INFO "aztcd module released.\n");
-}
-
-module_init(aztcd_init);
-module_exit(aztcd_exit);
-
-/*##########################################################################
- Aztcd State Machine: Controls Drive Operating State
- ##########################################################################
-*/
-static void azt_poll(void)
-{
- int st = 0;
- int loop_ctl = 1;
- int skip = 0;
-
- if (azt_error) {
- if (aztSendCmd(ACMD_GET_ERROR))
- RETURN("azt_poll 1");
- STEN_LOW;
- azt_error = inb(DATA_PORT) & 0xFF;
- printk("aztcd: I/O error 0x%02x\n", azt_error);
- azt_invalidate_buffers();
-#ifdef WARN_IF_READ_FAILURE
- if (AztTries == 5)
- printk
- ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n",
- azt_next_bn);
-#endif
- if (!AztTries--) {
- printk
- ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n",
- azt_next_bn);
- if (azt_transfer_is_active) {
- AztTries = 0;
- loop_ctl = 0;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- AztTries = 5;
- }
- azt_error = 0;
- azt_state = AZT_S_STOP;
- }
-
- while (loop_ctl) {
- loop_ctl = 0; /* each case must flip this back to 1 if we want
- to come back up here */
- switch (azt_state) {
-
- case AZT_S_IDLE:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_IDLE\n");
- }
-#endif
- return;
-
- case AZT_S_START:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_START\n");
- }
-#endif
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURN("azt_poll 2"); /*result will be checked by aztStatus() */
- azt_state =
- azt_mode == 1 ? AZT_S_READ : AZT_S_MODE;
- AztTimeout = 3000;
- break;
-
- case AZT_S_MODE:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_MODE\n");
- }
-#endif
- if (!skip) {
- if ((st = aztStatus()) != -1) {
- if ((st & AST_DSK_CHG)
- || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- azt_invalidate_buffers();
- end_request(CURRENT, 0);
- printk
- ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n");
- }
- } else
- break;
- }
- skip = 0;
-
- if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- printk
- ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n");
- end_request(CURRENT, 0);
- printk((st & AST_DOOR_OPEN) ?
- "aztcd: door open\n" :
- "aztcd: disk removed\n");
- if (azt_transfer_is_active) {
- azt_state = AZT_S_START;
- loop_ctl = 1; /* goto immediately */
- break;
- }
- azt_state = AZT_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
-
-/* if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3");
- outb(0x01, DATA_PORT);
- PA_OK;
- STEN_LOW;
-*/
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURN("azt_poll 4");
- STEN_LOW;
- azt_mode = 1;
- azt_state = AZT_S_READ;
- AztTimeout = 3000;
-
- break;
-
-
- case AZT_S_READ:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_READ\n");
- }
-#endif
- if (!skip) {
- if ((st = aztStatus()) != -1) {
- if ((st & AST_DSK_CHG)
- || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- azt_invalidate_buffers();
- printk
- ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n");
- end_request(CURRENT, 0);
- }
- } else
- break;
- }
-
- skip = 0;
- if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- printk((st & AST_DOOR_OPEN) ?
- "aztcd: door open\n" :
- "aztcd: disk removed\n");
- if (azt_transfer_is_active) {
- azt_state = AZT_S_START;
- loop_ctl = 1;
- break;
- }
- azt_state = AZT_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
-
- if (current_valid()) {
- struct azt_Play_msf msf;
- int i;
- azt_next_bn = CURRENT->sector / 4;
- azt_hsg2msf(azt_next_bn, &msf.start);
- i = 0;
- /* find out in which track we are */
- while (azt_msf2hsg(&msf.start) >
- azt_msf2hsg(&Toc[++i].trackTime)) {
- };
- if (azt_msf2hsg(&msf.start) <
- azt_msf2hsg(&Toc[i].trackTime) -
- AZT_BUF_SIZ) {
- azt_read_count = AZT_BUF_SIZ; /*fast, because we read ahead */
- /*azt_read_count=CURRENT->nr_sectors; slow, no read ahead */
- } else /* don't read beyond end of track */
-#if AZT_MULTISESSION
- {
- azt_read_count =
- (azt_msf2hsg(&Toc[i].trackTime)
- / 4) * 4 -
- azt_msf2hsg(&msf.start);
- if (azt_read_count < 0)
- azt_read_count = 0;
- if (azt_read_count > AZT_BUF_SIZ)
- azt_read_count =
- AZT_BUF_SIZ;
- printk
- ("aztcd: warning - trying to read beyond end of track\n");
-/* printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime));
-*/ }
-#else
- {
- azt_read_count = AZT_BUF_SIZ;
- }
-#endif
- msf.end.min = 0;
- msf.end.sec = 0;
- msf.end.frame = azt_read_count; /*Mitsumi here reads 0xffffff sectors */
-#ifdef AZT_TEST3
- printk
- ("---reading msf-address %x:%x:%x %x:%x:%x\n",
- msf.start.min, msf.start.sec,
- msf.start.frame, msf.end.min,
- msf.end.sec, msf.end.frame);
- printk
- ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n",
- azt_next_bn, azt_buf_in, azt_buf_out,
- azt_buf_bn[azt_buf_in]);
-#endif
- if (azt_read_mode == AZT_MODE_2) {
- sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode */
- } else {
- sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode */
- }
- azt_state = AZT_S_DATA;
- AztTimeout = READ_TIMEOUT;
- } else {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
-
- break;
-
-
- case AZT_S_DATA:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_DATA\n");
- }
-#endif
-
- st = inb(STATUS_PORT) & AFL_STATUSorDATA;
-
- switch (st) {
-
- case AFL_DATA:
-#ifdef AZT_TEST3
- if (st != azt_st_old) {
- azt_st_old = st;
- printk("---AFL_DATA st:%x\n", st);
- }
-#endif
- if (!AztTries--) {
- printk
- ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n",
- azt_next_bn);
- if (azt_transfer_is_active) {
- AztTries = 0;
- break;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- AztTries = 5;
- }
- azt_state = AZT_S_START;
- AztTimeout = READ_TIMEOUT;
- loop_ctl = 1;
- break;
-
- case AFL_STATUSorDATA:
-#ifdef AZT_TEST3
- if (st != azt_st_old) {
- azt_st_old = st;
- printk
- ("---AFL_STATUSorDATA st:%x\n",
- st);
- }
-#endif
- break;
-
- default:
-#ifdef AZT_TEST3
- if (st != azt_st_old) {
- azt_st_old = st;
- printk("---default: st:%x\n", st);
- }
-#endif
- AztTries = 5;
- if (!current_valid() && azt_buf_in == azt_buf_out) {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
- if (azt_read_count <= 0)
- printk
- ("aztcd: warning - try to read 0 frames\n");
- while (azt_read_count) { /*??? fast read ahead loop */
- azt_buf_bn[azt_buf_in] = -1;
- DTEN_LOW; /*??? unsolved problem, very
- seldom we get timeouts
- here, don't now the real
- reason. With my drive this
- sometimes also happens with
- Aztech's original driver under
- DOS. Is it a hardware bug?
- I tried to recover from such
- situations here. Zimmermann */
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk
- ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n",
- azt_read_count,
- CURRENT->nr_sectors,
- azt_buf_in);
- printk
- ("azt_transfer_is_active:%x\n",
- azt_transfer_is_active);
- azt_read_count = 0;
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- end_request(CURRENT, 1); /*should we have here (1) or (0)? */
- } else {
- if (azt_read_mode ==
- AZT_MODE_2) {
- insb(DATA_PORT,
- azt_buf +
- CD_FRAMESIZE_RAW
- * azt_buf_in,
- CD_FRAMESIZE_RAW);
- } else {
- insb(DATA_PORT,
- azt_buf +
- CD_FRAMESIZE *
- azt_buf_in,
- CD_FRAMESIZE);
- }
- azt_read_count--;
-#ifdef AZT_TEST3
- printk
- ("AZT_S_DATA; ---I've read data- read_count: %d\n",
- azt_read_count);
- printk
- ("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n",
- azt_next_bn,
- azt_buf_in,
- azt_buf_out,
- azt_buf_bn
- [azt_buf_in]);
-#endif
- azt_buf_bn[azt_buf_in] =
- azt_next_bn++;
- if (azt_buf_out == -1)
- azt_buf_out =
- azt_buf_in;
- azt_buf_in =
- azt_buf_in + 1 ==
- AZT_BUF_SIZ ? 0 :
- azt_buf_in + 1;
- }
- }
- if (!azt_transfer_is_active) {
- while (current_valid()) {
- azt_transfer();
- if (CURRENT->nr_sectors ==
- 0)
- end_request(CURRENT, 1);
- else
- break;
- }
- }
-
- if (current_valid()
- && (CURRENT->sector / 4 < azt_next_bn
- || CURRENT->sector / 4 >
- azt_next_bn + AZT_BUF_SIZ)) {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
- AztTimeout = READ_TIMEOUT;
- if (azt_read_count == 0) {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
- break;
- }
- break;
-
-
- case AZT_S_STOP:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_STOP\n");
- }
-#endif
- if (azt_read_count != 0)
- printk("aztcd: discard data=%x frames\n",
- azt_read_count);
- while (azt_read_count != 0) {
- int i;
- if (!(inb(STATUS_PORT) & AFL_DATA)) {
- if (azt_read_mode == AZT_MODE_2)
- for (i = 0;
- i < CD_FRAMESIZE_RAW;
- i++)
- inb(DATA_PORT);
- else
- for (i = 0;
- i < CD_FRAMESIZE; i++)
- inb(DATA_PORT);
- }
- azt_read_count--;
- }
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURN("azt_poll 5");
- azt_state = AZT_S_STOPPING;
- AztTimeout = 1000;
- break;
-
- case AZT_S_STOPPING:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_STOPPING\n");
- }
-#endif
-
- if ((st = aztStatus()) == -1 && AztTimeout)
- break;
-
- if ((st != -1)
- && ((st & AST_DSK_CHG)
- || (st & AST_NOT_READY))) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- azt_invalidate_buffers();
- printk
- ("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n");
- end_request(CURRENT, 0);
- }
-
-#ifdef AZT_TEST3
- printk("CURRENT_VALID %d azt_mode %d\n",
- current_valid(), azt_mode);
-#endif
-
- if (current_valid()) {
- if (st != -1) {
- if (azt_mode == 1) {
- azt_state = AZT_S_READ;
- loop_ctl = 1;
- skip = 1;
- break;
- } else {
- azt_state = AZT_S_MODE;
- loop_ctl = 1;
- skip = 1;
- break;
- }
- } else {
- azt_state = AZT_S_START;
- AztTimeout = 1;
- }
- } else {
- azt_state = AZT_S_IDLE;
- return;
- }
- break;
-
- default:
- printk("aztcd: invalid state %d\n", azt_state);
- return;
- } /* case */
- } /* while */
-
-
- if (!AztTimeout--) {
- printk("aztcd: timeout in state %d\n", azt_state);
- azt_state = AZT_S_STOP;
- if (aztSendCmd(ACMD_STOP))
- RETURN("azt_poll 6");
- STEN_LOW_WAIT;
- };
-
- SET_TIMER(azt_poll, HZ / 100);
-}
-
-
-/*###########################################################################
- * Miscellaneous support functions
- ###########################################################################
-*/
-static void azt_hsg2msf(long hsg, struct msf *msf)
-{
- hsg += 150;
- msf->min = hsg / 4500;
- hsg %= 4500;
- msf->sec = hsg / 75;
- msf->frame = hsg % 75;
-#ifdef AZT_DEBUG
- if (msf->min >= 70)
- printk("aztcd: Error hsg2msf address Minutes\n");
- if (msf->sec >= 60)
- printk("aztcd: Error hsg2msf address Seconds\n");
- if (msf->frame >= 75)
- printk("aztcd: Error hsg2msf address Frames\n");
-#endif
- azt_bin2bcd(&msf->min); /* convert to BCD */
- azt_bin2bcd(&msf->sec);
- azt_bin2bcd(&msf->frame);
-}
-
-static long azt_msf2hsg(struct msf *mp)
-{
- return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75
- + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET;
-}
-
-static void azt_bin2bcd(unsigned char *p)
-{
- int u, t;
-
- u = *p % 10;
- t = *p / 10;
- *p = u | (t << 4);
-}
-
-static int azt_bcd2bin(unsigned char bcd)
-{
- return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR);
diff --git a/drivers/cdrom/aztcd.h b/drivers/cdrom/aztcd.h
deleted file mode 100644
index 057501e3162..00000000000
--- a/drivers/cdrom/aztcd.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* $Id: aztcd.h,v 2.60 1997/11/29 09:51:22 root Exp root $
- *
- * Definitions for a AztechCD268 CD-ROM interface
- * Copyright (C) 1994-98 Werner Zimmermann
- *
- * based on Mitsumi CDROM driver by Martin Harriss
- *
- * 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.
- *
- * History: W.Zimmermann adaption to Aztech CD268-01A Version 1.3
- * October 1994 Email: Werner.Zimmermann@fht-esslingen.de
- */
-
-/* *** change this to set the I/O port address of your CD-ROM drive,
- set to '-1', if you want autoprobing */
-#define AZT_BASE_ADDR -1
-
-/* list of autoprobing addresses (not more than 15), last value must be 0x000
- Note: Autoprobing is only enabled, if AZT_BASE_ADDR is set to '-1' ! */
-#define AZT_BASE_AUTO { 0x320, 0x300, 0x310, 0x330, 0x000 }
-
-/* Uncomment this, if your CDROM is connected to a Soundwave32-soundcard
- and configure AZT_BASE_ADDR and AZT_SW32_BASE_ADDR */
-/*#define AZT_SW32 1
-*/
-
-#ifdef AZT_SW32
-#define AZT_SW32_BASE_ADDR 0x220 /*I/O port base address of your soundcard*/
-#endif
-
-/* Set this to 1, if you want your tray to be locked, set to 0 to prevent tray
- from locking */
-#define AZT_ALLOW_TRAY_LOCK 1
-
-/*Set this to 1 to allow auto-eject when unmounting a disk, set to 0, if you
- don't want the auto-eject feature*/
-#define AZT_AUTO_EJECT 0
-
-/*Set this to 1, if you want to use incompatible ioctls for reading in raw and
- cooked mode */
-#define AZT_PRIVATE_IOCTLS 1
-
-/*Set this to 1, if you want multisession support by the ISO fs. Even if you set
- this value to '0' you can use multisession CDs. In that case the drive's firm-
- ware will do the appropriate redirection automatically. The CD will then look
- like a single session CD (but nevertheless all data may be read). Please read
- chapter '5.1 Multisession support' in README.aztcd for details. Normally it's
- uncritical to leave this setting untouched */
-#define AZT_MULTISESSION 1
-
-/*Uncomment this, if you are using a linux kernel version prior to 2.1.0 */
-/*#define AZT_KERNEL_PRIOR_2_1 */
-
-/*---------------------------------------------------------------------------*/
-/*-----nothing to be configured for normal applications below this line------*/
-
-
-/* Increase this if you get lots of timeouts; if you get kernel panic, replace
- STEN_LOW_WAIT by STEN_LOW in the source code */
-#define AZT_STATUS_DELAY 400 /*for timer wait, STEN_LOW_WAIT*/
-#define AZT_TIMEOUT 8000000 /*for busy wait STEN_LOW, DTEN_LOW*/
-#define AZT_FAST_TIMEOUT 10000 /*for reading the version string*/
-
-/* number of times to retry a command before giving up */
-#define AZT_RETRY_ATTEMPTS 3
-
-/* port access macros */
-#define CMD_PORT azt_port
-#define DATA_PORT azt_port
-#define STATUS_PORT azt_port+1
-#define MODE_PORT azt_port+2
-#ifdef AZT_SW32
- #define AZT_SW32_INIT (unsigned int) (0xFF00 & (AZT_BASE_ADDR*16))
- #define AZT_SW32_CONFIG_REG AZT_SW32_BASE_ADDR+0x16 /*Soundwave32 Config. Register*/
- #define AZT_SW32_ID_REG AZT_SW32_BASE_ADDR+0x04 /*Soundwave32 ID Version Register*/
-#endif
-
-/* status bits */
-#define AST_CMD_CHECK 0x80 /* 1 = command error */
-#define AST_DOOR_OPEN 0x40 /* 1 = door is open */
-#define AST_NOT_READY 0x20 /* 1 = no disk in the drive */
-#define AST_DSK_CHG 0x02 /* 1 = disk removed or changed */
-#define AST_MODE 0x01 /* 0=MODE1, 1=MODE2 */
-#define AST_MODE_BITS 0x1C /* Mode Bits */
-#define AST_INITIAL 0x0C /* initial, only valid ... */
-#define AST_BUSY 0x04 /* now playing, only valid
- in combination with mode
- bits */
-/* flag bits */
-#define AFL_DATA 0x02 /* data available if low */
-#define AFL_STATUS 0x04 /* status available if low */
-#define AFL_OP_OK 0x01 /* OP_OK command correct*/
-#define AFL_PA_OK 0x02 /* PA_OK parameter correct*/
-#define AFL_OP_ERR 0x05 /* error in command*/
-#define AFL_PA_ERR 0x06 /* error in parameters*/
-#define POLLED 0x04 /* polled mode */
-
-/* commands */
-#define ACMD_SOFT_RESET 0x10 /* reset drive */
-#define ACMD_PLAY_READ 0x20 /* read data track in cooked mode */
-#define ACMD_PLAY_READ_RAW 0x21 /* reading in raw mode*/
-#define ACMD_SEEK 0x30 /* seek msf address*/
-#define ACMD_SEEK_TO_LEADIN 0x31 /* seek to leadin track*/
-#define ACMD_GET_ERROR 0x40 /* get error code */
-#define ACMD_GET_STATUS 0x41 /* get status */
-#define ACMD_GET_Q_CHANNEL 0x50 /* read info from q channel */
-#define ACMD_EJECT 0x60 /* eject/open tray */
-#define ACMD_CLOSE 0x61 /* close tray */
-#define ACMD_LOCK 0x71 /* lock tray closed */
-#define ACMD_UNLOCK 0x72 /* unlock tray */
-#define ACMD_PAUSE 0x80 /* pause */
-#define ACMD_STOP 0x81 /* stop play */
-#define ACMD_PLAY_AUDIO 0x90 /* play audio track */
-#define ACMD_SET_VOLUME 0x93 /* set audio level */
-#define ACMD_GET_VERSION 0xA0 /* get firmware version */
-#define ACMD_SET_DISK_TYPE 0xA1 /* set disk data mode */
-
-#define MAX_TRACKS 104
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct azt_Play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct azt_DiskInfo {
- unsigned char first;
- unsigned char next;
- unsigned char last;
- struct msf diskLength;
- struct msf firstTrack;
- unsigned char multi;
- struct msf nextSession;
- struct msf lastSession;
- unsigned char xa;
- unsigned char audio;
-};
-
-struct azt_Toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char pointIndex;
- struct msf trackTime;
- struct msf diskTime;
-};
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 3625a05bc3d..aa5468f487b 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -302,7 +302,7 @@ module_param(lockdoor, bool, 0);
module_param(check_media_type, bool, 0);
module_param(mrw_format_restart, bool, 0);
-static DEFINE_SPINLOCK(cdrom_lock);
+static DEFINE_MUTEX(cdrom_mutex);
static const char *mrw_format_status[] = {
"not mrw",
@@ -438,10 +438,10 @@ int register_cdrom(struct cdrom_device_info *cdi)
cdo->generic_packet = cdrom_dummy_generic_packet;
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
- spin_lock(&cdrom_lock);
+ mutex_lock(&cdrom_mutex);
cdi->next = topCdromPtr;
topCdromPtr = cdi;
- spin_unlock(&cdrom_lock);
+ mutex_unlock(&cdrom_mutex);
return 0;
}
#undef ENSURE
@@ -452,7 +452,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
cdinfo(CD_OPEN, "entering unregister_cdrom\n");
prev = NULL;
- spin_lock(&cdrom_lock);
+ mutex_lock(&cdrom_mutex);
cdi = topCdromPtr;
while (cdi && cdi != unreg) {
prev = cdi;
@@ -460,7 +460,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
}
if (cdi == NULL) {
- spin_unlock(&cdrom_lock);
+ mutex_unlock(&cdrom_mutex);
return -2;
}
if (prev)
@@ -468,7 +468,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
else
topCdromPtr = cdi->next;
- spin_unlock(&cdrom_lock);
+ mutex_unlock(&cdrom_mutex);
if (cdi->exit)
cdi->exit(cdi);
@@ -3289,103 +3289,137 @@ static struct cdrom_sysctl_settings {
int check; /* check media type */
} cdrom_sysctl_settings;
+enum cdrom_print_option {
+ CTL_NAME,
+ CTL_SPEED,
+ CTL_SLOTS,
+ CTL_CAPABILITY
+};
+
+static int cdrom_print_info(const char *header, int val, char *info,
+ int *pos, enum cdrom_print_option option)
+{
+ const int max_size = sizeof(cdrom_sysctl_settings.info);
+ struct cdrom_device_info *cdi;
+ int ret;
+
+ ret = scnprintf(info + *pos, max_size - *pos, header);
+ if (!ret)
+ return 1;
+
+ *pos += ret;
+
+ for (cdi = topCdromPtr; cdi; cdi = cdi->next) {
+ switch (option) {
+ case CTL_NAME:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%s", cdi->name);
+ break;
+ case CTL_SPEED:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%d", cdi->speed);
+ break;
+ case CTL_SLOTS:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%d", cdi->capacity);
+ break;
+ case CTL_CAPABILITY:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%d", CDROM_CAN(val) != 0);
+ break;
+ default:
+ printk(KERN_INFO "cdrom: invalid option%d\n", option);
+ return 1;
+ }
+ if (!ret)
+ return 1;
+ *pos += ret;
+ }
+
+ return 0;
+}
+
static int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- int pos;
- struct cdrom_device_info *cdi;
+ int pos;
char *info = cdrom_sysctl_settings.info;
+ const int max_size = sizeof(cdrom_sysctl_settings.info);
if (!*lenp || (*ppos && !write)) {
*lenp = 0;
return 0;
}
+ mutex_lock(&cdrom_mutex);
+
pos = sprintf(info, "CD-ROM information, " VERSION "\n");
- pos += sprintf(info+pos, "\ndrive name:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%s", cdi->name);
-
- pos += sprintf(info+pos, "\ndrive speed:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", cdi->speed);
-
- pos += sprintf(info+pos, "\ndrive # of slots:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", cdi->capacity);
-
- pos += sprintf(info+pos, "\nCan close tray:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0);
-
- pos += sprintf(info+pos, "\nCan open tray:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0);
-
- pos += sprintf(info+pos, "\nCan lock tray:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0);
-
- pos += sprintf(info+pos, "\nCan change speed:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0);
-
- pos += sprintf(info+pos, "\nCan select disk:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0);
-
- pos += sprintf(info+pos, "\nCan read multisession:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0);
-
- pos += sprintf(info+pos, "\nCan read MCN:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0);
-
- pos += sprintf(info+pos, "\nReports media changed:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0);
-
- pos += sprintf(info+pos, "\nCan play audio:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0);
-
- pos += sprintf(info+pos, "\nCan write CD-R:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0);
-
- pos += sprintf(info+pos, "\nCan write CD-RW:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0);
-
- pos += sprintf(info+pos, "\nCan read DVD:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0);
-
- pos += sprintf(info+pos, "\nCan write DVD-R:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0);
-
- pos += sprintf(info+pos, "\nCan write DVD-RAM:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
-
- pos += sprintf(info+pos, "\nCan read MRW:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0);
-
- pos += sprintf(info+pos, "\nCan write MRW:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0);
-
- pos += sprintf(info+pos, "\nCan write RAM:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
-
- strcpy(info+pos,"\n\n");
-
- return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+ if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME))
+ goto done;
+ if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED))
+ goto done;
+ if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS))
+ goto done;
+ if (cdrom_print_info("\nCan close tray:\t",
+ CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan open tray:\t",
+ CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan lock tray:\t",
+ CDC_LOCK, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan change speed:",
+ CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan select disk:",
+ CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read multisession:",
+ CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read MCN:\t",
+ CDC_MCN, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nReports media changed:",
+ CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan play audio:\t",
+ CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write CD-R:\t",
+ CDC_CD_R, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write CD-RW:",
+ CDC_CD_RW, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read DVD:\t",
+ CDC_DVD, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write DVD-R:",
+ CDC_DVD_R, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write DVD-RAM:",
+ CDC_DVD_RAM, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read MRW:\t",
+ CDC_MRW, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write MRW:\t",
+ CDC_MRW_W, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write RAM:\t",
+ CDC_RAM, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (!scnprintf(info + pos, max_size - pos, "\n\n"))
+ goto done;
+doit:
+ mutex_unlock(&cdrom_mutex);
+ return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+done:
+ printk(KERN_INFO "cdrom: info buffer too small\n");
+ goto doit;
}
/* Unfortunately, per device settings are not implemented through
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
deleted file mode 100644
index 2157c58755e..00000000000
--- a/drivers/cdrom/cdu31a.c
+++ /dev/null
@@ -1,3251 +0,0 @@
-/*
-* Sony CDU-31A CDROM interface device driver.
-*
-* Corey Minyard (minyard@wf-rch.cirr.com)
-*
-* Colossians 3:17
-*
-* See Documentation/cdrom/cdu31a for additional details about this driver.
-*
-* The Sony interface device driver handles Sony interface CDROM
-* drives and provides a complete block-level interface as well as an
-* ioctl() interface compatible with the Sun (as specified in
-* include/linux/cdrom.h). With this interface, CDROMs can be
-* accessed and standard audio CDs can be played back normally.
-*
-* WARNING - All autoprobes have been removed from the driver.
-* You MUST configure the CDU31A via a LILO config
-* at boot time or in lilo.conf. I have the
-* following in my lilo.conf:
-*
-* append="cdu31a=0x1f88,0,PAS"
-*
-* The first number is the I/O base address of the
-* card. The second is the interrupt (0 means none).
- * The third should be "PAS" if on a Pro-Audio
- * spectrum, or nothing if on something else.
- *
- * This interface is (unfortunately) a polled interface. This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables. Some (like mine) do not even have the capability to
- * handle interrupts or DMA. For this reason you will see a lot of
- * the following:
- *
- * retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
- * while (time_before(jiffies, retry_count) && (! <some condition to wait for))
- * {
- * while (handle_sony_cd_attention())
- * ;
- *
- * sony_sleep();
- * }
- * if (the condition not met)
- * {
- * return an error;
- * }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try. it also handles attentions, which are
- * asynchronous events from the drive informing the driver that a disk
- * has been inserted, removed, etc.
- *
- * NEWS FLASH - The driver now supports interrupts but they are
- * turned off by default. Use of interrupts is highly encouraged, it
- * cuts CPU usage down to a reasonable level. I had DMA in for a while
- * but PC DMA is just too slow. Better to just insb() it.
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk. The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal. A lot of conversion goes on.
- *
- * DRIVER SPECIAL FEATURES
- * -----------------------
- *
- * This section describes features beyond the normal audio and CD-ROM
- * functions of the drive.
- *
- * XA compatibility
- *
- * The driver should support XA disks for both the CDU31A and CDU33A.
- * It does this transparently, the using program doesn't need to set it.
- *
- * Multi-Session
- *
- * A multi-session disk looks just like a normal disk to the user.
- * Just mount one normally, and all the data should be there.
- * A special thanks to Koen for help with this!
- *
- * Raw sector I/O
- *
- * Using the CDROMREADAUDIO it is possible to read raw audio and data
- * tracks. Both operations return 2352 bytes per sector. On the data
- * tracks, the first 12 bytes is not returned by the drive and the value
- * of that data is indeterminate.
- *
- *
- * Copyright (C) 1993 Corey Minyard
- *
- * 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.
- *
- * TODO:
- * CDs with form1 and form2 sectors cause problems
- * with current read-ahead strategy.
- *
- * Credits:
- * Heiko Eissfeldt <heiko@colossus.escape.de>
- * For finding abug in the return of the track numbers.
- * TOC processing redone for proper multisession support.
- *
- *
- * It probably a little late to be adding a history, but I guess I
- * will start.
- *
- * 10/24/95 - Added support for disabling the eject button when the
- * drive is open. Note that there is a small problem
- * still here, if the eject button is pushed while the
- * drive light is flashing, the drive will return a bad
- * status and be reset. It recovers, though.
- *
- * 03/07/97 - Fixed a problem with timers.
- *
- *
- * 18 Spetember 1997 -- Ported to Uniform CD-ROM driver by
- * Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- * changes by Erik Andersen <andersee@debian.org>
- *
- * 24 January 1998 -- Removed the scd_disc_status() function, which was now
- * just dead code left over from the port.
- * Erik Andersen <andersee@debian.org>
- *
- * 16 July 1998 -- Drive donated to Erik Andersen by John Kodis
- * <kodis@jagunet.com>. Work begun on fixing driver to
- * work under 2.1.X. Added temporary extra printks
- * which seem to slow it down enough to work.
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * 22 October 2004 -- Make the driver work in 2.6.X
- * Added workaround to fix hard lockups on eject
- * Fixed door locking problem after mounting empty drive
- * Set double-speed drives to double speed by default
- * Removed all readahead things - not needed anymore
- * Ondrej Zary <rainbow@rainbow-software.org>
-*/
-
-#define DEBUG 1
-
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/cdrom.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/dma.h>
-
-#include "cdu31a.h"
-
-#define MAJOR_NR CDU31A_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
-
-#define PFX "CDU31A: "
-
-/*
-** Edit the following data to change interrupts, DMA channels, etc.
-** Default is polled and no DMA. DMA is not recommended for double-speed
-** drives.
-*/
-static struct {
- unsigned short base; /* I/O Base Address */
- short int_num; /* Interrupt Number (-1 means scan for it,
- 0 means don't use) */
-} cdu31a_addresses[] __initdata = {
- {0}
-};
-
-static int handle_sony_cd_attention(void);
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int scd_spinup(void);
-/*static int scd_open(struct inode *inode, struct file *filp);*/
-static int scd_open(struct cdrom_device_info *, int);
-static void do_sony_cd_cmd(unsigned char cmd,
- unsigned char *params,
- unsigned int num_params,
- unsigned char *result_buffer,
- unsigned int *result_size);
-static void size_to_buf(unsigned int size, unsigned char *buf);
-
-/* Parameters for the read-ahead. */
-static unsigned int sony_next_block; /* Next 512 byte block offset */
-static unsigned int sony_blocks_left = 0; /* Number of 512 byte blocks left
- in the current read command. */
-
-
-/* The base I/O address of the Sony Interface. This is a variable (not a
- #define) so it can be easily changed via some future ioctl() */
-static unsigned int cdu31a_port = 0;
-module_param(cdu31a_port, uint, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive. The
- * comment for the base address also applies here.
- */
-static volatile unsigned short sony_cd_cmd_reg;
-static volatile unsigned short sony_cd_param_reg;
-static volatile unsigned short sony_cd_write_reg;
-static volatile unsigned short sony_cd_control_reg;
-static volatile unsigned short sony_cd_status_reg;
-static volatile unsigned short sony_cd_result_reg;
-static volatile unsigned short sony_cd_read_reg;
-static volatile unsigned short sony_cd_fifost_reg;
-
-static struct request_queue *cdu31a_queue;
-static DEFINE_SPINLOCK(cdu31a_lock); /* queue lock */
-
-static int sony_spun_up = 0; /* Has the drive been spun up? */
-
-static int sony_speed = 0; /* Last wanted speed */
-
-static int sony_xa_mode = 0; /* Is an XA disk in the drive
- and the drive a CDU31A? */
-
-static int sony_raw_data_mode = 1; /* 1 if data tracks, 0 if audio.
- For raw data reads. */
-
-static unsigned int sony_usage = 0; /* How many processes have the
- drive open. */
-
-static int sony_pas_init = 0; /* Initialize the Pro-Audio
- Spectrum card? */
-
-static struct s_sony_session_toc single_toc; /* Holds the
- table of
- contents. */
-
-static struct s_all_sessions_toc sony_toc; /* entries gathered from all
- sessions */
-
-static int sony_toc_read = 0; /* Has the TOC been read for
- the drive? */
-
-static struct s_sony_subcode last_sony_subcode; /* Points to the last
- subcode address read */
-
-static DECLARE_MUTEX(sony_sem); /* Semaphore for drive hardware access */
-
-static int is_double_speed = 0; /* does the drive support double speed ? */
-
-static int is_auto_eject = 1; /* Door has been locked? 1=No/0=Yes */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static volatile int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play. The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over. This holds the
- * position during a pause so a resume can restart it. It uses the
- * audio status variable above to tell if it is paused.
- */
-static unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 };
-static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 };
-
-/* What IRQ is the drive using? 0 if none. */
-static int cdu31a_irq = 0;
-module_param(cdu31a_irq, int, 0);
-
-/* The interrupt handler will wake this queue up when it gets an
- interrupts. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
-static int irq_flag = 0;
-
-static int curr_control_reg = 0; /* Current value of the control register */
-
-/* A disk changed variable. When a disk change is detected, it will
- all be set to TRUE. As the upper layers ask for disk_changed status
- it will be cleared. */
-static char disk_changed;
-
-/* This was readahead_buffer once... Now it's used only for audio reads */
-static char audio_buffer[CD_FRAMESIZE_RAW];
-
-/* Used to time a short period to abort an operation after the
- drive has been idle for a while. This keeps the light on
- the drive from flashing for very long. */
-static struct timer_list cdu31a_abort_timer;
-
-/* Marks if the timeout has started an abort read. This is used
- on entry to the drive to tell the code to read out the status
- from the abort read. */
-static int abort_read_started = 0;
-
-/*
- * Uniform cdrom interface function
- * report back, if disc has changed from time of last request.
- */
-static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- int retval;
-
- retval = disk_changed;
- disk_changed = 0;
-
- return retval;
-}
-
-/*
- * Uniform cdrom interface function
- * report back, if drive is ready
- */
-static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- if (CDSL_CURRENT != slot_nr)
- /* we have no changer support */
- return -EINVAL;
- if (sony_spun_up)
- return CDS_DISC_OK;
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- if (scd_spinup() == 0)
- sony_spun_up = 1;
- up(&sony_sem);
- return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
-}
-
-static inline void enable_interrupts(void)
-{
- curr_control_reg |= (SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-}
-
-static inline void disable_interrupts(void)
-{
- curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-}
-
-/*
- * Wait a little while (used for polling the drive). If in initialization,
- * setting a timeout doesn't work, so just loop for a while.
- */
-static inline void sony_sleep(void)
-{
- if (cdu31a_irq <= 0) {
- yield();
- } else { /* Interrupt driven */
- DEFINE_WAIT(w);
- int first = 1;
-
- while (1) {
- prepare_to_wait(&cdu31a_irq_wait, &w,
- TASK_INTERRUPTIBLE);
- if (first) {
- enable_interrupts();
- first = 0;
- }
-
- if (irq_flag != 0)
- break;
- if (!signal_pending(current)) {
- schedule();
- continue;
- } else
- disable_interrupts();
- break;
- }
- finish_wait(&cdu31a_irq_wait, &w);
- irq_flag = 0;
- }
-}
-
-
-/*
- * The following are convenience routine to read various status and set
- * various conditions in the drive.
- */
-static inline int is_attention(void)
-{
- return (inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0;
-}
-
-static inline int is_busy(void)
-{
- return (inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0;
-}
-
-static inline int is_data_ready(void)
-{
- return (inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0;
-}
-
-static inline int is_data_requested(void)
-{
- return (inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0;
-}
-
-static inline int is_result_ready(void)
-{
- return (inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0;
-}
-
-static inline int is_param_write_rdy(void)
-{
- return (inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0;
-}
-
-static inline int is_result_reg_not_empty(void)
-{
- return (inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0;
-}
-
-static inline void reset_drive(void)
-{
- curr_control_reg = 0;
- sony_toc_read = 0;
- outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
-}
-
-/*
- * Uniform cdrom interface function
- * reset drive and return when it is ready
- */
-static int scd_reset(struct cdrom_device_info *cdi)
-{
- unsigned long retry_count;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- reset_drive();
-
- retry_count = jiffies + SONY_RESET_TIMEOUT;
- while (time_before(jiffies, retry_count) && (!is_attention())) {
- sony_sleep();
- }
-
- up(&sony_sem);
- return 0;
-}
-
-static inline void clear_attention(void)
-{
- outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_result_ready(void)
-{
- outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_data_ready(void)
-{
- outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT,
- sony_cd_control_reg);
-}
-
-static inline void clear_param_reg(void)
-{
- outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline unsigned char read_status_register(void)
-{
- return inb(sony_cd_status_reg);
-}
-
-static inline unsigned char read_result_register(void)
-{
- return inb(sony_cd_result_reg);
-}
-
-static inline unsigned char read_data_register(void)
-{
- return inb(sony_cd_read_reg);
-}
-
-static inline void write_param(unsigned char param)
-{
- outb(param, sony_cd_param_reg);
-}
-
-static inline void write_cmd(unsigned char cmd)
-{
- outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT,
- sony_cd_control_reg);
- outb(cmd, sony_cd_cmd_reg);
-}
-
-static irqreturn_t cdu31a_interrupt(int irq, void *dev_id)
-{
- unsigned char val;
-
- if (abort_read_started) {
- /* We might be waiting for an abort to finish. Don't
- disable interrupts yet, though, because we handle
- this one here. */
- /* Clear out the result registers. */
- while (is_result_reg_not_empty()) {
- val = read_result_register();
- }
- clear_data_ready();
- clear_result_ready();
-
- /* Clear out the data */
- while (is_data_requested()) {
- val = read_data_register();
- }
- abort_read_started = 0;
-
- /* If something was waiting, wake it up now. */
- if (waitqueue_active(&cdu31a_irq_wait)) {
- disable_interrupts();
- irq_flag = 1;
- wake_up_interruptible(&cdu31a_irq_wait);
- }
- } else if (waitqueue_active(&cdu31a_irq_wait)) {
- disable_interrupts();
- irq_flag = 1;
- wake_up_interruptible(&cdu31a_irq_wait);
- } else {
- disable_interrupts();
- printk(KERN_NOTICE PFX
- "Got an interrupt but nothing was waiting\n");
- }
- return IRQ_HANDLED;
-}
-
-/*
- * give more verbose error messages
- */
-static unsigned char *translate_error(unsigned char err_code)
-{
- static unsigned char errbuf[80];
-
- switch (err_code) {
- case 0x10: return "illegal command ";
- case 0x11: return "illegal parameter ";
-
- case 0x20: return "not loaded ";
- case 0x21: return "no disc ";
- case 0x22: return "not spinning ";
- case 0x23: return "spinning ";
- case 0x25: return "spindle servo ";
- case 0x26: return "focus servo ";
- case 0x29: return "eject mechanism ";
- case 0x2a: return "audio playing ";
- case 0x2c: return "emergency eject ";
-
- case 0x30: return "focus ";
- case 0x31: return "frame sync ";
- case 0x32: return "subcode address ";
- case 0x33: return "block sync ";
- case 0x34: return "header address ";
-
- case 0x40: return "illegal track read ";
- case 0x41: return "mode 0 read ";
- case 0x42: return "illegal mode read ";
- case 0x43: return "illegal block size read ";
- case 0x44: return "mode read ";
- case 0x45: return "form read ";
- case 0x46: return "leadout read ";
- case 0x47: return "buffer overrun ";
-
- case 0x53: return "unrecoverable CIRC ";
- case 0x57: return "unrecoverable LECC ";
-
- case 0x60: return "no TOC ";
- case 0x61: return "invalid subcode data ";
- case 0x63: return "focus on TOC read ";
- case 0x64: return "frame sync on TOC read ";
- case 0x65: return "TOC data ";
-
- case 0x70: return "hardware failure ";
- case 0x91: return "leadin ";
- case 0x92: return "leadout ";
- case 0x93: return "data track ";
- }
- sprintf(errbuf, "unknown 0x%02x ", err_code);
- return errbuf;
-}
-
-/*
- * Set the drive parameters so the drive will auto-spin-up when a
- * disk is inserted.
- */
-static void set_drive_params(int want_doublespeed)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned char params[3];
-
-
- params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME;
- params[1] = 0x00; /* Never spin down the drive. */
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_NOTICE PFX
- "Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);
- }
-
- params[0] = SONY_SD_MECH_CONTROL;
- params[1] = SONY_AUTO_SPIN_UP_BIT; /* Set auto spin up */
-
- if (is_auto_eject)
- params[1] |= SONY_AUTO_EJECT_BIT;
-
- if (is_double_speed && want_doublespeed) {
- params[1] |= SONY_DOUBLE_SPEED_BIT; /* Set the drive to double speed if
- possible */
- }
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_NOTICE PFX "Unable to set mechanical "
- "parameters: 0x%2.2x\n", res_reg[1]);
- }
-}
-
-/*
- * Uniform cdrom interface function
- * select reading speed for data access
- */
-static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
- if (speed == 0)
- sony_speed = 1;
- else
- sony_speed = speed - 1;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- set_drive_params(sony_speed);
- up(&sony_sem);
- return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * lock or unlock eject button
- */
-static int scd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
- if (lock == 0) {
- is_auto_eject = 1;
- } else {
- is_auto_eject = 0;
- }
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- set_drive_params(sony_speed);
- up(&sony_sem);
- return 0;
-}
-
-/*
- * This code will reset the drive and attempt to restore sane parameters.
- */
-static void restart_on_error(void)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned long retry_count;
-
-
- printk(KERN_NOTICE PFX "Resetting drive on error\n");
- reset_drive();
- retry_count = jiffies + SONY_RESET_TIMEOUT;
- while (time_before(jiffies, retry_count) && (!is_attention())) {
- sony_sleep();
- }
- set_drive_params(sony_speed);
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_NOTICE PFX "Unable to spin up drive: 0x%2.2x\n",
- res_reg[1]);
- }
-
- msleep(2000);
-
- sony_get_toc();
-}
-
-/*
- * This routine writes data to the parameter register. Since this should
- * happen fairly fast, it is polled with no OS waits between.
- */
-static int write_params(unsigned char *params, int num_params)
-{
- unsigned int retry_count;
-
-
- retry_count = SONY_READY_RETRIES;
- while ((retry_count > 0) && (!is_param_write_rdy())) {
- retry_count--;
- }
- if (!is_param_write_rdy()) {
- return -EIO;
- }
-
- while (num_params > 0) {
- write_param(*params);
- params++;
- num_params--;
- }
-
- return 0;
-}
-
-
-/*
- * The following reads data from the command result register. It is a
- * fairly complex routine, all status info flows back through this
- * interface. The algorithm is stolen directly from the flowcharts in
- * the drive manual.
- */
-static void
-get_result(unsigned char *result_buffer, unsigned int *result_size)
-{
- unsigned char a, b;
- int i;
- unsigned long retry_count;
-
-
- while (handle_sony_cd_attention());
- /* Wait for the result data to be ready */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && (is_busy() || (!(is_result_ready())))) {
- sony_sleep();
-
- while (handle_sony_cd_attention());
- }
- if (is_busy() || (!(is_result_ready()))) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] = SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- return;
- }
-
- /*
- * Get the first two bytes. This determines what else needs
- * to be done.
- */
- clear_result_ready();
- a = read_result_register();
- *result_buffer = a;
- result_buffer++;
-
- /* Check for block error status result. */
- if ((a & 0xf0) == 0x50) {
- *result_size = 1;
- return;
- }
-
- b = read_result_register();
- *result_buffer = b;
- result_buffer++;
- *result_size = 2;
-
- /*
- * 0x20 means an error occurred. Byte 2 will have the error code.
- * Otherwise, the command succeeded, byte 2 will have the count of
- * how many more status bytes are coming.
- *
- * The result register can be read 10 bytes at a time, a wait for
- * result ready to be asserted must be done between every 10 bytes.
- */
- if ((a & 0xf0) != 0x20) {
- if (b > 8) {
- for (i = 0; i < 8; i++) {
- *result_buffer = read_result_register();
- result_buffer++;
- (*result_size)++;
- }
- b = b - 8;
-
- while (b > 10) {
- retry_count = SONY_READY_RETRIES;
- while ((retry_count > 0)
- && (!is_result_ready())) {
- retry_count--;
- }
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n",
- __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] =
- SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- return;
- }
-
- clear_result_ready();
-
- for (i = 0; i < 10; i++) {
- *result_buffer =
- read_result_register();
- result_buffer++;
- (*result_size)++;
- }
- b = b - 10;
- }
-
- if (b > 0) {
- retry_count = SONY_READY_RETRIES;
- while ((retry_count > 0)
- && (!is_result_ready())) {
- retry_count--;
- }
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n",
- __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] =
- SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- return;
- }
- }
- }
-
- while (b > 0) {
- *result_buffer = read_result_register();
- result_buffer++;
- (*result_size)++;
- b--;
- }
- }
-}
-
-/*
- * Do a command that does not involve data transfer. This routine must
- * be re-entrant from the same task to support being called from the
- * data operation code when an error occurs.
- */
-static void
-do_sony_cd_cmd(unsigned char cmd,
- unsigned char *params,
- unsigned int num_params,
- unsigned char *result_buffer, unsigned int *result_size)
-{
- unsigned long retry_count;
- int num_retries = 0;
-
-retry_cd_operation:
-
- while (handle_sony_cd_attention());
-
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count) && (is_busy())) {
- sony_sleep();
-
- while (handle_sony_cd_attention());
- }
- if (is_busy()) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] = SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- } else {
- clear_result_ready();
- clear_param_reg();
-
- write_params(params, num_params);
- write_cmd(cmd);
-
- get_result(result_buffer, result_size);
- }
-
- if (((result_buffer[0] & 0xf0) == 0x20)
- && (num_retries < MAX_CDU31A_RETRIES)) {
- num_retries++;
- msleep(100);
- goto retry_cd_operation;
- }
-}
-
-
-/*
- * Handle an attention from the drive. This will return 1 if it found one
- * or 0 if not (if one is found, the caller might want to call again).
- *
- * This routine counts the number of consecutive times it is called
- * (since this is always called from a while loop until it returns
- * a 0), and returns a 0 if it happens too many times. This will help
- * prevent a lockup.
- */
-static int handle_sony_cd_attention(void)
-{
- unsigned char atten_code;
- static int num_consecutive_attentions = 0;
- volatile int val;
-
-
-#if 0
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-#endif
- if (is_attention()) {
- if (num_consecutive_attentions >
- CDU31A_MAX_CONSECUTIVE_ATTENTIONS) {
- printk(KERN_NOTICE PFX "Too many consecutive "
- "attentions: %d\n", num_consecutive_attentions);
- num_consecutive_attentions = 0;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__,
- __LINE__);
- return 0;
- }
-
- clear_attention();
- atten_code = read_result_register();
-
- switch (atten_code) {
- /* Someone changed the CD. Mark it as changed */
- case SONY_MECH_LOADED_ATTN:
- disk_changed = 1;
- sony_toc_read = 0;
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- sony_blocks_left = 0;
- break;
-
- case SONY_SPIN_DOWN_COMPLETE_ATTN:
- /* Mark the disk as spun down. */
- sony_spun_up = 0;
- break;
-
- case SONY_AUDIO_PLAY_DONE_ATTN:
- sony_audio_status = CDROM_AUDIO_COMPLETED;
- read_subcode();
- break;
-
- case SONY_EJECT_PUSHED_ATTN:
- if (is_auto_eject) {
- sony_audio_status = CDROM_AUDIO_INVALID;
- }
- break;
-
- case SONY_LEAD_IN_ERR_ATTN:
- case SONY_LEAD_OUT_ERR_ATTN:
- case SONY_DATA_TRACK_ERR_ATTN:
- case SONY_AUDIO_PLAYBACK_ERR_ATTN:
- sony_audio_status = CDROM_AUDIO_ERROR;
- break;
- }
-
- num_consecutive_attentions++;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 1;
- } else if (abort_read_started) {
- while (is_result_reg_not_empty()) {
- val = read_result_register();
- }
- clear_data_ready();
- clear_result_ready();
- /* Clear out the data */
- while (is_data_requested()) {
- val = read_data_register();
- }
- abort_read_started = 0;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 1;
- }
-
- num_consecutive_attentions = 0;
-#if 0
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-#endif
- return 0;
-}
-
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int int_to_bcd(unsigned int val)
-{
- int retval;
-
-
- retval = (val / 10) << 4;
- retval = retval | val % 10;
- return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int bcd_to_int(unsigned int bcd)
-{
- return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void log_to_msf(unsigned int log, unsigned char *msf)
-{
- log = log + LOG_START_OFFSET;
- msf[0] = int_to_bcd(log / 4500);
- log = log % 4500;
- msf[1] = int_to_bcd(log / 75);
- msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int msf_to_log(unsigned char *msf)
-{
- unsigned int log;
-
-
- log = msf[2];
- log += msf[1] * 75;
- log += msf[0] * 4500;
- log = log - LOG_START_OFFSET;
-
- return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void size_to_buf(unsigned int size, unsigned char *buf)
-{
- buf[0] = size / 65536;
- size = size % 65536;
- buf[1] = size / 256;
- buf[2] = size % 256;
-}
-
-/* Starts a read operation. Returns 0 on success and 1 on failure.
- The read operation used here allows multiple sequential sectors
- to be read and status returned for each sector. The driver will
- read the output one at a time as the requests come and abort the
- operation if the requested sector is not the next one from the
- drive. */
-static int
-start_request(unsigned int sector, unsigned int nsect)
-{
- unsigned char params[6];
- unsigned long retry_count;
-
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
- log_to_msf(sector, params);
- size_to_buf(nsect, &params[3]);
-
- /*
- * Clear any outstanding attentions and wait for the drive to
- * complete any pending operations.
- */
- while (handle_sony_cd_attention());
-
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count) && (is_busy())) {
- sony_sleep();
-
- while (handle_sony_cd_attention());
- }
-
- if (is_busy()) {
- printk(KERN_NOTICE PFX "Timeout while waiting "
- "to issue command\n");
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 1;
- } else {
- /* Issue the command */
- clear_result_ready();
- clear_param_reg();
-
- write_params(params, 6);
- write_cmd(SONY_READ_BLKERR_STAT_CMD);
-
- sony_blocks_left = nsect * 4;
- sony_next_block = sector * 4;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 0;
- }
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-/* Abort a pending read operation. Clear all the drive status variables. */
-static void abort_read(void)
-{
- unsigned char result_reg[2];
- int result_size;
- volatile int val;
-
-
- do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);
- if ((result_reg[0] & 0xf0) == 0x20) {
- printk(KERN_ERR PFX "Aborting read, %s error\n",
- translate_error(result_reg[1]));
- }
-
- while (is_result_reg_not_empty()) {
- val = read_result_register();
- }
- clear_data_ready();
- clear_result_ready();
- /* Clear out the data */
- while (is_data_requested()) {
- val = read_data_register();
- }
-
- sony_blocks_left = 0;
-}
-
-/* Called when the timer times out. This will abort the
- pending read operation. */
-static void handle_abort_timeout(unsigned long data)
-{
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
- /* If it is in use, ignore it. */
- if (down_trylock(&sony_sem) == 0) {
- /* We can't use abort_read(), because it will sleep
- or schedule in the timer interrupt. Just start
- the operation, finish it on the next access to
- the drive. */
- clear_result_ready();
- clear_param_reg();
- write_cmd(SONY_ABORT_CMD);
-
- sony_blocks_left = 0;
- abort_read_started = 1;
- up(&sony_sem);
- }
- pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* Actually get one sector of data from the drive. */
-static void
-input_data_sector(char *buffer)
-{
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- /* If an XA disk on a CDU31A, skip the first 12 bytes of data from
- the disk. The real data is after that. We can use audio_buffer. */
- if (sony_xa_mode)
- insb(sony_cd_read_reg, audio_buffer, CD_XA_HEAD);
-
- clear_data_ready();
-
- insb(sony_cd_read_reg, buffer, 2048);
-
- /* If an XA disk, we have to clear out the rest of the unused
- error correction data. We can use audio_buffer for that. */
- if (sony_xa_mode)
- insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL);
-
- pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* read data from the drive. Note the nsect must be <= 4. */
-static void
-read_data_block(char *buffer,
- unsigned int block,
- unsigned int nblocks,
- unsigned char res_reg[], int *res_size)
-{
- unsigned long retry_count;
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- res_reg[0] = 0;
- res_reg[1] = 0;
- *res_size = 0;
-
- /* Wait for the drive to tell us we have something */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count) && !(is_data_ready())) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
- if (!(is_data_ready())) {
- if (is_result_ready()) {
- get_result(res_reg, res_size);
- if ((res_reg[0] & 0xf0) != 0x20) {
- printk(KERN_NOTICE PFX "Got result that should"
- " have been error: %d\n", res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- abort_read();
- } else {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- }
- } else {
- input_data_sector(buffer);
- sony_blocks_left -= nblocks;
- sony_next_block += nblocks;
-
- /* Wait for the status from the drive. */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && !(is_result_ready())) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
-
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- } else {
- get_result(res_reg, res_size);
-
- /* If we got a buffer status, handle that. */
- if ((res_reg[0] & 0xf0) == 0x50) {
-
- if ((res_reg[0] ==
- SONY_NO_CIRC_ERR_BLK_STAT)
- || (res_reg[0] ==
- SONY_NO_LECC_ERR_BLK_STAT)
- || (res_reg[0] ==
- SONY_RECOV_LECC_ERR_BLK_STAT)) {
- /* nothing here */
- } else {
- printk(KERN_ERR PFX "Data block "
- "error: 0x%x\n", res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
-
- /* Final transfer is done for read command, get final result. */
- if (sony_blocks_left == 0) {
- get_result(res_reg, res_size);
- }
- } else if ((res_reg[0] & 0xf0) != 0x20) {
- /* The drive gave me bad status, I don't know what to do.
- Reset the driver and return an error. */
- printk(KERN_ERR PFX "Invalid block "
- "status: 0x%x\n", res_reg[0]);
- restart_on_error();
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- }
- }
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail. Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations. This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void do_cdu31a_request(request_queue_t * q)
-{
- struct request *req;
- int block, nblock, num_retries;
- unsigned char res_reg[12];
- unsigned int res_size;
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- spin_unlock_irq(q->queue_lock);
- if (down_interruptible(&sony_sem)) {
- spin_lock_irq(q->queue_lock);
- return;
- }
-
- /* Get drive status before doing anything. */
- while (handle_sony_cd_attention());
-
- /* Make sure we have a valid TOC. */
- sony_get_toc();
-
-
- /* Make sure the timer is cancelled. */
- del_timer(&cdu31a_abort_timer);
-
- while (1) {
- /*
- * The beginning here is stolen from the hard disk driver. I hope
- * it's right.
- */
- req = elv_next_request(q);
- if (!req)
- goto end_do_cdu31a_request;
-
- if (!sony_spun_up)
- scd_spinup();
-
- block = req->sector;
- nblock = req->nr_sectors;
- pr_debug(PFX "request at block %d, length %d blocks\n",
- block, nblock);
- if (!sony_toc_read) {
- printk(KERN_NOTICE PFX "TOC not read\n");
- end_request(req, 0);
- continue;
- }
-
- /* WTF??? */
- if (!blk_fs_request(req)) {
- end_request(req, 0);
- continue;
- }
- if (rq_data_dir(req) == WRITE) {
- end_request(req, 0);
- continue;
- }
-
- /*
- * If the block address is invalid or the request goes beyond the end of
- * the media, return an error.
- */
- if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
- printk(KERN_NOTICE PFX "Request past end of media\n");
- end_request(req, 0);
- continue;
- }
-
- if (nblock > 4)
- nblock = 4;
- num_retries = 0;
-
- try_read_again:
- while (handle_sony_cd_attention());
-
- if (!sony_toc_read) {
- printk(KERN_NOTICE PFX "TOC not read\n");
- end_request(req, 0);
- continue;
- }
-
- /* If no data is left to be read from the drive, start the
- next request. */
- if (sony_blocks_left == 0) {
- if (start_request(block / 4, nblock / 4)) {
- end_request(req, 0);
- continue;
- }
- }
- /* If the requested block is not the next one waiting in
- the driver, abort the current operation and start a
- new one. */
- else if (block != sony_next_block) {
- pr_debug(PFX "Read for block %d, expected %d\n",
- block, sony_next_block);
- abort_read();
- if (!sony_toc_read) {
- printk(KERN_NOTICE PFX "TOC not read\n");
- end_request(req, 0);
- continue;
- }
- if (start_request(block / 4, nblock / 4)) {
- printk(KERN_NOTICE PFX "start request failed\n");
- end_request(req, 0);
- continue;
- }
- }
-
- read_data_block(req->buffer, block, nblock, res_reg, &res_size);
-
- if (res_reg[0] != 0x20) {
- if (!end_that_request_first(req, 1, nblock)) {
- spin_lock_irq(q->queue_lock);
- blkdev_dequeue_request(req);
- end_that_request_last(req, 1);
- spin_unlock_irq(q->queue_lock);
- }
- continue;
- }
-
- if (num_retries > MAX_CDU31A_RETRIES) {
- end_request(req, 0);
- continue;
- }
-
- num_retries++;
- if (res_reg[1] == SONY_NOT_SPIN_ERR) {
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
- } else {
- printk(KERN_NOTICE PFX "%s error for block %d, nblock %d\n",
- translate_error(res_reg[1]), block, nblock);
- }
- goto try_read_again;
- }
- end_do_cdu31a_request:
-#if 0
- /* After finished, cancel any pending operations. */
- abort_read();
-#else
- /* Start a timer to time out after a while to disable
- the read. */
- cdu31a_abort_timer.expires = jiffies + 2 * HZ; /* Wait 2 seconds */
- add_timer(&cdu31a_abort_timer);
-#endif
-
- up(&sony_sem);
- spin_lock_irq(q->queue_lock);
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * Read the table of contents from the drive and set up TOC if
- * successful.
- */
-static void sony_get_toc(void)
-{
- unsigned char res_reg[2];
- unsigned int res_size;
- unsigned char parms[1];
- int session;
- int num_spin_ups;
- int totaltracks = 0;
- int mint = 99;
- int maxt = 0;
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- num_spin_ups = 0;
- if (!sony_toc_read) {
- respinup_on_gettoc:
- /* Ignore the result, since it might error if spinning already. */
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg,
- &res_size);
-
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2)
- || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- /* If the drive is already playing, it's ok. */
- if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
- || (res_reg[1] == 0)) {
- goto gettoc_drive_spinning;
- }
-
- /* If the drive says it is not spun up (even though we just did it!)
- then retry the operation at least a few times. */
- if ((res_reg[1] == SONY_NOT_SPIN_ERR)
- && (num_spin_ups < MAX_CDU31A_RETRIES)) {
- num_spin_ups++;
- goto respinup_on_gettoc;
- }
-
- printk("cdu31a: Error reading TOC: %x %s\n",
- res_reg[0], translate_error(res_reg[1]));
- return;
- }
-
- gettoc_drive_spinning:
-
- /* The idea here is we keep asking for sessions until the command
- fails. Then we know what the last valid session on the disk is.
- No need to check session 0, since session 0 is the same as session
- 1; the command returns different information if you give it 0.
- */
-#if DEBUG
- memset(&sony_toc, 0x0e, sizeof(sony_toc));
- memset(&single_toc, 0x0f, sizeof(single_toc));
-#endif
- session = 1;
- while (1) {
-/* This seems to slow things down enough to make it work. This
- * appears to be a problem in do_sony_cd_cmd. This printk seems
- * to address the symptoms... -Erik */
- pr_debug(PFX "Trying session %d\n", session);
- parms[0] = session;
- do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD,
- parms, 1, res_reg, &res_size);
-
- pr_debug(PFX "%2.2x %2.2x\n", res_reg[0], res_reg[1]);
-
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- /* An error reading the TOC, this must be past the last session. */
- if (session == 1)
- printk
- ("Yikes! Couldn't read any sessions!");
- break;
- }
- pr_debug(PFX "Reading session %d\n", session);
-
- parms[0] = session;
- do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
- parms,
- 1,
- (unsigned char *) &single_toc,
- &res_size);
- if ((res_size < 2)
- || ((single_toc.exec_status[0] & 0xf0) ==
- 0x20)) {
- printk(KERN_ERR PFX "Error reading "
- "session %d: %x %s\n",
- session, single_toc.exec_status[0],
- translate_error(single_toc.
- exec_status[1]));
- /* An error reading the TOC. Return without sony_toc_read
- set. */
- return;
- }
- pr_debug(PFX "add0 %01x, con0 %01x, poi0 %02x, "
- "1st trk %d, dsktyp %x, dum0 %x\n",
- single_toc.address0, single_toc.control0,
- single_toc.point0,
- bcd_to_int(single_toc.first_track_num),
- single_toc.disk_type, single_toc.dummy0);
- pr_debug(PFX "add1 %01x, con1 %01x, poi1 %02x, "
- "lst trk %d, dummy1 %x, dum2 %x\n",
- single_toc.address1, single_toc.control1,
- single_toc.point1,
- bcd_to_int(single_toc.last_track_num),
- single_toc.dummy1, single_toc.dummy2);
- pr_debug(PFX "add2 %01x, con2 %01x, poi2 %02x "
- "leadout start min %d, sec %d, frame %d\n",
- single_toc.address2, single_toc.control2,
- single_toc.point2,
- bcd_to_int(single_toc.lead_out_start_msf[0]),
- bcd_to_int(single_toc.lead_out_start_msf[1]),
- bcd_to_int(single_toc.lead_out_start_msf[2]));
- if (res_size > 18 && single_toc.pointb0 > 0xaf)
- pr_debug(PFX "addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
- "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",
- single_toc.addressb0,
- single_toc.controlb0,
- single_toc.pointb0,
- bcd_to_int(single_toc.
- next_poss_prog_area_msf
- [0]),
- bcd_to_int(single_toc.
- next_poss_prog_area_msf
- [1]),
- bcd_to_int(single_toc.
- next_poss_prog_area_msf
- [2]),
- single_toc.num_mode_5_pointers,
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [0]),
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [1]),
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [2]));
- if (res_size > 27 && single_toc.pointb1 > 0xaf)
- pr_debug(PFX "addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
- single_toc.addressb1,
- single_toc.controlb1,
- single_toc.pointb1,
- single_toc.dummyb0_1[0],
- single_toc.dummyb0_1[1],
- single_toc.dummyb0_1[2],
- single_toc.dummyb0_1[3],
- single_toc.num_skip_interval_pointers,
- single_toc.num_skip_track_assignments,
- single_toc.dummyb0_2);
- if (res_size > 36 && single_toc.pointb2 > 0xaf)
- pr_debug(PFX "addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressb2,
- single_toc.controlb2,
- single_toc.pointb2,
- single_toc.tracksb2[0],
- single_toc.tracksb2[1],
- single_toc.tracksb2[2],
- single_toc.tracksb2[3],
- single_toc.tracksb2[4],
- single_toc.tracksb2[5],
- single_toc.tracksb2[6]);
- if (res_size > 45 && single_toc.pointb3 > 0xaf)
- pr_debug(PFX "addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressb3,
- single_toc.controlb3,
- single_toc.pointb3,
- single_toc.tracksb3[0],
- single_toc.tracksb3[1],
- single_toc.tracksb3[2],
- single_toc.tracksb3[3],
- single_toc.tracksb3[4],
- single_toc.tracksb3[5],
- single_toc.tracksb3[6]);
- if (res_size > 54 && single_toc.pointb4 > 0xaf)
- pr_debug(PFX "addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressb4,
- single_toc.controlb4,
- single_toc.pointb4,
- single_toc.tracksb4[0],
- single_toc.tracksb4[1],
- single_toc.tracksb4[2],
- single_toc.tracksb4[3],
- single_toc.tracksb4[4],
- single_toc.tracksb4[5],
- single_toc.tracksb4[6]);
- if (res_size > 63 && single_toc.pointc0 > 0xaf)
- pr_debug(PFX "addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressc0,
- single_toc.controlc0,
- single_toc.pointc0,
- single_toc.dummyc0[0],
- single_toc.dummyc0[1],
- single_toc.dummyc0[2],
- single_toc.dummyc0[3],
- single_toc.dummyc0[4],
- single_toc.dummyc0[5],
- single_toc.dummyc0[6]);
-#undef DEBUG
-#define DEBUG 0
-
- sony_toc.lead_out_start_msf[0] =
- bcd_to_int(single_toc.lead_out_start_msf[0]);
- sony_toc.lead_out_start_msf[1] =
- bcd_to_int(single_toc.lead_out_start_msf[1]);
- sony_toc.lead_out_start_msf[2] =
- bcd_to_int(single_toc.lead_out_start_msf[2]);
- sony_toc.lead_out_start_lba =
- single_toc.lead_out_start_lba =
- msf_to_log(sony_toc.lead_out_start_msf);
-
- /* For points that do not exist, move the data over them
- to the right location. */
- if (single_toc.pointb0 != 0xb0) {
- memmove(((char *) &single_toc) + 27,
- ((char *) &single_toc) + 18,
- res_size - 18);
- res_size += 9;
- } else if (res_size > 18) {
- sony_toc.lead_out_start_msf[0] =
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [0]);
- sony_toc.lead_out_start_msf[1] =
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [1]);
- sony_toc.lead_out_start_msf[2] =
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [2]);
- sony_toc.lead_out_start_lba =
- msf_to_log(sony_toc.
- lead_out_start_msf);
- }
- if (single_toc.pointb1 != 0xb1) {
- memmove(((char *) &single_toc) + 36,
- ((char *) &single_toc) + 27,
- res_size - 27);
- res_size += 9;
- }
- if (single_toc.pointb2 != 0xb2) {
- memmove(((char *) &single_toc) + 45,
- ((char *) &single_toc) + 36,
- res_size - 36);
- res_size += 9;
- }
- if (single_toc.pointb3 != 0xb3) {
- memmove(((char *) &single_toc) + 54,
- ((char *) &single_toc) + 45,
- res_size - 45);
- res_size += 9;
- }
- if (single_toc.pointb4 != 0xb4) {
- memmove(((char *) &single_toc) + 63,
- ((char *) &single_toc) + 54,
- res_size - 54);
- res_size += 9;
- }
- if (single_toc.pointc0 != 0xc0) {
- memmove(((char *) &single_toc) + 72,
- ((char *) &single_toc) + 63,
- res_size - 63);
- res_size += 9;
- }
-#if DEBUG
- printk(PRINT_INFO PFX "start track lba %u, "
- "leadout start lba %u\n",
- single_toc.start_track_lba,
- single_toc.lead_out_start_lba);
- {
- int i;
- for (i = 0;
- i <
- 1 +
- bcd_to_int(single_toc.last_track_num)
- -
- bcd_to_int(single_toc.
- first_track_num); i++) {
- printk(KERN_INFO PFX "trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n",
- i,
- single_toc.tracks[i].address,
- single_toc.tracks[i].control,
- bcd_to_int(single_toc.
- tracks[i].track),
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf
- [0]),
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf
- [1]),
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf
- [2]));
- if (mint >
- bcd_to_int(single_toc.
- tracks[i].track))
- mint =
- bcd_to_int(single_toc.
- tracks[i].
- track);
- if (maxt <
- bcd_to_int(single_toc.
- tracks[i].track))
- maxt =
- bcd_to_int(single_toc.
- tracks[i].
- track);
- }
- printk(KERN_INFO PFX "min track number %d, "
- "max track number %d\n",
- mint, maxt);
- }
-#endif
-
- /* prepare a special table of contents for a CD-I disc. They don't have one. */
- if (single_toc.disk_type == 0x10 &&
- single_toc.first_track_num == 2 &&
- single_toc.last_track_num == 2 /* CD-I */ ) {
- sony_toc.tracks[totaltracks].address = 1;
- sony_toc.tracks[totaltracks].control = 4; /* force data tracks */
- sony_toc.tracks[totaltracks].track = 1;
- sony_toc.tracks[totaltracks].
- track_start_msf[0] = 0;
- sony_toc.tracks[totaltracks].
- track_start_msf[1] = 2;
- sony_toc.tracks[totaltracks].
- track_start_msf[2] = 0;
- mint = maxt = 1;
- totaltracks++;
- } else
- /* gather track entries from this session */
- {
- int i;
- for (i = 0;
- i <
- 1 +
- bcd_to_int(single_toc.last_track_num)
- -
- bcd_to_int(single_toc.
- first_track_num);
- i++, totaltracks++) {
- sony_toc.tracks[totaltracks].
- address =
- single_toc.tracks[i].address;
- sony_toc.tracks[totaltracks].
- control =
- single_toc.tracks[i].control;
- sony_toc.tracks[totaltracks].
- track =
- bcd_to_int(single_toc.
- tracks[i].track);
- sony_toc.tracks[totaltracks].
- track_start_msf[0] =
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf[0]);
- sony_toc.tracks[totaltracks].
- track_start_msf[1] =
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf[1]);
- sony_toc.tracks[totaltracks].
- track_start_msf[2] =
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf[2]);
- if (i == 0)
- single_toc.
- start_track_lba =
- msf_to_log(sony_toc.
- tracks
- [totaltracks].
- track_start_msf);
- if (mint >
- sony_toc.tracks[totaltracks].
- track)
- mint =
- sony_toc.
- tracks[totaltracks].
- track;
- if (maxt <
- sony_toc.tracks[totaltracks].
- track)
- maxt =
- sony_toc.
- tracks[totaltracks].
- track;
- }
- }
- sony_toc.first_track_num = mint;
- sony_toc.last_track_num = maxt;
- /* Disk type of last session wins. For example:
- CD-Extra has disk type 0 for the first session, so
- a dumb HiFi CD player thinks it is a plain audio CD.
- We are interested in the disk type of the last session,
- which is 0x20 (XA) for CD-Extra, so we can access the
- data track ... */
- sony_toc.disk_type = single_toc.disk_type;
- sony_toc.sessions = session;
-
- /* don't believe everything :-) */
- if (session == 1)
- single_toc.start_track_lba = 0;
- sony_toc.start_track_lba =
- single_toc.start_track_lba;
-
- if (session > 1 && single_toc.pointb0 == 0xb0 &&
- sony_toc.lead_out_start_lba ==
- single_toc.lead_out_start_lba) {
- break;
- }
-
- /* Let's not get carried away... */
- if (session > 40) {
- printk(KERN_NOTICE PFX "too many sessions: "
- "%d\n", session);
- break;
- }
- session++;
- }
- sony_toc.track_entries = totaltracks;
- /* add one entry for the LAST track with track number CDROM_LEADOUT */
- sony_toc.tracks[totaltracks].address = single_toc.address2;
- sony_toc.tracks[totaltracks].control = single_toc.control2;
- sony_toc.tracks[totaltracks].track = CDROM_LEADOUT;
- sony_toc.tracks[totaltracks].track_start_msf[0] =
- sony_toc.lead_out_start_msf[0];
- sony_toc.tracks[totaltracks].track_start_msf[1] =
- sony_toc.lead_out_start_msf[1];
- sony_toc.tracks[totaltracks].track_start_msf[2] =
- sony_toc.lead_out_start_msf[2];
-
- sony_toc_read = 1;
-
- pr_debug(PFX "Disk session %d, start track: %d, "
- "stop track: %d\n",
- session, single_toc.start_track_lba,
- single_toc.lead_out_start_lba);
- }
- pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-
-/*
- * Uniform cdrom interface function
- * return multisession offset and sector information
- */
-static int scd_get_last_session(struct cdrom_device_info *cdi,
- struct cdrom_multisession *ms_info)
-{
- if (ms_info == NULL)
- return 1;
-
- if (!sony_toc_read) {
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- sony_get_toc();
- up(&sony_sem);
- }
-
- ms_info->addr_format = CDROM_LBA;
- ms_info->addr.lba = sony_toc.start_track_lba;
- ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE ||
- sony_toc.disk_type == 0x10 /* CDI */ ;
-
- return 0;
-}
-
-/*
- * Search for a specific track in the table of contents.
- */
-static int find_track(int track)
-{
- int i;
-
- for (i = 0; i <= sony_toc.track_entries; i++) {
- if (sony_toc.tracks[i].track == track) {
- return i;
- }
- }
-
- return -1;
-}
-
-
-/*
- * Read the subcode and put it in last_sony_subcode for future use.
- */
-static int read_subcode(void)
-{
- unsigned int res_size;
-
-
- do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,
- NULL,
- 0, (unsigned char *) &last_sony_subcode, &res_size);
- if ((res_size < 2)
- || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Sony CDROM error %s (read_subcode)\n",
- translate_error(last_sony_subcode.exec_status[1]));
- return -EIO;
- }
-
- last_sony_subcode.track_num =
- bcd_to_int(last_sony_subcode.track_num);
- last_sony_subcode.index_num =
- bcd_to_int(last_sony_subcode.index_num);
- last_sony_subcode.abs_msf[0] =
- bcd_to_int(last_sony_subcode.abs_msf[0]);
- last_sony_subcode.abs_msf[1] =
- bcd_to_int(last_sony_subcode.abs_msf[1]);
- last_sony_subcode.abs_msf[2] =
- bcd_to_int(last_sony_subcode.abs_msf[2]);
-
- last_sony_subcode.rel_msf[0] =
- bcd_to_int(last_sony_subcode.rel_msf[0]);
- last_sony_subcode.rel_msf[1] =
- bcd_to_int(last_sony_subcode.rel_msf[1]);
- last_sony_subcode.rel_msf[2] =
- bcd_to_int(last_sony_subcode.rel_msf[2]);
- return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * return the media catalog number found on some older audio cds
- */
-static int
-scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
- unsigned char resbuffer[2 + 14];
- unsigned char *mcnp = mcn->medium_catalog_number;
- unsigned char *resp = resbuffer + 3;
- unsigned int res_size;
-
- memset(mcn->medium_catalog_number, 0, 14);
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
- NULL, 0, resbuffer, &res_size);
- up(&sony_sem);
- if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20));
- else {
- /* packed bcd to single ASCII digits */
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- }
- *mcnp = '\0';
- return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing). If the drive is paused or completed, the subcode information has
- * already been stored, just use that. The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int sony_get_subchnl_info(struct cdrom_subchnl *schi)
-{
- /* Get attention stuff */
- while (handle_sony_cd_attention());
-
- sony_get_toc();
- if (!sony_toc_read) {
- return -EIO;
- }
-
- switch (sony_audio_status) {
- case CDROM_AUDIO_NO_STATUS:
- case CDROM_AUDIO_PLAY:
- if (read_subcode() < 0) {
- return -EIO;
- }
- break;
-
- case CDROM_AUDIO_PAUSED:
- case CDROM_AUDIO_COMPLETED:
- break;
-
-#if 0
- case CDROM_AUDIO_NO_STATUS:
- schi->cdsc_audiostatus = sony_audio_status;
- return 0;
- break;
-#endif
- case CDROM_AUDIO_INVALID:
- case CDROM_AUDIO_ERROR:
- default:
- return -EIO;
- }
-
- schi->cdsc_audiostatus = sony_audio_status;
- schi->cdsc_adr = last_sony_subcode.address;
- schi->cdsc_ctrl = last_sony_subcode.control;
- schi->cdsc_trk = last_sony_subcode.track_num;
- schi->cdsc_ind = last_sony_subcode.index_num;
- if (schi->cdsc_format == CDROM_MSF) {
- schi->cdsc_absaddr.msf.minute =
- last_sony_subcode.abs_msf[0];
- schi->cdsc_absaddr.msf.second =
- last_sony_subcode.abs_msf[1];
- schi->cdsc_absaddr.msf.frame =
- last_sony_subcode.abs_msf[2];
-
- schi->cdsc_reladdr.msf.minute =
- last_sony_subcode.rel_msf[0];
- schi->cdsc_reladdr.msf.second =
- last_sony_subcode.rel_msf[1];
- schi->cdsc_reladdr.msf.frame =
- last_sony_subcode.rel_msf[2];
- } else if (schi->cdsc_format == CDROM_LBA) {
- schi->cdsc_absaddr.lba =
- msf_to_log(last_sony_subcode.abs_msf);
- schi->cdsc_reladdr.lba =
- msf_to_log(last_sony_subcode.rel_msf);
- }
-
- return 0;
-}
-
-/* Get audio data from the drive. This is fairly complex because I
- am looking for status and data at the same time, but if I get status
- then I just look for data. I need to get the status immediately so
- the switch from audio to data tracks will happen quickly. */
-static void
-read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
-{
- unsigned long retry_count;
- int result_read;
-
-
- res_reg[0] = 0;
- res_reg[1] = 0;
- *res_size = 0;
- result_read = 0;
-
- /* Wait for the drive to tell us we have something */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- continue_read_audio_wait:
- while (time_before(jiffies, retry_count) && !(is_data_ready())
- && !(is_result_ready() || result_read)) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
- if (!(is_data_ready())) {
- if (is_result_ready() && !result_read) {
- get_result(res_reg, res_size);
-
- /* Read block status and continue waiting for data. */
- if ((res_reg[0] & 0xf0) == 0x50) {
- result_read = 1;
- goto continue_read_audio_wait;
- }
- /* Invalid data from the drive. Shut down the operation. */
- else if ((res_reg[0] & 0xf0) != 0x20) {
- printk(KERN_WARNING PFX "Got result that "
- "should have been error: %d\n",
- res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- abort_read();
- } else {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- }
- } else {
- clear_data_ready();
-
- /* If data block, then get 2340 bytes offset by 12. */
- if (sony_raw_data_mode) {
- insb(sony_cd_read_reg, buffer + CD_XA_HEAD,
- CD_FRAMESIZE_RAW1);
- } else {
- /* Audio gets the whole 2352 bytes. */
- insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW);
- }
-
- /* If I haven't already gotten the result, get it now. */
- if (!result_read) {
- /* Wait for the drive to tell us we have something */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && !(is_result_ready())) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
-
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- return;
- } else {
- get_result(res_reg, res_size);
- }
- }
-
- if ((res_reg[0] & 0xf0) == 0x50) {
- if ((res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT)
- || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT)
- || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT)
- || (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) {
- /* Ok, nothing to do. */
- } else {
- printk(KERN_ERR PFX "Data block error: 0x%x\n",
- res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- } else if ((res_reg[0] & 0xf0) != 0x20) {
- /* The drive gave me bad status, I don't know what to do.
- Reset the driver and return an error. */
- printk(KERN_NOTICE PFX "Invalid block status: 0x%x\n",
- res_reg[0]);
- restart_on_error();
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- }
-}
-
-/* Perform a raw data read. This will automatically detect the
- track type and read the proper data (audio or data). */
-static int read_audio(struct cdrom_read_audio *ra)
-{
- int retval;
- unsigned char params[2];
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned int cframe;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- if (!sony_spun_up)
- scd_spinup();
-
- /* Set the drive to do raw operations. */
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x06 | sony_raw_data_mode;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Unable to set decode params: 0x%2.2x\n",
- res_reg[1]);
- retval = -EIO;
- goto out_up;
- }
-
- /* From here down, we have to goto exit_read_audio instead of returning
- because the drive parameters have to be set back to data before
- return. */
-
- retval = 0;
- if (start_request(ra->addr.lba, ra->nframes)) {
- retval = -EIO;
- goto exit_read_audio;
- }
-
- /* For every requested frame. */
- cframe = 0;
- while (cframe < ra->nframes) {
- read_audio_data(audio_buffer, res_reg, &res_size);
- if ((res_reg[0] & 0xf0) == 0x20) {
- if (res_reg[1] == SONY_BAD_DATA_ERR) {
- printk(KERN_ERR PFX "Data error on audio "
- "sector %d\n",
- ra->addr.lba + cframe);
- } else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) {
- /* Illegal track type, change track types and start over. */
- sony_raw_data_mode =
- (sony_raw_data_mode) ? 0 : 1;
-
- /* Set the drive mode. */
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x06 | sony_raw_data_mode;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params,
- 2, res_reg, &res_size);
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Unable to set "
- "decode params: 0x%2.2x\n",
- res_reg[1]);
- retval = -EIO;
- goto exit_read_audio;
- }
-
- /* Restart the request on the current frame. */
- if (start_request
- (ra->addr.lba + cframe,
- ra->nframes - cframe)) {
- retval = -EIO;
- goto exit_read_audio;
- }
-
- /* Don't go back to the top because don't want to get into
- and infinite loop. A lot of code gets duplicated, but
- that's no big deal, I don't guess. */
- read_audio_data(audio_buffer, res_reg,
- &res_size);
- if ((res_reg[0] & 0xf0) == 0x20) {
- if (res_reg[1] ==
- SONY_BAD_DATA_ERR) {
- printk(KERN_ERR PFX "Data error"
- " on audio sector %d\n",
- ra->addr.lba +
- cframe);
- } else {
- printk(KERN_ERR PFX "Error reading audio data on sector %d: %s\n",
- ra->addr.lba + cframe,
- translate_error
- (res_reg[1]));
- retval = -EIO;
- goto exit_read_audio;
- }
- } else if (copy_to_user(ra->buf +
- (CD_FRAMESIZE_RAW
- * cframe),
- audio_buffer,
- CD_FRAMESIZE_RAW)) {
- retval = -EFAULT;
- goto exit_read_audio;
- }
- } else {
- printk(KERN_ERR PFX "Error reading audio "
- "data on sector %d: %s\n",
- ra->addr.lba + cframe,
- translate_error(res_reg[1]));
- retval = -EIO;
- goto exit_read_audio;
- }
- } else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe),
- (char *)audio_buffer,
- CD_FRAMESIZE_RAW)) {
- retval = -EFAULT;
- goto exit_read_audio;
- }
-
- cframe++;
- }
-
- get_result(res_reg, &res_size);
- if ((res_reg[0] & 0xf0) == 0x20) {
- printk(KERN_ERR PFX "Error return from audio read: %s\n",
- translate_error(res_reg[1]));
- retval = -EIO;
- goto exit_read_audio;
- }
-
- exit_read_audio:
-
- /* Set the drive mode back to the proper one for the disk. */
- params[0] = SONY_SD_DECODE_PARAM;
- if (!sony_xa_mode) {
- params[1] = 0x0f;
- } else {
- params[1] = 0x07;
- }
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Unable to reset decode params: 0x%2.2x\n",
- res_reg[1]);
- retval = -EIO;
- }
-
- out_up:
- up(&sony_sem);
-
- return retval;
-}
-
-static int
-do_sony_cd_cmd_chk(const char *name,
- unsigned char cmd,
- unsigned char *params,
- unsigned int num_params,
- unsigned char *result_buffer, unsigned int *result_size)
-{
- do_sony_cd_cmd(cmd, params, num_params, result_buffer,
- result_size);
- if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Error %s (CDROM%s)\n",
- translate_error(result_buffer[1]), name);
- return -EIO;
- }
- return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * open the tray
- */
-static int scd_tray_move(struct cdrom_device_info *cdi, int position)
-{
- int retval;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- if (position == 1 /* open tray */ ) {
- unsigned char res_reg[12];
- unsigned int res_size;
-
- do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size);
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
- &res_size);
-
- sony_audio_status = CDROM_AUDIO_INVALID;
- retval = do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
- res_reg, &res_size);
- } else {
- if (0 == scd_spinup())
- sony_spun_up = 1;
- retval = 0;
- }
- up(&sony_sem);
- return retval;
-}
-
-/*
- * The big ugly ioctl handler.
- */
-static int scd_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned char params[7];
- int i, retval;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- retval = do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
- 0, res_reg, &res_size);
- break;
-
- case CDROMSTOP: /* Spin down the drive */
- do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size);
-
- /*
- * Spin the drive down, ignoring the error if the disk was
- * already not spinning.
- */
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- retval = do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
- 0, res_reg, &res_size);
- break;
-
- case CDROMPAUSE: /* Pause the drive */
- if (do_sony_cd_cmd_chk
- ("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size)) {
- retval = -EIO;
- break;
- }
- /* Get the current position and save it for resuming */
- if (read_subcode() < 0) {
- retval = -EIO;
- break;
- }
- cur_pos_msf[0] = last_sony_subcode.abs_msf[0];
- cur_pos_msf[1] = last_sony_subcode.abs_msf[1];
- cur_pos_msf[2] = last_sony_subcode.abs_msf[2];
- sony_audio_status = CDROM_AUDIO_PAUSED;
- retval = 0;
- break;
-
- case CDROMRESUME: /* Start the drive after being paused */
- if (sony_audio_status != CDROM_AUDIO_PAUSED) {
- retval = -EINVAL;
- break;
- }
-
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- /* Start the drive at the saved position. */
- params[1] = int_to_bcd(cur_pos_msf[0]);
- params[2] = int_to_bcd(cur_pos_msf[1]);
- params[3] = int_to_bcd(cur_pos_msf[2]);
- params[4] = int_to_bcd(final_pos_msf[0]);
- params[5] = int_to_bcd(final_pos_msf[1]);
- params[6] = int_to_bcd(final_pos_msf[2]);
- params[0] = 0x03;
- if (do_sony_cd_cmd_chk
- ("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg,
- &res_size) < 0) {
- retval = -EIO;
- break;
- }
- sony_audio_status = CDROM_AUDIO_PLAY;
- retval = 0;
- break;
-
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- /* The parameters are given in int, must be converted */
- for (i = 1; i < 7; i++) {
- params[i] =
- int_to_bcd(((unsigned char *) arg)[i - 1]);
- }
- params[0] = 0x03;
- if (do_sony_cd_cmd_chk
- ("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7,
- res_reg, &res_size) < 0) {
- retval = -EIO;
- break;
- }
-
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = bcd_to_int(params[4]);
- final_pos_msf[1] = bcd_to_int(params[5]);
- final_pos_msf[2] = bcd_to_int(params[6]);
- sony_audio_status = CDROM_AUDIO_PLAY;
- retval = 0;
- break;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- {
- struct cdrom_tochdr *hdr;
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- hdr = (struct cdrom_tochdr *) arg;
- hdr->cdth_trk0 = sony_toc.first_track_num;
- hdr->cdth_trk1 = sony_toc.last_track_num;
- }
- retval = 0;
- break;
-
- case CDROMREADTOCENTRY: /* Read a given table of contents entry */
- {
- struct cdrom_tocentry *entry;
- int track_idx;
- unsigned char *msf_val = NULL;
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- entry = (struct cdrom_tocentry *) arg;
-
- track_idx = find_track(entry->cdte_track);
- if (track_idx < 0) {
- retval = -EINVAL;
- break;
- }
-
- entry->cdte_adr =
- sony_toc.tracks[track_idx].address;
- entry->cdte_ctrl =
- sony_toc.tracks[track_idx].control;
- msf_val =
- sony_toc.tracks[track_idx].track_start_msf;
-
- /* Logical buffer address or MSF format requested? */
- if (entry->cdte_format == CDROM_LBA) {
- entry->cdte_addr.lba = msf_to_log(msf_val);
- } else if (entry->cdte_format == CDROM_MSF) {
- entry->cdte_addr.msf.minute = *msf_val;
- entry->cdte_addr.msf.second =
- *(msf_val + 1);
- entry->cdte_addr.msf.frame =
- *(msf_val + 2);
- }
- }
- retval = 0;
- break;
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- {
- struct cdrom_ti *ti = (struct cdrom_ti *) arg;
- int track_idx;
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- if ((ti->cdti_trk0 < sony_toc.first_track_num)
- || (ti->cdti_trk0 > sony_toc.last_track_num)
- || (ti->cdti_trk1 < ti->cdti_trk0)) {
- retval = -EINVAL;
- break;
- }
-
- track_idx = find_track(ti->cdti_trk0);
- if (track_idx < 0) {
- retval = -EINVAL;
- break;
- }
- params[1] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[0]);
- params[2] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[1]);
- params[3] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[2]);
-
- /*
- * If we want to stop after the last track, use the lead-out
- * MSF to do that.
- */
- if (ti->cdti_trk1 >= sony_toc.last_track_num) {
- track_idx = find_track(CDROM_LEADOUT);
- } else {
- track_idx = find_track(ti->cdti_trk1 + 1);
- }
- if (track_idx < 0) {
- retval = -EINVAL;
- break;
- }
- params[4] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[0]);
- params[5] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[1]);
- params[6] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[2]);
- params[0] = 0x03;
-
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7,
- res_reg, &res_size);
-
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX
- "Params: %x %x %x %x %x %x %x\n",
- params[0], params[1], params[2],
- params[3], params[4], params[5],
- params[6]);
- printk(KERN_ERR PFX
- "Error %s (CDROMPLAYTRKIND)\n",
- translate_error(res_reg[1]));
- retval = -EIO;
- break;
- }
-
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = bcd_to_int(params[4]);
- final_pos_msf[1] = bcd_to_int(params[5]);
- final_pos_msf[2] = bcd_to_int(params[6]);
- sony_audio_status = CDROM_AUDIO_PLAY;
- retval = 0;
- break;
- }
-
- case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
- {
- struct cdrom_volctrl *volctrl =
- (struct cdrom_volctrl *) arg;
-
- params[0] = SONY_SD_AUDIO_VOLUME;
- params[1] = volctrl->channel0;
- params[2] = volctrl->channel1;
- retval = do_sony_cd_cmd_chk("VOLCTRL",
- SONY_SET_DRIVE_PARAM_CMD,
- params, 3, res_reg,
- &res_size);
- break;
- }
- case CDROMSUBCHNL: /* Get subchannel info */
- retval = sony_get_subchnl_info((struct cdrom_subchnl *) arg);
- break;
-
- default:
- retval = -EINVAL;
- break;
- }
- up(&sony_sem);
- return retval;
-}
-
-static int scd_read_audio(struct cdrom_device_info *cdi,
- unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int retval;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- switch (cmd) {
- case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte
- raw data tracks. */
- {
- struct cdrom_read_audio ra;
-
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- if (copy_from_user(&ra, argp, sizeof(ra))) {
- retval = -EFAULT;
- break;
- }
-
- if (ra.nframes == 0) {
- retval = 0;
- break;
- }
-
- if (!access_ok(VERIFY_WRITE, ra.buf,
- CD_FRAMESIZE_RAW * ra.nframes))
- return -EFAULT;
-
- if (ra.addr_format == CDROM_LBA) {
- if ((ra.addr.lba >=
- sony_toc.lead_out_start_lba)
- || (ra.addr.lba + ra.nframes >=
- sony_toc.lead_out_start_lba)) {
- retval = -EINVAL;
- break;
- }
- } else if (ra.addr_format == CDROM_MSF) {
- if ((ra.addr.msf.minute >= 75)
- || (ra.addr.msf.second >= 60)
- || (ra.addr.msf.frame >= 75)) {
- retval = -EINVAL;
- break;
- }
-
- ra.addr.lba = ((ra.addr.msf.minute * 4500)
- + (ra.addr.msf.second * 75)
- + ra.addr.msf.frame);
- if ((ra.addr.lba >=
- sony_toc.lead_out_start_lba)
- || (ra.addr.lba + ra.nframes >=
- sony_toc.lead_out_start_lba)) {
- retval = -EINVAL;
- break;
- }
-
- /* I know, this can go negative on an unsigned. However,
- the first thing done to the data is to add this value,
- so this should compensate and allow direct msf access. */
- ra.addr.lba -= LOG_START_OFFSET;
- } else {
- retval = -EINVAL;
- break;
- }
-
- retval = read_audio(&ra);
- break;
- }
- retval = 0;
- break;
-
- default:
- retval = -EINVAL;
- }
- up(&sony_sem);
- return retval;
-}
-
-static int scd_spinup(void)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- int num_spin_ups;
-
- num_spin_ups = 0;
-
- respinup_on_open:
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- printk(KERN_ERR PFX "%s error (scd_open, spin up)\n",
- translate_error(res_reg[1]));
- return 1;
- }
-
- do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
-
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- /* If the drive is already playing, it's ok. */
- if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
- || (res_reg[1] == 0)) {
- return 0;
- }
-
- /* If the drive says it is not spun up (even though we just did it!)
- then retry the operation at least a few times. */
- if ((res_reg[1] == SONY_NOT_SPIN_ERR)
- && (num_spin_ups < MAX_CDU31A_RETRIES)) {
- num_spin_ups++;
- goto respinup_on_open;
- }
-
- printk(KERN_ERR PFX "Error %s (scd_open, read toc)\n",
- translate_error(res_reg[1]));
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
- &res_size);
- return 1;
- }
- return 0;
-}
-
-/*
- * Open the drive for operations. Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int scd_open(struct cdrom_device_info *cdi, int purpose)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned char params[2];
-
- if (purpose == 1) {
- /* Open for IOCTLs only - no media check */
- sony_usage++;
- return 0;
- }
-
- if (sony_usage == 0) {
- if (scd_spinup() != 0)
- return -EIO;
- sony_get_toc();
- if (!sony_toc_read) {
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0,
- res_reg, &res_size);
- return -EIO;
- }
-
- /* For XA on the CDU31A only, we have to do special reads.
- The CDU33A handles XA automagically. */
- /* if ( (sony_toc.disk_type == SONY_XA_DISK_TYPE) */
- if ((sony_toc.disk_type != 0x00)
- && (!is_double_speed)) {
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x07;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_WARNING PFX "Unable to set "
- "XA params: 0x%2.2x\n", res_reg[1]);
- }
- sony_xa_mode = 1;
- }
- /* A non-XA disk. Set the parms back if necessary. */
- else if (sony_xa_mode) {
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x0f;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_WARNING PFX "Unable to reset "
- "XA params: 0x%2.2x\n", res_reg[1]);
- }
- sony_xa_mode = 0;
- }
-
- sony_spun_up = 1;
- }
-
- sony_usage++;
-
- return 0;
-}
-
-
-/*
- * Close the drive. Spin it down if no task is using it. The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static void scd_release(struct cdrom_device_info *cdi)
-{
- if (sony_usage == 1) {
- unsigned char res_reg[12];
- unsigned int res_size;
-
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
- &res_size);
-
- sony_spun_up = 0;
- }
- sony_usage--;
-}
-
-static struct cdrom_device_ops scd_dops = {
- .open = scd_open,
- .release = scd_release,
- .drive_status = scd_drive_status,
- .media_changed = scd_media_changed,
- .tray_move = scd_tray_move,
- .lock_door = scd_lock_door,
- .select_speed = scd_select_speed,
- .get_last_session = scd_get_last_session,
- .get_mcn = scd_get_mcn,
- .reset = scd_reset,
- .audio_ioctl = scd_audio_ioctl,
- .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
- CDC_SELECT_SPEED | CDC_MULTI_SESSION |
- CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
- CDC_RESET | CDC_DRIVE_STATUS,
- .n_minors = 1,
-};
-
-static struct cdrom_device_info scd_info = {
- .ops = &scd_dops,
- .speed = 2,
- .capacity = 1,
- .name = "cdu31a"
-};
-
-static int scd_block_open(struct inode *inode, struct file *file)
-{
- return cdrom_open(&scd_info, inode, file);
-}
-
-static int scd_block_release(struct inode *inode, struct file *file)
-{
- return cdrom_release(&scd_info, file);
-}
-
-static int scd_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- int retval;
-
- /* The eject and close commands should be handled by Uniform CD-ROM
- * driver - but I always got hard lockup instead of eject
- * until I put this here.
- */
- switch (cmd) {
- case CDROMEJECT:
- scd_lock_door(&scd_info, 0);
- retval = scd_tray_move(&scd_info, 1);
- break;
- case CDROMCLOSETRAY:
- retval = scd_tray_move(&scd_info, 0);
- break;
- case CDROMREADAUDIO:
- retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg);
- break;
- default:
- retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg);
- }
- return retval;
-}
-
-static int scd_block_media_changed(struct gendisk *disk)
-{
- return cdrom_media_changed(&scd_info);
-}
-
-static struct block_device_operations scd_bdops =
-{
- .owner = THIS_MODULE,
- .open = scd_block_open,
- .release = scd_block_release,
- .ioctl = scd_block_ioctl,
- .media_changed = scd_block_media_changed,
-};
-
-static struct gendisk *scd_gendisk;
-
-/* The different types of disc loading mechanisms supported */
-static char *load_mech[] __initdata =
- { "caddy", "tray", "pop-up", "unknown" };
-
-static int __init
-get_drive_configuration(unsigned short base_io,
- unsigned char res_reg[], unsigned int *res_size)
-{
- unsigned long retry_count;
-
-
- if (!request_region(base_io, 4, "cdu31a"))
- return 0;
-
- /* Set the base address */
- cdu31a_port = base_io;
-
- /* Set up all the register locations */
- sony_cd_cmd_reg = cdu31a_port + SONY_CMD_REG_OFFSET;
- sony_cd_param_reg = cdu31a_port + SONY_PARAM_REG_OFFSET;
- sony_cd_write_reg = cdu31a_port + SONY_WRITE_REG_OFFSET;
- sony_cd_control_reg = cdu31a_port + SONY_CONTROL_REG_OFFSET;
- sony_cd_status_reg = cdu31a_port + SONY_STATUS_REG_OFFSET;
- sony_cd_result_reg = cdu31a_port + SONY_RESULT_REG_OFFSET;
- sony_cd_read_reg = cdu31a_port + SONY_READ_REG_OFFSET;
- sony_cd_fifost_reg = cdu31a_port + SONY_FIFOST_REG_OFFSET;
-
- /*
- * Check to see if anything exists at the status register location.
- * I don't know if this is a good way to check, but it seems to work
- * ok for me.
- */
- if (read_status_register() != 0xff) {
- /*
- * Reset the drive and wait for attention from it (to say it's reset).
- * If you don't wait, the next operation will probably fail.
- */
- reset_drive();
- retry_count = jiffies + SONY_RESET_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && (!is_attention())) {
- sony_sleep();
- }
-
-#if 0
- /* If attention is never seen probably not a CDU31a present */
- if (!is_attention()) {
- res_reg[0] = 0x20;
- goto out_err;
- }
-#endif
-
- /*
- * Get the drive configuration.
- */
- do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,
- NULL,
- 0, (unsigned char *) res_reg, res_size);
- if (*res_size <= 2 || (res_reg[0] & 0xf0) != 0)
- goto out_err;
- return 1;
- }
-
- /* Return an error */
- res_reg[0] = 0x20;
-out_err:
- release_region(cdu31a_port, 4);
- cdu31a_port = 0;
- return 0;
-}
-
-#ifndef MODULE
-/*
- * Set up base I/O and interrupts, called from main.c.
- */
-
-static int __init cdu31a_setup(char *strings)
-{
- int ints[4];
-
- (void) get_options(strings, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0) {
- cdu31a_port = ints[1];
- }
- if (ints[0] > 1) {
- cdu31a_irq = ints[2];
- }
- if ((strings != NULL) && (*strings != '\0')) {
- if (strcmp(strings, "PAS") == 0) {
- sony_pas_init = 1;
- } else {
- printk(KERN_NOTICE PFX "Unknown interface type: %s\n",
- strings);
- }
- }
-
- return 1;
-}
-
-__setup("cdu31a=", cdu31a_setup);
-
-#endif
-
-/*
- * Initialize the driver.
- */
-int __init cdu31a_init(void)
-{
- struct s_sony_drive_config drive_config;
- struct gendisk *disk;
- int deficiency = 0;
- unsigned int res_size;
- char msg[255];
- char buf[40];
- int i;
- int tmp_irq;
-
- /*
- * According to Alex Freed (freed@europa.orion.adobe.com), this is
- * required for the Fusion CD-16 package. If the sound driver is
- * loaded, it should work fine, but just in case...
- *
- * The following turn on the CD-ROM interface for a Fusion CD-16.
- */
- if (sony_pas_init) {
- outb(0xbc, 0x9a01);
- outb(0xe2, 0x9a01);
- }
-
- /* Setting the base I/O address to 0xffff will disable it. */
- if (cdu31a_port == 0xffff)
- goto errout3;
-
- if (cdu31a_port != 0) {
- /* Need IRQ 0 because we can't sleep here. */
- tmp_irq = cdu31a_irq;
- cdu31a_irq = 0;
- if (!get_drive_configuration(cdu31a_port,
- drive_config.exec_status,
- &res_size))
- goto errout3;
- cdu31a_irq = tmp_irq;
- } else {
- cdu31a_irq = 0;
- for (i = 0; cdu31a_addresses[i].base; i++) {
- if (get_drive_configuration(cdu31a_addresses[i].base,
- drive_config.exec_status,
- &res_size)) {
- cdu31a_irq = cdu31a_addresses[i].int_num;
- break;
- }
- }
- if (!cdu31a_port)
- goto errout3;
- }
-
- if (register_blkdev(MAJOR_NR, "cdu31a"))
- goto errout2;
-
- disk = alloc_disk(1);
- if (!disk)
- goto errout1;
- disk->major = MAJOR_NR;
- disk->first_minor = 0;
- sprintf(disk->disk_name, "cdu31a");
- disk->fops = &scd_bdops;
- disk->flags = GENHD_FL_CD;
-
- if (SONY_HWC_DOUBLE_SPEED(drive_config))
- is_double_speed = 1;
-
- tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */
- cdu31a_irq = 0;
-
- sony_speed = is_double_speed; /* Set 2X drives to 2X by default */
- set_drive_params(sony_speed);
-
- cdu31a_irq = tmp_irq;
-
- if (cdu31a_irq > 0) {
- if (request_irq
- (cdu31a_irq, cdu31a_interrupt, IRQF_DISABLED,
- "cdu31a", NULL)) {
- printk(KERN_WARNING PFX "Unable to grab IRQ%d for "
- "the CDU31A driver\n", cdu31a_irq);
- cdu31a_irq = 0;
- }
- }
-
- sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n",
- drive_config.vendor_id,
- drive_config.product_id,
- drive_config.product_rev_level);
- sprintf(buf, " Capabilities: %s",
- load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
- strcat(msg, buf);
- if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
- strcat(msg, ", audio");
- else
- deficiency |= CDC_PLAY_AUDIO;
- if (SONY_HWC_EJECT(drive_config))
- strcat(msg, ", eject");
- else
- deficiency |= CDC_OPEN_TRAY;
- if (SONY_HWC_LED_SUPPORT(drive_config))
- strcat(msg, ", LED");
- if (SONY_HWC_ELECTRIC_VOLUME(drive_config))
- strcat(msg, ", elec. Vol");
- if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config))
- strcat(msg, ", sep. Vol");
- if (is_double_speed)
- strcat(msg, ", double speed");
- else
- deficiency |= CDC_SELECT_SPEED;
- if (cdu31a_irq > 0) {
- sprintf(buf, ", irq %d", cdu31a_irq);
- strcat(msg, buf);
- }
- strcat(msg, "\n");
- printk(KERN_INFO PFX "%s",msg);
-
- cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock);
- if (!cdu31a_queue)
- goto errout0;
- blk_queue_hardsect_size(cdu31a_queue, 2048);
-
- init_timer(&cdu31a_abort_timer);
- cdu31a_abort_timer.function = handle_abort_timeout;
-
- scd_info.mask = deficiency;
- scd_gendisk = disk;
- if (register_cdrom(&scd_info))
- goto err;
- disk->queue = cdu31a_queue;
- add_disk(disk);
-
- disk_changed = 1;
- return 0;
-
-err:
- blk_cleanup_queue(cdu31a_queue);
-errout0:
- if (cdu31a_irq)
- free_irq(cdu31a_irq, NULL);
- printk(KERN_ERR PFX "Unable to register with Uniform cdrom driver\n");
- put_disk(disk);
-errout1:
- if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
- printk(KERN_WARNING PFX "Can't unregister block device\n");
- }
-errout2:
- release_region(cdu31a_port, 4);
-errout3:
- return -EIO;
-}
-
-
-static void __exit cdu31a_exit(void)
-{
- del_gendisk(scd_gendisk);
- put_disk(scd_gendisk);
- if (unregister_cdrom(&scd_info)) {
- printk(KERN_WARNING PFX "Can't unregister from Uniform "
- "cdrom driver\n");
- return;
- }
- if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
- printk(KERN_WARNING PFX "Can't unregister\n");
- return;
- }
-
- blk_cleanup_queue(cdu31a_queue);
-
- if (cdu31a_irq > 0)
- free_irq(cdu31a_irq, NULL);
-
- release_region(cdu31a_port, 4);
- printk(KERN_INFO PFX "module released.\n");
-}
-
-#ifdef MODULE
-module_init(cdu31a_init);
-#endif
-module_exit(cdu31a_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU31A_CDROM_MAJOR);
diff --git a/drivers/cdrom/cdu31a.h b/drivers/cdrom/cdu31a.h
deleted file mode 100644
index 61d4768c412..00000000000
--- a/drivers/cdrom/cdu31a.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Definitions for a Sony interface CDROM drive.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com)
- *
- * Copyright (C) 1993 Corey Minyard
- *
- * 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.
- *
- */
-
-/*
- * General defines.
- */
-#define SONY_XA_DISK_TYPE 0x20
-
-/*
- * Offsets (from the base address) and bits for the various write registers
- * of the drive.
- */
-#define SONY_CMD_REG_OFFSET 0
-#define SONY_PARAM_REG_OFFSET 1
-#define SONY_WRITE_REG_OFFSET 2
-#define SONY_CONTROL_REG_OFFSET 3
-# define SONY_ATTN_CLR_BIT 0x01
-# define SONY_RES_RDY_CLR_BIT 0x02
-# define SONY_DATA_RDY_CLR_BIT 0x04
-# define SONY_ATTN_INT_EN_BIT 0x08
-# define SONY_RES_RDY_INT_EN_BIT 0x10
-# define SONY_DATA_RDY_INT_EN_BIT 0x20
-# define SONY_PARAM_CLR_BIT 0x40
-# define SONY_DRIVE_RESET_BIT 0x80
-
-/*
- * Offsets (from the base address) and bits for the various read registers
- * of the drive.
- */
-#define SONY_STATUS_REG_OFFSET 0
-# define SONY_ATTN_BIT 0x01
-# define SONY_RES_RDY_BIT 0x02
-# define SONY_DATA_RDY_BIT 0x04
-# define SONY_ATTN_INT_ST_BIT 0x08
-# define SONY_RES_RDY_INT_ST_BIT 0x10
-# define SONY_DATA_RDY_INT_ST_BIT 0x20
-# define SONY_DATA_REQUEST_BIT 0x40
-# define SONY_BUSY_BIT 0x80
-#define SONY_RESULT_REG_OFFSET 1
-#define SONY_READ_REG_OFFSET 2
-#define SONY_FIFOST_REG_OFFSET 3
-# define SONY_PARAM_WRITE_RDY_BIT 0x01
-# define SONY_PARAM_REG_EMPTY_BIT 0x02
-# define SONY_RES_REG_NOT_EMP_BIT 0x04
-# define SONY_RES_REG_FULL_BIT 0x08
-
-#define LOG_START_OFFSET 150 /* Offset of first logical sector */
-
-#define SONY_DETECT_TIMEOUT (8*HZ/10) /* Maximum amount of time
- that drive detection code
- will wait for response
- from drive (in 1/100th's
- of seconds). */
-
-#define SONY_JIFFIES_TIMEOUT (10*HZ) /* Maximum number of times the
- drive will wait/try for an
- operation */
-#define SONY_RESET_TIMEOUT HZ /* Maximum number of times the
- drive will wait/try a reset
- operation */
-#define SONY_READY_RETRIES 20000 /* How many times to retry a
- spin waiting for a register
- to come ready */
-
-#define MAX_CDU31A_RETRIES 3 /* How many times to retry an
- operation */
-
-/* Commands to request or set drive control parameters and disc information */
-#define SONY_REQ_DRIVE_CONFIG_CMD 0x00 /* Returns s_sony_drive_config */
-#define SONY_REQ_DRIVE_MODE_CMD 0x01
-#define SONY_REQ_DRIVE_PARAM_CMD 0x02
-#define SONY_REQ_MECH_STATUS_CMD 0x03
-#define SONY_REQ_AUDIO_STATUS_CMD 0x04
-#define SONY_SET_DRIVE_PARAM_CMD 0x10
-#define SONY_REQ_TOC_DATA_CMD 0x20 /* Returns s_sony_toc */
-#define SONY_REQ_SUBCODE_ADDRESS_CMD 0x21 /* Returns s_sony_subcode */
-#define SONY_REQ_UPC_EAN_CMD 0x22
-#define SONY_REQ_ISRC_CMD 0x23
-#define SONY_REQ_TOC_DATA_SPEC_CMD 0x24 /* Returns s_sony_session_toc */
-
-/* Commands to request information from the drive */
-#define SONY_READ_TOC_CMD 0x30 /* let the drive firmware grab the TOC */
-#define SONY_SEEK_CMD 0x31
-#define SONY_READ_CMD 0x32
-#define SONY_READ_BLKERR_STAT_CMD 0x34
-#define SONY_ABORT_CMD 0x35
-#define SONY_READ_TOC_SPEC_CMD 0x36
-
-/* Commands to control audio */
-#define SONY_AUDIO_PLAYBACK_CMD 0x40
-#define SONY_AUDIO_STOP_CMD 0x41
-#define SONY_AUDIO_SCAN_CMD 0x42
-
-/* Miscellaneous control commands */
-#define SONY_EJECT_CMD 0x50
-#define SONY_SPIN_UP_CMD 0x51
-#define SONY_SPIN_DOWN_CMD 0x52
-
-/* Diagnostic commands */
-#define SONY_WRITE_BUFFER_CMD 0x60
-#define SONY_READ_BUFFER_CMD 0x61
-#define SONY_DIAGNOSTICS_CMD 0x62
-
-
-/*
- * The following are command parameters for the set drive parameter command
- */
-#define SONY_SD_DECODE_PARAM 0x00
-#define SONY_SD_INTERFACE_PARAM 0x01
-#define SONY_SD_BUFFERING_PARAM 0x02
-#define SONY_SD_AUDIO_PARAM 0x03
-#define SONY_SD_AUDIO_VOLUME 0x04
-#define SONY_SD_MECH_CONTROL 0x05
-#define SONY_SD_AUTO_SPIN_DOWN_TIME 0x06
-
-/*
- * The following are parameter bits for the mechanical control command
- */
-#define SONY_AUTO_SPIN_UP_BIT 0x01
-#define SONY_AUTO_EJECT_BIT 0x02
-#define SONY_DOUBLE_SPEED_BIT 0x04
-
-/*
- * The following extract information from the drive configuration about
- * the drive itself.
- */
-#define SONY_HWC_GET_LOAD_MECH(c) (c.hw_config[0] & 0x03)
-#define SONY_HWC_EJECT(c) (c.hw_config[0] & 0x04)
-#define SONY_HWC_LED_SUPPORT(c) (c.hw_config[0] & 0x08)
-#define SONY_HWC_DOUBLE_SPEED(c) (c.hw_config[0] & 0x10)
-#define SONY_HWC_GET_BUF_MEM_SIZE(c) ((c.hw_config[0] & 0xc0) >> 6)
-#define SONY_HWC_AUDIO_PLAYBACK(c) (c.hw_config[1] & 0x01)
-#define SONY_HWC_ELECTRIC_VOLUME(c) (c.hw_config[1] & 0x02)
-#define SONY_HWC_ELECTRIC_VOLUME_CTL(c) (c.hw_config[1] & 0x04)
-
-#define SONY_HWC_CADDY_LOAD_MECH 0x00
-#define SONY_HWC_TRAY_LOAD_MECH 0x01
-#define SONY_HWC_POPUP_LOAD_MECH 0x02
-#define SONY_HWC_UNKWN_LOAD_MECH 0x03
-
-#define SONY_HWC_8KB_BUFFER 0x00
-#define SONY_HWC_32KB_BUFFER 0x01
-#define SONY_HWC_64KB_BUFFER 0x02
-#define SONY_HWC_UNKWN_BUFFER 0x03
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s_sony_drive_config
-{
- unsigned char exec_status[2];
- char vendor_id[8];
- char product_id[16];
- char product_rev_level[8];
- unsigned char hw_config[2];
-};
-
-/* The following is returned from the request subcode address command */
-struct s_sony_subcode
-{
- unsigned char exec_status[2];
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track_num;
- unsigned char index_num;
- unsigned char rel_msf[3];
- unsigned char reserved1;
- unsigned char abs_msf[3];
-};
-
-#define MAX_TRACKS 100 /* The maximum tracks a disk may have. */
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s_sony_toc
-{
- unsigned char exec_status[2];
- unsigned char address0 :4;
- unsigned char control0 :4;
- unsigned char point0;
- unsigned char first_track_num;
- unsigned char disk_type;
- unsigned char dummy0;
- unsigned char address1 :4;
- unsigned char control1 :4;
- unsigned char point1;
- unsigned char last_track_num;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char address2 :4;
- unsigned char control2 :4;
- unsigned char point2;
- unsigned char lead_out_start_msf[3];
- struct
- {
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[MAX_TRACKS];
-
- unsigned int lead_out_start_lba;
-};
-
-struct s_sony_session_toc
-{
- unsigned char exec_status[2];
- unsigned char session_number;
- unsigned char address0 :4;
- unsigned char control0 :4;
- unsigned char point0;
- unsigned char first_track_num;
- unsigned char disk_type;
- unsigned char dummy0;
- unsigned char address1 :4;
- unsigned char control1 :4;
- unsigned char point1;
- unsigned char last_track_num;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char address2 :4;
- unsigned char control2 :4;
- unsigned char point2;
- unsigned char lead_out_start_msf[3];
- unsigned char addressb0 :4;
- unsigned char controlb0 :4;
- unsigned char pointb0;
- unsigned char next_poss_prog_area_msf[3];
- unsigned char num_mode_5_pointers;
- unsigned char max_start_outer_leadout_msf[3];
- unsigned char addressb1 :4;
- unsigned char controlb1 :4;
- unsigned char pointb1;
- unsigned char dummyb0_1[4];
- unsigned char num_skip_interval_pointers;
- unsigned char num_skip_track_assignments;
- unsigned char dummyb0_2;
- unsigned char addressb2 :4;
- unsigned char controlb2 :4;
- unsigned char pointb2;
- unsigned char tracksb2[7];
- unsigned char addressb3 :4;
- unsigned char controlb3 :4;
- unsigned char pointb3;
- unsigned char tracksb3[7];
- unsigned char addressb4 :4;
- unsigned char controlb4 :4;
- unsigned char pointb4;
- unsigned char tracksb4[7];
- unsigned char addressc0 :4;
- unsigned char controlc0 :4;
- unsigned char pointc0;
- unsigned char dummyc0[7];
- struct
- {
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[MAX_TRACKS];
-
- unsigned int start_track_lba;
- unsigned int lead_out_start_lba;
- unsigned int mint;
- unsigned int maxt;
-};
-
-struct s_all_sessions_toc
-{
- unsigned char sessions;
- unsigned int track_entries;
- unsigned char first_track_num;
- unsigned char last_track_num;
- unsigned char disk_type;
- unsigned char lead_out_start_msf[3];
- struct
- {
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[MAX_TRACKS];
-
- unsigned int start_track_lba;
- unsigned int lead_out_start_lba;
-};
-
-
-/*
- * The following are errors returned from the drive.
- */
-
-/* Command error group */
-#define SONY_ILL_CMD_ERR 0x10
-#define SONY_ILL_PARAM_ERR 0x11
-
-/* Mechanism group */
-#define SONY_NOT_LOAD_ERR 0x20
-#define SONY_NO_DISK_ERR 0x21
-#define SONY_NOT_SPIN_ERR 0x22
-#define SONY_SPIN_ERR 0x23
-#define SONY_SPINDLE_SERVO_ERR 0x25
-#define SONY_FOCUS_SERVO_ERR 0x26
-#define SONY_EJECT_MECH_ERR 0x29
-#define SONY_AUDIO_PLAYING_ERR 0x2a
-#define SONY_EMERGENCY_EJECT_ERR 0x2c
-
-/* Seek error group */
-#define SONY_FOCUS_ERR 0x30
-#define SONY_FRAME_SYNC_ERR 0x31
-#define SONY_SUBCODE_ADDR_ERR 0x32
-#define SONY_BLOCK_SYNC_ERR 0x33
-#define SONY_HEADER_ADDR_ERR 0x34
-
-/* Read error group */
-#define SONY_ILL_TRACK_R_ERR 0x40
-#define SONY_MODE_0_R_ERR 0x41
-#define SONY_ILL_MODE_R_ERR 0x42
-#define SONY_ILL_BLOCK_SIZE_R_ERR 0x43
-#define SONY_MODE_R_ERR 0x44
-#define SONY_FORM_R_ERR 0x45
-#define SONY_LEAD_OUT_R_ERR 0x46
-#define SONY_BUFFER_OVERRUN_R_ERR 0x47
-
-/* Data error group */
-#define SONY_UNREC_CIRC_ERR 0x53
-#define SONY_UNREC_LECC_ERR 0x57
-
-/* Subcode error group */
-#define SONY_NO_TOC_ERR 0x60
-#define SONY_SUBCODE_DATA_NVAL_ERR 0x61
-#define SONY_FOCUS_ON_TOC_READ_ERR 0x63
-#define SONY_FRAME_SYNC_ON_TOC_READ_ERR 0x64
-#define SONY_TOC_DATA_ERR 0x65
-
-/* Hardware failure group */
-#define SONY_HW_FAILURE_ERR 0x70
-#define SONY_LEAD_IN_A_ERR 0x91
-#define SONY_LEAD_OUT_A_ERR 0x92
-#define SONY_DATA_TRACK_A_ERR 0x93
-
-/*
- * The following are returned from the Read With Block Error Status command.
- * They are not errors but information (Errors from the 0x5x group above may
- * also be returned
- */
-#define SONY_NO_CIRC_ERR_BLK_STAT 0x50
-#define SONY_NO_LECC_ERR_BLK_STAT 0x54
-#define SONY_RECOV_LECC_ERR_BLK_STAT 0x55
-#define SONY_NO_ERR_DETECTION_STAT 0x59
-
-/*
- * The following is not an error returned by the drive, but by the code
- * that talks to the drive. It is returned because of a timeout.
- */
-#define SONY_TIMEOUT_OP_ERR 0x01
-#define SONY_SIGNAL_OP_ERR 0x02
-#define SONY_BAD_DATA_ERR 0x03
-
-
-/*
- * The following are attention code for asynchronous events from the drive.
- */
-
-/* Standard attention group */
-#define SONY_EMER_EJECT_ATTN 0x2c
-#define SONY_HW_FAILURE_ATTN 0x70
-#define SONY_MECH_LOADED_ATTN 0x80
-#define SONY_EJECT_PUSHED_ATTN 0x81
-
-/* Audio attention group */
-#define SONY_AUDIO_PLAY_DONE_ATTN 0x90
-#define SONY_LEAD_IN_ERR_ATTN 0x91
-#define SONY_LEAD_OUT_ERR_ATTN 0x92
-#define SONY_DATA_TRACK_ERR_ATTN 0x93
-#define SONY_AUDIO_PLAYBACK_ERR_ATTN 0x94
-
-/* Auto spin up group */
-#define SONY_SPIN_UP_COMPLETE_ATTN 0x24
-#define SONY_SPINDLE_SERVO_ERR_ATTN 0x25
-#define SONY_FOCUS_SERVO_ERR_ATTN 0x26
-#define SONY_TOC_READ_DONE_ATTN 0x62
-#define SONY_FOCUS_ON_TOC_READ_ERR_ATTN 0x63
-#define SONY_SYNC_ON_TOC_READ_ERR_ATTN 0x65
-
-/* Auto eject group */
-#define SONY_SPIN_DOWN_COMPLETE_ATTN 0x27
-#define SONY_EJECT_COMPLETE_ATTN 0x28
-#define SONY_EJECT_MECH_ERR_ATTN 0x29
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
deleted file mode 100644
index 23013116324..00000000000
--- a/drivers/cdrom/cm206.c
+++ /dev/null
@@ -1,1594 +0,0 @@
-/* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card.
- Copyright (c) 1995--1997 David A. van Leeuwen.
- $Id: cm206.c,v 1.5 1997/12/26 11:02:51 david Exp $
-
- 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.
-
-History:
- Started 25 jan 1994. Waiting for documentation...
- 22 feb 1995: 0.1a first reasonably safe polling driver.
- Two major bugs, one in read_sector and one in
- do_cm206_request, happened to cancel!
- 25 feb 1995: 0.2a first reasonable interrupt driven version of above.
- uart writes are still done in polling mode.
- 25 feb 1995: 0.21a writes also in interrupt mode, still some
- small bugs to be found... Larger buffer.
- 2 mrt 1995: 0.22 Bug found (cd-> nowhere, interrupt was called in
- initialization), read_ahead of 16. Timeouts implemented.
- unclear if they do something...
- 7 mrt 1995: 0.23 Start of background read-ahead.
- 18 mrt 1995: 0.24 Working background read-ahead. (still problems)
- 26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
- Statistics implemented, though separate stats206.h.
- Accessible through ioctl 0x1000 (just a number).
- Hard to choose between v1.2 development and 1.1.75.
- Bottom-half doesn't work with 1.2...
- 0.25a: fixed... typo. Still problems...
- 1 apr 1995: 0.26 Module support added. Most bugs found. Use kernel 1.2.n.
- 5 apr 1995: 0.27 Auto-probe for the adapter card base address.
- Auto-probe for the adaptor card irq line.
- 7 apr 1995: 0.28 Added lilo setup support for base address and irq.
- Use major number 32 (not in this source), officially
- assigned to this driver.
- 9 apr 1995: 0.29 Added very limited audio support. Toc_header, stop, pause,
- resume, eject. Play_track ignores track info, because we can't
- read a table-of-contents entry. Toc_entry is implemented
- as a `placebo' function: always returns start of disc.
- 3 may 1995: 0.30 Audio support completed. The get_toc_entry function
- is implemented as a binary search.
- 15 may 1995: 0.31 More work on audio stuff. Workman is not easy to
- satisfy; changed binary search into linear search.
- Auto-probe for base address somewhat relaxed.
- 1 jun 1995: 0.32 Removed probe_irq_on/off for module version.
- 10 jun 1995: 0.33 Workman still behaves funny, but you should be
- able to eject and substitute another disc.
-
- An adaptation of 0.33 is included in linux-1.3.7 by Eberhard Moenkeberg
-
- 18 jul 1995: 0.34 Patch by Heiko Eissfeldt included, mainly considering
- verify_area's in the ioctls. Some bugs introduced by
- EM considering the base port and irq fixed.
-
- 18 dec 1995: 0.35 Add some code for error checking... no luck...
-
- We jump to reach our goal: version 1.0 in the next stable linux kernel.
-
- 19 mar 1996: 0.95 Different implementation of CDROM_GET_UPC, on
- request of Thomas Quinot.
- 25 mar 1996: 0.96 Interpretation of opening with O_WRONLY or O_RDWR:
- open only for ioctl operation, e.g., for operation of
- tray etc.
- 4 apr 1996: 0.97 First implementation of layer between VFS and cdrom
- driver, a generic interface. Much of the functionality
- of cm206_open() and cm206_ioctl() is transferred to a
- new file cdrom.c and its header ucdrom.h.
-
- Upgrade to Linux kernel 1.3.78.
-
- 11 apr 1996 0.98 Upgrade to Linux kernel 1.3.85
- More code moved to cdrom.c
-
- 0.99 Some more small changes to decrease number
- of oopses at module load;
-
- 27 jul 1996 0.100 Many hours of debugging, kernel change from 1.2.13
- to 2.0.7 seems to have introduced some weird behavior
- in (interruptible_)sleep_on(&cd->data): the process
- seems to be woken without any explicit wake_up in my own
- code. Patch to try 100x in case such untriggered wake_up's
- occur.
-
- 28 jul 1996 0.101 Rewriting of the code that receives the command echo,
- using a fifo to store echoed bytes.
-
- Branch from 0.99:
-
- 0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
- (emoenke) various typos found by others. extra
- module-load oops protection.
-
- 0.99.1.1 Initialization constant cdrom_dops.speed
- changed from float (2.0) to int (2); Cli()-sti() pair
- around cm260_reset() in module initialization code.
-
- 0.99.1.2 Changes literally as proposed by Scott Snyder
- <snyder@d0sgif.fnal.gov> for the 2.1 kernel line, which
- have to do mainly with the poor minor support i had. The
- major new concept is to change a cdrom driver's
- operations struct from the capabilities struct. This
- reflects the fact that there is one major for a driver,
- whilst there can be many minors whith completely
- different capabilities.
-
- 0.99.1.3 More changes for operations/info separation.
-
- 0.99.1.4 Added speed selection (someone had to do this
- first).
-
- 23 jan 1997 0.99.1.5 MODULE_PARMS call added.
-
- 23 jan 1997 0.100.1.2--0.100.1.5 following similar lines as
- 0.99.1.1--0.99.1.5. I get too many complaints about the
- drive making read errors. What't wrong with the 2.0+
- kernel line? Why get i (and othe cm206 owners) weird
- results? Why were things good in the good old 1.1--1.2
- era? Why don't i throw away the drive?
-
- 2 feb 1997 0.102 Added `volatile' to values in cm206_struct. Seems to
- reduce many of the problems. Rewrote polling routines
- to use fixed delays between polls.
- 0.103 Changed printk behavior.
- 0.104 Added a 0.100 -> 0.100.1.1 change
-
-11 feb 1997 0.105 Allow auto_probe during module load, disable
- with module option "auto_probe=0". Moved some debugging
- statements to lower priority. Implemented select_speed()
- function.
-
-13 feb 1997 1.0 Final version for 2.0 kernel line.
-
- All following changes will be for the 2.1 kernel line.
-
-15 feb 1997 1.1 Keep up with kernel 2.1.26, merge in changes from
- cdrom.c 0.100.1.1--1.0. Add some more MODULE_PARMS.
-
-14 sep 1997 1.2 Upgrade to Linux 2.1.55. Added blksize_size[], patch
- sent by James Bottomley <James.Bottomley@columbiasc.ncr.com>.
-
-21 dec 1997 1.4 Upgrade to Linux 2.1.72.
-
-24 jan 1998 Removed the cm206_disc_status() function, as it was now dead
- code. The Uniform CDROM driver now provides this functionality.
-
-9 Nov. 1999 Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
- *
- * Parts of the code are based upon lmscd.c written by Kai Petzke,
- * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
- * Harriss, but any off-the-shelf dynamic programming algorithm won't
- * be able to find them.
- *
- * The cm206 drive interface and the cm260 adapter card seem to be
- * sufficiently different from their cm205/cm250 counterparts
- * in order to write a complete new driver.
- *
- * I call all routines connected to the Linux kernel something
- * with `cm206' in it, as this stuff is too series-dependent.
- *
- * Currently, my limited knowledge is based on:
- * - The Linux Kernel Hacker's guide, v. 0.5, by Michael K. Johnson
- * - Linux Kernel Programmierung, by Michael Beck and others
- * - Philips/LMS cm206 and cm226 product specification
- * - Philips/LMS cm260 product specification
- *
- * David van Leeuwen, david@tm.tno.nl. */
-#define REVISION "$Revision: 1.5 $"
-
-#include <linux/module.h>
-
-#include <linux/errno.h> /* These include what we really need */
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-/* #include <linux/ucdrom.h> */
-
-#include <asm/io.h>
-
-#define MAJOR_NR CM206_CDROM_MAJOR
-
-#include <linux/blkdev.h>
-
-#undef DEBUG
-#define STATISTICS /* record times and frequencies of events */
-#define AUTO_PROBE_MODULE
-#define USE_INSW
-
-#include "cm206.h"
-
-/* This variable defines whether or not to probe for adapter base port
- address and interrupt request. It can be overridden by the boot
- parameter `auto'.
-*/
-static int auto_probe = 1; /* Yes, why not? */
-
-static int cm206_base = CM206_BASE;
-static int cm206_irq = CM206_IRQ;
-#ifdef MODULE
-static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */
-module_param_array(cm206, int, NULL, 0); /* base,irq or irq,base */
-#endif
-
-module_param(cm206_base, int, 0); /* base */
-module_param(cm206_irq, int, 0); /* irq */
-module_param(auto_probe, bool, 0); /* auto probe base and irq */
-MODULE_LICENSE("GPL");
-
-#define POLLOOP 100 /* milliseconds */
-#define READ_AHEAD 1 /* defines private buffer, waste! */
-#define BACK_AHEAD 1 /* defines adapter-read ahead */
-#define DATA_TIMEOUT (3*HZ) /* measured in jiffies (10 ms) */
-#define UART_TIMEOUT (5*HZ/100)
-#define DSB_TIMEOUT (7*HZ) /* time for the slowest command to finish */
-#define UR_SIZE 4 /* uart receive buffer fifo size */
-
-#define LINUX_BLOCK_SIZE 512 /* WHERE is this defined? */
-#define RAW_SECTOR_SIZE 2352 /* ok, is also defined in cdrom.h */
-#define ISO_SECTOR_SIZE 2048
-#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE) /* 4 */
-#define CD_SYNC_HEAD 16 /* CD_SYNC + CD_HEAD */
-
-#ifdef STATISTICS /* keep track of errors in counters */
-#define stats(i) { ++cd->stats[st_ ## i]; \
- cd->last_stat[st_ ## i] = cd->stat_counter++; \
- }
-#else
-#define stats(i) (void) 0;
-#endif
-
-#define Debug(a) {printk (KERN_DEBUG); printk a;}
-#ifdef DEBUG
-#define debug(a) Debug(a)
-#else
-#define debug(a) (void) 0;
-#endif
-
-typedef unsigned char uch; /* 8-bits */
-typedef unsigned short ush; /* 16-bits */
-
-struct toc_struct { /* private copy of Table of Contents */
- uch track, fsm[3], q0;
-};
-
-struct cm206_struct {
- volatile ush intr_ds; /* data status read on last interrupt */
- volatile ush intr_ls; /* uart line status read on last interrupt */
- volatile uch ur[UR_SIZE]; /* uart receive buffer fifo */
- volatile uch ur_w, ur_r; /* write/read buffer index */
- volatile uch dsb, cc; /* drive status byte and condition (error) code */
- int command; /* command to be written to the uart */
- int openfiles;
- ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2]; /* buffered cd-sector */
- int sector_first, sector_last; /* range of these sectors */
- wait_queue_head_t uart; /* wait queues for interrupt */
- wait_queue_head_t data;
- struct timer_list timer; /* time-out */
- char timed_out;
- signed char max_sectors; /* number of sectors that fit in adapter mem */
- char wait_back; /* we're waiting for a background-read */
- char background; /* is a read going on in the background? */
- int adapter_first; /* if so, that's the starting sector */
- int adapter_last;
- char fifo_overflowed;
- uch disc_status[7]; /* result of get_disc_status command */
-#ifdef STATISTICS
- int stats[NR_STATS];
- int last_stat[NR_STATS]; /* `time' at which stat was stat */
- int stat_counter;
-#endif
- struct toc_struct toc[101]; /* The whole table of contents + lead-out */
- uch q[10]; /* Last read q-channel info */
- uch audio_status[5]; /* last read position on pause */
- uch media_changed; /* record if media changed */
-};
-
-#define DISC_STATUS cd->disc_status[0]
-#define FIRST_TRACK cd->disc_status[1]
-#define LAST_TRACK cd->disc_status[2]
-#define PAUSED cd->audio_status[0] /* misuse this memory byte! */
-#define PLAY_TO cd->toc[0] /* toc[0] records end-time in play */
-
-static struct cm206_struct *cd; /* the main memory structure */
-static struct request_queue *cm206_queue;
-static DEFINE_SPINLOCK(cm206_lock);
-
-/* First, we define some polling functions. These are actually
- only being used in the initialization. */
-
-static void send_command_polled(int command)
-{
- int loop = POLLOOP;
- while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
- && loop > 0) {
- mdelay(1); /* one millisec delay */
- --loop;
- }
- outw(command, r_uart_transmit);
-}
-
-static uch receive_echo_polled(void)
-{
- int loop = POLLOOP;
- while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
- mdelay(1);
- --loop;
- }
- return ((uch) inw(r_uart_receive));
-}
-
-static uch send_receive_polled(int command)
-{
- send_command_polled(command);
- return receive_echo_polled();
-}
-
-static inline void clear_ur(void)
-{
- if (cd->ur_r != cd->ur_w) {
- debug(("Deleting bytes from fifo:"));
- for (; cd->ur_r != cd->ur_w;
- cd->ur_r++, cd->ur_r %= UR_SIZE)
- debug((" 0x%x", cd->ur[cd->ur_r]));
- debug(("\n"));
- }
-}
-
-static struct tasklet_struct cm206_tasklet;
-
-/* The interrupt handler. When the cm260 generates an interrupt, very
- much care has to be taken in reading out the registers in the right
- order; in case of a receive_buffer_full interrupt, first the
- uart_receive must be read, and then the line status again to
- de-assert the interrupt line. It took me a couple of hours to find
- this out:-(
-
- The function reset_cm206 appears to cause an interrupt, because
- pulling up the INIT line clears both the uart-write-buffer /and/
- the uart-write-buffer-empty mask. We call this a `lost interrupt,'
- as there seems so reason for this to happen.
-*/
-
-static irqreturn_t cm206_interrupt(int sig, void *dev_id)
-{
- volatile ush fool;
- cd->intr_ds = inw(r_data_status); /* resets data_ready, data_error,
- crc_error, sync_error, toc_ready
- interrupts */
- cd->intr_ls = inw(r_line_status); /* resets overrun bit */
- debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls,
- cd->background));
- if (cd->intr_ls & ls_attention)
- stats(attention);
- /* receive buffer full? */
- if (cd->intr_ls & ls_receive_buffer_full) {
- cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */
- cd->intr_ls = inw(r_line_status); /* resets rbf interrupt */
- debug(("receiving #%d: 0x%x\n", cd->ur_w,
- cd->ur[cd->ur_w]));
- cd->ur_w++;
- cd->ur_w %= UR_SIZE;
- if (cd->ur_w == cd->ur_r)
- debug(("cd->ur overflow!\n"));
- if (waitqueue_active(&cd->uart) && cd->background < 2) {
- del_timer(&cd->timer);
- wake_up_interruptible(&cd->uart);
- }
- }
- /* data ready in fifo? */
- else if (cd->intr_ds & ds_data_ready) {
- if (cd->background)
- ++cd->adapter_last;
- if (waitqueue_active(&cd->data)
- && (cd->wait_back || !cd->background)) {
- del_timer(&cd->timer);
- wake_up_interruptible(&cd->data);
- }
- stats(data_ready);
- }
- /* ready to issue a write command? */
- else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
- outw(dc_normal | (inw(r_data_status) & 0x7f),
- r_data_control);
- outw(cd->command, r_uart_transmit);
- cd->command = 0;
- if (!cd->background)
- wake_up_interruptible(&cd->uart);
- }
- /* now treat errors (at least, identify them for debugging) */
- else if (cd->intr_ds & ds_fifo_overflow) {
- debug(("Fifo overflow at sectors 0x%x\n",
- cd->sector_first));
- fool = inw(r_fifo_output_buffer); /* de-assert the interrupt */
- cd->fifo_overflowed = 1; /* signal one word less should be read */
- stats(fifo_overflow);
- } else if (cd->intr_ds & ds_data_error) {
- debug(("Data error at sector 0x%x\n", cd->sector_first));
- stats(data_error);
- } else if (cd->intr_ds & ds_crc_error) {
- debug(("CRC error at sector 0x%x\n", cd->sector_first));
- stats(crc_error);
- } else if (cd->intr_ds & ds_sync_error) {
- debug(("Sync at sector 0x%x\n", cd->sector_first));
- stats(sync_error);
- } else if (cd->intr_ds & ds_toc_ready) {
- /* do something appropriate */
- }
- /* couldn't see why this interrupt, maybe due to init */
- else {
- outw(dc_normal | READ_AHEAD, r_data_control);
- stats(lost_intr);
- }
- if (cd->background
- && (cd->adapter_last - cd->adapter_first == cd->max_sectors
- || cd->fifo_overflowed))
- tasklet_schedule(&cm206_tasklet); /* issue a stop read command */
- stats(interrupt);
- return IRQ_HANDLED;
-}
-
-/* we have put the address of the wait queue in who */
-static void cm206_timeout(unsigned long who)
-{
- cd->timed_out = 1;
- debug(("Timing out\n"));
- wake_up_interruptible((wait_queue_head_t *) who);
-}
-
-/* This function returns 1 if a timeout occurred, 0 if an interrupt
- happened */
-static int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
-{
- cd->timed_out = 0;
- init_timer(&cd->timer);
- cd->timer.data = (unsigned long) wait;
- cd->timer.expires = jiffies + timeout;
- add_timer(&cd->timer);
- debug(("going to sleep\n"));
- interruptible_sleep_on(wait);
- del_timer(&cd->timer);
- if (cd->timed_out) {
- cd->timed_out = 0;
- return 1;
- } else
- return 0;
-}
-
-static void send_command(int command)
-{
- debug(("Sending 0x%x\n", command));
- if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
- cd->command = command;
- cli(); /* don't interrupt before sleep */
- outw(dc_mask_sync_error | dc_no_stop_on_error |
- (inw(r_data_status) & 0x7f), r_data_control);
- /* interrupt routine sends command */
- if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
- debug(("Time out on write-buffer\n"));
- stats(write_timeout);
- outw(command, r_uart_transmit);
- }
- debug(("Write commmand delayed\n"));
- } else
- outw(command, r_uart_transmit);
-}
-
-static uch receive_byte(int timeout)
-{
- uch ret;
- cli();
- debug(("cli\n"));
- ret = cd->ur[cd->ur_r];
- if (cd->ur_r != cd->ur_w) {
- sti();
- debug(("returning #%d: 0x%x\n", cd->ur_r,
- cd->ur[cd->ur_r]));
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- return ret;
- } else if (sleep_or_timeout(&cd->uart, timeout)) { /* does sti() */
- debug(("Time out on receive-buffer\n"));
-#ifdef STATISTICS
- if (timeout == UART_TIMEOUT)
- stats(receive_timeout) /* no `;'! */
- else
- stats(dsb_timeout);
-#endif
- return 0xda;
- }
- ret = cd->ur[cd->ur_r];
- debug(("slept; returning #%d: 0x%x\n", cd->ur_r,
- cd->ur[cd->ur_r]));
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- return ret;
-}
-
-static inline uch receive_echo(void)
-{
- return receive_byte(UART_TIMEOUT);
-}
-
-static inline uch send_receive(int command)
-{
- send_command(command);
- return receive_echo();
-}
-
-static inline uch wait_dsb(void)
-{
- return receive_byte(DSB_TIMEOUT);
-}
-
-static int type_0_command(int command, int expect_dsb)
-{
- int e;
- clear_ur();
- if (command != (e = send_receive(command))) {
- debug(("command 0x%x echoed as 0x%x\n", command, e));
- stats(echo);
- return -1;
- }
- if (expect_dsb) {
- cd->dsb = wait_dsb(); /* wait for command to finish */
- }
- return 0;
-}
-
-static int type_1_command(int command, int bytes, uch * status)
-{ /* returns info */
- int i;
- if (type_0_command(command, 0))
- return -1;
- for (i = 0; i < bytes; i++)
- status[i] = send_receive(c_gimme);
- return 0;
-}
-
-/* This function resets the adapter card. We'd better not do this too
- * often, because it tends to generate `lost interrupts.' */
-static void reset_cm260(void)
-{
- outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
- udelay(10); /* 3.3 mu sec minimum */
- outw(dc_normal | READ_AHEAD, r_data_control);
-}
-
-/* fsm: frame-sec-min from linear address; one of many */
-static void fsm(int lba, uch * fsm)
-{
- fsm[0] = lba % 75;
- lba /= 75;
- lba += 2;
- fsm[1] = lba % 60;
- fsm[2] = lba / 60;
-}
-
-static inline int fsm2lba(uch * fsm)
-{
- return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
-}
-
-static inline int f_s_m2lba(uch f, uch s, uch m)
-{
- return f + 75 * (s - 2 + 60 * m);
-}
-
-static int start_read(int start)
-{
- uch read_sector[4] = { c_read_data, };
- int i, e;
-
- fsm(start, &read_sector[1]);
- clear_ur();
- for (i = 0; i < 4; i++)
- if (read_sector[i] != (e = send_receive(read_sector[i]))) {
- debug(("read_sector: %x echoes %x\n",
- read_sector[i], e));
- stats(echo);
- if (e == 0xff) { /* this seems to happen often */
- e = receive_echo();
- debug(("Second try %x\n", e));
- if (e != read_sector[i])
- return -1;
- }
- }
- return 0;
-}
-
-static int stop_read(void)
-{
- int e;
- type_0_command(c_stop, 0);
- if ((e = receive_echo()) != 0xff) {
- debug(("c_stop didn't send 0xff, but 0x%x\n", e));
- stats(stop_0xff);
- return -1;
- }
- return 0;
-}
-
-/* This function starts to read sectors in adapter memory, the
- interrupt routine should stop the read. In fact, the bottom_half
- routine takes care of this. Set a flag `background' in the cd
- struct to indicate the process. */
-
-static int read_background(int start, int reading)
-{
- if (cd->background)
- return -1; /* can't do twice */
- outw(dc_normal | BACK_AHEAD, r_data_control);
- if (!reading && start_read(start))
- return -2;
- cd->adapter_first = cd->adapter_last = start;
- cd->background = 1; /* flag a read is going on */
- return 0;
-}
-
-#ifdef USE_INSW
-#define transport_data insw
-#else
-/* this routine implements insw(,,). There was a time i had the
- impression that there would be any difference in error-behaviour. */
-void transport_data(int port, ush * dest, int count)
-{
- int i;
- ush *d;
- for (i = 0, d = dest; i < count; i++, d++)
- *d = inw(port);
-}
-#endif
-
-
-#define MAX_TRIES 100
-static int read_sector(int start)
-{
- int tries = 0;
- if (cd->background) {
- cd->background = 0;
- cd->adapter_last = -1; /* invalidate adapter memory */
- stop_read();
- }
- cd->fifo_overflowed = 0;
- reset_cm260(); /* empty fifo etc. */
- if (start_read(start))
- return -1;
- do {
- if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
- debug(("Read timed out sector 0x%x\n", start));
- stats(read_timeout);
- stop_read();
- return -3;
- }
- tries++;
- } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
- if (tries > 1)
- debug(("Took me some tries\n"))
- else
- if (tries == MAX_TRIES)
- debug(("MAX_TRIES tries for read sector\n"));
- transport_data(r_fifo_output_buffer, cd->sector,
- READ_AHEAD * RAW_SECTOR_SIZE / 2);
- if (read_background(start + READ_AHEAD, 1))
- stats(read_background);
- cd->sector_first = start;
- cd->sector_last = start + READ_AHEAD;
- stats(read_restarted);
- return 0;
-}
-
-/* The function of bottom-half is to send a stop command to the drive
- This isn't easy because the routine is not `owned' by any process;
- we can't go to sleep! The variable cd->background gives the status:
- 0 no read pending
- 1 a read is pending
- 2 c_stop waits for write_buffer_empty
- 3 c_stop waits for receive_buffer_full: echo
- 4 c_stop waits for receive_buffer_full: 0xff
-*/
-
-static void cm206_tasklet_func(unsigned long ignore)
-{
- debug(("bh: %d\n", cd->background));
- switch (cd->background) {
- case 1:
- stats(bh);
- if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
- cd->command = c_stop;
- outw(dc_mask_sync_error | dc_no_stop_on_error |
- (inw(r_data_status) & 0x7f), r_data_control);
- cd->background = 2;
- break; /* we'd better not time-out here! */
- } else
- outw(c_stop, r_uart_transmit);
- /* fall into case 2: */
- case 2:
- /* the write has been satisfied by interrupt routine */
- cd->background = 3;
- break;
- case 3:
- if (cd->ur_r != cd->ur_w) {
- if (cd->ur[cd->ur_r] != c_stop) {
- debug(("cm206_bh: c_stop echoed 0x%x\n",
- cd->ur[cd->ur_r]));
- stats(echo);
- }
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- }
- cd->background++;
- break;
- case 4:
- if (cd->ur_r != cd->ur_w) {
- if (cd->ur[cd->ur_r] != 0xff) {
- debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
- stats(stop_0xff);
- }
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- }
- cd->background = 0;
- }
-}
-
-static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
-
-/* This command clears the dsb_possible_media_change flag, so we must
- * retain it.
- */
-static void get_drive_status(void)
-{
- uch status[2];
- type_1_command(c_drive_status, 2, status); /* this might be done faster */
- cd->dsb = status[0];
- cd->cc = status[1];
- cd->media_changed |=
- !!(cd->dsb & (dsb_possible_media_change |
- dsb_drive_not_ready | dsb_tray_not_closed));
-}
-
-static void get_disc_status(void)
-{
- if (type_1_command(c_disc_status, 7, cd->disc_status)) {
- debug(("get_disc_status: error\n"));
- }
-}
-
-/* The new open. The real opening strategy is defined in cdrom.c. */
-
-static int cm206_open(struct cdrom_device_info *cdi, int purpose)
-{
- if (!cd->openfiles) { /* reset only first time */
- cd->background = 0;
- reset_cm260();
- cd->adapter_last = -1; /* invalidate adapter memory */
- cd->sector_last = -1;
- }
- ++cd->openfiles;
- stats(open);
- return 0;
-}
-
-static void cm206_release(struct cdrom_device_info *cdi)
-{
- if (cd->openfiles == 1) {
- if (cd->background) {
- cd->background = 0;
- stop_read();
- }
- cd->sector_last = -1; /* Make our internal buffer invalid */
- FIRST_TRACK = 0; /* No valid disc status */
- }
- --cd->openfiles;
-}
-
-/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
- * and then reads a sector in kernel memory. */
-static void empty_buffer(int sectors)
-{
- while (sectors >= 0) {
- transport_data(r_fifo_output_buffer,
- cd->sector + cd->fifo_overflowed,
- RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed);
- --sectors;
- ++cd->adapter_first; /* update the current adapter sector */
- cd->fifo_overflowed = 0; /* reset overflow bit */
- stats(sector_transferred);
- }
- cd->sector_first = cd->adapter_first - 1;
- cd->sector_last = cd->adapter_first; /* update the buffer sector */
-}
-
-/* try_adapter. This function determines if the requested sector is
- in adapter memory, or will appear there soon. Returns 0 upon
- success */
-static int try_adapter(int sector)
-{
- if (cd->adapter_first <= sector && sector < cd->adapter_last) {
- /* sector is in adapter memory */
- empty_buffer(sector - cd->adapter_first);
- return 0;
- } else if (cd->background == 1 && cd->adapter_first <= sector
- && sector < cd->adapter_first + cd->max_sectors) {
- /* a read is going on, we can wait for it */
- cd->wait_back = 1;
- while (sector >= cd->adapter_last) {
- if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
- debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background));
- stats(back_read_timeout);
- cd->wait_back = 0;
- return -1;
- }
- }
- cd->wait_back = 0;
- empty_buffer(sector - cd->adapter_first);
- return 0;
- } else
- return -2;
-}
-
-/* This is not a very smart implementation. We could optimize for
- consecutive block numbers. I'm not convinced this would really
- bring down the processor load. */
-static void do_cm206_request(request_queue_t * q)
-{
- long int i, cd_sec_no;
- int quarter, error;
- uch *source, *dest;
- struct request *req;
-
- while (1) { /* repeat until all requests have been satisfied */
- req = elv_next_request(q);
- if (!req)
- return;
-
- if (req->cmd != READ) {
- debug(("Non-read command %d on cdrom\n", req->cmd));
- end_request(req, 0);
- continue;
- }
- spin_unlock_irq(q->queue_lock);
- error = 0;
- for (i = 0; i < req->nr_sectors; i++) {
- int e1, e2;
- cd_sec_no = (req->sector + i) / BLOCKS_ISO; /* 4 times 512 bytes */
- quarter = (req->sector + i) % BLOCKS_ISO;
- dest = req->buffer + i * LINUX_BLOCK_SIZE;
- /* is already in buffer memory? */
- if (cd->sector_first <= cd_sec_no
- && cd_sec_no < cd->sector_last) {
- source =
- ((uch *) cd->sector) + 16 +
- quarter * LINUX_BLOCK_SIZE +
- (cd_sec_no -
- cd->sector_first) * RAW_SECTOR_SIZE;
- memcpy(dest, source, LINUX_BLOCK_SIZE);
- } else if (!(e1 = try_adapter(cd_sec_no)) ||
- !(e2 = read_sector(cd_sec_no))) {
- source =
- ((uch *) cd->sector) + 16 +
- quarter * LINUX_BLOCK_SIZE;
- memcpy(dest, source, LINUX_BLOCK_SIZE);
- } else {
- error = 1;
- debug(("cm206_request: %d %d\n", e1, e2));
- }
- }
- spin_lock_irq(q->queue_lock);
- end_request(req, !error);
- }
-}
-
-/* Audio support. I've tried very hard, but the cm206 drive doesn't
- seem to have a get_toc (table-of-contents) function, while i'm
- pretty sure it must read the toc upon disc insertion. Therefore
- this function has been implemented through a binary search
- strategy. All track starts that happen to be found are stored in
- cd->toc[], for future use.
-
- I've spent a whole day on a bug that only shows under Workman---
- I don't get it. Tried everything, nothing works. If workman asks
- for track# 0xaa, it'll get the wrong time back. Any other program
- receives the correct value. I'm stymied.
-*/
-
-/* seek seeks to address lba. It does wait to arrive there. */
-static void seek(int lba)
-{
- int i;
- uch seek_command[4] = { c_seek, };
-
- fsm(lba, &seek_command[1]);
- for (i = 0; i < 4; i++)
- type_0_command(seek_command[i], 0);
- cd->dsb = wait_dsb();
-}
-
-static uch bcdbin(unsigned char bcd)
-{ /* stolen from mcd.c! */
- return (bcd >> 4) * 10 + (bcd & 0xf);
-}
-
-static inline uch normalize_track(uch track)
-{
- if (track < 1)
- return 1;
- if (track > LAST_TRACK)
- return LAST_TRACK + 1;
- return track;
-}
-
-/* This function does a binary search for track start. It records all
- * tracks seen in the process. Input $track$ must be between 1 and
- * #-of-tracks+1. Note that the start of the disc must be in toc[1].fsm.
- */
-static int get_toc_lba(uch track)
-{
- int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
- int i, lba, l, old_lba = 0;
- uch *q = cd->q;
- uch ct; /* current track */
- int binary = 0;
- const int skip = 3 * 60 * 75; /* 3 minutes */
-
- for (i = track; i > 0; i--)
- if (cd->toc[i].track) {
- min = fsm2lba(cd->toc[i].fsm);
- break;
- }
- lba = min + skip;
- do {
- seek(lba);
- type_1_command(c_read_current_q, 10, q);
- ct = normalize_track(q[1]);
- if (!cd->toc[ct].track) {
- l = q[9] - bcdbin(q[5]) + 75 * (q[8] -
- bcdbin(q[4]) - 2 +
- 60 * (q[7] -
- bcdbin(q
- [3])));
- cd->toc[ct].track = q[1]; /* lead out still 0xaa */
- fsm(l, cd->toc[ct].fsm);
- cd->toc[ct].q0 = q[0]; /* contains adr and ctrl info */
- if (ct == track)
- return l;
- }
- old_lba = lba;
- if (binary) {
- if (ct < track)
- min = lba;
- else
- max = lba;
- lba = (min + max) / 2;
- } else {
- if (ct < track)
- lba += skip;
- else {
- binary = 1;
- max = lba;
- min = lba - skip;
- lba = (min + max) / 2;
- }
- }
- } while (lba != old_lba);
- return lba;
-}
-
-static void update_toc_entry(uch track)
-{
- track = normalize_track(track);
- if (!cd->toc[track].track)
- get_toc_lba(track);
-}
-
-/* return 0 upon success */
-static int read_toc_header(struct cdrom_tochdr *hp)
-{
- if (!FIRST_TRACK)
- get_disc_status();
- if (hp) {
- int i;
- hp->cdth_trk0 = FIRST_TRACK;
- hp->cdth_trk1 = LAST_TRACK;
- /* fill in first track position */
- for (i = 0; i < 3; i++)
- cd->toc[1].fsm[i] = cd->disc_status[3 + i];
- update_toc_entry(LAST_TRACK + 1); /* find most entries */
- return 0;
- }
- return -1;
-}
-
-static void play_from_to_msf(struct cdrom_msf *msfp)
-{
- uch play_command[] = { c_play,
- msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
- msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2,
- 2
- };
- int i;
- for (i = 0; i < 9; i++)
- type_0_command(play_command[i], 0);
- for (i = 0; i < 3; i++)
- PLAY_TO.fsm[i] = play_command[i + 4];
- PLAY_TO.track = 0; /* say no track end */
- cd->dsb = wait_dsb();
-}
-
-static void play_from_to_track(int from, int to)
-{
- uch play_command[8] = { c_play, };
- int i;
-
- if (from == 0) { /* continue paused play */
- for (i = 0; i < 3; i++) {
- play_command[i + 1] = cd->audio_status[i + 2];
- play_command[i + 4] = PLAY_TO.fsm[i];
- }
- } else {
- update_toc_entry(from);
- update_toc_entry(to + 1);
- for (i = 0; i < 3; i++) {
- play_command[i + 1] = cd->toc[from].fsm[i];
- PLAY_TO.fsm[i] = play_command[i + 4] =
- cd->toc[to + 1].fsm[i];
- }
- PLAY_TO.track = to;
- }
- for (i = 0; i < 7; i++)
- type_0_command(play_command[i], 0);
- for (i = 0; i < 2; i++)
- type_0_command(0x2, 0); /* volume */
- cd->dsb = wait_dsb();
-}
-
-static int get_current_q(struct cdrom_subchnl *qp)
-{
- int i;
- uch *q = cd->q;
- if (type_1_command(c_read_current_q, 10, q))
- return 0;
-/* q[0] = bcdbin(q[0]); Don't think so! */
- for (i = 2; i < 6; i++)
- q[i] = bcdbin(q[i]);
- qp->cdsc_adr = q[0] & 0xf;
- qp->cdsc_ctrl = q[0] >> 4; /* from mcd.c */
- qp->cdsc_trk = q[1];
- qp->cdsc_ind = q[2];
- if (qp->cdsc_format == CDROM_MSF) {
- qp->cdsc_reladdr.msf.minute = q[3];
- qp->cdsc_reladdr.msf.second = q[4];
- qp->cdsc_reladdr.msf.frame = q[5];
- qp->cdsc_absaddr.msf.minute = q[7];
- qp->cdsc_absaddr.msf.second = q[8];
- qp->cdsc_absaddr.msf.frame = q[9];
- } else {
- qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
- qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
- }
- get_drive_status();
- if (cd->dsb & dsb_play_in_progress)
- qp->cdsc_audiostatus = CDROM_AUDIO_PLAY;
- else if (PAUSED)
- qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
- else
- qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
- return 0;
-}
-
-static void invalidate_toc(void)
-{
- memset(cd->toc, 0, sizeof(cd->toc));
- memset(cd->disc_status, 0, sizeof(cd->disc_status));
-}
-
-/* cdrom.c guarantees that cdte_format == CDROM_MSF */
-static void get_toc_entry(struct cdrom_tocentry *ep)
-{
- uch track = normalize_track(ep->cdte_track);
- update_toc_entry(track);
- ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
- ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
- ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
- ep->cdte_adr = cd->toc[track].q0 & 0xf;
- ep->cdte_ctrl = cd->toc[track].q0 >> 4;
- ep->cdte_datamode = 0;
-}
-
-/* Audio ioctl. Ioctl commands connected to audio are in such an
- * idiosyncratic i/o format, that we leave these untouched. Return 0
- * upon success. Memory checking has been done by cdrom_ioctl(), the
- * calling function, as well as LBA/MSF sanitization.
-*/
-static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- void *arg)
-{
- switch (cmd) {
- case CDROMREADTOCHDR:
- return read_toc_header((struct cdrom_tochdr *) arg);
- case CDROMREADTOCENTRY:
- get_toc_entry((struct cdrom_tocentry *) arg);
- return 0;
- case CDROMPLAYMSF:
- play_from_to_msf((struct cdrom_msf *) arg);
- return 0;
- case CDROMPLAYTRKIND: /* admittedly, not particularly beautiful */
- play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0,
- ((struct cdrom_ti *) arg)->cdti_trk1);
- return 0;
- case CDROMSTOP:
- PAUSED = 0;
- if (cd->dsb & dsb_play_in_progress)
- return type_0_command(c_stop, 1);
- else
- return 0;
- case CDROMPAUSE:
- get_drive_status();
- if (cd->dsb & dsb_play_in_progress) {
- type_0_command(c_stop, 1);
- type_1_command(c_audio_status, 5,
- cd->audio_status);
- PAUSED = 1; /* say we're paused */
- }
- return 0;
- case CDROMRESUME:
- if (PAUSED)
- play_from_to_track(0, 0);
- PAUSED = 0;
- return 0;
- case CDROMSTART:
- case CDROMVOLCTRL:
- return 0;
- case CDROMSUBCHNL:
- return get_current_q((struct cdrom_subchnl *) arg);
- default:
- return -EINVAL;
- }
-}
-
-static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- if (cd != NULL) {
- int r;
- get_drive_status(); /* ensure cd->media_changed OK */
- r = cd->media_changed;
- cd->media_changed = 0; /* clear bit */
- return r;
- } else
- return -EIO;
-}
-
-/* The new generic cdrom support. Routines should be concise, most of
- the logic should be in cdrom.c */
-
-
-/* controls tray movement */
-static int cm206_tray_move(struct cdrom_device_info *cdi, int position)
-{
- if (position) { /* 1: eject */
- type_0_command(c_open_tray, 1);
- invalidate_toc();
- } else
- type_0_command(c_close_tray, 1); /* 0: close */
- return 0;
-}
-
-/* gives current state of the drive */
-static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- get_drive_status();
- if (cd->dsb & dsb_tray_not_closed)
- return CDS_TRAY_OPEN;
- if (!(cd->dsb & dsb_disc_present))
- return CDS_NO_DISC;
- if (cd->dsb & dsb_drive_not_ready)
- return CDS_DRIVE_NOT_READY;
- return CDS_DISC_OK;
-}
-
-/* locks or unlocks door lock==1: lock; return 0 upon success */
-static int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
-{
- uch command = (lock) ? c_lock_tray : c_unlock_tray;
- type_0_command(command, 1); /* wait and get dsb */
- /* the logic calculates the success, 0 means successful */
- return lock ^ ((cd->dsb & dsb_tray_locked) != 0);
-}
-
-/* Although a session start should be in LBA format, we return it in
- MSF format because it is slightly easier, and the new generic ioctl
- will take care of the necessary conversion. */
-static int cm206_get_last_session(struct cdrom_device_info *cdi,
- struct cdrom_multisession *mssp)
-{
- if (!FIRST_TRACK)
- get_disc_status();
- if (mssp != NULL) {
- if (DISC_STATUS & cds_multi_session) { /* multi-session */
- mssp->addr.msf.frame = cd->disc_status[3];
- mssp->addr.msf.second = cd->disc_status[4];
- mssp->addr.msf.minute = cd->disc_status[5];
- mssp->addr_format = CDROM_MSF;
- mssp->xa_flag = 1;
- } else {
- mssp->xa_flag = 0;
- }
- return 1;
- }
- return 0;
-}
-
-static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
- uch upc[10];
- char *ret = mcn->medium_catalog_number;
- int i;
-
- if (type_1_command(c_read_upc, 10, upc))
- return -EIO;
- for (i = 0; i < 13; i++) {
- int w = i / 2 + 1, r = i % 2;
- if (r)
- ret[i] = 0x30 | (upc[w] & 0x0f);
- else
- ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f);
- }
- ret[13] = '\0';
- return 0;
-}
-
-static int cm206_reset(struct cdrom_device_info *cdi)
-{
- stop_read();
- reset_cm260();
- outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
- mdelay(1); /* 750 musec minimum */
- outw(dc_normal | READ_AHEAD, r_data_control);
- cd->sector_last = -1; /* flag no data buffered */
- cd->adapter_last = -1;
- invalidate_toc();
- return 0;
-}
-
-static int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
-{
- int r;
- switch (speed) {
- case 0:
- r = type_0_command(c_auto_mode, 1);
- break;
- case 1:
- r = type_0_command(c_force_1x, 1);
- break;
- case 2:
- r = type_0_command(c_force_2x, 1);
- break;
- default:
- return -1;
- }
- if (r < 0)
- return r;
- else
- return 1;
-}
-
-static struct cdrom_device_ops cm206_dops = {
- .open = cm206_open,
- .release = cm206_release,
- .drive_status = cm206_drive_status,
- .media_changed = cm206_media_changed,
- .tray_move = cm206_tray_move,
- .lock_door = cm206_lock_door,
- .select_speed = cm206_select_speed,
- .get_last_session = cm206_get_last_session,
- .get_mcn = cm206_get_upc,
- .reset = cm206_reset,
- .audio_ioctl = cm206_audio_ioctl,
- .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
- CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
- CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
- CDC_DRIVE_STATUS,
- .n_minors = 1,
-};
-
-
-static struct cdrom_device_info cm206_info = {
- .ops = &cm206_dops,
- .speed = 2,
- .capacity = 1,
- .name = "cm206",
-};
-
-static int cm206_block_open(struct inode *inode, struct file *file)
-{
- return cdrom_open(&cm206_info, inode, file);
-}
-
-static int cm206_block_release(struct inode *inode, struct file *file)
-{
- return cdrom_release(&cm206_info, file);
-}
-
-static int cm206_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- switch (cmd) {
-#ifdef STATISTICS
- case CM206CTL_GET_STAT:
- if (arg >= NR_STATS)
- return -EINVAL;
- return cd->stats[arg];
- case CM206CTL_GET_LAST_STAT:
- if (arg >= NR_STATS)
- return -EINVAL;
- return cd->last_stat[arg];
-#endif
- default:
- break;
- }
-
- return cdrom_ioctl(file, &cm206_info, inode, cmd, arg);
-}
-
-static int cm206_block_media_changed(struct gendisk *disk)
-{
- return cdrom_media_changed(&cm206_info);
-}
-
-static struct block_device_operations cm206_bdops =
-{
- .owner = THIS_MODULE,
- .open = cm206_block_open,
- .release = cm206_block_release,
- .ioctl = cm206_block_ioctl,
- .media_changed = cm206_block_media_changed,
-};
-
-static struct gendisk *cm206_gendisk;
-
-/* This function probes for the adapter card. It returns the base
- address if it has found the adapter card. One can specify a base
- port to probe specifically, or 0 which means span all possible
- bases.
-
- Linus says it is too dangerous to use writes for probing, so we
- stick with pure reads for a while. Hope that 8 possible ranges,
- request_region, 15 bits of one port and 6 of another make things
- likely enough to accept the region on the first hit...
- */
-static int __init probe_base_port(int base)
-{
- int b = 0x300, e = 0x370; /* this is the range of start addresses */
- volatile int fool, i;
-
- if (base)
- b = e = base;
- for (base = b; base <= e; base += 0x10) {
- if (!request_region(base, 0x10,"cm206"))
- continue;
- for (i = 0; i < 3; i++)
- fool = inw(base + 2); /* empty possibly uart_receive_buffer */
- if ((inw(base + 6) & 0xffef) != 0x0001 || /* line_status */
- (inw(base) & 0xad00) != 0) { /* data status */
- release_region(base,0x10);
- continue;
- }
- return (base);
- }
- return 0;
-}
-
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
-/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
-static int __init probe_irq(int nr)
-{
- int irqs, irq;
- outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */
- sti();
- irqs = probe_irq_on();
- reset_cm260(); /* causes interrupt */
- udelay(100); /* wait for it */
- irq = probe_irq_off(irqs);
- outw(dc_normal | READ_AHEAD, r_data_control); /* services interrupt */
- if (nr && irq != nr && irq > 0)
- return 0; /* wrong interrupt happened */
- else
- return irq;
-}
-#endif
-
-int __init cm206_init(void)
-{
- uch e = 0;
- long int size = sizeof(struct cm206_struct);
- struct gendisk *disk;
-
- printk(KERN_INFO "cm206 cdrom driver " REVISION);
- cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
- if (!cm206_base) {
- printk(" can't find adapter!\n");
- return -EIO;
- }
- printk(" adapter at 0x%x", cm206_base);
- cd = kmalloc(size, GFP_KERNEL);
- if (!cd)
- goto out_base;
- /* Now we have found the adaptor card, try to reset it. As we have
- * found out earlier, this process generates an interrupt as well,
- * so we might just exploit that fact for irq probing! */
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
- cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
- if (cm206_irq <= 0) {
- printk("can't find IRQ!\n");
- goto out_probe;
- } else
- printk(" IRQ %d found\n", cm206_irq);
-#else
- cli();
- reset_cm260();
- /* Now, the problem here is that reset_cm260 can generate an
- interrupt. It seems that this can cause a kernel oops some time
- later. So we wait a while and `service' this interrupt. */
- mdelay(1);
- outw(dc_normal | READ_AHEAD, r_data_control);
- sti();
- printk(" using IRQ %d\n", cm206_irq);
-#endif
- if (send_receive_polled(c_drive_configuration) !=
- c_drive_configuration) {
- printk(KERN_INFO " drive not there\n");
- goto out_probe;
- }
- e = send_receive_polled(c_gimme);
- printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
- if (e & dcf_transfer_rate)
- printk(" double");
- else
- printk(" single");
- printk(" speed drive");
- if (e & dcf_motorized_tray)
- printk(", motorized tray");
- if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
- printk("\nUnable to reserve IRQ---aborted\n");
- goto out_probe;
- }
- printk(".\n");
-
- if (register_blkdev(MAJOR_NR, "cm206"))
- goto out_blkdev;
-
- disk = alloc_disk(1);
- if (!disk)
- goto out_disk;
- disk->major = MAJOR_NR;
- disk->first_minor = 0;
- sprintf(disk->disk_name, "cm206cd");
- disk->fops = &cm206_bdops;
- disk->flags = GENHD_FL_CD;
- cm206_gendisk = disk;
- if (register_cdrom(&cm206_info) != 0) {
- printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
- goto out_cdrom;
- }
- cm206_queue = blk_init_queue(do_cm206_request, &cm206_lock);
- if (!cm206_queue)
- goto out_queue;
-
- blk_queue_hardsect_size(cm206_queue, 2048);
- disk->queue = cm206_queue;
- add_disk(disk);
-
- memset(cd, 0, sizeof(*cd)); /* give'm some reasonable value */
- cd->sector_last = -1; /* flag no data buffered */
- cd->adapter_last = -1;
- init_timer(&cd->timer);
- cd->timer.function = cm206_timeout;
- cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
- printk(KERN_INFO "%d kB adapter memory available, "
- " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
- size);
- return 0;
-
-out_queue:
- unregister_cdrom(&cm206_info);
-out_cdrom:
- put_disk(disk);
-out_disk:
- unregister_blkdev(MAJOR_NR, "cm206");
-out_blkdev:
- free_irq(cm206_irq, NULL);
-out_probe:
- kfree(cd);
-out_base:
- release_region(cm206_base, 16);
- return -EIO;
-}
-
-#ifdef MODULE
-
-
-static void __init parse_options(void)
-{
- int i;
- for (i = 0; i < 2; i++) {
- if (0x300 <= cm206[i] && i <= 0x370
- && cm206[i] % 0x10 == 0) {
- cm206_base = cm206[i];
- auto_probe = 0;
- } else if (3 <= cm206[i] && cm206[i] <= 15) {
- cm206_irq = cm206[i];
- auto_probe = 0;
- }
- }
-}
-
-static int __init __cm206_init(void)
-{
- parse_options();
-#if !defined(AUTO_PROBE_MODULE)
- auto_probe = 0;
-#endif
- return cm206_init();
-}
-
-static void __exit cm206_exit(void)
-{
- del_gendisk(cm206_gendisk);
- put_disk(cm206_gendisk);
- if (unregister_cdrom(&cm206_info)) {
- printk("Can't unregister cdrom cm206\n");
- return;
- }
- if (unregister_blkdev(MAJOR_NR, "cm206")) {
- printk("Can't unregister major cm206\n");
- return;
- }
- blk_cleanup_queue(cm206_queue);
- free_irq(cm206_irq, NULL);
- kfree(cd);
- release_region(cm206_base, 16);
- printk(KERN_INFO "cm206 removed\n");
-}
-
-module_init(__cm206_init);
-module_exit(cm206_exit);
-
-#else /* !MODULE */
-
-/* This setup function accepts either `auto' or numbers in the range
- * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
-
-static int __init cm206_setup(char *s)
-{
- int i, p[4];
-
- (void) get_options(s, ARRAY_SIZE(p), p);
-
- if (!strcmp(s, "auto"))
- auto_probe = 1;
- for (i = 1; i <= p[0]; i++) {
- if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) {
- cm206_base = p[i];
- auto_probe = 0;
- } else if (3 <= p[i] && p[i] <= 15) {
- cm206_irq = p[i];
- auto_probe = 0;
- }
- }
- return 1;
-}
-
-__setup("cm206=", cm206_setup);
-
-#endif /* !MODULE */
-MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR);
-
diff --git a/drivers/cdrom/cm206.h b/drivers/cdrom/cm206.h
deleted file mode 100644
index 0ae51c1a0da..00000000000
--- a/drivers/cdrom/cm206.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* cm206.h Header file for cm206.c.
- Copyright (c) 1995 David van Leeuwen
-*/
-
-#ifndef LINUX_CM206_H
-#define LINUX_CM206_H
-
-#include <linux/ioctl.h>
-
-/* First, the cm260 stuff */
-/* The ports and irq used. Although CM206_BASE and CM206_IRQ are defined
- below, the values are not used unless autoprobing is turned off and
- no LILO boot options or module command line options are given. Change
- these values to your own as last resort if autoprobing and options
- don't work. */
-
-#define CM206_BASE 0x340
-#define CM206_IRQ 11
-
-#define r_data_status (cm206_base)
-#define r_uart_receive (cm206_base+0x2)
-#define r_fifo_output_buffer (cm206_base+0x4)
-#define r_line_status (cm206_base+0x6)
-#define r_data_control (cm206_base+0x8)
-#define r_uart_transmit (cm206_base+0xa)
-#define r_test_clock (cm206_base+0xc)
-#define r_test_control (cm206_base+0xe)
-
-/* the data_status flags */
-#define ds_ram_size 0x4000
-#define ds_toc_ready 0x2000
-#define ds_fifo_empty 0x1000
-#define ds_sync_error 0x800
-#define ds_crc_error 0x400
-#define ds_data_error 0x200
-#define ds_fifo_overflow 0x100
-#define ds_data_ready 0x80
-
-/* the line_status flags */
-#define ls_attention 0x10
-#define ls_parity_error 0x8
-#define ls_overrun 0x4
-#define ls_receive_buffer_full 0x2
-#define ls_transmitter_buffer_empty 0x1
-
-/* the data control register flags */
-#define dc_read_q_channel 0x4000
-#define dc_mask_sync_error 0x2000
-#define dc_toc_enable 0x1000
-#define dc_no_stop_on_error 0x800
-#define dc_break 0x400
-#define dc_initialize 0x200
-#define dc_mask_transmit_ready 0x100
-#define dc_flag_enable 0x80
-
-/* Define the default data control register flags here */
-#define dc_normal (dc_mask_sync_error | dc_no_stop_on_error | \
- dc_mask_transmit_ready)
-
-/* now some constants related to the cm206 */
-/* another drive status byte, echoed by the cm206 on most commands */
-
-#define dsb_error_condition 0x1
-#define dsb_play_in_progress 0x4
-#define dsb_possible_media_change 0x8
-#define dsb_disc_present 0x10
-#define dsb_drive_not_ready 0x20
-#define dsb_tray_locked 0x40
-#define dsb_tray_not_closed 0x80
-
-#define dsb_not_useful (dsb_drive_not_ready | dsb_tray_not_closed)
-
-/* the cm206 command set */
-
-#define c_close_tray 0
-#define c_lock_tray 0x01
-#define c_unlock_tray 0x04
-#define c_open_tray 0x05
-#define c_seek 0x10
-#define c_read_data 0x20
-#define c_force_1x 0x21
-#define c_force_2x 0x22
-#define c_auto_mode 0x23
-#define c_play 0x30
-#define c_set_audio_mode 0x31
-#define c_read_current_q 0x41
-#define c_stream_q 0x42
-#define c_drive_status 0x50
-#define c_disc_status 0x51
-#define c_audio_status 0x52
-#define c_drive_configuration 0x53
-#define c_read_upc 0x60
-#define c_stop 0x70
-#define c_calc_checksum 0xe5
-
-#define c_gimme 0xf8
-
-/* finally, the (error) condition that the drive can be in *
- * OK, this is not always an error, but let's prefix it with e_ */
-
-#define e_none 0
-#define e_illegal_command 0x01
-#define e_sync 0x02
-#define e_seek 0x03
-#define e_parity 0x04
-#define e_focus 0x05
-#define e_header_sync 0x06
-#define e_code_incompatibility 0x07
-#define e_reset_done 0x08
-#define e_bad_parameter 0x09
-#define e_radial 0x0a
-#define e_sub_code 0x0b
-#define e_no_data_track 0x0c
-#define e_scan 0x0d
-#define e_tray_open 0x0f
-#define e_no_disc 0x10
-#define e_tray stalled 0x11
-
-/* drive configuration masks */
-
-#define dcf_revision_code 0x7
-#define dcf_transfer_rate 0x60
-#define dcf_motorized_tray 0x80
-
-/* disc status byte */
-
-#define cds_multi_session 0x2
-#define cds_all_audio 0x8
-#define cds_xa_mode 0xf0
-
-/* finally some ioctls for the driver */
-
-#define CM206CTL_GET_STAT _IO( 0x20, 0 )
-#define CM206CTL_GET_LAST_STAT _IO( 0x20, 1 )
-
-#ifdef STATISTICS
-
-/* This is an ugly way to guarantee that the names of the statistics
- * are the same in the code and in the diagnostics program. */
-
-#ifdef __KERNEL__
-#define x(a) st_ ## a
-#define y enum
-#else
-#define x(a) #a
-#define y char * stats_name[] =
-#endif
-
-y {x(interrupt), x(data_ready), x(fifo_overflow), x(data_error),
- x(crc_error), x(sync_error), x(lost_intr), x(echo),
- x(write_timeout), x(receive_timeout), x(read_timeout),
- x(dsb_timeout), x(stop_0xff), x(back_read_timeout),
- x(sector_transferred), x(read_restarted), x(read_background),
- x(bh), x(open), x(ioctl_multisession), x(attention)
-#ifdef __KERNEL__
- , x(last_entry)
-#endif
- };
-
-#ifdef __KERNEL__
-#define NR_STATS st_last_entry
-#else
-#define NR_STATS (sizeof(stats_name)/sizeof(char*))
-#endif
-
-#undef y
-#undef x
-
-#endif /* STATISTICS */
-
-#endif /* LINUX_CM206_H */
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
deleted file mode 100644
index b3ab6e9b8df..00000000000
--- a/drivers/cdrom/gscd.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-#define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
-
-/*
- linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
-
- Copyright (C) 1995 Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
- based upon pre-works by Eberhard Moenkeberg <emoenke@gwdg.de>
-
-
- For all kind of other information about the GoldStar CDROM
- and this Linux device driver I installed a WWW-URL:
- http://linux.rz.fh-hannover.de/~raupach
-
-
- If you are the editor of a Linux CD, you should
- enable gscd.c within your boot floppy kernel and
- send me one of your CDs for free.
-
-
- --------------------------------------------------------------------
- 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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- --------------------------------------------------------------------
-
- 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-
-*/
-
-/* These settings are for various debug-level. Leave they untouched ... */
-#define NO_GSCD_DEBUG
-#define NO_IOCTL_DEBUG
-#define NO_MODULE_DEBUG
-#define NO_FUTURE_WORK
-/*------------------------*/
-
-#include <linux/module.h>
-
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#define MAJOR_NR GOLDSTAR_CDROM_MAJOR
-#include <linux/blkdev.h>
-#include "gscd.h"
-
-static int gscdPresent = 0;
-
-static unsigned char gscd_buf[2048]; /* buffer for block size conversion */
-static int gscd_bn = -1;
-static short gscd_port = GSCD_BASE_ADDR;
-module_param_named(gscd, gscd_port, short, 0);
-
-/* Kommt spaeter vielleicht noch mal dran ...
- * static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
- */
-
-static void gscd_read_cmd(struct request *req);
-static void gscd_hsg2msf(long hsg, struct msf *msf);
-static void gscd_bin2bcd(unsigned char *p);
-
-/* Schnittstellen zum Kern/FS */
-
-static void __do_gscd_request(unsigned long dummy);
-static int gscd_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
-static int gscd_open(struct inode *, struct file *);
-static int gscd_release(struct inode *, struct file *);
-static int check_gscd_med_chg(struct gendisk *disk);
-
-/* GoldStar Funktionen */
-
-static void cmd_out(int, char *, char *, int);
-static void cmd_status(void);
-static void init_cd_drive(int);
-
-static int get_status(void);
-static void clear_Audio(void);
-static void cc_invalidate(void);
-
-/* some things for the next version */
-#ifdef FUTURE_WORK
-static void update_state(void);
-static long gscd_msf2hsg(struct msf *mp);
-static int gscd_bcd2bin(unsigned char bcd);
-#endif
-
-
-/* lo-level cmd-Funktionen */
-
-static void cmd_info_in(char *, int);
-static void cmd_end(void);
-static void cmd_read_b(char *, int, int);
-static void cmd_read_w(char *, int, int);
-static int cmd_unit_alive(void);
-static void cmd_write_cmd(char *);
-
-
-/* GoldStar Variablen */
-
-static int curr_drv_state;
-static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-static int drv_mode;
-static int disk_state;
-static int speed;
-static int ndrives;
-
-static unsigned char drv_num_read;
-static unsigned char f_dsk_valid;
-static unsigned char current_drive;
-static unsigned char f_drv_ok;
-
-
-static char f_AudioPlay;
-static char f_AudioPause;
-static int AudioStart_m;
-static int AudioStart_f;
-static int AudioEnd_m;
-static int AudioEnd_f;
-
-static DEFINE_TIMER(gscd_timer, NULL, 0, 0);
-static DEFINE_SPINLOCK(gscd_lock);
-static struct request_queue *gscd_queue;
-
-static struct block_device_operations gscd_fops = {
- .owner = THIS_MODULE,
- .open = gscd_open,
- .release = gscd_release,
- .ioctl = gscd_ioctl,
- .media_changed = check_gscd_med_chg,
-};
-
-/*
- * Checking if the media has been changed
- * (not yet implemented)
- */
-static int check_gscd_med_chg(struct gendisk *disk)
-{
-#ifdef GSCD_DEBUG
- printk("gscd: check_med_change\n");
-#endif
- return 0;
-}
-
-
-#ifndef MODULE
-/* Using new interface for kernel-parameters */
-
-static int __init gscd_setup(char *str)
-{
- int ints[2];
- (void) get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0) {
- gscd_port = ints[1];
- }
- return 1;
-}
-
-__setup("gscd=", gscd_setup);
-
-#endif
-
-static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- unsigned char to_do[10];
- unsigned char dummy;
-
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- /* Don't think we can do this. Even if we could,
- * I think the drive times out and stops after a while
- * anyway. For now, ignore it.
- */
- return 0;
-
- case CDROMRESUME: /* keine Ahnung was das ist */
- return 0;
-
-
- case CDROMEJECT:
- cmd_status();
- to_do[0] = CMD_TRAY_CTL;
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
- return 0;
-
- default:
- return -EINVAL;
- }
-
-}
-
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static void gscd_transfer(struct request *req)
-{
- while (req->nr_sectors > 0 && gscd_bn == req->sector / 4) {
- long offs = (req->sector & 3) * 512;
- memcpy(req->buffer, gscd_buf + offs, 512);
- req->nr_sectors--;
- req->sector++;
- req->buffer += 512;
- }
-}
-
-
-/*
- * I/O request routine called from Linux kernel.
- */
-
-static void do_gscd_request(request_queue_t * q)
-{
- __do_gscd_request(0);
-}
-
-static void __do_gscd_request(unsigned long dummy)
-{
- struct request *req;
- unsigned int block;
- unsigned int nsect;
-
-repeat:
- req = elv_next_request(gscd_queue);
- if (!req)
- return;
-
- block = req->sector;
- nsect = req->nr_sectors;
-
- if (req->sector == -1)
- goto out;
-
- if (req->cmd != READ) {
- printk("GSCD: bad cmd %u\n", rq_data_dir(req));
- end_request(req, 0);
- goto repeat;
- }
-
- gscd_transfer(req);
-
- /* if we satisfied the request from the buffer, we're done. */
-
- if (req->nr_sectors == 0) {
- end_request(req, 1);
- goto repeat;
- }
-#ifdef GSCD_DEBUG
- printk("GSCD: block %d, nsect %d\n", block, nsect);
-#endif
- gscd_read_cmd(req);
-out:
- return;
-}
-
-
-
-/*
- * Check the result of the set-mode command. On success, send the
- * read-data command.
- */
-
-static void gscd_read_cmd(struct request *req)
-{
- long block;
- struct gscd_Play_msf gscdcmd;
- char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 }; /* cmd mode M-S-F secth sectl */
-
- cmd_status();
- if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
- printk("GSCD: no disk or door open\n");
- end_request(req, 0);
- } else {
- if (disk_state & ST_INVALID) {
- printk("GSCD: disk invalid\n");
- end_request(req, 0);
- } else {
- gscd_bn = -1; /* purge our buffer */
- block = req->sector / 4;
- gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */
-
- cmd[2] = gscdcmd.start.min;
- cmd[3] = gscdcmd.start.sec;
- cmd[4] = gscdcmd.start.frame;
-
-#ifdef GSCD_DEBUG
- printk("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3],
- cmd[4]);
-#endif
- cmd_out(TYPE_DATA, (char *) &cmd,
- (char *) &gscd_buf[0], 1);
-
- gscd_bn = req->sector / 4;
- gscd_transfer(req);
- end_request(req, 1);
- }
- }
- SET_TIMER(__do_gscd_request, 1);
-}
-
-
-/*
- * Open the device special file. Check that a disk is in.
- */
-
-static int gscd_open(struct inode *ip, struct file *fp)
-{
- int st;
-
-#ifdef GSCD_DEBUG
- printk("GSCD: open\n");
-#endif
-
- if (gscdPresent == 0)
- return -ENXIO; /* no hardware */
-
- get_status();
- st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
- if (st) {
- printk("GSCD: no disk or door open\n");
- return -ENXIO;
- }
-
-/* if (updateToc() < 0)
- return -EIO;
-*/
-
- return 0;
-}
-
-
-/*
- * On close, we flush all gscd blocks from the buffer cache.
- */
-
-static int gscd_release(struct inode *inode, struct file *file)
-{
-
-#ifdef GSCD_DEBUG
- printk("GSCD: release\n");
-#endif
-
- gscd_bn = -1;
-
- return 0;
-}
-
-
-static int get_status(void)
-{
- int status;
-
- cmd_status();
- status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
-
- if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) {
- cc_invalidate();
- return 1;
- } else {
- return 0;
- }
-}
-
-
-static void cc_invalidate(void)
-{
- drv_num_read = 0xFF;
- f_dsk_valid = 0xFF;
- current_drive = 0xFF;
- f_drv_ok = 0xFF;
-
- clear_Audio();
-
-}
-
-static void clear_Audio(void)
-{
-
- f_AudioPlay = 0;
- f_AudioPause = 0;
- AudioStart_m = 0;
- AudioStart_f = 0;
- AudioEnd_m = 0;
- AudioEnd_f = 0;
-
-}
-
-/*
- * waiting ?
- */
-
-static int wait_drv_ready(void)
-{
- int found, read;
-
- do {
- found = inb(GSCDPORT(0));
- found &= 0x0f;
- read = inb(GSCDPORT(0));
- read &= 0x0f;
- } while (read != found);
-
-#ifdef GSCD_DEBUG
- printk("Wait for: %d\n", read);
-#endif
-
- return read;
-}
-
-static void cc_Ident(char *respons)
-{
- char to_do[] = { CMD_IDENT, 0, 0 };
-
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E);
-
-}
-
-static void cc_SetSpeed(void)
-{
- char to_do[] = { CMD_SETSPEED, 0, 0 };
- char dummy;
-
- if (speed > 0) {
- to_do[1] = speed & 0x0F;
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
- }
-}
-
-static void cc_Reset(void)
-{
- char to_do[] = { CMD_RESET, 0 };
- char dummy;
-
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-}
-
-static void cmd_status(void)
-{
- char to_do[] = { CMD_STATUS, 0 };
- char dummy;
-
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
-#ifdef GSCD_DEBUG
- printk("GSCD: Status: %d\n", disk_state);
-#endif
-
-}
-
-static void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
-{
- int result;
-
-
- result = wait_drv_ready();
- if (result != drv_mode) {
- unsigned long test_loops = 0xFFFF;
- int i, dummy;
-
- outb(curr_drv_state, GSCDPORT(0));
-
- /* LOCLOOP_170 */
- do {
- result = wait_drv_ready();
- test_loops--;
- } while ((result != drv_mode) && (test_loops > 0));
-
- if (result != drv_mode) {
- disk_state = ST_x08 | ST_x04 | ST_INVALID;
- return;
- }
-
- /* ...and waiting */
- for (i = 1, dummy = 1; i < 0xFFFF; i++) {
- dummy *= i;
- }
- }
-
- /* LOC_172 */
- /* check the unit */
- /* and wake it up */
- if (cmd_unit_alive() != 0x08) {
- /* LOC_174 */
- /* game over for this unit */
- disk_state = ST_x08 | ST_x04 | ST_INVALID;
- return;
- }
-
- /* LOC_176 */
-#ifdef GSCD_DEBUG
- printk("LOC_176 ");
-#endif
- if (drv_mode == 0x09) {
- /* magic... */
- printk("GSCD: magic ...\n");
- outb(result, GSCDPORT(2));
- }
-
- /* write the command to the drive */
- cmd_write_cmd(cmd);
-
- /* LOC_178 */
- for (;;) {
- result = wait_drv_ready();
- if (result != drv_mode) {
- /* LOC_179 */
- if (result == 0x04) { /* Mode 4 */
- /* LOC_205 */
-#ifdef GSCD_DEBUG
- printk("LOC_205 ");
-#endif
- disk_state = inb(GSCDPORT(2));
-
- do {
- result = wait_drv_ready();
- } while (result != drv_mode);
- return;
-
- } else {
- if (result == 0x06) { /* Mode 6 */
- /* LOC_181 */
-#ifdef GSCD_DEBUG
- printk("LOC_181 ");
-#endif
-
- if (cmd_type == TYPE_DATA) {
- /* read data */
- /* LOC_184 */
- if (drv_mode == 9) {
- /* read the data to the buffer (word) */
-
- /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
- cmd_read_w
- (respo_buf,
- respo_count,
- CD_FRAMESIZE /
- 2);
- return;
- } else {
- /* read the data to the buffer (byte) */
-
- /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW) */
- cmd_read_b
- (respo_buf,
- respo_count,
- CD_FRAMESIZE);
- return;
- }
- } else {
- /* read the info to the buffer */
- cmd_info_in(respo_buf,
- respo_count);
- return;
- }
-
- return;
- }
- }
-
- } else {
- disk_state = ST_x08 | ST_x04 | ST_INVALID;
- return;
- }
- } /* for (;;) */
-
-
-#ifdef GSCD_DEBUG
- printk("\n");
-#endif
-}
-
-
-static void cmd_write_cmd(char *pstr)
-{
- int i, j;
-
- /* LOC_177 */
-#ifdef GSCD_DEBUG
- printk("LOC_177 ");
-#endif
-
- /* calculate the number of parameter */
- j = *pstr & 0x0F;
-
- /* shift it out */
- for (i = 0; i < j; i++) {
- outb(*pstr, GSCDPORT(2));
- pstr++;
- }
-}
-
-
-static int cmd_unit_alive(void)
-{
- int result;
- unsigned long max_test_loops;
-
-
- /* LOC_172 */
-#ifdef GSCD_DEBUG
- printk("LOC_172 ");
-#endif
-
- outb(curr_drv_state, GSCDPORT(0));
- max_test_loops = 0xFFFF;
-
- do {
- result = wait_drv_ready();
- max_test_loops--;
- } while ((result != 0x08) && (max_test_loops > 0));
-
- return result;
-}
-
-
-static void cmd_info_in(char *pb, int count)
-{
- int result;
- char read;
-
-
- /* read info */
- /* LOC_182 */
-#ifdef GSCD_DEBUG
- printk("LOC_182 ");
-#endif
-
- do {
- read = inb(GSCDPORT(2));
- if (count > 0) {
- *pb = read;
- pb++;
- count--;
- }
-
- /* LOC_183 */
- do {
- result = wait_drv_ready();
- } while (result == 0x0E);
- } while (result == 6);
-
- cmd_end();
- return;
-}
-
-
-static void cmd_read_b(char *pb, int count, int size)
-{
- int result;
- int i;
-
-
- /* LOC_188 */
- /* LOC_189 */
-#ifdef GSCD_DEBUG
- printk("LOC_189 ");
-#endif
-
- do {
- do {
- result = wait_drv_ready();
- } while (result != 6 || result == 0x0E);
-
- if (result != 6) {
- cmd_end();
- return;
- }
-#ifdef GSCD_DEBUG
- printk("LOC_191 ");
-#endif
-
- for (i = 0; i < size; i++) {
- *pb = inb(GSCDPORT(2));
- pb++;
- }
- count--;
- } while (count > 0);
-
- cmd_end();
- return;
-}
-
-
-static void cmd_end(void)
-{
- int result;
-
-
- /* LOC_204 */
-#ifdef GSCD_DEBUG
- printk("LOC_204 ");
-#endif
-
- do {
- result = wait_drv_ready();
- if (result == drv_mode) {
- return;
- }
- } while (result != 4);
-
- /* LOC_205 */
-#ifdef GSCD_DEBUG
- printk("LOC_205 ");
-#endif
-
- disk_state = inb(GSCDPORT(2));
-
- do {
- result = wait_drv_ready();
- } while (result != drv_mode);
- return;
-
-}
-
-
-static void cmd_read_w(char *pb, int count, int size)
-{
- int result;
- int i;
-
-
-#ifdef GSCD_DEBUG
- printk("LOC_185 ");
-#endif
-
- do {
- /* LOC_185 */
- do {
- result = wait_drv_ready();
- } while (result != 6 || result == 0x0E);
-
- if (result != 6) {
- cmd_end();
- return;
- }
-
- for (i = 0; i < size; i++) {
- /* na, hier muss ich noch mal drueber nachdenken */
- *pb = inw(GSCDPORT(2));
- pb++;
- }
- count--;
- } while (count > 0);
-
- cmd_end();
- return;
-}
-
-static int __init find_drives(void)
-{
- int *pdrv;
- int drvnum;
- int subdrv;
- int i;
-
- speed = 0;
- pdrv = (int *) &drv_states;
- curr_drv_state = 0xFE;
- subdrv = 0;
- drvnum = 0;
-
- for (i = 0; i < 8; i++) {
- subdrv++;
- cmd_status();
- disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
- if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) {
- /* LOC_240 */
- *pdrv = curr_drv_state;
- init_cd_drive(drvnum);
- pdrv++;
- drvnum++;
- } else {
- if (subdrv < 2) {
- continue;
- } else {
- subdrv = 0;
- }
- }
-
-/* curr_drv_state<<1; <-- das geht irgendwie nicht */
-/* muss heissen: curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
- curr_drv_state *= 2;
- curr_drv_state |= 1;
-#ifdef GSCD_DEBUG
- printk("DriveState: %d\n", curr_drv_state);
-#endif
- }
-
- ndrives = drvnum;
- return drvnum;
-}
-
-static void __init init_cd_drive(int num)
-{
- char resp[50];
- int i;
-
- printk("GSCD: init unit %d\n", num);
- cc_Ident((char *) &resp);
-
- printk("GSCD: identification: ");
- for (i = 0; i < 0x1E; i++) {
- printk("%c", resp[i]);
- }
- printk("\n");
-
- cc_SetSpeed();
-
-}
-
-#ifdef FUTURE_WORK
-/* return_done */
-static void update_state(void)
-{
- unsigned int AX;
-
-
- if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) {
- if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) {
- AX = ST_INVALID;
- }
-
- if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01))
- == 0) {
- invalidate();
- f_drv_ok = 0;
- }
-
- AX |= 0x8000;
- }
-
- if (disk_state & ST_PLAYING) {
- AX |= 0x200;
- }
-
- AX |= 0x100;
- /* pkt_esbx = AX; */
-
- disk_state = 0;
-
-}
-#endif
-
-static struct gendisk *gscd_disk;
-
-static void __exit gscd_exit(void)
-{
- CLEAR_TIMER;
-
- del_gendisk(gscd_disk);
- put_disk(gscd_disk);
- if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
- printk("What's that: can't unregister GoldStar-module\n");
- return;
- }
- blk_cleanup_queue(gscd_queue);
- release_region(gscd_port, GSCD_IO_EXTENT);
- printk(KERN_INFO "GoldStar-module released.\n");
-}
-
-/* This is the common initialisation for the GoldStar drive. */
-/* It is called at boot time AND for module init. */
-static int __init gscd_init(void)
-{
- int i;
- int result;
- int ret=0;
-
- printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
- printk(KERN_INFO
- "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n",
- gscd_port);
-
- if (!request_region(gscd_port, GSCD_IO_EXTENT, "gscd")) {
- printk(KERN_WARNING "GSCD: Init failed, I/O port (%X) already"
- " in use.\n", gscd_port);
- return -EIO;
- }
-
-
- /* check for card */
- result = wait_drv_ready();
- if (result == 0x09) {
- printk(KERN_WARNING "GSCD: DMA kann ich noch nicht!\n");
- ret = -EIO;
- goto err_out1;
- }
-
- if (result == 0x0b) {
- drv_mode = result;
- i = find_drives();
- if (i == 0) {
- printk(KERN_WARNING "GSCD: GoldStar CD-ROM Drive is"
- " not found.\n");
- ret = -EIO;
- goto err_out1;
- }
- }
-
- if ((result != 0x0b) && (result != 0x09)) {
- printk(KERN_WARNING "GSCD: GoldStar Interface Adapter does not "
- "exist or H/W error\n");
- ret = -EIO;
- goto err_out1;
- }
-
- /* reset all drives */
- i = 0;
- while (drv_states[i] != 0) {
- curr_drv_state = drv_states[i];
- printk(KERN_INFO "GSCD: Reset unit %d ... ", i);
- cc_Reset();
- printk("done\n");
- i++;
- }
-
- gscd_disk = alloc_disk(1);
- if (!gscd_disk)
- goto err_out1;
- gscd_disk->major = MAJOR_NR;
- gscd_disk->first_minor = 0;
- gscd_disk->fops = &gscd_fops;
- sprintf(gscd_disk->disk_name, "gscd");
-
- if (register_blkdev(MAJOR_NR, "gscd")) {
- ret = -EIO;
- goto err_out2;
- }
-
- gscd_queue = blk_init_queue(do_gscd_request, &gscd_lock);
- if (!gscd_queue) {
- ret = -ENOMEM;
- goto err_out3;
- }
-
- disk_state = 0;
- gscdPresent = 1;
-
- gscd_disk->queue = gscd_queue;
- add_disk(gscd_disk);
-
- printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
- return 0;
-
-err_out3:
- unregister_blkdev(MAJOR_NR, "gscd");
-err_out2:
- put_disk(gscd_disk);
-err_out1:
- release_region(gscd_port, GSCD_IO_EXTENT);
- return ret;
-}
-
-static void gscd_hsg2msf(long hsg, struct msf *msf)
-{
- hsg += CD_MSF_OFFSET;
- msf->min = hsg / (CD_FRAMES * CD_SECS);
- hsg %= CD_FRAMES * CD_SECS;
- msf->sec = hsg / CD_FRAMES;
- msf->frame = hsg % CD_FRAMES;
-
- gscd_bin2bcd(&msf->min); /* convert to BCD */
- gscd_bin2bcd(&msf->sec);
- gscd_bin2bcd(&msf->frame);
-}
-
-
-static void gscd_bin2bcd(unsigned char *p)
-{
- int u, t;
-
- u = *p % 10;
- t = *p / 10;
- *p = u | (t << 4);
-}
-
-
-#ifdef FUTURE_WORK
-static long gscd_msf2hsg(struct msf *mp)
-{
- return gscd_bcd2bin(mp->frame)
- + gscd_bcd2bin(mp->sec) * CD_FRAMES
- + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;
-}
-
-static int gscd_bcd2bin(unsigned char bcd)
-{
- return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-#endif
-
-MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
-MODULE_LICENSE("GPL");
-module_init(gscd_init);
-module_exit(gscd_exit);
-MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR);
diff --git a/drivers/cdrom/gscd.h b/drivers/cdrom/gscd.h
deleted file mode 100644
index a41e64bfc06..00000000000
--- a/drivers/cdrom/gscd.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Definitions for a GoldStar R420 CD-ROM interface
- *
- * Copyright (C) 1995 Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
- * Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- * Published under the GPL.
- *
- */
-
-
-/* The Interface Card default address is 0x340. This will work for most
- applications. Address selection is accomplished by jumpers PN801-1 to
- PN801-4 on the GoldStar Interface Card.
- Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360
- 0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0 */
-
-/* insert here the I/O port address and extent */
-#define GSCD_BASE_ADDR 0x340
-#define GSCD_IO_EXTENT 4
-
-
-/************** nothing to set up below here *********************/
-
-/* port access macro */
-#define GSCDPORT(x) (gscd_port + (x))
-
-/*
- * commands
- * the lower nibble holds the command length
- */
-#define CMD_STATUS 0x01
-#define CMD_READSUBQ 0x02 /* 1: ?, 2: UPC, 5: ? */
-#define CMD_SEEK 0x05 /* read_mode M-S-F */
-#define CMD_READ 0x07 /* read_mode M-S-F nsec_h nsec_l */
-#define CMD_RESET 0x11
-#define CMD_SETMODE 0x15
-#define CMD_PLAY 0x17 /* M-S-F M-S-F */
-#define CMD_LOCK_CTL 0x22 /* 0: unlock, 1: lock */
-#define CMD_IDENT 0x31
-#define CMD_SETSPEED 0x32 /* 0: auto */ /* ??? */
-#define CMD_GETMODE 0x41
-#define CMD_PAUSE 0x51
-#define CMD_READTOC 0x61
-#define CMD_DISKINFO 0x71
-#define CMD_TRAY_CTL 0x81
-
-/*
- * disk_state:
- */
-#define ST_PLAYING 0x80
-#define ST_UNLOCKED 0x40
-#define ST_NO_DISK 0x20
-#define ST_DOOR_OPEN 0x10
-#define ST_x08 0x08
-#define ST_x04 0x04
-#define ST_INVALID 0x02
-#define ST_x01 0x01
-
-/*
- * cmd_type:
- */
-#define TYPE_INFO 0x01
-#define TYPE_DATA 0x02
-
-/*
- * read_mode:
- */
-#define MOD_POLLED 0x80
-#define MOD_x08 0x08
-#define MOD_RAW 0x04
-
-#define READ_DATA(port, buf, nr) insb(port, buf, nr)
-
-#define SET_TIMER(func, jifs) \
- ((mod_timer(&gscd_timer, jiffies + jifs)), \
- (gscd_timer.function = func))
-
-#define CLEAR_TIMER del_timer_sync(&gscd_timer)
-
-#define MAX_TRACKS 104
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct gscd_Play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct gscd_DiskInfo {
- unsigned char first;
- unsigned char last;
- struct msf diskLength;
- struct msf firstTrack;
-};
-
-struct gscd_Toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char pointIndex;
- struct msf trackTime;
- struct msf diskTime;
-};
-
diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c
deleted file mode 100644
index db0fd9a240e..00000000000
--- a/drivers/cdrom/isp16.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* -- ISP16 cdrom detection and configuration
- *
- * Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
- *
- * Version 0.6
- *
- * History:
- * 0.5 First release.
- * Was included in the sjcd and optcd cdrom drivers.
- * 0.6 First "stand-alone" version.
- * Removed sound configuration.
- * Added "module" support.
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * 19 June 2004 -- check_region() converted to request_region()
- * and return statement cleanups.
- * - Jesper Juhl
- *
- * Detect cdrom interface on ISP16 sound card.
- * Configure cdrom interface.
- *
- * Algorithm for the card with OPTi 82C928 taken
- * from the CDSETUP.SYS driver for MSDOS,
- * by OPTi Computers, version 2.03.
- * Algorithm for the card with OPTi 82C929 as communicated
- * to me by Vadim Model and Leo Spiekman.
- *
- * 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.
- *
- */
-
-#define ISP16_VERSION_MAJOR 0
-#define ISP16_VERSION_MINOR 6
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include "isp16.h"
-
-static short isp16_detect(void);
-static short isp16_c928__detect(void);
-static short isp16_c929__detect(void);
-static short isp16_cdi_config(int base, u_char drive_type, int irq,
- int dma);
-static short isp16_type; /* dependent on type of interface card */
-static u_char isp16_ctrl;
-static u_short isp16_enable_port;
-
-static int isp16_cdrom_base = ISP16_CDROM_IO_BASE;
-static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
-static int isp16_cdrom_dma = ISP16_CDROM_DMA;
-static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
-
-module_param(isp16_cdrom_base, int, 0);
-module_param(isp16_cdrom_irq, int, 0);
-module_param(isp16_cdrom_dma, int, 0);
-module_param(isp16_cdrom_type, charp, 0);
-
-#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
-#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
-
-#ifndef MODULE
-
-static int
-__init isp16_setup(char *str)
-{
- int ints[4];
-
- (void) get_options(str, ARRAY_SIZE(ints), ints);
- if (ints[0] > 0)
- isp16_cdrom_base = ints[1];
- if (ints[0] > 1)
- isp16_cdrom_irq = ints[2];
- if (ints[0] > 2)
- isp16_cdrom_dma = ints[3];
- if (str)
- isp16_cdrom_type = str;
-
- return 1;
-}
-
-__setup("isp16=", isp16_setup);
-
-#endif /* MODULE */
-
-/*
- * ISP16 initialisation.
- *
- */
-static int __init isp16_init(void)
-{
- u_char expected_drive;
-
- printk(KERN_INFO
- "ISP16: configuration cdrom interface, version %d.%d.\n",
- ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR);
-
- if (!strcmp(isp16_cdrom_type, "noisp16")) {
- printk("ISP16: no cdrom interface configured.\n");
- return 0;
- }
-
- if (!request_region(ISP16_IO_BASE, ISP16_IO_SIZE, "isp16")) {
- printk("ISP16: i/o ports already in use.\n");
- goto out;
- }
-
- if ((isp16_type = isp16_detect()) < 0) {
- printk("ISP16: no cdrom interface found.\n");
- goto cleanup_out;
- }
-
- printk(KERN_INFO
- "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n",
- (isp16_type == 2) ? 9 : 8);
-
- if (!strcmp(isp16_cdrom_type, "Sanyo"))
- expected_drive =
- (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0);
- else if (!strcmp(isp16_cdrom_type, "Sony"))
- expected_drive = ISP16_SONY;
- else if (!strcmp(isp16_cdrom_type, "Panasonic"))
- expected_drive =
- (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0);
- else if (!strcmp(isp16_cdrom_type, "Mitsumi"))
- expected_drive = ISP16_MITSUMI;
- else {
- printk("ISP16: %s not supported by cdrom interface.\n",
- isp16_cdrom_type);
- goto cleanup_out;
- }
-
- if (isp16_cdi_config(isp16_cdrom_base, expected_drive,
- isp16_cdrom_irq, isp16_cdrom_dma) < 0) {
- printk
- ("ISP16: cdrom interface has not been properly configured.\n");
- goto cleanup_out;
- }
- printk(KERN_INFO
- "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
- " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq,
- isp16_cdrom_dma, isp16_cdrom_type);
- return 0;
-
-cleanup_out:
- release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
-out:
- return -EIO;
-}
-
-static short __init isp16_detect(void)
-{
-
- if (isp16_c929__detect() >= 0)
- return 2;
- else
- return (isp16_c928__detect());
-}
-
-static short __init isp16_c928__detect(void)
-{
- u_char ctrl;
- u_char enable_cdrom;
- u_char io;
- short i = -1;
-
- isp16_ctrl = ISP16_C928__CTRL;
- isp16_enable_port = ISP16_C928__ENABLE_PORT;
-
- /* read' and write' are a special read and write, respectively */
-
- /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
- ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC;
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
- /* read' 3,4 and 5-bit from the cdrom enable port */
- enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38;
-
- if (!(enable_cdrom & 0x20)) { /* 5-bit not set */
- /* read' last 2 bits of ISP16_IO_SET_PORT */
- io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03;
- if (((io & 0x01) << 1) == (io & 0x02)) { /* bits are the same */
- if (io == 0) { /* ...the same and 0 */
- i = 0;
- enable_cdrom |= 0x20;
- } else { /* ...the same and 1 *//* my card, first time 'round */
- i = 1;
- enable_cdrom |= 0x28;
- }
- ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom);
- } else { /* bits are not the same */
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
- return i; /* -> not detected: possibly incorrect conclusion */
- }
- } else if (enable_cdrom == 0x20)
- i = 0;
- else if (enable_cdrom == 0x28) /* my card, already initialised */
- i = 1;
-
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
- return i;
-}
-
-static short __init isp16_c929__detect(void)
-{
- u_char ctrl;
- u_char tmp;
-
- isp16_ctrl = ISP16_C929__CTRL;
- isp16_enable_port = ISP16_C929__ENABLE_PORT;
-
- /* read' and write' are a special read and write, respectively */
-
- /* read' ISP16_CTRL_PORT and save */
- ctrl = ISP16_IN(ISP16_CTRL_PORT);
-
- /* write' zero to the ctrl port and get response */
- ISP16_OUT(ISP16_CTRL_PORT, 0);
- tmp = ISP16_IN(ISP16_CTRL_PORT);
-
- if (tmp != 2) /* isp16 with 82C929 not detected */
- return -1;
-
- /* restore ctrl port value */
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
- return 2;
-}
-
-static short __init
-isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
-{
- u_char base_code;
- u_char irq_code;
- u_char dma_code;
- u_char i;
-
- if ((drive_type == ISP16_MITSUMI) && (dma != 0))
- printk("ISP16: Mitsumi cdrom drive has no dma support.\n");
-
- switch (base) {
- case 0x340:
- base_code = ISP16_BASE_340;
- break;
- case 0x330:
- base_code = ISP16_BASE_330;
- break;
- case 0x360:
- base_code = ISP16_BASE_360;
- break;
- case 0x320:
- base_code = ISP16_BASE_320;
- break;
- default:
- printk
- ("ISP16: base address 0x%03X not supported by cdrom interface.\n",
- base);
- return -1;
- }
- switch (irq) {
- case 0:
- irq_code = ISP16_IRQ_X;
- break; /* disable irq */
- case 5:
- irq_code = ISP16_IRQ_5;
- printk("ISP16: irq 5 shouldn't be used by cdrom interface,"
- " due to possible conflicts with the sound card.\n");
- break;
- case 7:
- irq_code = ISP16_IRQ_7;
- printk("ISP16: irq 7 shouldn't be used by cdrom interface,"
- " due to possible conflicts with the sound card.\n");
- break;
- case 3:
- irq_code = ISP16_IRQ_3;
- break;
- case 9:
- irq_code = ISP16_IRQ_9;
- break;
- case 10:
- irq_code = ISP16_IRQ_10;
- break;
- case 11:
- irq_code = ISP16_IRQ_11;
- break;
- default:
- printk("ISP16: irq %d not supported by cdrom interface.\n",
- irq);
- return -1;
- }
- switch (dma) {
- case 0:
- dma_code = ISP16_DMA_X;
- break; /* disable dma */
- case 1:
- printk("ISP16: dma 1 cannot be used by cdrom interface,"
- " due to conflict with the sound card.\n");
- return -1;
- break;
- case 3:
- dma_code = ISP16_DMA_3;
- break;
- case 5:
- dma_code = ISP16_DMA_5;
- break;
- case 6:
- dma_code = ISP16_DMA_6;
- break;
- case 7:
- dma_code = ISP16_DMA_7;
- break;
- default:
- printk("ISP16: dma %d not supported by cdrom interface.\n",
- dma);
- return -1;
- }
-
- if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
- drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
- drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
- drive_type != ISP16_DRIVE_X) {
- printk
- ("ISP16: drive type (code 0x%02X) not supported by cdrom"
- " interface.\n", drive_type);
- return -1;
- }
-
- /* set type of interface */
- i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */
- ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type);
-
- /* enable cdrom on interface with 82C929 chip */
- if (isp16_type > 1)
- ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM);
-
- /* set base address, irq and dma */
- i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */
- ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code);
-
- return 0;
-}
-
-static void __exit isp16_exit(void)
-{
- release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
- printk(KERN_INFO "ISP16: module released.\n");
-}
-
-module_init(isp16_init);
-module_exit(isp16_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/cdrom/isp16.h b/drivers/cdrom/isp16.h
deleted file mode 100644
index 5bd22c8f7a9..00000000000
--- a/drivers/cdrom/isp16.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -- isp16.h
- *
- * Header for detection and initialisation of cdrom interface (only) on
- * ISP16 (MAD16, Mozart) sound card.
- *
- * 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.
- *
- */
-
-/* These are the default values */
-#define ISP16_CDROM_TYPE "Sanyo"
-#define ISP16_CDROM_IO_BASE 0x340
-#define ISP16_CDROM_IRQ 0
-#define ISP16_CDROM_DMA 0
-
-/* Some (Media)Magic */
-/* define types of drive the interface on an ISP16 card may be looking at */
-#define ISP16_DRIVE_X 0x00
-#define ISP16_SONY 0x02
-#define ISP16_PANASONIC0 0x02
-#define ISP16_SANYO0 0x02
-#define ISP16_MITSUMI 0x04
-#define ISP16_PANASONIC1 0x06
-#define ISP16_SANYO1 0x06
-#define ISP16_DRIVE_NOT_USED 0x08 /* not used */
-#define ISP16_DRIVE_SET_MASK 0xF1 /* don't change 0-bit or 4-7-bits*/
-/* ...for port */
-#define ISP16_DRIVE_SET_PORT 0xF8D
-/* set io parameters */
-#define ISP16_BASE_340 0x00
-#define ISP16_BASE_330 0x40
-#define ISP16_BASE_360 0x80
-#define ISP16_BASE_320 0xC0
-#define ISP16_IRQ_X 0x00
-#define ISP16_IRQ_5 0x04 /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_7 0x08 /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_3 0x0C
-#define ISP16_IRQ_9 0x10
-#define ISP16_IRQ_10 0x14
-#define ISP16_IRQ_11 0x18
-#define ISP16_DMA_X 0x03
-#define ISP16_DMA_3 0x00
-#define ISP16_DMA_5 0x00
-#define ISP16_DMA_6 0x01
-#define ISP16_DMA_7 0x02
-#define ISP16_IO_SET_MASK 0x20 /* don't change 5-bit */
-/* ...for port */
-#define ISP16_IO_SET_PORT 0xF8E
-/* enable the card */
-#define ISP16_C928__ENABLE_PORT 0xF90 /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__ENABLE_PORT 0xF91 /* ISP16 with OPTi 82C929 chip */
-#define ISP16_ENABLE_CDROM 0x80 /* seven bit */
-
-/* the magic stuff */
-#define ISP16_CTRL_PORT 0xF8F
-#define ISP16_C928__CTRL 0xE2 /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__CTRL 0xE3 /* ISP16 with OPTi 82C929 chip */
-
-#define ISP16_IO_BASE 0xF8D
-#define ISP16_IO_SIZE 5 /* ports used from 0xF8D up to 0xF91 */
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
deleted file mode 100644
index 4310cc84dfe..00000000000
--- a/drivers/cdrom/mcdx.c
+++ /dev/null
@@ -1,1943 +0,0 @@
-/*
- * The Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.14(hs)
- *
- * ... anyway, I'm back again, thanks to Marcin, he adopted
- * large portions of my code (at least the parts containing
- * my main thoughts ...)
- *
- ****************** H E L P *********************************
- * If you ever plan to update your CD ROM drive and perhaps
- * want to sell or simply give away your Mitsumi FX-001[DS]
- * -- Please --
- * mail me (heiko@lotte.sax.de). When my last drive goes
- * ballistic no more driver support will be available from me!
- *************************************************************
- *
- * 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; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- * The Linux Community at all and ...
- * Martin Harriss (he wrote the first Mitsumi Driver)
- * Eberhard Moenkeberg (he gave me much support and the initial kick)
- * Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they
- * improved the original driver)
- * Jon Tombs, Bjorn Ekwall (module support)
- * Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- * Gerd Knorr (he lent me his PhotoCD)
- * Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- * Andreas Kies (testing the mysterious hang-ups)
- * Heiko Eissfeldt (VERIFY_READ/WRITE)
- * Marcin Dalecki (improved performance, shortened code)
- * ... somebody forgotten?
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- */
-
-
-#ifdef RCS
-static const char *mcdx_c_version
- = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $";
-#endif
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/current.h>
-#include <asm/uaccess.h>
-
-#include <linux/major.h>
-#define MAJOR_NR MITSUMI_X_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#include "mcdx.h"
-
-#ifndef HZ
-#error HZ not defined
-#endif
-
-#define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args)
-
-#if !MCDX_QUIET
-#define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args)
-#else
-#define xinfo(fmt, args...) { ; }
-#endif
-
-#if MCDX_DEBUG
-#define xtrace(lvl, fmt, args...) \
- { if (lvl > 0) \
- { printk(KERN_DEBUG MCDX ":: " fmt, ## args); } }
-#define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args)
-#else
-#define xtrace(lvl, fmt, args...) { ; }
-#define xdebug(fmt, args...) { ; }
-#endif
-
-/* CONSTANTS *******************************************************/
-
-/* Following are the number of sectors we _request_ from the drive
- every time an access outside the already requested range is done.
- The _direct_ size is the number of sectors we're allowed to skip
- directly (performing a read instead of requesting the new sector
- needed */
-static const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */
-static const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */
-
-enum drivemodes { TOC, DATA, RAW, COOKED };
-enum datamodes { MODE0, MODE1, MODE2 };
-enum resetmodes { SOFT, HARD };
-
-static const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */
-static const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */
-static const int DOOR = 0x04; /* door locking capability */
-static const int MULTI = 0x08; /* multi session capability */
-
-static const unsigned char READ1X = 0xc0;
-static const unsigned char READ2X = 0xc1;
-
-
-/* DECLARATIONS ****************************************************/
-struct s_subqcode {
- unsigned char control;
- unsigned char tno;
- unsigned char index;
- struct cdrom_msf0 tt;
- struct cdrom_msf0 dt;
-};
-
-struct s_diskinfo {
- unsigned int n_first;
- unsigned int n_last;
- struct cdrom_msf0 msf_leadout;
- struct cdrom_msf0 msf_first;
-};
-
-struct s_multi {
- unsigned char multi;
- struct cdrom_msf0 msf_last;
-};
-
-struct s_version {
- unsigned char code;
- unsigned char ver;
-};
-
-/* Per drive/controller stuff **************************************/
-
-struct s_drive_stuff {
- /* waitqueues */
- wait_queue_head_t busyq;
- wait_queue_head_t lockq;
- wait_queue_head_t sleepq;
-
- /* flags */
- volatile int introk; /* status of last irq operation */
- volatile int busy; /* drive performs an operation */
- volatile int lock; /* exclusive usage */
-
- /* cd infos */
- struct s_diskinfo di;
- struct s_multi multi;
- struct s_subqcode *toc; /* first entry of the toc array */
- struct s_subqcode start;
- struct s_subqcode stop;
- int xa; /* 1 if xa disk */
- int audio; /* 1 if audio disk */
- int audiostatus;
-
- /* `buffer' control */
- volatile int valid; /* pending, ..., values are valid */
- volatile int pending; /* next sector to be read */
- volatile int low_border; /* first sector not to be skipped direct */
- volatile int high_border; /* first sector `out of area' */
-#ifdef AK2
- volatile int int_err;
-#endif /* AK2 */
-
- /* adds and odds */
- unsigned wreg_data; /* w data */
- unsigned wreg_reset; /* w hardware reset */
- unsigned wreg_hcon; /* w hardware conf */
- unsigned wreg_chn; /* w channel */
- unsigned rreg_data; /* r data */
- unsigned rreg_status; /* r status */
-
- int irq; /* irq used by this drive */
- int present; /* drive present and its capabilities */
- unsigned char readcmd; /* read cmd depends on single/double speed */
- unsigned char playcmd; /* play should always be single speed */
- unsigned int xxx; /* set if changed, reset while open */
- unsigned int yyy; /* set if changed, reset by media_changed */
- int users; /* keeps track of open/close */
- int lastsector; /* last block accessible */
- int status; /* last operation's error / status */
- int readerrs; /* # of blocks read w/o error */
- struct cdrom_device_info info;
- struct gendisk *disk;
-};
-
-
-/* Prototypes ******************************************************/
-
-/* The following prototypes are already declared elsewhere. They are
- repeated here to show what's going on. And to sense, if they're
- changed elsewhere. */
-
-static int mcdx_init(void);
-
-static int mcdx_block_open(struct inode *inode, struct file *file)
-{
- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_open(&p->info, inode, file);
-}
-
-static int mcdx_block_release(struct inode *inode, struct file *file)
-{
- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_release(&p->info, file);
-}
-
-static int mcdx_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_ioctl(file, &p->info, inode, cmd, arg);
-}
-
-static int mcdx_block_media_changed(struct gendisk *disk)
-{
- struct s_drive_stuff *p = disk->private_data;
- return cdrom_media_changed(&p->info);
-}
-
-static struct block_device_operations mcdx_bdops =
-{
- .owner = THIS_MODULE,
- .open = mcdx_block_open,
- .release = mcdx_block_release,
- .ioctl = mcdx_block_ioctl,
- .media_changed = mcdx_block_media_changed,
-};
-
-
-/* Indirect exported functions. These functions are exported by their
- addresses, such as mcdx_open and mcdx_close in the
- structure mcdx_dops. */
-
-/* exported by file_ops */
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose);
-static void mcdx_close(struct cdrom_device_info *cdi);
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr);
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position);
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock);
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg);
-
-/* misc internal support functions */
-static void log2msf(unsigned int, struct cdrom_msf0 *);
-static unsigned int msf2log(const struct cdrom_msf0 *);
-static unsigned int uint2bcd(unsigned int);
-static unsigned int bcd2uint(unsigned char);
-static unsigned port(int *);
-static int irq(int *);
-static void mcdx_delay(struct s_drive_stuff *, long jifs);
-static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector,
- int nr_sectors);
-static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector,
- int nr_sectors);
-
-static int mcdx_config(struct s_drive_stuff *, int);
-static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *,
- int);
-static int mcdx_stop(struct s_drive_stuff *, int);
-static int mcdx_hold(struct s_drive_stuff *, int);
-static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int);
-static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int);
-static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int);
-static int mcdx_requestsubqcode(struct s_drive_stuff *,
- struct s_subqcode *, int);
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *,
- struct s_multi *, int);
-static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *,
- int);
-static int mcdx_getstatus(struct s_drive_stuff *, int);
-static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *);
-static int mcdx_talk(struct s_drive_stuff *,
- const unsigned char *cmd, size_t,
- void *buffer, size_t size, unsigned int timeout, int);
-static int mcdx_readtoc(struct s_drive_stuff *);
-static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *);
-static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *);
-static int mcdx_setattentuator(struct s_drive_stuff *,
- struct cdrom_volctrl *, int);
-
-/* static variables ************************************************/
-
-static int mcdx_drive_map[][2] = MCDX_DRIVEMAP;
-static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
-static DEFINE_SPINLOCK(mcdx_lock);
-static struct request_queue *mcdx_queue;
-
-/* You can only set the first two pairs, from old MODULE_PARM code. */
-static int mcdx_set(const char *val, struct kernel_param *kp)
-{
- get_options((char *)val, 4, (int *)mcdx_drive_map);
- return 0;
-}
-module_param_call(mcdx, mcdx_set, NULL, NULL, 0);
-
-static struct cdrom_device_ops mcdx_dops = {
- .open = mcdx_open,
- .release = mcdx_close,
- .media_changed = mcdx_media_changed,
- .tray_move = mcdx_tray_move,
- .lock_door = mcdx_lockdoor,
- .audio_ioctl = mcdx_audio_ioctl,
- .capability = CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED |
- CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
-};
-
-/* KERNEL INTERFACE FUNCTIONS **************************************/
-
-
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg)
-{
- struct s_drive_stuff *stuffp = cdi->handle;
-
- if (!stuffp->present)
- return -ENXIO;
-
- if (stuffp->xxx) {
- if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
- stuffp->lastsector = -1;
- } else {
- stuffp->lastsector = (CD_FRAMESIZE / 512)
- * msf2log(&stuffp->di.msf_leadout) - 1;
- }
-
- if (stuffp->toc) {
- kfree(stuffp->toc);
- stuffp->toc = NULL;
- if (-1 == mcdx_readtoc(stuffp))
- return -1;
- }
-
- stuffp->xxx = 0;
- }
-
- switch (cmd) {
- case CDROMSTART:{
- xtrace(IOCTL, "ioctl() START\n");
- /* Spin up the drive. Don't think we can do this.
- * For now, ignore it.
- */
- return 0;
- }
-
- case CDROMSTOP:{
- xtrace(IOCTL, "ioctl() STOP\n");
- stuffp->audiostatus = CDROM_AUDIO_INVALID;
- if (-1 == mcdx_stop(stuffp, 1))
- return -EIO;
- return 0;
- }
-
- case CDROMPLAYTRKIND:{
- struct cdrom_ti *ti = (struct cdrom_ti *) arg;
-
- xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
- if ((ti->cdti_trk0 < stuffp->di.n_first)
- || (ti->cdti_trk0 > stuffp->di.n_last)
- || (ti->cdti_trk1 < stuffp->di.n_first))
- return -EINVAL;
- if (ti->cdti_trk1 > stuffp->di.n_last)
- ti->cdti_trk1 = stuffp->di.n_last;
- xtrace(PLAYTRK, "ioctl() track %d to %d\n",
- ti->cdti_trk0, ti->cdti_trk1);
- return mcdx_playtrk(stuffp, ti);
- }
-
- case CDROMPLAYMSF:{
- struct cdrom_msf *msf = (struct cdrom_msf *) arg;
-
- xtrace(IOCTL, "ioctl() PLAYMSF\n");
-
- if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
- && (-1 == mcdx_hold(stuffp, 1)))
- return -EIO;
-
- msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
- msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
- msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
-
- msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
- msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
- msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
-
- stuffp->stop.dt.minute = msf->cdmsf_min1;
- stuffp->stop.dt.second = msf->cdmsf_sec1;
- stuffp->stop.dt.frame = msf->cdmsf_frame1;
-
- return mcdx_playmsf(stuffp, msf);
- }
-
- case CDROMRESUME:{
- xtrace(IOCTL, "ioctl() RESUME\n");
- return mcdx_playtrk(stuffp, NULL);
- }
-
- case CDROMREADTOCENTRY:{
- struct cdrom_tocentry *entry =
- (struct cdrom_tocentry *) arg;
- struct s_subqcode *tp = NULL;
- xtrace(IOCTL, "ioctl() READTOCENTRY\n");
-
- if (-1 == mcdx_readtoc(stuffp))
- return -1;
- if (entry->cdte_track == CDROM_LEADOUT)
- tp = &stuffp->toc[stuffp->di.n_last -
- stuffp->di.n_first + 1];
- else if (entry->cdte_track > stuffp->di.n_last
- || entry->cdte_track < stuffp->di.n_first)
- return -EINVAL;
- else
- tp = &stuffp->toc[entry->cdte_track -
- stuffp->di.n_first];
-
- if (NULL == tp)
- return -EIO;
- entry->cdte_adr = tp->control;
- entry->cdte_ctrl = tp->control >> 4;
- /* Always return stuff in MSF, and let the Uniform cdrom driver
- worry about what the user actually wants */
- entry->cdte_addr.msf.minute =
- bcd2uint(tp->dt.minute);
- entry->cdte_addr.msf.second =
- bcd2uint(tp->dt.second);
- entry->cdte_addr.msf.frame =
- bcd2uint(tp->dt.frame);
- return 0;
- }
-
- case CDROMSUBCHNL:{
- struct cdrom_subchnl *sub =
- (struct cdrom_subchnl *) arg;
- struct s_subqcode q;
-
- xtrace(IOCTL, "ioctl() SUBCHNL\n");
-
- if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
- return -EIO;
-
- xtrace(SUBCHNL, "audiostatus: %x\n",
- stuffp->audiostatus);
- sub->cdsc_audiostatus = stuffp->audiostatus;
- sub->cdsc_adr = q.control;
- sub->cdsc_ctrl = q.control >> 4;
- sub->cdsc_trk = bcd2uint(q.tno);
- sub->cdsc_ind = bcd2uint(q.index);
-
- xtrace(SUBCHNL, "trk %d, ind %d\n",
- sub->cdsc_trk, sub->cdsc_ind);
- /* Always return stuff in MSF, and let the Uniform cdrom driver
- worry about what the user actually wants */
- sub->cdsc_absaddr.msf.minute =
- bcd2uint(q.dt.minute);
- sub->cdsc_absaddr.msf.second =
- bcd2uint(q.dt.second);
- sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
- sub->cdsc_reladdr.msf.minute =
- bcd2uint(q.tt.minute);
- sub->cdsc_reladdr.msf.second =
- bcd2uint(q.tt.second);
- sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
- xtrace(SUBCHNL,
- "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
- sub->cdsc_absaddr.msf.minute,
- sub->cdsc_absaddr.msf.second,
- sub->cdsc_absaddr.msf.frame,
- sub->cdsc_reladdr.msf.minute,
- sub->cdsc_reladdr.msf.second,
- sub->cdsc_reladdr.msf.frame);
-
- return 0;
- }
-
- case CDROMREADTOCHDR:{
- struct cdrom_tochdr *toc =
- (struct cdrom_tochdr *) arg;
-
- xtrace(IOCTL, "ioctl() READTOCHDR\n");
- toc->cdth_trk0 = stuffp->di.n_first;
- toc->cdth_trk1 = stuffp->di.n_last;
- xtrace(TOCHDR,
- "ioctl() track0 = %d, track1 = %d\n",
- stuffp->di.n_first, stuffp->di.n_last);
- return 0;
- }
-
- case CDROMPAUSE:{
- xtrace(IOCTL, "ioctl() PAUSE\n");
- if (stuffp->audiostatus != CDROM_AUDIO_PLAY)
- return -EINVAL;
- if (-1 == mcdx_stop(stuffp, 1))
- return -EIO;
- stuffp->audiostatus = CDROM_AUDIO_PAUSED;
- if (-1 ==
- mcdx_requestsubqcode(stuffp, &stuffp->start,
- 1))
- return -EIO;
- return 0;
- }
-
- case CDROMMULTISESSION:{
- struct cdrom_multisession *ms =
- (struct cdrom_multisession *) arg;
- xtrace(IOCTL, "ioctl() MULTISESSION\n");
- /* Always return stuff in LBA, and let the Uniform cdrom driver
- worry about what the user actually wants */
- ms->addr.lba = msf2log(&stuffp->multi.msf_last);
- ms->xa_flag = !!stuffp->multi.multi;
- xtrace(MS,
- "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
- ms->xa_flag, ms->addr.lba,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
-
- return 0;
- }
-
- case CDROMEJECT:{
- xtrace(IOCTL, "ioctl() EJECT\n");
- if (stuffp->users > 1)
- return -EBUSY;
- return (mcdx_tray_move(cdi, 1));
- }
-
- case CDROMCLOSETRAY:{
- xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");
- return (mcdx_tray_move(cdi, 0));
- }
-
- case CDROMVOLCTRL:{
- struct cdrom_volctrl *volctrl =
- (struct cdrom_volctrl *) arg;
- xtrace(IOCTL, "ioctl() VOLCTRL\n");
-
-#if 0 /* not tested! */
- /* adjust for the weirdness of workman (md) */
- /* can't test it (hs) */
- volctrl.channel2 = volctrl.channel1;
- volctrl.channel1 = volctrl.channel3 = 0x00;
-#endif
- return mcdx_setattentuator(stuffp, volctrl, 2);
- }
-
- default:
- return -EINVAL;
- }
-}
-
-static void do_mcdx_request(request_queue_t * q)
-{
- struct s_drive_stuff *stuffp;
- struct request *req;
-
- again:
-
- req = elv_next_request(q);
- if (!req)
- return;
-
- stuffp = req->rq_disk->private_data;
-
- if (!stuffp->present) {
- xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name);
- xtrace(REQUEST, "end_request(0): bad device\n");
- end_request(req, 0);
- return;
- }
-
- if (stuffp->audio) {
- xwarn("do_request() attempt to read from audio cd\n");
- xtrace(REQUEST, "end_request(0): read from audio\n");
- end_request(req, 0);
- return;
- }
-
- xtrace(REQUEST, "do_request() (%lu + %lu)\n",
- req->sector, req->nr_sectors);
-
- if (req->cmd != READ) {
- xwarn("do_request(): non-read command to cd!!\n");
- xtrace(REQUEST, "end_request(0): write\n");
- end_request(req, 0);
- return;
- }
- else {
- stuffp->status = 0;
- while (req->nr_sectors) {
- int i;
-
- i = mcdx_transfer(stuffp,
- req->buffer,
- req->sector,
- req->nr_sectors);
-
- if (i == -1) {
- end_request(req, 0);
- goto again;
- }
- req->sector += i;
- req->nr_sectors -= i;
- req->buffer += (i * 512);
- }
- end_request(req, 1);
- goto again;
-
- xtrace(REQUEST, "end_request(1)\n");
- end_request(req, 1);
- }
-
- goto again;
-}
-
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose)
-{
- struct s_drive_stuff *stuffp;
- xtrace(OPENCLOSE, "open()\n");
- stuffp = cdi->handle;
- if (!stuffp->present)
- return -ENXIO;
-
- /* Make the modules looking used ... (thanx bjorn).
- * But we shouldn't forget to decrement the module counter
- * on error return */
-
- /* this is only done to test if the drive talks with us */
- if (-1 == mcdx_getstatus(stuffp, 1))
- return -EIO;
-
- if (stuffp->xxx) {
-
- xtrace(OPENCLOSE, "open() media changed\n");
- stuffp->audiostatus = CDROM_AUDIO_INVALID;
- stuffp->readcmd = 0;
- xtrace(OPENCLOSE, "open() Request multisession info\n");
- if (-1 ==
- mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6))
- xinfo("No multidiskinfo\n");
- } else {
- /* multisession ? */
- if (!stuffp->multi.multi)
- stuffp->multi.msf_last.second = 2;
-
- xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
- stuffp->multi.multi,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
-
- {;
- } /* got multisession information */
- /* request the disks table of contents (aka diskinfo) */
- if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-
- stuffp->lastsector = -1;
-
- } else {
-
- stuffp->lastsector = (CD_FRAMESIZE / 512)
- * msf2log(&stuffp->di.msf_leadout) - 1;
-
- xtrace(OPENCLOSE,
- "open() start %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_first,
- stuffp->di.msf_first.minute,
- stuffp->di.msf_first.second,
- stuffp->di.msf_first.frame,
- msf2log(&stuffp->di.msf_first));
- xtrace(OPENCLOSE,
- "open() last %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_last,
- stuffp->di.msf_leadout.minute,
- stuffp->di.msf_leadout.second,
- stuffp->di.msf_leadout.frame,
- msf2log(&stuffp->di.msf_leadout));
- }
-
- if (stuffp->toc) {
- xtrace(MALLOC, "open() free old toc @ %p\n",
- stuffp->toc);
- kfree(stuffp->toc);
-
- stuffp->toc = NULL;
- }
-
- xtrace(OPENCLOSE, "open() init irq generation\n");
- if (-1 == mcdx_config(stuffp, 1))
- return -EIO;
-#ifdef FALLBACK
- /* Set the read speed */
- xwarn("AAA %x AAA\n", stuffp->readcmd);
- if (stuffp->readerrs)
- stuffp->readcmd = READ1X;
- else
- stuffp->readcmd =
- stuffp->present | SINGLE ? READ1X : READ2X;
- xwarn("XXX %x XXX\n", stuffp->readcmd);
-#else
- stuffp->readcmd =
- stuffp->present | SINGLE ? READ1X : READ2X;
-#endif
-
- /* try to get the first sector, iff any ... */
- if (stuffp->lastsector >= 0) {
- char buf[512];
- int ans;
- int tries;
-
- stuffp->xa = 0;
- stuffp->audio = 0;
-
- for (tries = 6; tries; tries--) {
-
- stuffp->introk = 1;
-
- xtrace(OPENCLOSE, "open() try as %s\n",
- stuffp->xa ? "XA" : "normal");
- /* set data mode */
- if (-1 == (ans = mcdx_setdatamode(stuffp,
- stuffp->
- xa ?
- MODE2 :
- MODE1,
- 1))) {
- /* return -EIO; */
- stuffp->xa = 0;
- break;
- }
-
- if ((stuffp->audio = e_audio(ans)))
- break;
-
- while (0 ==
- (ans =
- mcdx_transfer(stuffp, buf, 0, 1)));
-
- if (ans == 1)
- break;
- stuffp->xa = !stuffp->xa;
- }
- }
- /* xa disks will be read in raw mode, others not */
- if (-1 == mcdx_setdrivemode(stuffp,
- stuffp->xa ? RAW : COOKED,
- 1))
- return -EIO;
- if (stuffp->audio) {
- xinfo("open() audio disk found\n");
- } else if (stuffp->lastsector >= 0) {
- xinfo("open() %s%s disk found\n",
- stuffp->xa ? "XA / " : "",
- stuffp->multi.
- multi ? "Multi Session" : "Single Session");
- }
- }
- stuffp->xxx = 0;
- stuffp->users++;
- return 0;
-}
-
-static void mcdx_close(struct cdrom_device_info *cdi)
-{
- struct s_drive_stuff *stuffp;
-
- xtrace(OPENCLOSE, "close()\n");
-
- stuffp = cdi->handle;
-
- --stuffp->users;
-}
-
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-/* Return: 1 if media changed since last call to this function
- 0 otherwise */
-{
- struct s_drive_stuff *stuffp;
-
- xinfo("mcdx_media_changed called for device %s\n", cdi->name);
-
- stuffp = cdi->handle;
- mcdx_getstatus(stuffp, 1);
-
- if (stuffp->yyy == 0)
- return 0;
-
- stuffp->yyy = 0;
- return 1;
-}
-
-#ifndef MODULE
-static int __init mcdx_setup(char *str)
-{
- int pi[4];
- (void) get_options(str, ARRAY_SIZE(pi), pi);
-
- if (pi[0] > 0)
- mcdx_drive_map[0][0] = pi[1];
- if (pi[0] > 1)
- mcdx_drive_map[0][1] = pi[2];
- return 1;
-}
-
-__setup("mcdx=", mcdx_setup);
-
-#endif
-
-/* DIRTY PART ******************************************************/
-
-static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
-/* This routine is used for sleeping.
- * A jifs value <0 means NO sleeping,
- * =0 means minimal sleeping (let the kernel
- * run for other processes)
- * >0 means at least sleep for that amount.
- * May be we could use a simple count loop w/ jumps to itself, but
- * I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
-{
- if (jifs < 0)
- return;
-
- xtrace(SLEEP, "*** delay: sleepq\n");
- interruptible_sleep_on_timeout(&stuff->sleepq, jifs);
- xtrace(SLEEP, "delay awoken\n");
- if (signal_pending(current)) {
- xtrace(SLEEP, "got signal\n");
- }
-}
-
-static irqreturn_t mcdx_intr(int irq, void *dev_id)
-{
- struct s_drive_stuff *stuffp = dev_id;
- unsigned char b;
-
-#ifdef AK2
- if (!stuffp->busy && stuffp->pending)
- stuffp->int_err = 1;
-
-#endif /* AK2 */
- /* get the interrupt status */
- b = inb(stuffp->rreg_status);
- stuffp->introk = ~b & MCDX_RBIT_DTEN;
-
- /* NOTE: We only should get interrupts if the data we
- * requested are ready to transfer.
- * But the drive seems to generate ``asynchronous'' interrupts
- * on several error conditions too. (Despite the err int enable
- * setting during initialisation) */
-
- /* if not ok, read the next byte as the drives status */
- if (!stuffp->introk) {
- xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
- if (~b & MCDX_RBIT_STEN) {
- xinfo("intr() irq %d status 0x%02x\n",
- irq, inb(stuffp->rreg_data));
- } else {
- xinfo("intr() irq %d ambiguous hw status\n", irq);
- }
- } else {
- xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b);
- }
-
- stuffp->busy = 0;
- wake_up_interruptible(&stuffp->busyq);
- return IRQ_HANDLED;
-}
-
-
-static int mcdx_talk(struct s_drive_stuff *stuffp,
- const unsigned char *cmd, size_t cmdlen,
- void *buffer, size_t size, unsigned int timeout, int tries)
-/* Send a command to the drive, wait for the result.
- * returns -1 on timeout, drive status otherwise
- * If buffer is not zero, the result (length size) is stored there.
- * If buffer is zero the size should be the number of bytes to read
- * from the drive. These bytes are discarded.
- */
-{
- int st;
- char c;
- int discard;
-
- /* Somebody wants the data read? */
- if ((discard = (buffer == NULL)))
- buffer = &c;
-
- while (stuffp->lock) {
- xtrace(SLEEP, "*** talk: lockq\n");
- interruptible_sleep_on(&stuffp->lockq);
- xtrace(SLEEP, "talk: awoken\n");
- }
-
- stuffp->lock = 1;
-
- /* An operation other then reading data destroys the
- * data already requested and remembered in stuffp->request, ... */
- stuffp->valid = 0;
-
-#if MCDX_DEBUG & TALK
- {
- unsigned char i;
- xtrace(TALK,
- "talk() %d / %d tries, res.size %d, command 0x%02x",
- tries, timeout, size, (unsigned char) cmd[0]);
- for (i = 1; i < cmdlen; i++)
- xtrace(TALK, " 0x%02x", cmd[i]);
- xtrace(TALK, "\n");
- }
-#endif
-
- /* give up if all tries are done (bad) or if the status
- * st != -1 (good) */
- for (st = -1; st == -1 && tries; tries--) {
-
- char *bp = (char *) buffer;
- size_t sz = size;
-
- outsb(stuffp->wreg_data, cmd, cmdlen);
- xtrace(TALK, "talk() command sent\n");
-
- /* get the status byte */
- if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
- xinfo("talk() %02x timed out (status), %d tr%s left\n",
- cmd[0], tries - 1, tries == 2 ? "y" : "ies");
- continue;
- }
- st = *bp;
- sz--;
- if (!discard)
- bp++;
-
- xtrace(TALK, "talk() got status 0x%02x\n", st);
-
- /* command error? */
- if (e_cmderr(st)) {
- xwarn("command error cmd = %02x %s \n",
- cmd[0], cmdlen > 1 ? "..." : "");
- st = -1;
- continue;
- }
-
- /* audio status? */
- if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
- stuffp->audiostatus =
- e_audiobusy(st) ? CDROM_AUDIO_PLAY :
- CDROM_AUDIO_NO_STATUS;
- else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
- && e_audiobusy(st) == 0)
- stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
-
- /* media change? */
- if (e_changed(st)) {
- xinfo("talk() media changed\n");
- stuffp->xxx = stuffp->yyy = 1;
- }
-
- /* now actually get the data */
- while (sz--) {
- if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
- xinfo("talk() %02x timed out (data), %d tr%s left\n",
- cmd[0], tries - 1,
- tries == 2 ? "y" : "ies");
- st = -1;
- break;
- }
- if (!discard)
- bp++;
- xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1));
- }
- }
-
-#if !MCDX_QUIET
- if (!tries && st == -1)
- xinfo("talk() giving up\n");
-#endif
-
- stuffp->lock = 0;
- wake_up_interruptible(&stuffp->lockq);
-
- xtrace(TALK, "talk() done with 0x%02x\n", st);
- return st;
-}
-
-/* MODULE STUFF ***********************************************************/
-
-static int __init __mcdx_init(void)
-{
- int i;
- int drives = 0;
-
- mcdx_init();
- for (i = 0; i < MCDX_NDRIVES; i++) {
- if (mcdx_stuffp[i]) {
- xtrace(INIT, "init_module() drive %d stuff @ %p\n",
- i, mcdx_stuffp[i]);
- drives++;
- }
- }
-
- if (!drives)
- return -EIO;
-
- return 0;
-}
-
-static void __exit mcdx_exit(void)
-{
- int i;
-
- xinfo("cleanup_module called\n");
-
- for (i = 0; i < MCDX_NDRIVES; i++) {
- struct s_drive_stuff *stuffp = mcdx_stuffp[i];
- if (!stuffp)
- continue;
- del_gendisk(stuffp->disk);
- if (unregister_cdrom(&stuffp->info)) {
- printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
- continue;
- }
- put_disk(stuffp->disk);
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- free_irq(stuffp->irq, NULL);
- if (stuffp->toc) {
- xtrace(MALLOC, "cleanup_module() free toc @ %p\n",
- stuffp->toc);
- kfree(stuffp->toc);
- }
- xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n",
- stuffp);
- mcdx_stuffp[i] = NULL;
- kfree(stuffp);
- }
-
- if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
- xwarn("cleanup() unregister_blkdev() failed\n");
- }
-#if !MCDX_QUIET
- else
- xinfo("cleanup() succeeded\n");
-#endif
- blk_cleanup_queue(mcdx_queue);
-}
-
-#ifdef MODULE
-module_init(__mcdx_init);
-#endif
-module_exit(mcdx_exit);
-
-
-/* Support functions ************************************************/
-
-static int __init mcdx_init_drive(int drive)
-{
- struct s_version version;
- struct gendisk *disk;
- struct s_drive_stuff *stuffp;
- int size = sizeof(*stuffp);
- char msg[80];
-
- xtrace(INIT, "init() try drive %d\n", drive);
-
- xtrace(INIT, "kmalloc space for stuffpt's\n");
- xtrace(MALLOC, "init() malloc %d bytes\n", size);
- if (!(stuffp = kzalloc(size, GFP_KERNEL))) {
- xwarn("init() malloc failed\n");
- return 1;
- }
-
- disk = alloc_disk(1);
- if (!disk) {
- xwarn("init() malloc failed\n");
- kfree(stuffp);
- return 1;
- }
-
- xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
- sizeof(*stuffp), stuffp);
-
- /* set default values */
- stuffp->present = 0; /* this should be 0 already */
- stuffp->toc = NULL; /* this should be NULL already */
-
- /* setup our irq and i/o addresses */
- stuffp->irq = irq(mcdx_drive_map[drive]);
- stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
- stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
- stuffp->wreg_hcon = stuffp->wreg_reset + 1;
- stuffp->wreg_chn = stuffp->wreg_hcon + 1;
-
- init_waitqueue_head(&stuffp->busyq);
- init_waitqueue_head(&stuffp->lockq);
- init_waitqueue_head(&stuffp->sleepq);
-
- /* check if i/o addresses are available */
- if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) {
- xwarn("0x%03x,%d: Init failed. "
- "I/O ports (0x%03x..0x%03x) already in use.\n",
- stuffp->wreg_data, stuffp->irq,
- stuffp->wreg_data,
- stuffp->wreg_data + MCDX_IO_SIZE - 1);
- xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
- kfree(stuffp);
- put_disk(disk);
- xtrace(INIT, "init() continue at next drive\n");
- return 0; /* next drive */
- }
-
- xtrace(INIT, "init() i/o port is available at 0x%03x\n"
- stuffp->wreg_data);
- xtrace(INIT, "init() hardware reset\n");
- mcdx_reset(stuffp, HARD, 1);
-
- xtrace(INIT, "init() get version\n");
- if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
- /* failed, next drive */
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n",
- MCDX, stuffp->wreg_data, stuffp->irq);
- xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
- kfree(stuffp);
- put_disk(disk);
- xtrace(INIT, "init() continue at next drive\n");
- return 0;
- }
-
- switch (version.code) {
- case 'D':
- stuffp->readcmd = READ2X;
- stuffp->present = DOUBLE | DOOR | MULTI;
- break;
- case 'F':
- stuffp->readcmd = READ1X;
- stuffp->present = SINGLE | DOOR | MULTI;
- break;
- case 'M':
- stuffp->readcmd = READ1X;
- stuffp->present = SINGLE;
- break;
- default:
- stuffp->present = 0;
- break;
- }
-
- stuffp->playcmd = READ1X;
-
- if (!stuffp->present) {
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n",
- MCDX, stuffp->wreg_data, stuffp->irq);
- kfree(stuffp);
- put_disk(disk);
- return 0; /* next drive */
- }
-
- xtrace(INIT, "init() register blkdev\n");
- if (register_blkdev(MAJOR_NR, "mcdx")) {
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- kfree(stuffp);
- put_disk(disk);
- return 1;
- }
-
- mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock);
- if (!mcdx_queue) {
- unregister_blkdev(MAJOR_NR, "mcdx");
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- kfree(stuffp);
- put_disk(disk);
- return 1;
- }
-
- xtrace(INIT, "init() subscribe irq and i/o\n");
- if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) {
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n",
- MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
- stuffp->irq = 0;
- blk_cleanup_queue(mcdx_queue);
- kfree(stuffp);
- put_disk(disk);
- return 0;
- }
-
- xtrace(INIT, "init() get garbage\n");
- {
- int i;
- mcdx_delay(stuffp, HZ / 2);
- for (i = 100; i; i--)
- (void) inb(stuffp->rreg_status);
- }
-
-
-#ifdef WE_KNOW_WHY
- /* irq 11 -> channel register */
- outb(0x50, stuffp->wreg_chn);
-#endif
-
- xtrace(INIT, "init() set non dma but irq mode\n");
- mcdx_config(stuffp, 1);
-
- stuffp->info.ops = &mcdx_dops;
- stuffp->info.speed = 2;
- stuffp->info.capacity = 1;
- stuffp->info.handle = stuffp;
- sprintf(stuffp->info.name, "mcdx%d", drive);
- disk->major = MAJOR_NR;
- disk->first_minor = drive;
- strcpy(disk->disk_name, stuffp->info.name);
- disk->fops = &mcdx_bdops;
- disk->flags = GENHD_FL_CD;
- stuffp->disk = disk;
-
- sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d."
- " (Firmware version %c %x)\n",
- stuffp->wreg_data, stuffp->irq, version.code, version.ver);
- mcdx_stuffp[drive] = stuffp;
- xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
- if (register_cdrom(&stuffp->info) != 0) {
- printk("Cannot register Mitsumi CD-ROM!\n");
- free_irq(stuffp->irq, NULL);
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- kfree(stuffp);
- put_disk(disk);
- if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
- xwarn("cleanup() unregister_blkdev() failed\n");
- blk_cleanup_queue(mcdx_queue);
- return 2;
- }
- disk->private_data = stuffp;
- disk->queue = mcdx_queue;
- add_disk(disk);
- printk(msg);
- return 0;
-}
-
-static int __init mcdx_init(void)
-{
- int drive;
- xwarn("Version 2.14(hs) \n");
-
- xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
-
- /* zero the pointer array */
- for (drive = 0; drive < MCDX_NDRIVES; drive++)
- mcdx_stuffp[drive] = NULL;
-
- /* do the initialisation */
- for (drive = 0; drive < MCDX_NDRIVES; drive++) {
- switch (mcdx_init_drive(drive)) {
- case 2:
- return -EIO;
- case 1:
- break;
- }
- }
- return 0;
-}
-
-static int mcdx_transfer(struct s_drive_stuff *stuffp,
- char *p, int sector, int nr_sectors)
-/* This seems to do the actually transfer. But it does more. It
- keeps track of errors occurred and will (if possible) fall back
- to single speed on error.
- Return: -1 on timeout or other error
- else status byte (as in stuff->st) */
-{
- int ans;
-
- ans = mcdx_xfer(stuffp, p, sector, nr_sectors);
- return ans;
-#ifdef FALLBACK
- if (-1 == ans)
- stuffp->readerrs++;
- else
- return ans;
-
- if (stuffp->readerrs && stuffp->readcmd == READ1X) {
- xwarn("XXX Already reading 1x -- no chance\n");
- return -1;
- }
-
- xwarn("XXX Fallback to 1x\n");
-
- stuffp->readcmd = READ1X;
- return mcdx_transfer(stuffp, p, sector, nr_sectors);
-#endif
-
-}
-
-
-static int mcdx_xfer(struct s_drive_stuff *stuffp,
- char *p, int sector, int nr_sectors)
-/* This does actually the transfer from the drive.
- Return: -1 on timeout or other error
- else status byte (as in stuff->st) */
-{
- int border;
- int done = 0;
- long timeout;
-
- if (stuffp->audio) {
- xwarn("Attempt to read from audio CD.\n");
- return -1;
- }
-
- if (!stuffp->readcmd) {
- xinfo("Can't transfer from missing disk.\n");
- return -1;
- }
-
- while (stuffp->lock) {
- interruptible_sleep_on(&stuffp->lockq);
- }
-
- if (stuffp->valid && (sector >= stuffp->pending)
- && (sector < stuffp->low_border)) {
-
- /* All (or at least a part of the sectors requested) seems
- * to be already requested, so we don't need to bother the
- * drive with new requests ...
- * Wait for the drive become idle, but first
- * check for possible occurred errors --- the drive
- * seems to report them asynchronously */
-
-
- border = stuffp->high_border < (border =
- sector + nr_sectors)
- ? stuffp->high_border : border;
-
- stuffp->lock = current->pid;
-
- do {
-
- while (stuffp->busy) {
-
- timeout =
- interruptible_sleep_on_timeout
- (&stuffp->busyq, 5 * HZ);
-
- if (!stuffp->introk) {
- xtrace(XFER,
- "error via interrupt\n");
- } else if (!timeout) {
- xtrace(XFER, "timeout\n");
- } else if (signal_pending(current)) {
- xtrace(XFER, "signal\n");
- } else
- continue;
-
- stuffp->lock = 0;
- stuffp->busy = 0;
- stuffp->valid = 0;
-
- wake_up_interruptible(&stuffp->lockq);
- xtrace(XFER, "transfer() done (-1)\n");
- return -1;
- }
-
- /* check if we need to set the busy flag (as we
- * expect an interrupt */
- stuffp->busy = (3 == (stuffp->pending & 3));
-
- /* Test if it's the first sector of a block,
- * there we have to skip some bytes as we read raw data */
- if (stuffp->xa && (0 == (stuffp->pending & 3))) {
- const int HEAD =
- CD_FRAMESIZE_RAW - CD_XA_TAIL -
- CD_FRAMESIZE;
- insb(stuffp->rreg_data, p, HEAD);
- }
-
- /* now actually read the data */
- insb(stuffp->rreg_data, p, 512);
-
- /* test if it's the last sector of a block,
- * if so, we have to handle XA special */
- if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
- char dummy[CD_XA_TAIL];
- insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL);
- }
-
- if (stuffp->pending == sector) {
- p += 512;
- done++;
- sector++;
- }
- } while (++(stuffp->pending) < border);
-
- stuffp->lock = 0;
- wake_up_interruptible(&stuffp->lockq);
-
- } else {
-
- /* The requested sector(s) is/are out of the
- * already requested range, so we have to bother the drive
- * with a new request. */
-
- static unsigned char cmd[] = {
- 0,
- 0, 0, 0,
- 0, 0, 0
- };
-
- cmd[0] = stuffp->readcmd;
-
- /* The numbers held in ->pending, ..., should be valid */
- stuffp->valid = 1;
- stuffp->pending = sector & ~3;
-
- /* do some sanity checks */
- if (stuffp->pending > stuffp->lastsector) {
- xwarn
- ("transfer() sector %d from nirvana requested.\n",
- stuffp->pending);
- stuffp->status = MCDX_ST_EOM;
- stuffp->valid = 0;
- xtrace(XFER, "transfer() done (-1)\n");
- return -1;
- }
-
- if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)
- > stuffp->lastsector + 1) {
- xtrace(XFER, "cut low_border\n");
- stuffp->low_border = stuffp->lastsector + 1;
- }
- if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)
- > stuffp->lastsector + 1) {
- xtrace(XFER, "cut high_border\n");
- stuffp->high_border = stuffp->lastsector + 1;
- }
-
- { /* Convert the sector to be requested to MSF format */
- struct cdrom_msf0 pending;
- log2msf(stuffp->pending / 4, &pending);
- cmd[1] = pending.minute;
- cmd[2] = pending.second;
- cmd[3] = pending.frame;
- }
-
- cmd[6] =
- (unsigned
- char) ((stuffp->high_border - stuffp->pending) / 4);
- xtrace(XFER, "[%2d]\n", cmd[6]);
-
- stuffp->busy = 1;
- /* Now really issue the request command */
- outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
- }
-#ifdef AK2
- if (stuffp->int_err) {
- stuffp->valid = 0;
- stuffp->int_err = 0;
- return -1;
- }
-#endif /* AK2 */
-
- stuffp->low_border = (stuffp->low_border +=
- done) <
- stuffp->high_border ? stuffp->low_border : stuffp->high_border;
-
- return done;
-}
-
-
-/* Access to elements of the mcdx_drive_map members */
-
-static unsigned port(int *ip)
-{
- return ip[0];
-}
-static int irq(int *ip)
-{
- return ip[1];
-}
-
-/* Misc number converters */
-
-static unsigned int bcd2uint(unsigned char c)
-{
- return (c >> 4) * 10 + (c & 0x0f);
-}
-
-static unsigned int uint2bcd(unsigned int ival)
-{
- return ((ival / 10) << 4) | (ival % 10);
-}
-
-static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf)
-{
- l += CD_MSF_OFFSET;
- pmsf->minute = uint2bcd(l / 4500), l %= 4500;
- pmsf->second = uint2bcd(l / 75);
- pmsf->frame = uint2bcd(l % 75);
-}
-
-static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
-{
- return bcd2uint(pmsf->frame)
- + bcd2uint(pmsf->second) * 75
- + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET;
-}
-
-int mcdx_readtoc(struct s_drive_stuff *stuffp)
-/* Read the toc entries from the CD,
- * Return: -1 on failure, else 0 */
-{
-
- if (stuffp->toc) {
- xtrace(READTOC, "ioctl() toc already read\n");
- return 0;
- }
-
- xtrace(READTOC, "ioctl() readtoc for %d tracks\n",
- stuffp->di.n_last - stuffp->di.n_first + 1);
-
- if (-1 == mcdx_hold(stuffp, 1))
- return -1;
-
- xtrace(READTOC, "ioctl() tocmode\n");
- if (-1 == mcdx_setdrivemode(stuffp, TOC, 1))
- return -EIO;
-
- /* all seems to be ok so far ... malloc */
- {
- int size;
- size =
- sizeof(struct s_subqcode) * (stuffp->di.n_last -
- stuffp->di.n_first + 2);
-
- xtrace(MALLOC, "ioctl() malloc %d bytes\n", size);
- stuffp->toc = kmalloc(size, GFP_KERNEL);
- if (!stuffp->toc) {
- xwarn("Cannot malloc %d bytes for toc\n", size);
- mcdx_setdrivemode(stuffp, DATA, 1);
- return -EIO;
- }
- }
-
- /* now read actually the index */
- {
- int trk;
- int retries;
-
- for (trk = 0;
- trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
- trk++)
- stuffp->toc[trk].index = 0;
-
- for (retries = 300; retries; retries--) { /* why 300? */
- struct s_subqcode q;
- unsigned int idx;
-
- if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
- mcdx_setdrivemode(stuffp, DATA, 1);
- return -EIO;
- }
-
- idx = bcd2uint(q.index);
-
- if ((idx > 0)
- && (idx <= stuffp->di.n_last)
- && (q.tno == 0)
- && (stuffp->toc[idx - stuffp->di.n_first].
- index == 0)) {
- stuffp->toc[idx - stuffp->di.n_first] = q;
- xtrace(READTOC,
- "ioctl() toc idx %d (trk %d)\n",
- idx, trk);
- trk--;
- }
- if (trk == 0)
- break;
- }
- memset(&stuffp->
- toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0,
- sizeof(stuffp->toc[0]));
- stuffp->toc[stuffp->di.n_last - stuffp->di.n_first +
- 1].dt = stuffp->di.msf_leadout;
- }
-
- /* unset toc mode */
- xtrace(READTOC, "ioctl() undo toc mode\n");
- if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))
- return -EIO;
-
-#if MCDX_DEBUG && READTOC
- {
- int trk;
- for (trk = 0;
- trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
- trk++)
- xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
- " %02x:%02x.%02x %02x:%02x.%02x\n",
- trk + stuffp->di.n_first,
- stuffp->toc[trk].control,
- stuffp->toc[trk].tno,
- stuffp->toc[trk].index,
- stuffp->toc[trk].tt.minute,
- stuffp->toc[trk].tt.second,
- stuffp->toc[trk].tt.frame,
- stuffp->toc[trk].dt.minute,
- stuffp->toc[trk].dt.second,
- stuffp->toc[trk].dt.frame);
- }
-#endif
-
- return 0;
-}
-
-static int
-mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
-{
- unsigned char cmd[7] = {
- 0, 0, 0, 0, 0, 0, 0
- };
-
- if (!stuffp->readcmd) {
- xinfo("Can't play from missing disk.\n");
- return -1;
- }
-
- cmd[0] = stuffp->playcmd;
-
- cmd[1] = msf->cdmsf_min0;
- cmd[2] = msf->cdmsf_sec0;
- cmd[3] = msf->cdmsf_frame0;
- cmd[4] = msf->cdmsf_min1;
- cmd[5] = msf->cdmsf_sec1;
- cmd[6] = msf->cdmsf_frame1;
-
- xtrace(PLAYMSF, "ioctl(): play %x "
- "%02x:%02x:%02x -- %02x:%02x:%02x\n",
- cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
-
- outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
- if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
- xwarn("playmsf() timeout\n");
- return -1;
- }
-
- stuffp->audiostatus = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-static int
-mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
-{
- struct s_subqcode *p;
- struct cdrom_msf msf;
-
- if (-1 == mcdx_readtoc(stuffp))
- return -1;
-
- if (ti)
- p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
- else
- p = &stuffp->start;
-
- msf.cdmsf_min0 = p->dt.minute;
- msf.cdmsf_sec0 = p->dt.second;
- msf.cdmsf_frame0 = p->dt.frame;
-
- if (ti) {
- p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
- stuffp->stop = *p;
- } else
- p = &stuffp->stop;
-
- msf.cdmsf_min1 = p->dt.minute;
- msf.cdmsf_sec1 = p->dt.second;
- msf.cdmsf_frame1 = p->dt.frame;
-
- return mcdx_playmsf(stuffp, &msf);
-}
-
-
-/* Drive functions ************************************************/
-
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
-{
- struct s_drive_stuff *stuffp = cdi->handle;
-
- if (!stuffp->present)
- return -ENXIO;
- if (!(stuffp->present & DOOR))
- return -ENOSYS;
-
- if (position) /* 1: eject */
- return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
- else /* 0: close */
- return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
- return 1;
-}
-
-static int mcdx_stop(struct s_drive_stuff *stuffp, int tries)
-{
- return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_hold(struct s_drive_stuff *stuffp, int tries)
-{
- return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
- struct s_subqcode *sub, int tries)
-{
- char buf[11];
- int ans;
-
- if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf),
- 2 * HZ, tries)))
- return -1;
- sub->control = buf[1];
- sub->tno = buf[2];
- sub->index = buf[3];
- sub->tt.minute = buf[4];
- sub->tt.second = buf[5];
- sub->tt.frame = buf[6];
- sub->dt.minute = buf[8];
- sub->dt.second = buf[9];
- sub->dt.frame = buf[10];
-
- return ans;
-}
-
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp,
- struct s_multi *multi, int tries)
-{
- char buf[5];
- int ans;
-
- if (stuffp->present & MULTI) {
- ans =
- mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ,
- tries);
- multi->multi = buf[1];
- multi->msf_last.minute = buf[2];
- multi->msf_last.second = buf[3];
- multi->msf_last.frame = buf[4];
- return ans;
- } else {
- multi->multi = 0;
- return 0;
- }
-}
-
-static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info,
- int tries)
-{
- char buf[9];
- int ans;
- ans =
- mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries);
- if (ans == -1) {
- info->n_first = 0;
- info->n_last = 0;
- } else {
- info->n_first = bcd2uint(buf[1]);
- info->n_last = bcd2uint(buf[2]);
- info->msf_leadout.minute = buf[3];
- info->msf_leadout.second = buf[4];
- info->msf_leadout.frame = buf[5];
- info->msf_first.minute = buf[6];
- info->msf_first.second = buf[7];
- info->msf_first.frame = buf[8];
- }
- return ans;
-}
-
-static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode,
- int tries)
-{
- char cmd[2];
- int ans;
-
- xtrace(HW, "setdrivemode() %d\n", mode);
-
- if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))
- return -1;
-
- switch (mode) {
- case TOC:
- cmd[1] |= 0x04;
- break;
- case DATA:
- cmd[1] &= ~0x04;
- break;
- case RAW:
- cmd[1] |= 0x40;
- break;
- case COOKED:
- cmd[1] &= ~0x40;
- break;
- default:
- break;
- }
- cmd[0] = 0x50;
- return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode,
- int tries)
-{
- unsigned char cmd[2] = { 0xa0 };
- xtrace(HW, "setdatamode() %d\n", mode);
- switch (mode) {
- case MODE0:
- cmd[1] = 0x00;
- break;
- case MODE1:
- cmd[1] = 0x01;
- break;
- case MODE2:
- cmd[1] = 0x02;
- break;
- default:
- return -EINVAL;
- }
- return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_config(struct s_drive_stuff *stuffp, int tries)
-{
- char cmd[4];
-
- xtrace(HW, "config()\n");
-
- cmd[0] = 0x90;
-
- cmd[1] = 0x10; /* irq enable */
- cmd[2] = 0x05; /* pre, err irq enable */
-
- if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))
- return -1;
-
- cmd[1] = 0x02; /* dma select */
- cmd[2] = 0x00; /* no dma */
-
- return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);
-}
-
-static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver,
- int tries)
-{
- char buf[3];
- int ans;
-
- if (-1 == (ans = mcdx_talk(stuffp, "\xdc",
- 1, buf, sizeof(buf), 2 * HZ, tries)))
- return ans;
-
- ver->code = buf[1];
- ver->ver = buf[2];
-
- return ans;
-}
-
-static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
-{
- if (mode == HARD) {
- outb(0, stuffp->wreg_chn); /* no dma, no irq -> hardware */
- outb(0, stuffp->wreg_reset); /* hw reset */
- return 0;
- } else
- return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
-{
- struct s_drive_stuff *stuffp = cdi->handle;
- char cmd[2] = { 0xfe };
-
- if (!(stuffp->present & DOOR))
- return -ENOSYS;
- if (stuffp->present & DOOR) {
- cmd[1] = lock ? 0x01 : 0x00;
- return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
- } else
- return 0;
-}
-
-static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
-{
- return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int
-mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
-{
- unsigned long timeout = to + jiffies;
- char c;
-
- if (!buf)
- buf = &c;
-
- while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) {
- if (time_after(jiffies, timeout))
- return -1;
- mcdx_delay(stuffp, delay);
- }
-
- *buf = (unsigned char) inb(stuffp->rreg_data) & 0xff;
-
- return 0;
-}
-
-static int mcdx_setattentuator(struct s_drive_stuff *stuffp,
- struct cdrom_volctrl *vol, int tries)
-{
- char cmd[5];
- cmd[0] = 0xae;
- cmd[1] = vol->channel0;
- cmd[2] = 0;
- cmd[3] = vol->channel1;
- cmd[4] = 0;
-
- return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR);
diff --git a/drivers/cdrom/mcdx.h b/drivers/cdrom/mcdx.h
deleted file mode 100644
index 83c364a74dc..00000000000
--- a/drivers/cdrom/mcdx.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Definitions for the Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: @VERSION@
- *
- * 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; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- * The Linux Community at all and ...
- * Martin Harris (he wrote the first Mitsumi Driver)
- * Eberhard Moenkeberg (he gave me much support and the initial kick)
- * Bernd Huebner, Ruediger Helsch (Unifix-Software Gmbh, they
- * improved the original driver)
- * Jon Tombs, Bjorn Ekwall (module support)
- * Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- * Gerd Knorr (he lent me his PhotoCD)
- * Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- * Andreas Kies (testing the mysterious hang up's)
- * ... somebody forgotten?
- * Marcin Dalecki
- *
- */
-
-/*
- * The following lines are for user configuration
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * {0|1} -- 1 if you want the driver detect your drive, may crash and
- * needs a long time to seek. The higher the address the longer the
- * seek.
- *
- * WARNING: AUTOPROBE doesn't work.
- */
-#define MCDX_AUTOPROBE 0
-
-/*
- * Drive specific settings according to the jumpers on the controller
- * board(s).
- * o MCDX_NDRIVES : number of used entries of the following table
- * o MCDX_DRIVEMAP : table of {i/o base, irq} per controller
- *
- * NOTE: I didn't get a drive at irq 9(2) working. Not even alone.
- */
-#if MCDX_AUTOPROBE == 0
- #define MCDX_NDRIVES 1
- #define MCDX_DRIVEMAP { \
- {0x300, 11}, \
- {0x304, 05}, \
- {0x000, 00}, \
- {0x000, 00}, \
- {0x000, 00}, \
- }
-#else
- #error Autoprobing is not implemented yet.
-#endif
-
-#ifndef MCDX_QUIET
-#define MCDX_QUIET 1
-#endif
-
-#ifndef MCDX_DEBUG
-#define MCDX_DEBUG 0
-#endif
-
-/* *** make the following line uncommented, if you're sure,
- * *** all configuration is done */
-/* #define I_WAS_HERE */
-
-/* The name of the device */
-#define MCDX "mcdx"
-
-/* Flags for DEBUGGING */
-#define INIT 0
-#define MALLOC 0
-#define IOCTL 0
-#define PLAYTRK 0
-#define SUBCHNL 0
-#define TOCHDR 0
-#define MS 0
-#define PLAYMSF 0
-#define READTOC 0
-#define OPENCLOSE 0
-#define HW 0
-#define TALK 0
-#define IRQ 0
-#define XFER 0
-#define REQUEST 0
-#define SLEEP 0
-
-/* The following addresses are taken from the Mitsumi Reference
- * and describe the possible i/o range for the controller.
- */
-#define MCDX_IO_BEGIN ((char*) 0x300) /* first base of i/o addr */
-#define MCDX_IO_END ((char*) 0x3fc) /* last base of i/o addr */
-
-/* Per controller 4 bytes i/o are needed. */
-#define MCDX_IO_SIZE 4
-
-/*
- * Bits
- */
-
-/* The status byte, returned from every command, set if
- * the description is true */
-#define MCDX_RBIT_OPEN 0x80 /* door is open */
-#define MCDX_RBIT_DISKSET 0x40 /* disk set (recognised) */
-#define MCDX_RBIT_CHANGED 0x20 /* disk was changed */
-#define MCDX_RBIT_CHECK 0x10 /* disk rotates, servo is on */
-#define MCDX_RBIT_AUDIOTR 0x08 /* current track is audio */
-#define MCDX_RBIT_RDERR 0x04 /* read error, refer SENSE KEY */
-#define MCDX_RBIT_AUDIOBS 0x02 /* currently playing audio */
-#define MCDX_RBIT_CMDERR 0x01 /* command, param or format error */
-
-/* The I/O Register holding the h/w status of the drive,
- * can be read at i/o base + 1 */
-#define MCDX_RBIT_DOOR 0x10 /* door is open */
-#define MCDX_RBIT_STEN 0x04 /* if 0, i/o base contains drive status */
-#define MCDX_RBIT_DTEN 0x02 /* if 0, i/o base contains data */
-
-/*
- * The commands.
- */
-
-#define OPCODE 1 /* offset of opcode */
-#define MCDX_CMD_REQUEST_TOC 1, 0x10
-#define MCDX_CMD_REQUEST_STATUS 1, 0x40
-#define MCDX_CMD_RESET 1, 0x60
-#define MCDX_CMD_REQUEST_DRIVE_MODE 1, 0xc2
-#define MCDX_CMD_SET_INTERLEAVE 2, 0xc8, 0
-#define MCDX_CMD_DATAMODE_SET 2, 0xa0, 0
- #define MCDX_DATAMODE1 0x01
- #define MCDX_DATAMODE2 0x02
-#define MCDX_CMD_LOCK_DOOR 2, 0xfe, 0
-
-#define READ_AHEAD 4 /* 8 Sectors (4K) */
-
-/* Useful macros */
-#define e_door(x) ((x) & MCDX_RBIT_OPEN)
-#define e_check(x) (~(x) & MCDX_RBIT_CHECK)
-#define e_notset(x) (~(x) & MCDX_RBIT_DISKSET)
-#define e_changed(x) ((x) & MCDX_RBIT_CHANGED)
-#define e_audio(x) ((x) & MCDX_RBIT_AUDIOTR)
-#define e_audiobusy(x) ((x) & MCDX_RBIT_AUDIOBS)
-#define e_cmderr(x) ((x) & MCDX_RBIT_CMDERR)
-#define e_readerr(x) ((x) & MCDX_RBIT_RDERR)
-
-/** no drive specific */
-#define MCDX_CDBLK 2048 /* 2048 cooked data each blk */
-
-#define MCDX_DATA_TIMEOUT (HZ/10) /* 0.1 second */
-
-/*
- * Access to the msf array
- */
-#define MSF_MIN 0 /* minute */
-#define MSF_SEC 1 /* second */
-#define MSF_FRM 2 /* frame */
-
-/*
- * Errors
- */
-#define MCDX_E 1 /* unspec error */
-#define MCDX_ST_EOM 0x0100 /* end of media */
-#define MCDX_ST_DRV 0x00ff /* mask to query the drive status */
-
-#ifndef I_WAS_HERE
-#ifndef MODULE
-#warning You have not edited mcdx.h
-#warning Perhaps irq and i/o settings are wrong.
-#endif
-#endif
-
-/* ex:set ts=4 sw=4: */
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
deleted file mode 100644
index 3541690a77d..00000000000
--- a/drivers/cdrom/optcd.c
+++ /dev/null
@@ -1,2105 +0,0 @@
-/* linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver
- $Id: optcd.c,v 1.11 1997/01/26 07:13:00 davem Exp $
-
- Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
- Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
- by Eberhard Moenkeberg (emoenke@gwdg.de).
-
- 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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/* Revision history
-
-
- 14-5-95 v0.0 Plays sound tracks. No reading of data CDs yet.
- Detection of disk change doesn't work.
- 21-5-95 v0.1 First ALPHA version. CD can be mounted. The
- device major nr is borrowed from the Aztech
- driver. Speed is around 240 kb/s, as measured
- with "time dd if=/dev/cdrom of=/dev/null \
- bs=2048 count=4096".
- 24-6-95 v0.2 Reworked the #defines for the command codes
- and the like, as well as the structure of
- the hardware communication protocol, to
- reflect the "official" documentation, kindly
- supplied by C.K. Tan, Optics Storage Pte. Ltd.
- Also tidied up the state machine somewhat.
- 28-6-95 v0.3 Removed the ISP-16 interface code, as this
- should go into its own driver. The driver now
- has its own major nr.
- Disk change detection now seems to work, too.
- This version became part of the standard
- kernel as of version 1.3.7
- 24-9-95 v0.4 Re-inserted ISP-16 interface code which I
- copied from sjcd.c, with a few changes.
- Updated README.optcd. Submitted for
- inclusion in 1.3.21
- 29-9-95 v0.4a Fixed bug that prevented compilation as module
- 25-10-95 v0.5 Started multisession code. Implementation
- copied from Werner Zimmermann, who copied it
- from Heiko Schlittermann's mcdx.
- 17-1-96 v0.6 Multisession works; some cleanup too.
- 18-4-96 v0.7 Increased some timing constants;
- thanks to Luke McFarlane. Also tidied up some
- printk behaviour. ISP16 initialization
- is now handled by a separate driver.
-
- 09-11-99 Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-*/
-
-/* Includes */
-
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <linux/blkdev.h>
-
-#include <linux/cdrom.h>
-#include "optcd.h"
-
-#include <asm/uaccess.h>
-
-#define MAJOR_NR OPTICS_CDROM_MAJOR
-#define QUEUE (opt_queue)
-#define CURRENT elv_next_request(opt_queue)
-
-
-/* Debug support */
-
-
-/* Don't forget to add new debug flags here. */
-#if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \
- DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS
-#define DEBUG(x) debug x
-static void debug(int debug_this, const char* fmt, ...)
-{
- char s[1024];
- va_list args;
-
- if (!debug_this)
- return;
-
- va_start(args, fmt);
- vsnprintf(s, sizeof(s), fmt, args);
- printk(KERN_DEBUG "optcd: %s\n", s);
- va_end(args);
-}
-#else
-#define DEBUG(x)
-#endif
-
-
-/* Drive hardware/firmware characteristics
- Identifiers in accordance with Optics Storage documentation */
-
-
-#define optcd_port optcd /* Needed for the modutils. */
-static short optcd_port = OPTCD_PORTBASE; /* I/O base of drive. */
-module_param(optcd_port, short, 0);
-/* Drive registers, read */
-#define DATA_PORT optcd_port /* Read data/status */
-#define STATUS_PORT optcd_port+1 /* Indicate data/status availability */
-
-/* Drive registers, write */
-#define COMIN_PORT optcd_port /* For passing command/parameter */
-#define RESET_PORT optcd_port+1 /* Write anything and wait 0.5 sec */
-#define HCON_PORT optcd_port+2 /* Host Xfer Configuration */
-
-
-/* Command completion/status read from DATA register */
-#define ST_DRVERR 0x80
-#define ST_DOOR_OPEN 0x40
-#define ST_MIXEDMODE_DISK 0x20
-#define ST_MODE_BITS 0x1c
-#define ST_M_STOP 0x00
-#define ST_M_READ 0x04
-#define ST_M_AUDIO 0x04
-#define ST_M_PAUSE 0x08
-#define ST_M_INITIAL 0x0c
-#define ST_M_ERROR 0x10
-#define ST_M_OTHERS 0x14
-#define ST_MODE2TRACK 0x02
-#define ST_DSK_CHG 0x01
-#define ST_L_LOCK 0x01
-#define ST_CMD_OK 0x00
-#define ST_OP_OK 0x01
-#define ST_PA_OK 0x02
-#define ST_OP_ERROR 0x05
-#define ST_PA_ERROR 0x06
-
-
-/* Error codes (appear as command completion code from DATA register) */
-/* Player related errors */
-#define ERR_ILLCMD 0x11 /* Illegal command to player module */
-#define ERR_ILLPARM 0x12 /* Illegal parameter to player module */
-#define ERR_SLEDGE 0x13
-#define ERR_FOCUS 0x14
-#define ERR_MOTOR 0x15
-#define ERR_RADIAL 0x16
-#define ERR_PLL 0x17 /* PLL lock error */
-#define ERR_SUB_TIM 0x18 /* Subcode timeout error */
-#define ERR_SUB_NF 0x19 /* Subcode not found error */
-#define ERR_TRAY 0x1a
-#define ERR_TOC 0x1b /* Table of Contents read error */
-#define ERR_JUMP 0x1c
-/* Data errors */
-#define ERR_MODE 0x21
-#define ERR_FORM 0x22
-#define ERR_HEADADDR 0x23 /* Header Address not found */
-#define ERR_CRC 0x24
-#define ERR_ECC 0x25 /* Uncorrectable ECC error */
-#define ERR_CRC_UNC 0x26 /* CRC error and uncorrectable error */
-#define ERR_ILLBSYNC 0x27 /* Illegal block sync error */
-#define ERR_VDST 0x28 /* VDST not found */
-/* Timeout errors */
-#define ERR_READ_TIM 0x31 /* Read timeout error */
-#define ERR_DEC_STP 0x32 /* Decoder stopped */
-#define ERR_DEC_TIM 0x33 /* Decoder interrupt timeout error */
-/* Function abort codes */
-#define ERR_KEY 0x41 /* Key -Detected abort */
-#define ERR_READ_FINISH 0x42 /* Read Finish */
-/* Second Byte diagnostic codes */
-#define ERR_NOBSYNC 0x01 /* No block sync */
-#define ERR_SHORTB 0x02 /* Short block */
-#define ERR_LONGB 0x03 /* Long block */
-#define ERR_SHORTDSP 0x04 /* Short DSP word */
-#define ERR_LONGDSP 0x05 /* Long DSP word */
-
-
-/* Status availability flags read from STATUS register */
-#define FL_EJECT 0x20
-#define FL_WAIT 0x10 /* active low */
-#define FL_EOP 0x08 /* active low */
-#define FL_STEN 0x04 /* Status available when low */
-#define FL_DTEN 0x02 /* Data available when low */
-#define FL_DRQ 0x01 /* active low */
-#define FL_RESET 0xde /* These bits are high after a reset */
-#define FL_STDT (FL_STEN|FL_DTEN)
-
-
-/* Transfer mode, written to HCON register */
-#define HCON_DTS 0x08
-#define HCON_SDRQB 0x04
-#define HCON_LOHI 0x02
-#define HCON_DMA16 0x01
-
-
-/* Drive command set, written to COMIN register */
-/* Quick response commands */
-#define COMDRVST 0x20 /* Drive Status Read */
-#define COMERRST 0x21 /* Error Status Read */
-#define COMIOCTLISTAT 0x22 /* Status Read; reset disk changed bit */
-#define COMINITSINGLE 0x28 /* Initialize Single Speed */
-#define COMINITDOUBLE 0x29 /* Initialize Double Speed */
-#define COMUNLOCK 0x30 /* Unlock */
-#define COMLOCK 0x31 /* Lock */
-#define COMLOCKST 0x32 /* Lock/Unlock Status */
-#define COMVERSION 0x40 /* Get Firmware Revision */
-#define COMVOIDREADMODE 0x50 /* Void Data Read Mode */
-/* Read commands */
-#define COMFETCH 0x60 /* Prefetch Data */
-#define COMREAD 0x61 /* Read */
-#define COMREADRAW 0x62 /* Read Raw Data */
-#define COMREADALL 0x63 /* Read All 2646 Bytes */
-/* Player control commands */
-#define COMLEADIN 0x70 /* Seek To Lead-in */
-#define COMSEEK 0x71 /* Seek */
-#define COMPAUSEON 0x80 /* Pause On */
-#define COMPAUSEOFF 0x81 /* Pause Off */
-#define COMSTOP 0x82 /* Stop */
-#define COMOPEN 0x90 /* Open Tray Door */
-#define COMCLOSE 0x91 /* Close Tray Door */
-#define COMPLAY 0xa0 /* Audio Play */
-#define COMPLAY_TNO 0xa2 /* Audio Play By Track Number */
-#define COMSUBQ 0xb0 /* Read Sub-q Code */
-#define COMLOCATION 0xb1 /* Read Head Position */
-/* Audio control commands */
-#define COMCHCTRL 0xc0 /* Audio Channel Control */
-/* Miscellaneous (test) commands */
-#define COMDRVTEST 0xd0 /* Write Test Bytes */
-#define COMTEST 0xd1 /* Diagnostic Test */
-
-/* Low level drive interface. Only here we do actual I/O
- Waiting for status / data available */
-
-
-/* Busy wait until FLAG goes low. Return 0 on timeout. */
-static inline int flag_low(int flag, unsigned long timeout)
-{
- int flag_high;
- unsigned long count = 0;
-
- while ((flag_high = (inb(STATUS_PORT) & flag)))
- if (++count >= timeout)
- break;
-
- DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s",
- flag, count, flag_high ? " timeout" : ""));
- return !flag_high;
-}
-
-
-/* Timed waiting for status or data */
-static int sleep_timeout; /* max # of ticks to sleep */
-static DECLARE_WAIT_QUEUE_HEAD(waitq);
-static void sleep_timer(unsigned long data);
-static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
-static DEFINE_SPINLOCK(optcd_lock);
-static struct request_queue *opt_queue;
-
-/* Timer routine: wake up when desired flag goes low,
- or when timeout expires. */
-static void sleep_timer(unsigned long data)
-{
- int flags = inb(STATUS_PORT) & FL_STDT;
-
- if (flags == FL_STDT && --sleep_timeout > 0) {
- mod_timer(&delay_timer, jiffies + HZ/100); /* multi-statement macro */
- } else
- wake_up(&waitq);
-}
-
-
-/* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */
-static int sleep_flag_low(int flag, unsigned long timeout)
-{
- int flag_high;
-
- DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low"));
-
- sleep_timeout = timeout;
- flag_high = inb(STATUS_PORT) & flag;
- if (flag_high && sleep_timeout > 0) {
- mod_timer(&delay_timer, jiffies + HZ/100);
- sleep_on(&waitq);
- flag_high = inb(STATUS_PORT) & flag;
- }
-
- DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s",
- flag, timeout, flag_high ? " timeout" : ""));
- return !flag_high;
-}
-
-/* Low level drive interface. Only here we do actual I/O
- Sending commands and parameters */
-
-
-/* Errors in the command protocol */
-#define ERR_IF_CMD_TIMEOUT 0x100
-#define ERR_IF_ERR_TIMEOUT 0x101
-#define ERR_IF_RESP_TIMEOUT 0x102
-#define ERR_IF_DATA_TIMEOUT 0x103
-#define ERR_IF_NOSTAT 0x104
-
-
-/* Send command code. Return <0 indicates error */
-static int send_cmd(int cmd)
-{
- unsigned char ack;
-
- DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd));
-
- outb(HCON_DTS, HCON_PORT); /* Enable Suspend Data Transfer */
- outb(cmd, COMIN_PORT); /* Send command code */
- if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */
- return -ERR_IF_CMD_TIMEOUT;
- ack = inb(DATA_PORT); /* read command acknowledge */
- outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */
- return ack==ST_OP_OK ? 0 : -ack;
-}
-
-
-/* Send command parameters. Return <0 indicates error */
-static int send_params(struct cdrom_msf *params)
-{
- unsigned char ack;
-
- DEBUG((DEBUG_DRIVE_IF, "sending parameters"
- " %02x:%02x:%02x"
- " %02x:%02x:%02x",
- params->cdmsf_min0,
- params->cdmsf_sec0,
- params->cdmsf_frame0,
- params->cdmsf_min1,
- params->cdmsf_sec1,
- params->cdmsf_frame1));
-
- outb(params->cdmsf_min0, COMIN_PORT);
- outb(params->cdmsf_sec0, COMIN_PORT);
- outb(params->cdmsf_frame0, COMIN_PORT);
- outb(params->cdmsf_min1, COMIN_PORT);
- outb(params->cdmsf_sec1, COMIN_PORT);
- outb(params->cdmsf_frame1, COMIN_PORT);
- if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */
- return -ERR_IF_CMD_TIMEOUT;
- ack = inb(DATA_PORT); /* read command acknowledge */
- return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Send parameters for SEEK command. Return <0 indicates error */
-static int send_seek_params(struct cdrom_msf *params)
-{
- unsigned char ack;
-
- DEBUG((DEBUG_DRIVE_IF, "sending seek parameters"
- " %02x:%02x:%02x",
- params->cdmsf_min0,
- params->cdmsf_sec0,
- params->cdmsf_frame0));
-
- outb(params->cdmsf_min0, COMIN_PORT);
- outb(params->cdmsf_sec0, COMIN_PORT);
- outb(params->cdmsf_frame0, COMIN_PORT);
- if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */
- return -ERR_IF_CMD_TIMEOUT;
- ack = inb(DATA_PORT); /* read command acknowledge */
- return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Wait for command execution status. Choice between busy waiting
- and sleeping. Return value <0 indicates timeout. */
-static inline int get_exec_status(int busy_waiting)
-{
- unsigned char exec_status;
-
- if (busy_waiting
- ? !flag_low(FL_STEN, BUSY_TIMEOUT)
- : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT))
- return -ERR_IF_CMD_TIMEOUT;
-
- exec_status = inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status));
- return exec_status;
-}
-
-
-/* Wait busy for extra byte of data that a command returns.
- Return value <0 indicates timeout. */
-static inline int get_data(int short_timeout)
-{
- unsigned char data;
-
- if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT))
- return -ERR_IF_DATA_TIMEOUT;
-
- data = inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data));
- return data;
-}
-
-
-/* Returns 0 if failed */
-static int reset_drive(void)
-{
- unsigned long count = 0;
- int flags;
-
- DEBUG((DEBUG_DRIVE_IF, "reset drive"));
-
- outb(0, RESET_PORT);
- while (++count < RESET_WAIT)
- inb(DATA_PORT);
-
- count = 0;
- while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
- if (++count >= BUSY_TIMEOUT)
- break;
-
- DEBUG((DEBUG_DRIVE_IF, "reset %s",
- flags == FL_RESET ? "succeeded" : "failed"));
-
- if (flags != FL_RESET)
- return 0; /* Reset failed */
- outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */
- return 1; /* Reset succeeded */
-}
-
-
-/* Facilities for asynchronous operation */
-
-/* Read status/data availability flags FL_STEN and FL_DTEN */
-static inline int stdt_flags(void)
-{
- return inb(STATUS_PORT) & FL_STDT;
-}
-
-
-/* Fetch status that has previously been waited for. <0 means not available */
-static inline int fetch_status(void)
-{
- unsigned char status;
-
- if (inb(STATUS_PORT) & FL_STEN)
- return -ERR_IF_NOSTAT;
-
- status = inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status));
- return status;
-}
-
-
-/* Fetch data that has previously been waited for. */
-static inline void fetch_data(char *buf, int n)
-{
- insb(DATA_PORT, buf, n);
- DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n));
-}
-
-
-/* Flush status and data fifos */
-static inline void flush_data(void)
-{
- while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT)
- inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "flushed fifos"));
-}
-
-/* Command protocol */
-
-
-/* Send a simple command and wait for response. Command codes < COMFETCH
- are quick response commands */
-static inline int exec_cmd(int cmd)
-{
- int ack = send_cmd(cmd);
- if (ack < 0)
- return ack;
- return get_exec_status(cmd < COMFETCH);
-}
-
-
-/* Send a command with parameters. Don't wait for the response,
- * which consists of data blocks read from the CD. */
-static inline int exec_read_cmd(int cmd, struct cdrom_msf *params)
-{
- int ack = send_cmd(cmd);
- if (ack < 0)
- return ack;
- return send_params(params);
-}
-
-
-/* Send a seek command with parameters and wait for response */
-static inline int exec_seek_cmd(int cmd, struct cdrom_msf *params)
-{
- int ack = send_cmd(cmd);
- if (ack < 0)
- return ack;
- ack = send_seek_params(params);
- if (ack < 0)
- return ack;
- return 0;
-}
-
-
-/* Send a command with parameters and wait for response */
-static inline int exec_long_cmd(int cmd, struct cdrom_msf *params)
-{
- int ack = exec_read_cmd(cmd, params);
- if (ack < 0)
- return ack;
- return get_exec_status(0);
-}
-
-/* Address conversion routines */
-
-
-/* Binary to BCD (2 digits) */
-static inline void single_bin2bcd(u_char *p)
-{
- DEBUG((DEBUG_CONV, "bin2bcd %02d", *p));
- *p = (*p % 10) | ((*p / 10) << 4);
-}
-
-
-/* Convert entire msf struct */
-static void bin2bcd(struct cdrom_msf *msf)
-{
- single_bin2bcd(&msf->cdmsf_min0);
- single_bin2bcd(&msf->cdmsf_sec0);
- single_bin2bcd(&msf->cdmsf_frame0);
- single_bin2bcd(&msf->cdmsf_min1);
- single_bin2bcd(&msf->cdmsf_sec1);
- single_bin2bcd(&msf->cdmsf_frame1);
-}
-
-
-/* Linear block address to minute, second, frame form */
-#define CD_FPM (CD_SECS * CD_FRAMES) /* frames per minute */
-
-static void lba2msf(int lba, struct cdrom_msf *msf)
-{
- DEBUG((DEBUG_CONV, "lba2msf %d", lba));
- lba += CD_MSF_OFFSET;
- msf->cdmsf_min0 = lba / CD_FPM; lba %= CD_FPM;
- msf->cdmsf_sec0 = lba / CD_FRAMES;
- msf->cdmsf_frame0 = lba % CD_FRAMES;
- msf->cdmsf_min1 = 0;
- msf->cdmsf_sec1 = 0;
- msf->cdmsf_frame1 = 0;
- bin2bcd(msf);
-}
-
-
-/* Two BCD digits to binary */
-static inline u_char bcd2bin(u_char bcd)
-{
- DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
- return (bcd >> 4) * 10 + (bcd & 0x0f);
-}
-
-
-static void msf2lba(union cdrom_addr *addr)
-{
- addr->lba = addr->msf.minute * CD_FPM
- + addr->msf.second * CD_FRAMES
- + addr->msf.frame - CD_MSF_OFFSET;
-}
-
-
-/* Minute, second, frame address BCD to binary or to linear address,
- depending on MODE */
-static void msf_bcd2bin(union cdrom_addr *addr)
-{
- addr->msf.minute = bcd2bin(addr->msf.minute);
- addr->msf.second = bcd2bin(addr->msf.second);
- addr->msf.frame = bcd2bin(addr->msf.frame);
-}
-
-/* High level drive commands */
-
-
-static int audio_status = CDROM_AUDIO_NO_STATUS;
-static char toc_uptodate = 0;
-static char disk_changed = 1;
-
-/* Get drive status, flagging completion of audio play and disk changes. */
-static int drive_status(void)
-{
- int status;
-
- status = exec_cmd(COMIOCTLISTAT);
- DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
- if (status < 0)
- return status;
- if (status == 0xff) /* No status available */
- return -ERR_IF_NOSTAT;
-
- if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
- (audio_status == CDROM_AUDIO_PLAY)) {
- audio_status = CDROM_AUDIO_COMPLETED;
- }
-
- if (status & ST_DSK_CHG) {
- toc_uptodate = 0;
- disk_changed = 1;
- audio_status = CDROM_AUDIO_NO_STATUS;
- }
-
- return status;
-}
-
-
-/* Read the current Q-channel info. Also used for reading the
- table of contents. qp->cdsc_format must be set on entry to
- indicate the desired address format */
-static int get_q_channel(struct cdrom_subchnl *qp)
-{
- int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
-
- status = drive_status();
- if (status < 0)
- return status;
- qp->cdsc_audiostatus = audio_status;
-
- status = exec_cmd(COMSUBQ);
- if (status < 0)
- return status;
-
- d1 = get_data(0);
- if (d1 < 0)
- return d1;
- qp->cdsc_adr = d1;
- qp->cdsc_ctrl = d1 >> 4;
-
- d2 = get_data(0);
- if (d2 < 0)
- return d2;
- qp->cdsc_trk = bcd2bin(d2);
-
- d3 = get_data(0);
- if (d3 < 0)
- return d3;
- qp->cdsc_ind = bcd2bin(d3);
-
- d4 = get_data(0);
- if (d4 < 0)
- return d4;
- qp->cdsc_reladdr.msf.minute = d4;
-
- d5 = get_data(0);
- if (d5 < 0)
- return d5;
- qp->cdsc_reladdr.msf.second = d5;
-
- d6 = get_data(0);
- if (d6 < 0)
- return d6;
- qp->cdsc_reladdr.msf.frame = d6;
-
- d7 = get_data(0);
- if (d7 < 0)
- return d7;
- /* byte not used */
-
- d8 = get_data(0);
- if (d8 < 0)
- return d8;
- qp->cdsc_absaddr.msf.minute = d8;
-
- d9 = get_data(0);
- if (d9 < 0)
- return d9;
- qp->cdsc_absaddr.msf.second = d9;
-
- d10 = get_data(0);
- if (d10 < 0)
- return d10;
- qp->cdsc_absaddr.msf.frame = d10;
-
- DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
- d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
-
- msf_bcd2bin(&qp->cdsc_absaddr);
- msf_bcd2bin(&qp->cdsc_reladdr);
- if (qp->cdsc_format == CDROM_LBA) {
- msf2lba(&qp->cdsc_absaddr);
- msf2lba(&qp->cdsc_reladdr);
- }
-
- return 0;
-}
-
-/* Table of contents handling */
-
-
-/* Errors in table of contents */
-#define ERR_TOC_MISSINGINFO 0x120
-#define ERR_TOC_MISSINGENTRY 0x121
-
-
-struct cdrom_disk_info {
- unsigned char first;
- unsigned char last;
- struct cdrom_msf0 disk_length;
- struct cdrom_msf0 first_track;
- /* Multisession info: */
- unsigned char next;
- struct cdrom_msf0 next_session;
- struct cdrom_msf0 last_session;
- unsigned char multi;
- unsigned char xa;
- unsigned char audio;
-};
-static struct cdrom_disk_info disk_info;
-
-#define MAX_TRACKS 111
-static struct cdrom_subchnl toc[MAX_TRACKS];
-
-#define QINFO_FIRSTTRACK 100 /* bcd2bin(0xa0) */
-#define QINFO_LASTTRACK 101 /* bcd2bin(0xa1) */
-#define QINFO_DISKLENGTH 102 /* bcd2bin(0xa2) */
-#define QINFO_NEXTSESSION 110 /* bcd2bin(0xb0) */
-
-#define I_FIRSTTRACK 0x01
-#define I_LASTTRACK 0x02
-#define I_DISKLENGTH 0x04
-#define I_NEXTSESSION 0x08
-#define I_ALL (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
-
-
-#if DEBUG_TOC
-static void toc_debug_info(int i)
-{
- printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d"
- " %2d:%02d.%02d %2d:%02d.%02d\n",
- i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
- toc[i].cdsc_trk, toc[i].cdsc_ind,
- toc[i].cdsc_reladdr.msf.minute,
- toc[i].cdsc_reladdr.msf.second,
- toc[i].cdsc_reladdr.msf.frame,
- toc[i].cdsc_absaddr.msf.minute,
- toc[i].cdsc_absaddr.msf.second,
- toc[i].cdsc_absaddr.msf.frame);
-}
-#endif
-
-
-static int read_toc(void)
-{
- int status, limit, count;
- unsigned char got_info = 0;
- struct cdrom_subchnl q_info;
-#if DEBUG_TOC
- int i;
-#endif
-
- DEBUG((DEBUG_TOC, "starting read_toc"));
-
- count = 0;
- for (limit = 60; limit > 0; limit--) {
- int index;
-
- q_info.cdsc_format = CDROM_MSF;
- status = get_q_channel(&q_info);
- if (status < 0)
- return status;
-
- index = q_info.cdsc_ind;
- if (index > 0 && index < MAX_TRACKS
- && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
- toc[index] = q_info;
- DEBUG((DEBUG_TOC, "got %d", index));
- if (index < 100)
- count++;
-
- switch (q_info.cdsc_ind) {
- case QINFO_FIRSTTRACK:
- got_info |= I_FIRSTTRACK;
- break;
- case QINFO_LASTTRACK:
- got_info |= I_LASTTRACK;
- break;
- case QINFO_DISKLENGTH:
- got_info |= I_DISKLENGTH;
- break;
- case QINFO_NEXTSESSION:
- got_info |= I_NEXTSESSION;
- break;
- }
- }
-
- if ((got_info & I_ALL) == I_ALL
- && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
- >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
- break;
- }
-
- /* Construct disk_info from TOC */
- if (disk_info.first == 0) {
- disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
- disk_info.first_track.minute =
- toc[disk_info.first].cdsc_absaddr.msf.minute;
- disk_info.first_track.second =
- toc[disk_info.first].cdsc_absaddr.msf.second;
- disk_info.first_track.frame =
- toc[disk_info.first].cdsc_absaddr.msf.frame;
- }
- disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
- disk_info.disk_length.minute =
- toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
- disk_info.disk_length.second =
- toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
- disk_info.disk_length.frame =
- toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
- disk_info.next_session.minute =
- toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
- disk_info.next_session.second =
- toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
- disk_info.next_session.frame =
- toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
- disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
- disk_info.last_session.minute =
- toc[disk_info.next].cdsc_absaddr.msf.minute;
- disk_info.last_session.second =
- toc[disk_info.next].cdsc_absaddr.msf.second;
- disk_info.last_session.frame =
- toc[disk_info.next].cdsc_absaddr.msf.frame;
- toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
- disk_info.disk_length.minute;
- toc[disk_info.last + 1].cdsc_absaddr.msf.second =
- disk_info.disk_length.second;
- toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
- disk_info.disk_length.frame;
-#if DEBUG_TOC
- for (i = 1; i <= disk_info.last + 1; i++)
- toc_debug_info(i);
- toc_debug_info(QINFO_FIRSTTRACK);
- toc_debug_info(QINFO_LASTTRACK);
- toc_debug_info(QINFO_DISKLENGTH);
- toc_debug_info(QINFO_NEXTSESSION);
-#endif
-
- DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
- got_info, count));
- if ((got_info & I_ALL) != I_ALL
- || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
- < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
- return -ERR_TOC_MISSINGINFO;
- return 0;
-}
-
-
-#ifdef MULTISESSION
-static int get_multi_disk_info(void)
-{
- int sessions, status;
- struct cdrom_msf multi_index;
-
-
- for (sessions = 2; sessions < 10 /* %%for now */; sessions++) {
- int count;
-
- for (count = 100; count < MAX_TRACKS; count++)
- toc[count].cdsc_ind = 0;
-
- multi_index.cdmsf_min0 = disk_info.next_session.minute;
- multi_index.cdmsf_sec0 = disk_info.next_session.second;
- multi_index.cdmsf_frame0 = disk_info.next_session.frame;
- if (multi_index.cdmsf_sec0 >= 20)
- multi_index.cdmsf_sec0 -= 20;
- else {
- multi_index.cdmsf_sec0 += 40;
- multi_index.cdmsf_min0--;
- }
- DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
- multi_index.cdmsf_min0,
- multi_index.cdmsf_sec0,
- multi_index.cdmsf_frame0));
- bin2bcd(&multi_index);
- multi_index.cdmsf_min1 = 0;
- multi_index.cdmsf_sec1 = 0;
- multi_index.cdmsf_frame1 = 1;
-
- status = exec_read_cmd(COMREAD, &multi_index);
- if (status < 0) {
- DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
- -status));
- break;
- }
- status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
- 0 : -ERR_TOC_MISSINGINFO;
- flush_data();
- if (status < 0) {
- DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
- break;
- }
-
- status = read_toc();
- if (status < 0) {
- DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
- break;
- }
-
- disk_info.multi = 1;
- }
-
- exec_cmd(COMSTOP);
-
- if (status < 0)
- return -EIO;
- return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int update_toc(void)
-{
- int status, count;
-
- if (toc_uptodate)
- return 0;
-
- DEBUG((DEBUG_TOC, "starting update_toc"));
-
- disk_info.first = 0;
- for (count = 0; count < MAX_TRACKS; count++)
- toc[count].cdsc_ind = 0;
-
- status = exec_cmd(COMLEADIN);
- if (status < 0)
- return -EIO;
-
- status = read_toc();
- if (status < 0) {
- DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
- return -EIO;
- }
-
- /* Audio disk detection. Look at first track. */
- disk_info.audio =
- (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
-
- /* XA detection */
- disk_info.xa = drive_status() & ST_MODE2TRACK;
-
- /* Multisession detection: if we want this, define MULTISESSION */
- disk_info.multi = 0;
-#ifdef MULTISESSION
- if (disk_info.xa)
- get_multi_disk_info(); /* Here disk_info.multi is set */
-#endif /* MULTISESSION */
- if (disk_info.multi)
- printk(KERN_WARNING "optcd: Multisession support experimental, "
- "see Documentation/cdrom/optcd\n");
-
- DEBUG((DEBUG_TOC, "exiting update_toc"));
-
- toc_uptodate = 1;
- return 0;
-}
-
-/* Request handling */
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-/* Buffers for block size conversion. */
-#define NOBUF -1
-
-static char buf[CD_FRAMESIZE * N_BUFS];
-static volatile int buf_bn[N_BUFS], next_bn;
-static volatile int buf_in = 0, buf_out = NOBUF;
-
-static inline void opt_invalidate_buffers(void)
-{
- int i;
-
- DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
-
- for (i = 0; i < N_BUFS; i++)
- buf_bn[i] = NOBUF;
- buf_out = NOBUF;
-}
-
-
-/* Take care of the different block sizes between cdrom and Linux.
- When Linux gets variable block sizes this will probably go away. */
-static void transfer(void)
-{
-#if DEBUG_BUFFERS | DEBUG_REQUEST
- printk(KERN_DEBUG "optcd: executing transfer\n");
-#endif
-
- if (!current_valid())
- return;
- while (CURRENT -> nr_sectors) {
- int bn = CURRENT -> sector / 4;
- int i, offs, nr_sectors;
- for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
-
- DEBUG((DEBUG_REQUEST, "found %d", i));
-
- if (i >= N_BUFS) {
- buf_out = NOBUF;
- break;
- }
-
- offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
- nr_sectors = 4 - (CURRENT -> sector & 3);
-
- if (buf_out != i) {
- buf_out = i;
- if (buf_bn[i] != bn) {
- buf_out = NOBUF;
- continue;
- }
- }
-
- if (nr_sectors > CURRENT -> nr_sectors)
- nr_sectors = CURRENT -> nr_sectors;
- memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
- CURRENT -> nr_sectors -= nr_sectors;
- CURRENT -> sector += nr_sectors;
- CURRENT -> buffer += nr_sectors * 512;
- }
-}
-
-
-/* State machine for reading disk blocks */
-
-enum state_e {
- S_IDLE, /* 0 */
- S_START, /* 1 */
- S_READ, /* 2 */
- S_DATA, /* 3 */
- S_STOP, /* 4 */
- S_STOPPING /* 5 */
-};
-
-static volatile enum state_e state = S_IDLE;
-#if DEBUG_STATE
-static volatile enum state_e state_old = S_STOP;
-static volatile int flags_old = 0;
-static volatile long state_n = 0;
-#endif
-
-
-/* Used as mutex to keep do_optcd_request (and other processes calling
- ioctl) out while some process is inside a VFS call.
- Reverse is accomplished by checking if state = S_IDLE upon entry
- of opt_ioctl and opt_media_change. */
-static int in_vfs = 0;
-
-
-static volatile int transfer_is_active = 0;
-static volatile int error = 0; /* %% do something with this?? */
-static int tries; /* ibid?? */
-static int timeout = 0;
-
-static void poll(unsigned long data);
-static struct timer_list req_timer = {.function = poll};
-
-
-static void poll(unsigned long data)
-{
- static volatile int read_count = 1;
- int flags;
- int loop_again = 1;
- int status = 0;
- int skip = 0;
-
- if (error) {
- printk(KERN_ERR "optcd: I/O error 0x%02x\n", error);
- opt_invalidate_buffers();
- if (!tries--) {
- printk(KERN_ERR "optcd: read block %d failed;"
- " Giving up\n", next_bn);
- if (transfer_is_active)
- loop_again = 0;
- if (current_valid())
- end_request(CURRENT, 0);
- tries = 5;
- }
- error = 0;
- state = S_STOP;
- }
-
- while (loop_again)
- {
- loop_again = 0; /* each case must flip this back to 1 if we want
- to come back up here */
-
-#if DEBUG_STATE
- if (state == state_old)
- state_n++;
- else {
- state_old = state;
- if (++state_n > 1)
- printk(KERN_DEBUG "optcd: %ld times "
- "in previous state\n", state_n);
- printk(KERN_DEBUG "optcd: state %d\n", state);
- state_n = 0;
- }
-#endif
-
- switch (state) {
- case S_IDLE:
- return;
- case S_START:
- if (in_vfs)
- break;
- if (send_cmd(COMDRVST)) {
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- state = S_READ;
- timeout = READ_TIMEOUT;
- break;
- case S_READ: {
- struct cdrom_msf msf;
- if (!skip) {
- status = fetch_status();
- if (status < 0)
- break;
- if (status & ST_DSK_CHG) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- }
- }
- skip = 0;
- if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- printk(KERN_WARNING "optcd: %s\n",
- (status & ST_DOOR_OPEN)
- ? "door open"
- : "disk removed");
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- if (!current_valid()) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- next_bn = CURRENT -> sector / 4;
- lba2msf(next_bn, &msf);
- read_count = N_BUFS;
- msf.cdmsf_frame1 = read_count; /* Not BCD! */
-
- DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x",
- msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0,
- msf.cdmsf_min1,
- msf.cdmsf_sec1,
- msf.cdmsf_frame1));
- DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d"
- " buf_out:%d buf_bn:%d",
- next_bn,
- buf_in,
- buf_out,
- buf_bn[buf_in]));
-
- exec_read_cmd(COMREAD, &msf);
- state = S_DATA;
- timeout = READ_TIMEOUT;
- break;
- }
- case S_DATA:
- flags = stdt_flags() & (FL_STEN|FL_DTEN);
-
-#if DEBUG_STATE
- if (flags != flags_old) {
- flags_old = flags;
- printk(KERN_DEBUG "optcd: flags:%x\n", flags);
- }
- if (flags == FL_STEN)
- printk(KERN_DEBUG "timeout cnt: %d\n", timeout);
-#endif
-
- switch (flags) {
- case FL_DTEN: /* only STEN low */
- if (!tries--) {
- printk(KERN_ERR
- "optcd: read block %d failed; "
- "Giving up\n", next_bn);
- if (transfer_is_active) {
- tries = 0;
- break;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- tries = 5;
- }
- state = S_START;
- timeout = READ_TIMEOUT;
- loop_again = 1;
- case (FL_STEN|FL_DTEN): /* both high */
- break;
- default: /* DTEN low */
- tries = 5;
- if (!current_valid() && buf_in == buf_out) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- if (read_count<=0)
- printk(KERN_WARNING
- "optcd: warning - try to read"
- " 0 frames\n");
- while (read_count) {
- buf_bn[buf_in] = NOBUF;
- if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) {
- /* should be no waiting here!?? */
- printk(KERN_ERR
- "read_count:%d "
- "CURRENT->nr_sectors:%ld "
- "buf_in:%d\n",
- read_count,
- CURRENT->nr_sectors,
- buf_in);
- printk(KERN_ERR
- "transfer active: %x\n",
- transfer_is_active);
- read_count = 0;
- state = S_STOP;
- loop_again = 1;
- end_request(CURRENT, 0);
- break;
- }
- fetch_data(buf+
- CD_FRAMESIZE*buf_in,
- CD_FRAMESIZE);
- read_count--;
-
- DEBUG((DEBUG_REQUEST,
- "S_DATA; ---I've read data- "
- "read_count: %d",
- read_count));
- DEBUG((DEBUG_REQUEST,
- "next_bn:%d buf_in:%d "
- "buf_out:%d buf_bn:%d",
- next_bn,
- buf_in,
- buf_out,
- buf_bn[buf_in]));
-
- buf_bn[buf_in] = next_bn++;
- if (buf_out == NOBUF)
- buf_out = buf_in;
- buf_in = buf_in + 1 ==
- N_BUFS ? 0 : buf_in + 1;
- }
- if (!transfer_is_active) {
- while (current_valid()) {
- transfer();
- if (CURRENT -> nr_sectors == 0)
- end_request(CURRENT, 1);
- else
- break;
- }
- }
-
- if (current_valid()
- && (CURRENT -> sector / 4 < next_bn ||
- CURRENT -> sector / 4 >
- next_bn + N_BUFS)) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- timeout = READ_TIMEOUT;
- if (read_count == 0) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- }
- break;
- case S_STOP:
- if (read_count != 0)
- printk(KERN_ERR
- "optcd: discard data=%x frames\n",
- read_count);
- flush_data();
- if (send_cmd(COMDRVST)) {
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- state = S_STOPPING;
- timeout = STOP_TIMEOUT;
- break;
- case S_STOPPING:
- status = fetch_status();
- if (status < 0 && timeout)
- break;
- if ((status >= 0) && (status & ST_DSK_CHG)) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- }
- if (current_valid()) {
- if (status >= 0) {
- state = S_READ;
- loop_again = 1;
- skip = 1;
- break;
- } else {
- state = S_START;
- timeout = 1;
- }
- } else {
- state = S_IDLE;
- return;
- }
- break;
- default:
- printk(KERN_ERR "optcd: invalid state %d\n", state);
- return;
- } /* case */
- } /* while */
-
- if (!timeout--) {
- printk(KERN_ERR "optcd: timeout in state %d\n", state);
- state = S_STOP;
- if (exec_cmd(COMSTOP) < 0) {
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- }
-
- mod_timer(&req_timer, jiffies + HZ/100);
-}
-
-
-static void do_optcd_request(request_queue_t * q)
-{
- DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
- CURRENT -> sector, CURRENT -> nr_sectors));
-
- if (disk_info.audio) {
- printk(KERN_WARNING "optcd: tried to mount an Audio CD\n");
- end_request(CURRENT, 0);
- return;
- }
-
- transfer_is_active = 1;
- while (current_valid()) {
- transfer(); /* First try to transfer block from buffers */
- if (CURRENT -> nr_sectors == 0) {
- end_request(CURRENT, 1);
- } else { /* Want to read a block not in buffer */
- buf_out = NOBUF;
- if (state == S_IDLE) {
- /* %% Should this block the request queue?? */
- if (update_toc() < 0) {
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- /* Start state machine */
- state = S_START;
- timeout = READ_TIMEOUT;
- tries = 5;
- /* %% why not start right away?? */
- mod_timer(&req_timer, jiffies + HZ/100);
- }
- break;
- }
- }
- transfer_is_active = 0;
-
- DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d buf_out:%d buf_bn:%d",
- next_bn, buf_in, buf_out, buf_bn[buf_in]));
- DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
-}
-
-/* IOCTLs */
-
-
-static char auto_eject = 0;
-
-static int cdrompause(void)
-{
- int status;
-
- if (audio_status != CDROM_AUDIO_PLAY)
- return -EINVAL;
-
- status = exec_cmd(COMPAUSEON);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
- return -EIO;
- }
- audio_status = CDROM_AUDIO_PAUSED;
- return 0;
-}
-
-
-static int cdromresume(void)
-{
- int status;
-
- if (audio_status != CDROM_AUDIO_PAUSED)
- return -EINVAL;
-
- status = exec_cmd(COMPAUSEOFF);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
- audio_status = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- audio_status = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-
-static int cdromplaymsf(void __user *arg)
-{
- int status;
- struct cdrom_msf msf;
-
- if (copy_from_user(&msf, arg, sizeof msf))
- return -EFAULT;
-
- bin2bcd(&msf);
- status = exec_long_cmd(COMPLAY, &msf);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
- audio_status = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audio_status = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-
-static int cdromplaytrkind(void __user *arg)
-{
- int status;
- struct cdrom_ti ti;
- struct cdrom_msf msf;
-
- if (copy_from_user(&ti, arg, sizeof ti))
- return -EFAULT;
-
- if (ti.cdti_trk0 < disk_info.first
- || ti.cdti_trk0 > disk_info.last
- || ti.cdti_trk1 < ti.cdti_trk0)
- return -EINVAL;
- if (ti.cdti_trk1 > disk_info.last)
- ti.cdti_trk1 = disk_info.last;
-
- msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
- msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
- msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
- msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
- msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
- msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
-
- DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
- msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0,
- msf.cdmsf_min1,
- msf.cdmsf_sec1,
- msf.cdmsf_frame1));
-
- bin2bcd(&msf);
- status = exec_long_cmd(COMPLAY, &msf);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
- audio_status = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audio_status = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-
-static int cdromreadtochdr(void __user *arg)
-{
- struct cdrom_tochdr tochdr;
-
- tochdr.cdth_trk0 = disk_info.first;
- tochdr.cdth_trk1 = disk_info.last;
-
- return copy_to_user(arg, &tochdr, sizeof tochdr) ? -EFAULT : 0;
-}
-
-
-static int cdromreadtocentry(void __user *arg)
-{
- struct cdrom_tocentry entry;
- struct cdrom_subchnl *tocptr;
-
- if (copy_from_user(&entry, arg, sizeof entry))
- return -EFAULT;
-
- if (entry.cdte_track == CDROM_LEADOUT)
- tocptr = &toc[disk_info.last + 1];
- else if (entry.cdte_track > disk_info.last
- || entry.cdte_track < disk_info.first)
- return -EINVAL;
- else
- tocptr = &toc[entry.cdte_track];
-
- entry.cdte_adr = tocptr->cdsc_adr;
- entry.cdte_ctrl = tocptr->cdsc_ctrl;
- entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
- entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
- entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
- /* %% What should go into entry.cdte_datamode? */
-
- if (entry.cdte_format == CDROM_LBA)
- msf2lba(&entry.cdte_addr);
- else if (entry.cdte_format != CDROM_MSF)
- return -EINVAL;
-
- return copy_to_user(arg, &entry, sizeof entry) ? -EFAULT : 0;
-}
-
-
-static int cdromvolctrl(void __user *arg)
-{
- int status;
- struct cdrom_volctrl volctrl;
- struct cdrom_msf msf;
-
- if (copy_from_user(&volctrl, arg, sizeof volctrl))
- return -EFAULT;
-
- msf.cdmsf_min0 = 0x10;
- msf.cdmsf_sec0 = 0x32;
- msf.cdmsf_frame0 = volctrl.channel0;
- msf.cdmsf_min1 = volctrl.channel1;
- msf.cdmsf_sec1 = volctrl.channel2;
- msf.cdmsf_frame1 = volctrl.channel3;
-
- status = exec_long_cmd(COMCHCTRL, &msf);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
- return -EIO;
- }
- return 0;
-}
-
-
-static int cdromsubchnl(void __user *arg)
-{
- int status;
- struct cdrom_subchnl subchnl;
-
- if (copy_from_user(&subchnl, arg, sizeof subchnl))
- return -EFAULT;
-
- if (subchnl.cdsc_format != CDROM_LBA
- && subchnl.cdsc_format != CDROM_MSF)
- return -EINVAL;
-
- status = get_q_channel(&subchnl);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
- return -EIO;
- }
-
- if (copy_to_user(arg, &subchnl, sizeof subchnl))
- return -EFAULT;
- return 0;
-}
-
-
-static struct gendisk *optcd_disk;
-
-
-static int cdromread(void __user *arg, int blocksize, int cmd)
-{
- int status;
- struct cdrom_msf msf;
-
- if (copy_from_user(&msf, arg, sizeof msf))
- return -EFAULT;
-
- bin2bcd(&msf);
- msf.cdmsf_min1 = 0;
- msf.cdmsf_sec1 = 0;
- msf.cdmsf_frame1 = 1; /* read only one frame */
- status = exec_read_cmd(cmd, &msf);
-
- DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
-
- if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
- return -EIO;
-
- fetch_data(optcd_disk->private_data, blocksize);
-
- if (copy_to_user(arg, optcd_disk->private_data, blocksize))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int cdromseek(void __user *arg)
-{
- int status;
- struct cdrom_msf msf;
-
- if (copy_from_user(&msf, arg, sizeof msf))
- return -EFAULT;
-
- bin2bcd(&msf);
- status = exec_seek_cmd(COMSEEK, &msf);
-
- DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
-
- if (status < 0)
- return -EIO;
- return 0;
-}
-
-
-#ifdef MULTISESSION
-static int cdrommultisession(void __user *arg)
-{
- struct cdrom_multisession ms;
-
- if (copy_from_user(&ms, arg, sizeof ms))
- return -EFAULT;
-
- ms.addr.msf.minute = disk_info.last_session.minute;
- ms.addr.msf.second = disk_info.last_session.second;
- ms.addr.msf.frame = disk_info.last_session.frame;
-
- if (ms.addr_format != CDROM_LBA
- && ms.addr_format != CDROM_MSF)
- return -EINVAL;
- if (ms.addr_format == CDROM_LBA)
- msf2lba(&ms.addr);
-
- ms.xa_flag = disk_info.xa;
-
- if (copy_to_user(arg, &ms, sizeof(struct cdrom_multisession)))
- return -EFAULT;
-
-#if DEBUG_MULTIS
- if (ms.addr_format == CDROM_MSF)
- printk(KERN_DEBUG
- "optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
- ms.xa_flag,
- ms.addr.msf.minute,
- ms.addr.msf.second,
- ms.addr.msf.frame);
- else
- printk(KERN_DEBUG
- "optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
- ms.xa_flag,
- ms.addr.lba,
- disk_info.last_session.minute,
- disk_info.last_session.second,
- disk_info.last_session.frame);
-#endif /* DEBUG_MULTIS */
-
- return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int cdromreset(void)
-{
- if (state != S_IDLE) {
- error = 1;
- tries = 0;
- }
-
- toc_uptodate = 0;
- disk_changed = 1;
- opt_invalidate_buffers();
- audio_status = CDROM_AUDIO_NO_STATUS;
-
- if (!reset_drive())
- return -EIO;
- return 0;
-}
-
-/* VFS calls */
-
-
-static int opt_ioctl(struct inode *ip, struct file *fp,
- unsigned int cmd, unsigned long arg)
-{
- int status, err, retval = 0;
- void __user *argp = (void __user *)arg;
-
- DEBUG((DEBUG_VFS, "starting opt_ioctl"));
-
- if (!ip)
- return -EINVAL;
-
- if (cmd == CDROMRESET)
- return cdromreset();
-
- /* is do_optcd_request or another ioctl busy? */
- if (state != S_IDLE || in_vfs)
- return -EBUSY;
-
- in_vfs = 1;
-
- status = drive_status();
- if (status < 0) {
- DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
- in_vfs = 0;
- return -EIO;
- }
-
- if (status & ST_DOOR_OPEN)
- switch (cmd) { /* Actions that can be taken with door open */
- case CDROMCLOSETRAY:
- /* We do this before trying to read the toc. */
- err = exec_cmd(COMCLOSE);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMCLOSE: %02x", -err));
- in_vfs = 0;
- return -EIO;
- }
- break;
- default: in_vfs = 0;
- return -EBUSY;
- }
-
- err = update_toc();
- if (err < 0) {
- DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
- in_vfs = 0;
- return -EIO;
- }
-
- DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
-
- switch (cmd) {
- case CDROMPAUSE: retval = cdrompause(); break;
- case CDROMRESUME: retval = cdromresume(); break;
- case CDROMPLAYMSF: retval = cdromplaymsf(argp); break;
- case CDROMPLAYTRKIND: retval = cdromplaytrkind(argp); break;
- case CDROMREADTOCHDR: retval = cdromreadtochdr(argp); break;
- case CDROMREADTOCENTRY: retval = cdromreadtocentry(argp); break;
-
- case CDROMSTOP: err = exec_cmd(COMSTOP);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMSTOP: %02x",
- -err));
- retval = -EIO;
- } else
- audio_status = CDROM_AUDIO_NO_STATUS;
- break;
- case CDROMSTART: break; /* This is a no-op */
- case CDROMEJECT: err = exec_cmd(COMUNLOCK);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMUNLOCK: %02x",
- -err));
- retval = -EIO;
- break;
- }
- err = exec_cmd(COMOPEN);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMOPEN: %02x",
- -err));
- retval = -EIO;
- }
- break;
-
- case CDROMVOLCTRL: retval = cdromvolctrl(argp); break;
- case CDROMSUBCHNL: retval = cdromsubchnl(argp); break;
-
- /* The drive detects the mode and automatically delivers the
- correct 2048 bytes, so we don't need these IOCTLs */
- case CDROMREADMODE2: retval = -EINVAL; break;
- case CDROMREADMODE1: retval = -EINVAL; break;
-
- /* Drive doesn't support reading audio */
- case CDROMREADAUDIO: retval = -EINVAL; break;
-
- case CDROMEJECT_SW: auto_eject = (char) arg;
- break;
-
-#ifdef MULTISESSION
- case CDROMMULTISESSION: retval = cdrommultisession(argp); break;
-#endif
-
- case CDROM_GET_MCN: retval = -EINVAL; break; /* not implemented */
- case CDROMVOLREAD: retval = -EINVAL; break; /* not implemented */
-
- case CDROMREADRAW:
- /* this drive delivers 2340 bytes in raw mode */
- retval = cdromread(argp, CD_FRAMESIZE_RAW1, COMREADRAW);
- break;
- case CDROMREADCOOKED:
- retval = cdromread(argp, CD_FRAMESIZE, COMREAD);
- break;
- case CDROMREADALL:
- retval = cdromread(argp, CD_FRAMESIZE_RAWER, COMREADALL);
- break;
-
- case CDROMSEEK: retval = cdromseek(argp); break;
- case CDROMPLAYBLK: retval = -EINVAL; break; /* not implemented */
- case CDROMCLOSETRAY: break; /* The action was taken earlier */
- default: retval = -EINVAL;
- }
- in_vfs = 0;
- return retval;
-}
-
-
-static int open_count = 0;
-
-/* Open device special file; check that a disk is in. */
-static int opt_open(struct inode *ip, struct file *fp)
-{
- DEBUG((DEBUG_VFS, "starting opt_open"));
-
- if (!open_count && state == S_IDLE) {
- int status;
- char *buf;
-
- buf = kmalloc(CD_FRAMESIZE_RAWER, GFP_KERNEL);
- if (!buf) {
- printk(KERN_INFO "optcd: cannot allocate read buffer\n");
- return -ENOMEM;
- }
- optcd_disk->private_data = buf; /* save read buffer */
-
- toc_uptodate = 0;
- opt_invalidate_buffers();
-
- status = exec_cmd(COMCLOSE); /* close door */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMCLOSE: %02x", -status));
- }
-
- status = drive_status();
- if (status < 0) {
- DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
- goto err_out;
- }
- DEBUG((DEBUG_VFS, "status: %02x", status));
- if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
- printk(KERN_INFO "optcd: no disk or door open\n");
- goto err_out;
- }
- status = exec_cmd(COMLOCK); /* Lock door */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
- }
- status = update_toc(); /* Read table of contents */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
- status = exec_cmd(COMUNLOCK); /* Unlock door */
- if (status < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMUNLOCK: %02x", -status));
- }
- goto err_out;
- }
- open_count++;
- }
-
- DEBUG((DEBUG_VFS, "exiting opt_open"));
-
- return 0;
-
-err_out:
- return -EIO;
-}
-
-
-/* Release device special file; flush all blocks from the buffer cache */
-static int opt_release(struct inode *ip, struct file *fp)
-{
- int status;
-
- DEBUG((DEBUG_VFS, "executing opt_release"));
- DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
- ip, ip->i_bdev->bd_disk->disk_name, fp));
-
- if (!--open_count) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- status = exec_cmd(COMUNLOCK); /* Unlock door */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
- }
- if (auto_eject) {
- status = exec_cmd(COMOPEN);
- DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
- }
- kfree(optcd_disk->private_data);
- del_timer(&delay_timer);
- del_timer(&req_timer);
- }
- return 0;
-}
-
-
-/* Check if disk has been changed */
-static int opt_media_change(struct gendisk *disk)
-{
- DEBUG((DEBUG_VFS, "executing opt_media_change"));
- DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n",
- disk->disk_name, disk_changed));
-
- if (disk_changed) {
- disk_changed = 0;
- return 1;
- }
- return 0;
-}
-
-/* Driver initialisation */
-
-
-/* Returns 1 if a drive is detected with a version string
- starting with "DOLPHIN". Otherwise 0. */
-static int __init version_ok(void)
-{
- char devname[100];
- int count, i, ch, status;
-
- status = exec_cmd(COMVERSION);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
- return 0;
- }
- if ((count = get_data(1)) < 0) {
- DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
- return 0;
- }
- for (i = 0, ch = -1; count > 0; count--) {
- if ((ch = get_data(1)) < 0) {
- DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
- break;
- }
- if (i < 99)
- devname[i++] = ch;
- }
- devname[i] = '\0';
- if (ch < 0)
- return 0;
-
- printk(KERN_INFO "optcd: Device %s detected\n", devname);
- return ((devname[0] == 'D')
- && (devname[1] == 'O')
- && (devname[2] == 'L')
- && (devname[3] == 'P')
- && (devname[4] == 'H')
- && (devname[5] == 'I')
- && (devname[6] == 'N'));
-}
-
-
-static struct block_device_operations opt_fops = {
- .owner = THIS_MODULE,
- .open = opt_open,
- .release = opt_release,
- .ioctl = opt_ioctl,
- .media_changed = opt_media_change,
-};
-
-#ifndef MODULE
-/* Get kernel parameter when used as a kernel driver */
-static int optcd_setup(char *str)
-{
- int ints[4];
- (void)get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0)
- optcd_port = ints[1];
-
- return 1;
-}
-
-__setup("optcd=", optcd_setup);
-
-#endif /* MODULE */
-
-/* Test for presence of drive and initialize it. Called at boot time
- or during module initialisation. */
-static int __init optcd_init(void)
-{
- int status;
-
- if (optcd_port <= 0) {
- printk(KERN_INFO
- "optcd: no Optics Storage CDROM Initialization\n");
- return -EIO;
- }
- optcd_disk = alloc_disk(1);
- if (!optcd_disk) {
- printk(KERN_ERR "optcd: can't allocate disk\n");
- return -ENOMEM;
- }
- optcd_disk->major = MAJOR_NR;
- optcd_disk->first_minor = 0;
- optcd_disk->fops = &opt_fops;
- sprintf(optcd_disk->disk_name, "optcd");
-
- if (!request_region(optcd_port, 4, "optcd")) {
- printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n",
- optcd_port);
- put_disk(optcd_disk);
- return -EIO;
- }
-
- if (!reset_drive()) {
- printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port);
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -EIO;
- }
- if (!version_ok()) {
- printk(KERN_ERR "optcd: unknown drive detected; aborting\n");
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -EIO;
- }
- status = exec_cmd(COMINITDOUBLE);
- if (status < 0) {
- printk(KERN_ERR "optcd: cannot init double speed mode\n");
- release_region(optcd_port, 4);
- DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
- put_disk(optcd_disk);
- return -EIO;
- }
- if (register_blkdev(MAJOR_NR, "optcd")) {
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -EIO;
- }
-
-
- opt_queue = blk_init_queue(do_optcd_request, &optcd_lock);
- if (!opt_queue) {
- unregister_blkdev(MAJOR_NR, "optcd");
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -ENOMEM;
- }
-
- blk_queue_hardsect_size(opt_queue, 2048);
- optcd_disk->queue = opt_queue;
- add_disk(optcd_disk);
-
- printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
- return 0;
-}
-
-
-static void __exit optcd_exit(void)
-{
- del_gendisk(optcd_disk);
- put_disk(optcd_disk);
- if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
- printk(KERN_ERR "optcd: what's that: can't unregister\n");
- return;
- }
- blk_cleanup_queue(opt_queue);
- release_region(optcd_port, 4);
- printk(KERN_INFO "optcd: module released.\n");
-}
-
-module_init(optcd_init);
-module_exit(optcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(OPTICS_CDROM_MAJOR);
diff --git a/drivers/cdrom/optcd.h b/drivers/cdrom/optcd.h
deleted file mode 100644
index 1911bb92ee2..00000000000
--- a/drivers/cdrom/optcd.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* linux/include/linux/optcd.h - Optics Storage 8000 AT CDROM driver
- $Id: optcd.h,v 1.2 1996/01/15 18:43:44 root Exp root $
-
- Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
- Configuration file for linux/drivers/cdrom/optcd.c
-*/
-
-#ifndef _LINUX_OPTCD_H
-#define _LINUX_OPTCD_H
-
-
-/* I/O base of drive. Drive uses base to base+2.
- This setting can be overridden with the kernel or insmod command
- line option 'optcd=<portbase>'. Use address of 0 to disable driver. */
-#define OPTCD_PORTBASE 0x340
-
-
-/* enable / disable parts of driver by define / undef */
-#define MULTISESSION /* multisession support (ALPHA) */
-
-
-/* Change 0 to 1 to debug various parts of the driver */
-#define DEBUG_DRIVE_IF 0 /* Low level drive interface */
-#define DEBUG_CONV 0 /* Address conversions */
-#define DEBUG_BUFFERS 0 /* Buffering and block size conversion */
-#define DEBUG_REQUEST 0 /* Request mechanism */
-#define DEBUG_STATE 0 /* State machine */
-#define DEBUG_TOC 0 /* Q-channel and Table of Contents */
-#define DEBUG_MULTIS 0 /* Multisession code */
-#define DEBUG_VFS 0 /* VFS interface */
-
-
-/* Don't touch these unless you know what you're doing. */
-
-/* Various timeout loop repetition counts. */
-#define BUSY_TIMEOUT 10000000 /* for busy wait */
-#define FAST_TIMEOUT 100000 /* ibid. for probing */
-#define SLEEP_TIMEOUT 6000 /* for timer wait */
-#define MULTI_SEEK_TIMEOUT 1000 /* for timer wait */
-#define READ_TIMEOUT 6000 /* for poll wait */
-#define STOP_TIMEOUT 2000 /* for poll wait */
-#define RESET_WAIT 5000 /* busy wait at drive reset */
-
-/* # of buffers for block size conversion. 6 is optimal for my setup (P75),
- giving 280 kb/s, with 0.4% CPU usage. Experiment to find your optimal
- setting */
-#define N_BUFS 6
-
-
-#endif /* _LINUX_OPTCD_H */
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
deleted file mode 100644
index a1283b1ef98..00000000000
--- a/drivers/cdrom/sbpcd.c
+++ /dev/null
@@ -1,5966 +0,0 @@
-/*
- * sbpcd.c CD-ROM device driver for the whole family of traditional,
- * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives.
- * Works with SoundBlaster compatible cards and with "no-sound"
- * interface cards like Lasermate, Panasonic CI-101P, Teac, ...
- * Also for the Longshine LCS-7260 drive.
- * Also for the IBM "External ISA CD-Rom" drive.
- * Also for the CreativeLabs CD200 drive.
- * Also for the TEAC CD-55A drive.
- * Also for the ECS-AT "Vertos 100" drive.
- * Not for Sanyo drives (but for the H94A, sjcd is there...).
- * Not for any other Funai drives than the CD200 types (sometimes
- * labelled E2550UA or MK4015 or 2800F).
- */
-
-#define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000"
-
-/* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * If you change this software, you should mail a .diff file with some
- * description lines to emoenke@gwdg.de. I want to know about it.
- *
- * If you are the editor of a Linux CD, you should enable sbpcd.c within
- * your boot floppy kernel and send me one of your CDs for free.
- *
- * If you would like to port the driver to an other operating system (f.e.
- * FreeBSD or NetBSD) or use it as an information source, you shall not be
- * restricted by the GPL under the following conditions:
- * a) the source code of your work is freely available
- * b) my part of the work gets mentioned at all places where your
- * authorship gets mentioned
- * c) I receive a copy of your code together with a full installation
- * package of your operating system for free.
- *
- *
- * VERSION HISTORY
- *
- * 0.1 initial release, April/May 93, after mcd.c (Martin Harriss)
- *
- * 0.2 thek "repeat:"-loop in do_sbpcd_request did not check for
- * end-of-request_queue (resulting in kernel panic).
- * Flow control seems stable, but throughput is not better.
- *
- * 0.3 interrupt locking totally eliminated (maybe "inb" and "outb"
- * are still locking) - 0.2 made keyboard-type-ahead losses.
- * check_sbpcd_media_change added (to use by isofs/inode.c)
- * - but it detects almost nothing.
- *
- * 0.4 use MAJOR 25 definitely.
- * Almost total re-design to support double-speed drives and
- * "naked" (no sound) interface cards ("LaserMate" interface type).
- * Flow control should be exact now.
- * Don't occupy the SbPro IRQ line (not needed either); will
- * live together with Hannu Savolainen's sndkit now.
- * Speeded up data transfer to 150 kB/sec, with help from Kai
- * Makisara, the "provider" of the "mt" tape utility.
- * Give "SpinUp" command if necessary.
- * First steps to support up to 4 drives (but currently only one).
- * Implemented audio capabilities - workman should work, xcdplayer
- * gives some problems.
- * This version is still consuming too much CPU time, and
- * sleeping still has to be worked on.
- * During "long" implied seeks, it seems possible that a
- * ReadStatus command gets ignored. That gives the message
- * "ResponseStatus timed out" (happens about 6 times here during
- * a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is
- * handled without data error, but it should get done better.
- *
- * 0.5 Free CPU during waits (again with help from Kai Makisara).
- * Made it work together with the LILO/kernel setup standard.
- * Included auto-probing code, as suggested by YGGDRASIL.
- * Formal redesign to add DDI debugging.
- * There are still flaws in IOCTL (workman with double speed drive).
- *
- * 1.0 Added support for all drive IDs (0...3, no longer only 0)
- * and up to 4 drives on one controller.
- * Added "#define MANY_SESSION" for "old" multi session CDs.
- *
- * 1.1 Do SpinUp for new drives, too.
- * Revised for clean compile under "old" kernels (0.99pl9).
- *
- * 1.2 Found the "workman with double-speed drive" bug: use the driver's
- * audio_state, not what the drive is reporting with ReadSubQ.
- *
- * 1.3 Minor cleanups.
- * Refinements regarding Workman.
- *
- * 1.4 Read XA disks (PhotoCDs) with "old" drives, too (but only the first
- * session - no chance to fully access a "multi-session" CD).
- * This currently still is too slow (50 kB/sec) - but possibly
- * the old drives won't do it faster.
- * Implemented "door (un)lock" for new drives (still does not work
- * as wanted - no lock possible after an unlock).
- * Added some debugging printout for the UPC/EAN code - but my drives
- * return only zeroes. Is there no UPC/EAN code written?
- *
- * 1.5 Laborate with UPC/EAN code (not better yet).
- * Adapt to kernel 1.1.8 change (have to explicitly include
- * <linux/string.h> now).
- *
- * 1.6 Trying to read audio frames as data. Impossible with the current
- * drive firmware levels, as it seems. Awaiting any hint. ;-)
- * Changed "door unlock": repeat it until success.
- * Changed CDROMSTOP routine (stop somewhat "softer" so that Workman
- * won't get confused).
- * Added a third interface type: Sequoia S-1000, as used with the SPEA
- * Media FX sound card. This interface (usable for Sony and Mitsumi
- * drives, too) needs a special configuration setup and behaves like a
- * LaserMate type after that. Still experimental - I do not have such
- * an interface.
- * Use the "variable BLOCK_SIZE" feature (2048). But it does only work
- * if you give the mount option "block=2048".
- * The media_check routine is currently disabled; now that it gets
- * called as it should I fear it must get synchronized for not to
- * disturb the normal driver's activity.
- *
- * 2.0 Version number bumped - two reasons:
- * - reading audio tracks as data works now with CR-562 and CR-563. We
- * currently do it by an IOCTL (yet has to get standardized), one frame
- * at a time; that is pretty slow. But it works.
- * - we are maintaining now up to 4 interfaces (each up to 4 drives):
- * did it the easy way - a different MAJOR (25, 26, ...) and a different
- * copy of the driver (sbpcd.c, sbpcd2.c, sbpcd3.c, sbpcd4.c - only
- * distinguished by the value of SBPCD_ISSUE and the driver's name),
- * and a common sbpcd.h file.
- * Bettered the "ReadCapacity error" problem with old CR-52x drives (the
- * drives sometimes need a manual "eject/insert" before work): just
- * reset the drive and do again. Needs lots of resets here and sometimes
- * that does not cure, so this can't be the solution.
- *
- * 2.1 Found bug with multisession CDs (accessing frame 16).
- * "read audio" works now with address type CDROM_MSF, too.
- * Bigger audio frame buffer: allows reading max. 4 frames at time; this
- * gives a significant speedup, but reading more than one frame at once
- * gives missing chunks at each single frame boundary.
- *
- * 2.2 Kernel interface cleanups: timers, init, setup, media check.
- *
- * 2.3 Let "door lock" and "eject" live together.
- * Implemented "close tray" (done automatically during open).
- *
- * 2.4 Use different names for device registering.
- *
- * 2.5 Added "#if EJECT" code (default: enabled) to automatically eject
- * the tray during last call to "sbpcd_release".
- * Added "#if JUKEBOX" code (default: disabled) to automatically eject
- * the tray during call to "sbpcd_open" if no disk is in.
- * Turn on the CD volume of "compatible" sound cards, too; just define
- * SOUND_BASE (in sbpcd.h) accordingly (default: disabled).
- *
- * 2.6 Nothing new.
- *
- * 2.7 Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly:
- * 0 disables, 1 enables auto-ejecting. Useful to keep the tray in
- * during shutdown.
- *
- * 2.8 Added first support (still BETA, I need feedback or a drive) for
- * the Longshine LCS-7260 drives. They appear as double-speed drives
- * using the "old" command scheme, extended by tray control and door
- * lock functions.
- * Found (and fixed preliminary) a flaw with some multisession CDs: we
- * have to re-direct not only the accesses to frame 16 (the isofs
- * routines drive it up to max. 100), but also those to the continuation
- * (repetition) frames (as far as they exist - currently set fix as
- * 16..20).
- * Changed default of the "JUKEBOX" define. If you use this default,
- * your tray will eject if you try to mount without a disk in. Next
- * mount command will insert the tray - so, just fill in a disk. ;-)
- *
- * 2.9 Fulfilled the Longshine LCS-7260 support; with great help and
- * experiments by Serge Robyns.
- * First attempts to support the TEAC CD-55A drives; but still not
- * usable yet.
- * Implemented the CDROMMULTISESSION ioctl; this is an attempt to handle
- * multi session CDs more "transparent" (redirection handling has to be
- * done within the isofs routines, and only for the special purpose of
- * obtaining the "right" volume descriptor; accesses to the raw device
- * should not get redirected).
- *
- * 3.0 Just a "normal" increment, with some provisions to do it better. ;-)
- * Introduced "#define READ_AUDIO" to specify the maximum number of
- * audio frames to grab with one request. This defines a buffer size
- * within kernel space; a value of 0 will reserve no such space and
- * disable the CDROMREADAUDIO ioctl. A value of 75 enables the reading
- * of a whole second with one command, but will use a buffer of more
- * than 172 kB.
- * Started CD200 support. Drive detection should work, but nothing
- * more.
- *
- * 3.1 Working to support the CD200 and the Teac CD-55A drives.
- * AT-BUS style device numbering no longer used: use SCSI style now.
- * So, the first "found" device has MINOR 0, regardless of the
- * jumpered drive ID. This implies modifications to the /dev/sbpcd*
- * entries for some people, but will help the DAU (german TLA, english:
- * "newbie", maybe ;-) to install his "first" system from a CD.
- *
- * 3.2 Still testing with CD200 and CD-55A drives.
- *
- * 3.3 Working with CD200 support.
- *
- * 3.4 Auto-probing stops if an address of 0 is seen (to be entered with
- * the kernel command line).
- * Made the driver "loadable". If used as a module, "audio copy" is
- * disabled, and the internal read ahead data buffer has a reduced size
- * of 4 kB; so, throughput may be reduced a little bit with slow CPUs.
- *
- * 3.5 Provisions to handle weird photoCDs which have an interrupted
- * "formatting" immediately after the last frames of some files: simply
- * never "read ahead" with MultiSession CDs. By this, CPU usage may be
- * increased with those CDs, and there may be a loss in speed.
- * Re-structured the messaging system.
- * The "loadable" version no longer has a limited READ_AUDIO buffer
- * size.
- * Removed "MANY_SESSION" handling for "old" multi session CDs.
- * Added "private" IOCTLs CDROMRESET and CDROMVOLREAD.
- * Started again to support the TEAC CD-55A drives, now that I found
- * the money for "my own" drive. ;-)
- * The TEAC CD-55A support is fairly working now.
- * I have measured that the drive "delivers" at 600 kB/sec (even with
- * bigger requests than the drive's 64 kB buffer can satisfy), but
- * the "real" rate does not exceed 520 kB/sec at the moment.
- * Caused by the various changes to build in TEAC support, the timed
- * loops are de-optimized at the moment (less throughput with CR-52x
- * drives, and the TEAC will give speed only with SBP_BUFFER_FRAMES 64).
- *
- * 3.6 Fixed TEAC data read problems with SbPro interfaces.
- * Initial size of the READ_AUDIO buffer is 0. Can get set to any size
- * during runtime.
- *
- * 3.7 Introduced MAX_DRIVES for some poor interface cards (seen with TEAC
- * drives) which allow only one drive (ID 0); this avoids repetitive
- * detection under IDs 1..3.
- * Elongated cmd_out_T response waiting; necessary for photo CDs with
- * a lot of sessions.
- * Bettered the sbpcd_open() behavior with TEAC drives.
- *
- * 3.8 Elongated max_latency for CR-56x drives.
- *
- * 3.9 Finally fixed the long-known SoundScape/SPEA/Sequoia S-1000 interface
- * configuration bug.
- * Now Corey, Heiko, Ken, Leo, Vadim/Eric & Werner are invited to copy
- * the config_spea() routine into their drivers. ;-)
- *
- * 4.0 No "big step" - normal version increment.
- * Adapted the benefits from 1.3.33.
- * Fiddled with CDROMREADAUDIO flaws.
- * Avoid ReadCapacity command with CD200 drives (the MKE 1.01 version
- * seems not to support it).
- * Fulfilled "read audio" for CD200 drives, with help of Pete Heist
- * (heistp@rpi.edu).
- *
- * 4.1 Use loglevel KERN_INFO with printk().
- * Added support for "Vertos 100" drive ("ECS-AT") - it is very similar
- * to the Longshine LCS-7260. Give feedback if you can - I never saw
- * such a drive, and I have no specs.
- *
- * 4.2 Support for Teac 16-bit interface cards. Can't get auto-detected,
- * so you have to jumper your card to 0x2C0. Still not 100% - come
- * in contact if you can give qualified feedback.
- * Use loglevel KERN_NOTICE with printk(). If you get annoyed by a
- * flood of unwanted messages and the accompanied delay, try to read
- * my documentation. Especially the Linux CDROM drivers have to do an
- * important job for the newcomers, so the "distributed" version has
- * to fit some special needs. Since generations, the flood of messages
- * is user-configurable (even at runtime), but to get aware of this, one
- * needs a special mental quality: the ability to read.
- *
- * 4.3 CD200F does not like to receive a command while the drive is
- * reading the ToC; still trying to solve it.
- * Removed some redundant verify_area calls (yes, Heiko Eissfeldt
- * is visiting all the Linux CDROM drivers ;-).
- *
- * 4.4 Adapted one idea from tiensivu@pilot.msu.edu's "stripping-down"
- * experiments: "KLOGD_PAUSE".
- * Inhibited "play audio" attempts with data CDs. Provisions for a
- * "data-safe" handling of "mixed" (data plus audio) Cds.
- *
- * 4.5 Meanwhile Gonzalo Tornaria <tornaria@cmat.edu.uy> (GTL) built a
- * special end_request routine: we seem to have to take care for not
- * to have two processes working at the request list. My understanding
- * was and is that ll_rw_blk should not call do_sbpcd_request as long
- * as there is still one call active (the first call will care for all
- * outstanding I/Os, and if a second call happens, that is a bug in
- * ll_rw_blk.c).
- * "Check media change" without touching any drive.
- *
- * 4.6 Use a semaphore to synchronize multi-activity; elaborated by Rob
- * Riggs <rriggs@tesser.com>. At the moment, we simply block "read"
- * against "ioctl" and vice versa. This could be refined further, but
- * I guess with almost no performance increase.
- * Experiments to speed up the CD-55A; again with help of Rob Riggs
- * (to be true, he gave both, idea & code. ;-)
- *
- * 4.61 Ported to Uniform CD-ROM driver by
- * Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- * changes by Erik Andersen <andersee@debian.org>
- *
- * 4.62 Fix a bug where playing audio left the drive in an unusable state.
- * Heiko Eissfeldt <heiko@colossus.escape.de>
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * 4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer.
- * Annoying things fixed:
- * TOC reread on automated disk changes
- * TOC reread on manual cd changes
- * Play IOCTL tries to play CD before it's actually ready... sometimes.
- * CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play.
- * Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000
- *
- * 4.64 Fix module parameters - were being completely ignored.
- * Can also specify max_drives=N as a setup int to get rid of
- * "ghost" drives on crap hardware (aren't they all?) Paul Gortmaker
- *
- * TODO
- * implement "read all subchannel data" (96 bytes per frame)
- * remove alot of the virtual status bits and deal with hardware status
- * move the change of cd for audio to a better place
- * add debug levels to insmod parameters (trivial)
- *
- * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
- * elaborated speed-up experiments (and the fabulous results!), for
- * the "push" towards load-free wait loops, and for the extensive mail
- * thread which brought additional hints and bug fixes.
- *
- */
-
-/*
- * Trying to merge requests breaks this driver horribly (as in it goes
- * boom and apparently has done so since 2.3.41). As it is a legacy
- * driver for a horribly slow double speed CD on a hideous interface
- * designed for polled operation, I won't lose any sleep in simply
- * disallowing merging. Paul G. 02/2001
- *
- * Thu May 30 14:14:47 CEST 2002:
- *
- * I have presumably found the reson for the above - there was a bogous
- * end_request substitute, which was manipulating the request queues
- * incorrectly. If someone has access to the actual hardware, and it's
- * still operations - well please free to test it.
- *
- * Marcin Dalecki
- */
-
-/*
- * Add bio/kdev_t changes for 2.5.x required to make it work again.
- * Still room for improvement in the request handling here if anyone
- * actually cares. Bring your own chainsaw. Paul G. 02/2002
- */
-
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <stdarg.h>
-#include "sbpcd.h"
-
-#define MAJOR_NR MATSUSHITA_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-/*==========================================================================*/
-#if SBPCD_DIS_IRQ
-# define SBPCD_CLI cli()
-# define SBPCD_STI sti()
-#else
-# define SBPCD_CLI
-# define SBPCD_STI
-#endif
-
-/*==========================================================================*/
-/*
- * auto-probing address list
- * inspired by Adam J. Richter from Yggdrasil
- *
- * still not good enough - can cause a hang.
- * example: a NE 2000 ethernet card at 300 will cause a hang probing 310.
- * if that happens, reboot and use the LILO (kernel) command line.
- * The possibly conflicting ethernet card addresses get NOT probed
- * by default - to minimize the hang possibilities.
- *
- * The SB Pro addresses get "mirrored" at 0x6xx and some more locations - to
- * avoid a type error, the 0x2xx-addresses must get checked before 0x6xx.
- *
- * send mail to emoenke@gwdg.de if your interface card is not FULLY
- * represented here.
- */
-static int sbpcd[] =
-{
- CDROM_PORT, SBPRO, /* probe with user's setup first */
-#if DISTRIBUTION
- 0x230, 1, /* Soundblaster Pro and 16 (default) */
-#if 0
- 0x300, 0, /* CI-101P (default), WDH-7001C (default),
- Galaxy (default), Reveal (one default) */
- 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */
- 0x2C0, 3, /* Teac 16-bit cards */
- 0x260, 1, /* OmniCD */
- 0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default),
- Longshine LCS-6853 (default) */
- 0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */
- 0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */
- 0x360, 0, /* Lasermate, CI-101P */
- 0x270, 1, /* Soundblaster 16 */
- 0x670, 0, /* "sound card #9" */
- 0x690, 0, /* "sound card #9" */
- 0x338, 2, /* SPEA Media FX, Ensonic SoundScape (default) */
- 0x328, 2, /* SPEA Media FX */
- 0x348, 2, /* SPEA Media FX */
- 0x634, 0, /* some newer sound cards */
- 0x638, 0, /* some newer sound cards */
- 0x230, 1, /* some newer sound cards */
- /* due to incomplete address decoding of the SbPro card, these must be last */
- 0x630, 0, /* "sound card #9" (default) */
- 0x650, 0, /* "sound card #9" */
-#ifdef MODULE
- /*
- * some "hazardous" locations (no harm with the loadable version)
- * (will stop the bus if a NE2000 ethernet card resides at offset -0x10)
- */
- 0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
- 0x350, 0, /* Lasermate, CI-101P */
- 0x358, 2, /* SPEA Media FX */
- 0x370, 0, /* Lasermate, CI-101P */
- 0x290, 1, /* Soundblaster 16 */
- 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
-#endif /* MODULE */
-#endif
-#endif /* DISTRIBUTION */
-};
-
-/*
- * Protects access to global structures etc.
- */
-static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock);
-static struct request_queue *sbpcd_queue;
-
-/* You can only set the first pair, from old MODULE_PARM code. */
-static int sbpcd_set(const char *val, struct kernel_param *kp)
-{
- get_options((char *)val, 2, (int *)sbpcd);
- return 0;
-}
-module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0);
-
-#define NUM_PROBE (sizeof(sbpcd) / sizeof(int))
-
-/*==========================================================================*/
-
-#define INLINE inline
-
-/*==========================================================================*/
-/*
- * the forward references:
- */
-static void sbp_sleep(u_int);
-static void mark_timeout_delay(u_long);
-static void mark_timeout_data(u_long);
-#if 0
-static void mark_timeout_audio(u_long);
-#endif
-static void sbp_read_cmd(struct request *req);
-static int sbp_data(struct request *req);
-static int cmd_out(void);
-static int DiskInfo(void);
-
-/*==========================================================================*/
-
-/*
- * pattern for printk selection:
- *
- * (1<<DBG_INF) necessary information
- * (1<<DBG_BSZ) BLOCK_SIZE trace
- * (1<<DBG_REA) "read" status trace
- * (1<<DBG_CHK) "media check" trace
- * (1<<DBG_TIM) datarate timer test
- * (1<<DBG_INI) initialization trace
- * (1<<DBG_TOC) tell TocEntry values
- * (1<<DBG_IOC) ioctl trace
- * (1<<DBG_STA) "ResponseStatus" trace
- * (1<<DBG_ERR) "cc_ReadError" trace
- * (1<<DBG_CMD) "cmd_out" trace
- * (1<<DBG_WRN) give explanation before auto-probing
- * (1<<DBG_MUL) multi session code test
- * (1<<DBG_IDX) "drive_id != 0" test code
- * (1<<DBG_IOX) some special information
- * (1<<DBG_DID) drive ID test
- * (1<<DBG_RES) drive reset info
- * (1<<DBG_SPI) SpinUp test info
- * (1<<DBG_IOS) ioctl trace: "subchannel"
- * (1<<DBG_IO2) ioctl trace: general
- * (1<<DBG_UPC) show UPC info
- * (1<<DBG_XA1) XA mode debugging
- * (1<<DBG_LCK) door (un)lock info
- * (1<<DBG_SQ1) dump SubQ frame
- * (1<<DBG_AUD) "read audio" debugging
- * (1<<DBG_SEQ) Sequoia interface configuration trace
- * (1<<DBG_LCS) Longshine LCS-7260 debugging trace
- * (1<<DBG_CD2) MKE/Funai CD200 debugging trace
- * (1<<DBG_TEA) TEAC CD-55A debugging trace
- * (1<<DBG_ECS) ECS-AT (Vertos-100) debugging trace
- * (1<<DBG_000) unnecessary information
- */
-#if DISTRIBUTION
-static int sbpcd_debug = (1<<DBG_INF);
-#else
-static int sbpcd_debug = 0 & ((1<<DBG_INF) |
- (1<<DBG_TOC) |
- (1<<DBG_MUL) |
- (1<<DBG_UPC));
-#endif /* DISTRIBUTION */
-
-static int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */
-static int sbpro_type = SBPRO;
-static unsigned char f_16bit;
-static unsigned char do_16bit;
-static int CDo_command, CDo_reset;
-static int CDo_sel_i_d, CDo_enable;
-static int CDi_info, CDi_status, CDi_data;
-static struct cdrom_msf msf;
-static struct cdrom_ti ti;
-static struct cdrom_tochdr tochdr;
-static struct cdrom_tocentry tocentry;
-static struct cdrom_subchnl SC;
-static struct cdrom_volctrl volctrl;
-static struct cdrom_read_audio read_audio;
-
-static unsigned char msgnum;
-static char msgbuf[80];
-
-static int max_drives = MAX_DRIVES;
-module_param(max_drives, int, 0);
-#ifndef MODULE
-static unsigned char setup_done;
-static const char *str_sb_l = "soundblaster";
-static const char *str_sp_l = "spea";
-static const char *str_ss_l = "soundscape";
-static const char *str_t16_l = "teac16bit";
-static const char *str_ss = "SoundScape";
-#endif
-static const char *str_sb = "SoundBlaster";
-static const char *str_lm = "LaserMate";
-static const char *str_sp = "SPEA";
-static const char *str_t16 = "Teac16bit";
-static const char *type;
-static const char *major_name="sbpcd";
-
-/*==========================================================================*/
-
-#ifdef FUTURE
-static DECLARE_WAIT_QUEUE_HEAD(sbp_waitq);
-#endif /* FUTURE */
-
-static int teac=SBP_TEAC_SPEED;
-static int buffers=SBP_BUFFER_FRAMES;
-
-static u_char family0[]="MATSHITA"; /* MKE CR-521, CR-522, CR-523 */
-static u_char family1[]="CR-56"; /* MKE CR-562, CR-563 */
-static u_char family2[]="CD200"; /* MKE CD200, Funai CD200F */
-static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */
-static u_char familyT[]="CD-55"; /* TEAC CD-55A */
-static u_char familyV[]="ECS-AT"; /* ECS Vertos 100 */
-
-static u_int recursion; /* internal testing only */
-static u_int fatal_err; /* internal testing only */
-static u_int response_count;
-static u_int flags_cmd_out;
-static u_char cmd_type;
-static u_char drvcmd[10];
-static u_char infobuf[20];
-static u_char xa_head_buf[CD_XA_HEAD];
-static u_char xa_tail_buf[CD_XA_TAIL];
-
-#if OLD_BUSY
-static volatile u_char busy_data;
-static volatile u_char busy_audio; /* true semaphores would be safer */
-#endif /* OLD_BUSY */
-static DECLARE_MUTEX(ioctl_read_sem);
-static u_long timeout;
-static volatile u_char timed_out_delay;
-static volatile u_char timed_out_data;
-#if 0
-static volatile u_char timed_out_audio;
-#endif
-static u_int datarate= 1000000;
-static u_int maxtim16=16000000;
-static u_int maxtim04= 4000000;
-static u_int maxtim02= 2000000;
-static u_int maxtim_8= 30000;
-#if LONG_TIMING
-static u_int maxtim_data= 9000;
-#else
-static u_int maxtim_data= 3000;
-#endif /* LONG_TIMING */
-#if DISTRIBUTION
-static int n_retries=6;
-#else
-static int n_retries=6;
-#endif
-/*==========================================================================*/
-
-static int ndrives;
-static u_char drv_pattern[NR_SBPCD]={speed_auto,speed_auto,speed_auto,speed_auto};
-
-/*==========================================================================*/
-/*
- * drive space begins here (needed separate for each unit)
- */
-static struct sbpcd_drive {
- char drv_id; /* "jumpered" drive ID or -1 */
- char drv_sel; /* drive select lines bits */
-
- char drive_model[9];
- u_char firmware_version[4];
- char f_eject; /* auto-eject flag: 0 or 1 */
- u_char *sbp_buf; /* Pointer to internal data buffer,
- space allocated during sbpcd_init() */
- u_int sbp_bufsiz; /* size of sbp_buf (# of frames) */
- int sbp_first_frame; /* First frame in buffer */
- int sbp_last_frame; /* Last frame in buffer */
- int sbp_read_frames; /* Number of frames being read to buffer */
- int sbp_current; /* Frame being currently read */
-
- u_char mode; /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */
- u_char *aud_buf; /* Pointer to audio data buffer,
- space allocated during sbpcd_init() */
- u_int sbp_audsiz; /* size of aud_buf (# of raw frames) */
- u_int drv_type;
- u_char drv_options;
- int status_bits;
- u_char diskstate_flags;
- u_char sense_byte;
-
- u_char CD_changed;
- char open_count;
- u_char error_byte;
-
- u_char f_multisession;
- u_int lba_multi;
- int first_session;
- int last_session;
- int track_of_last_session;
-
- u_char audio_state;
- u_int pos_audio_start;
- u_int pos_audio_end;
- char vol_chan0;
- u_char vol_ctrl0;
- char vol_chan1;
- u_char vol_ctrl1;
-#if 000 /* no supported drive has it */
- char vol_chan2;
- u_char vol_ctrl2;
- char vol_chan3;
- u_char vol_ctrl3;
-#endif /*000 */
- u_char volume_control; /* TEAC on/off bits */
-
- u_char SubQ_ctl_adr;
- u_char SubQ_trk;
- u_char SubQ_pnt_idx;
- u_int SubQ_run_tot;
- u_int SubQ_run_trk;
- u_char SubQ_whatisthis;
-
- u_char UPC_ctl_adr;
- u_char UPC_buf[7];
-
- int frame_size;
- int CDsize_frm;
-
- u_char xa_byte; /* 0x20: XA capabilities */
- u_char n_first_track; /* binary */
- u_char n_last_track; /* binary (not bcd), 0x01...0x63 */
- u_int size_msf; /* time of whole CD, position of LeadOut track */
- u_int size_blk;
-
- u_char TocEnt_nixbyte; /* em */
- u_char TocEnt_ctl_adr;
- u_char TocEnt_number;
- u_char TocEnt_format; /* em */
- u_int TocEnt_address;
-#ifdef SAFE_MIXED
- char has_data;
-#endif /* SAFE_MIXED */
- u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */
-
- struct {
- u_char nixbyte; /* em */
- u_char ctl_adr; /* 0x4x: data, 0x0x: audio */
- u_char number;
- u_char format; /* em */ /* 0x00: lba, 0x01: msf */
- u_int address;
- } TocBuffer[MAX_TRACKS+1]; /* last entry faked */
-
- int in_SpinUp; /* CR-52x test flag */
- int n_bytes; /* TEAC awaited response count */
- u_char error_state, b3, b4; /* TEAC command error state */
- u_char f_drv_error; /* TEAC command error flag */
- u_char speed_byte;
- int frmsiz;
- u_char f_XA; /* 1: XA */
- u_char type_byte; /* 0, 1, 3 */
- u_char mode_xb_6;
- u_char mode_yb_7;
- u_char mode_xb_8;
- u_char delay;
- struct cdrom_device_info *sbpcd_infop;
- struct gendisk *disk;
-} D_S[NR_SBPCD];
-
-static struct sbpcd_drive *current_drive = D_S;
-
-/*
- * drive space ends here (needed separate for each unit)
- */
-/*==========================================================================*/
-#if 0
-unsigned long cli_sti; /* for saving the processor flags */
-#endif
-/*==========================================================================*/
-static DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0);
-static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0);
-#if 0
-static DEFINE_TIMER(audio_timer, mark_timeout_audio, 0, 0);
-#endif
-/*==========================================================================*/
-/*
- * DDI interface
- */
-static void msg(int level, const char *fmt, ...)
-{
-#if DISTRIBUTION
-#define MSG_LEVEL KERN_NOTICE
-#else
-#define MSG_LEVEL KERN_INFO
-#endif /* DISTRIBUTION */
-
- char buf[256];
- va_list args;
-
- if (!(sbpcd_debug&(1<<level))) return;
-
- msgnum++;
- if (msgnum>99) msgnum=0;
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- printk(MSG_LEVEL "%s-%d [%02d]: %s", major_name, current_drive - D_S, msgnum, buf);
-#if KLOGD_PAUSE
- sbp_sleep(KLOGD_PAUSE); /* else messages get lost */
-#endif /* KLOGD_PAUSE */
- return;
-}
-/*==========================================================================*/
-/*
- * DDI interface: runtime trace bit pattern maintenance
- */
-static int sbpcd_dbg_ioctl(unsigned long arg, int level)
-{
- switch(arg)
- {
- case 0: /* OFF */
- sbpcd_debug = DBG_INF;
- break;
-
- default:
- if (arg>=128) sbpcd_debug &= ~(1<<(arg-128));
- else sbpcd_debug |= (1<<arg);
- }
- return (arg);
-}
-/*==========================================================================*/
-static void mark_timeout_delay(u_long i)
-{
- timed_out_delay=1;
-#if 0
- msg(DBG_TIM,"delay timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-static void mark_timeout_data(u_long i)
-{
- timed_out_data=1;
-#if 0
- msg(DBG_TIM,"data timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-#if 0
-static void mark_timeout_audio(u_long i)
-{
- timed_out_audio=1;
-#if 0
- msg(DBG_TIM,"audio timer expired.\n");
-#endif
-}
-#endif
-/*==========================================================================*/
-/*
- * Wait a little while (used for polling the drive).
- */
-static void sbp_sleep(u_int time)
-{
- sti();
- schedule_timeout_interruptible(time);
- sti();
-}
-/*==========================================================================*/
-#define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);}
-/*==========================================================================*/
-/*
- * convert logical_block_address to m-s-f_number (3 bytes only)
- */
-static INLINE void lba2msf(int lba, u_char *msf)
-{
- lba += CD_MSF_OFFSET;
- msf[0] = lba / (CD_SECS*CD_FRAMES);
- lba %= CD_SECS*CD_FRAMES;
- msf[1] = lba / CD_FRAMES;
- msf[2] = lba % CD_FRAMES;
-}
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * convert msf-bin to msf-bcd
- */
-static INLINE void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */
-{
- *p=((*p/10)<<4)|(*p%10);
-}
-/*==========================================================================*/
-static INLINE u_int blk2msf(u_int blk)
-{
- MSF msf;
- u_int mm;
-
- msf.c[3] = 0;
- msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES);
- mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES);
- msf.c[1] = mm / CD_FRAMES;
- msf.c[0] = mm % CD_FRAMES;
- return (msf.n);
-}
-/*==========================================================================*/
-static INLINE u_int make16(u_char rh, u_char rl)
-{
- return ((rh<<8)|rl);
-}
-/*==========================================================================*/
-static INLINE u_int make32(u_int rh, u_int rl)
-{
- return ((rh<<16)|rl);
-}
-/*==========================================================================*/
-static INLINE u_char swap_nibbles(u_char i)
-{
- return ((i<<4)|(i>>4));
-}
-/*==========================================================================*/
-static INLINE u_char byt2bcd(u_char i)
-{
- return (((i/10)<<4)+i%10);
-}
-/*==========================================================================*/
-static INLINE u_char bcd2bin(u_char bcd)
-{
- return ((bcd>>4)*10+(bcd&0x0F));
-}
-/*==========================================================================*/
-static INLINE int msf2blk(int msfx)
-{
- MSF msf;
- int i;
-
- msf.n=msfx;
- i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET;
- if (i<0) return (0);
- return (i);
-}
-/*==========================================================================*/
-/*
- * convert m-s-f_number (3 bytes only) to logical_block_address
- */
-static INLINE int msf2lba(u_char *msf)
-{
- int i;
-
- i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET;
- if (i<0) return (0);
- return (i);
-}
-/*==========================================================================*/
-/* evaluate cc_ReadError code */
-static int sta2err(int sta)
-{
- if (famT_drive)
- {
- if (sta==0x00) return (0);
- if (sta==0x01) return (-604); /* CRC error */
- if (sta==0x02) return (-602); /* drive not ready */
- if (sta==0x03) return (-607); /* unknown media */
- if (sta==0x04) return (-612); /* general failure */
- if (sta==0x05) return (0);
- if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */
- if (sta==0x0b) return (-612); /* general failure */
- if (sta==0xff) return (-612); /* general failure */
- return (0);
- }
- else
- {
- if (sta<=2) return (sta);
- if (sta==0x05) return (-604); /* CRC error */
- if (sta==0x06) return (-606); /* seek error */
- if (sta==0x0d) return (-606); /* seek error */
- if (sta==0x0e) return (-603); /* unknown command */
- if (sta==0x14) return (-603); /* unknown command */
- if (sta==0x0c) return (-611); /* read fault */
- if (sta==0x0f) return (-611); /* read fault */
- if (sta==0x10) return (-611); /* read fault */
- if (sta>=0x16) return (-612); /* general failure */
- if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */
- if (famL_drive)
- if (sta==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */
- return (-602); /* drive not ready */
- }
-}
-/*==========================================================================*/
-static INLINE void clr_cmdbuf(void)
-{
- int i;
-
- for (i=0;i<10;i++) drvcmd[i]=0;
- cmd_type=0;
-}
-/*==========================================================================*/
-static void flush_status(void)
-{
- int i;
-
- sbp_sleep(15*HZ/10);
- for (i=maxtim_data;i!=0;i--) inb(CDi_status);
-}
-/*====================================================================*/
-/*
- * CDi status loop for Teac CD-55A (Rob Riggs)
- *
- * This is needed because for some strange reason
- * the CD-55A can take a real long time to give a
- * status response. This seems to happen after we
- * issue a READ command where a long seek is involved.
- *
- * I tried to ensure that we get max throughput with
- * minimal busy waiting. We busy wait at first, then
- * "switch gears" and start sleeping. We sleep for
- * longer periods of time the longer we wait.
- *
- */
-static int CDi_stat_loop_T(void)
-{
- int i, gear=1;
- u_long timeout_1, timeout_2, timeout_3, timeout_4;
-
- timeout_1 = jiffies + HZ / 50; /* sbp_sleep(0) for a short period */
- timeout_2 = jiffies + HZ / 5; /* nap for no more than 200ms */
- timeout_3 = jiffies + 5 * HZ; /* sleep for up to 5s */
- timeout_4 = jiffies + 45 * HZ; /* long sleep for up to 45s. */
- do
- {
- i = inb(CDi_status);
- if (!(i&s_not_data_ready)) return (i);
- if (!(i&s_not_result_ready)) return (i);
- switch(gear)
- {
- case 4:
- sbp_sleep(HZ);
- if (time_after(jiffies, timeout_4)) gear++;
- msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
- break;
- case 3:
- sbp_sleep(HZ/10);
- if (time_after(jiffies, timeout_3)) gear++;
- break;
- case 2:
- sbp_sleep(HZ/100);
- if (time_after(jiffies, timeout_2)) gear++;
- break;
- case 1:
- sbp_sleep(0);
- if (time_after(jiffies, timeout_1)) gear++;
- }
- } while (gear < 5);
- return -1;
-}
-/*==========================================================================*/
-static int CDi_stat_loop(void)
-{
- int i,j;
-
- for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); )
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) return (j);
- if (!(j&s_not_result_ready)) return (j);
- if (fam0L_drive) if (j&s_attention) return (j);
- }
- sbp_sleep(1);
- i = 1;
- }
- msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
- return (-1);
-}
-/*==========================================================================*/
-#if 00000
-/*==========================================================================*/
-static int tst_DataReady(void)
-{
- int i;
-
- i=inb(CDi_status);
- if (i&s_not_data_ready) return (0);
- return (1);
-}
-/*==========================================================================*/
-static int tst_ResultReady(void)
-{
- int i;
-
- i=inb(CDi_status);
- if (i&s_not_result_ready) return (0);
- return (1);
-}
-/*==========================================================================*/
-static int tst_Attention(void)
-{
- int i;
-
- i=inb(CDi_status);
- if (i&s_attention) return (1);
- return (0);
-}
-/*==========================================================================*/
-#endif
-/*==========================================================================*/
-static int ResponseInfo(void)
-{
- int i,j,st=0;
- u_long timeout;
-
- for (i=0,timeout=jiffies+HZ;i<response_count;i++)
- {
- for (j=maxtim_data; ; )
- {
- for ( ;j!=0;j-- )
- {
- st=inb(CDi_status);
- if (!(st&s_not_result_ready)) break;
- }
- if ((j!=0)||time_after_eq(jiffies, timeout)) break;
- sbp_sleep(1);
- j = 1;
- }
- if (time_after_eq(jiffies, timeout)) break;
- infobuf[i]=inb(CDi_info);
- }
-#if 000
- while (!(inb(CDi_status)&s_not_result_ready))
- {
- infobuf[i++]=inb(CDi_info);
- }
- j=i-response_count;
- if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j);
-#endif /* 000 */
- for (j=0;j<i;j++)
- sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i);
- j=response_count-i;
- if (j>0) return (-j);
- else return (i);
-}
-/*==========================================================================*/
-static void EvaluateStatus(int st)
-{
- current_drive->status_bits=0;
- if (fam1_drive) current_drive->status_bits=st|p_success;
- else if (fam0_drive)
- {
- if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in;
- if (st&p_spinning) current_drive->status_bits |= p_spinning;
- if (st&p_check) current_drive->status_bits |= p_check;
- if (st&p_success_old) current_drive->status_bits |= p_success;
- if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
- if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok;
- }
- else if (famLV_drive)
- {
- current_drive->status_bits |= p_success;
- if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in;
- if (st&p_spinning) current_drive->status_bits |= p_spinning;
- if (st&p_check) current_drive->status_bits |= p_check;
- if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
- if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed;
- if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked;
- }
- else if (fam2_drive)
- {
- current_drive->status_bits |= p_success;
- if (st&p2_check) current_drive->status_bits |= p1_check;
- if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
- if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
- if (st&p2_busy1) current_drive->status_bits |= p1_busy;
- if (st&p2_busy2) current_drive->status_bits |= p1_busy;
- if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
- if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
- if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
- }
- else if (famT_drive)
- {
- return; /* still needs to get coded */
- current_drive->status_bits |= p_success;
- if (st&p2_check) current_drive->status_bits |= p1_check;
- if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
- if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
- if (st&p2_busy1) current_drive->status_bits |= p1_busy;
- if (st&p2_busy2) current_drive->status_bits |= p1_busy;
- if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
- if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
- if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
- }
- return;
-}
-/*==========================================================================*/
-static int cmd_out_T(void);
-
-static int get_state_T(void)
-{
- int i;
-
- clr_cmdbuf();
- current_drive->n_bytes=1;
- drvcmd[0]=CMDT_STATUS;
- i=cmd_out_T();
- if (i>=0) i=infobuf[0];
- else
- {
- msg(DBG_TEA,"get_state_T error %d\n", i);
- return (i);
- }
- if (i>=0)
- /* 2: closed, disk in */
- current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok;
- else if (current_drive->error_state==6)
- {
- /* 3: closed, disk in, changed ("06 xx xx") */
- current_drive->status_bits=p1_door_closed|p1_disk_in;
- current_drive->CD_changed=0xFF;
- current_drive->diskstate_flags &= ~toc_bit;
- }
- else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00))
- {
- /* 1: closed, no disk ("xx yy zz"or "02 3A 00") */
- current_drive->status_bits=p1_door_closed;
- current_drive->open_count=0;
- }
- else if (current_drive->b4==0x01)
- {
- /* 0: open ("02 3A 01") */
- current_drive->status_bits=0;
- current_drive->open_count=0;
- }
- else
- {
- /* 1: closed, no disk ("02 3A xx") */
- current_drive->status_bits=p1_door_closed;
- current_drive->open_count=0;
- }
- return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static int ResponseStatus(void)
-{
- int i,j;
- u_long timeout;
-
- msg(DBG_STA,"doing ResponseStatus...\n");
- if (famT_drive) return (get_state_T());
- if (flags_cmd_out & f_respo3) timeout = jiffies;
- else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ;
- else timeout = jiffies + 4*HZ;
- j=maxtim_8;
- do
- {
- for ( ;j!=0;j--)
- {
- i=inb(CDi_status);
- if (!(i&s_not_result_ready)) break;
- }
- if ((j!=0)||time_after(jiffies, timeout)) break;
- sbp_sleep(1);
- j = 1;
- }
- while (1);
- if (j==0)
- {
- if ((flags_cmd_out & f_respo3) == 0)
- msg(DBG_STA,"ResponseStatus: timeout.\n");
- current_drive->status_bits=0;
- return (-401);
- }
- i=inb(CDi_info);
- msg(DBG_STA,"ResponseStatus: response %02X.\n", i);
- EvaluateStatus(i);
- msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i);
- return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static void cc_ReadStatus(void)
-{
- int i;
-
- msg(DBG_STA,"giving cc_ReadStatus command\n");
- if (famT_drive) return;
- SBPCD_CLI;
- if (fam0LV_drive) OUT(CDo_command,CMD0_STATUS);
- else if (fam1_drive) OUT(CDo_command,CMD1_STATUS);
- else if (fam2_drive) OUT(CDo_command,CMD2_STATUS);
- if (!fam0LV_drive) for (i=0;i<6;i++) OUT(CDo_command,0);
- SBPCD_STI;
-}
-/*==========================================================================*/
-static int cc_ReadError(void)
-{
- int i;
-
- clr_cmdbuf();
- msg(DBG_ERR,"giving cc_ReadError command.\n");
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_ERR;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_READ_ERR;
- response_count=6;
- if (famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ_ERR;
- response_count=6;
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- response_count=5;
- drvcmd[0]=CMDT_READ_ERR;
- }
- i=cmd_out();
- current_drive->error_byte=0;
- msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i);
- if (i<0) return (i);
- if (fam0V_drive) i=1;
- else i=2;
- current_drive->error_byte=infobuf[i];
- msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte);
- i=sta2err(infobuf[i]);
- if (i==-ERR_DISKCHANGE)
- {
- current_drive->CD_changed=0xFF;
- current_drive->diskstate_flags &= ~toc_bit;
- }
- return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void);
-
-static int cmd_out_T(void)
-{
-#undef CMDT_TRIES
-#define CMDT_TRIES 1000
-#define TEST_FALSE_FF 1
-
- int i, j, l=0, m, ntries;
- unsigned long flags;
-
- current_drive->error_state=0;
- current_drive->b3=0;
- current_drive->b4=0;
- current_drive->f_drv_error=0;
- for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]);
- msgbuf[i*3]=0;
- msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf);
-
- OUT(CDo_sel_i_d,0);
- OUT(CDo_enable,current_drive->drv_sel);
- i=inb(CDi_status);
- do_16bit=0;
- if ((f_16bit)&&(!(i&0x80)))
- {
- do_16bit=1;
- msg(DBG_TEA,"cmd_out_T: do_16bit set.\n");
- }
- if (!(i&s_not_result_ready))
- do
- {
- j=inb(CDi_info);
- i=inb(CDi_status);
- sbp_sleep(0);
- msg(DBG_TEA,"cmd_out_T: spurious !s_not_result_ready. (%02X)\n", j);
- }
- while (!(i&s_not_result_ready));
- save_flags(flags); cli();
- for (i=0;i<10;i++) OUT(CDo_command,drvcmd[i]);
- restore_flags(flags);
- for (ntries=CMDT_TRIES;ntries>0;ntries--)
- {
- if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */
-#if 01
- OUT(CDo_sel_i_d,1);
-#endif /* 01 */
- if (teac==2)
- {
- if ((i=CDi_stat_loop_T()) == -1) break;
- }
- else
- {
-#if 0
- OUT(CDo_sel_i_d,1);
-#endif /* 0 */
- i=inb(CDi_status);
- }
- if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */
- {
- OUT(CDo_sel_i_d,1);
- if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
- if (drvcmd[0]==CMDT_DISKINFO)
- {
- l=0;
- do
- {
- if (do_16bit)
- {
- i=inw(CDi_data);
- infobuf[l++]=i&0x0ff;
- infobuf[l++]=i>>8;
-#if TEST_FALSE_FF
- if ((l==2)&&(infobuf[0]==0x0ff))
- {
- infobuf[0]=infobuf[1];
- l=1;
- msg(DBG_TEA,"cmd_out_T: do_16bit: false first byte!\n");
- }
-#endif /* TEST_FALSE_FF */
- }
- else infobuf[l++]=inb(CDi_data);
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- for (j=0;j<l;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_CMD,"cmd_out_T data response:%s\n", msgbuf);
- }
- else
- {
- msg(DBG_TEA,"cmd_out_T: data response with cmd_%02X!\n",
- drvcmd[0]);
- j=0;
- do
- {
- if (do_16bit) i=inw(CDi_data);
- else i=inb(CDi_data);
- j++;
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- msg(DBG_TEA,"cmd_out_T: data response: discarded %d bytes/words.\n", j);
- fatal_err++;
- }
- }
- i=inb(CDi_status);
- if (!(i&s_not_result_ready))
- {
- OUT(CDo_sel_i_d,0);
- if (drvcmd[0]==CMDT_DISKINFO) m=l;
- else m=0;
- do
- {
- infobuf[m++]=inb(CDi_info);
- i=inb(CDi_status);
- }
- while (!(i&s_not_result_ready));
- for (j=0;j<m;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_CMD,"cmd_out_T info response:%s\n", msgbuf);
- if (drvcmd[0]==CMDT_DISKINFO)
- {
- infobuf[0]=infobuf[l];
- if (infobuf[0]!=0x02) return (l); /* data length */
- }
- else if (infobuf[0]!=0x02) return (m); /* info length */
- do
- {
- ++recursion;
- if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (%02X): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", drvcmd[0], recursion);
- clr_cmdbuf();
- drvcmd[0]=CMDT_READ_ERR;
- j=cmd_out_T(); /* !!! recursive here !!! */
- --recursion;
- sbp_sleep(1);
- }
- while (j<0);
- current_drive->error_state=infobuf[2];
- current_drive->b3=infobuf[3];
- current_drive->b4=infobuf[4];
- if (current_drive->f_drv_error)
- {
- current_drive->f_drv_error=0;
- cc_DriveReset();
- current_drive->error_state=2;
- }
- return (-current_drive->error_state-400);
- }
- if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
- if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10);
- else sbp_sleep(HZ/100);
- if (ntries>(CMDT_TRIES-50)) continue;
- msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1);
- }
- current_drive->f_drv_error=1;
- cc_DriveReset();
- current_drive->error_state=2;
- return (-99);
-}
-/*==========================================================================*/
-static int cmd_out(void)
-{
- int i=0;
-
- if (famT_drive) return(cmd_out_T());
-
- if (flags_cmd_out&f_putcmd)
- {
- unsigned long flags;
- for (i=0;i<7;i++)
- sprintf(&msgbuf[i*3], " %02X", drvcmd[i]);
- msgbuf[i*3]=0;
- msg(DBG_CMD,"cmd_out:%s\n", msgbuf);
- save_flags(flags); cli();
- for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
- restore_flags(flags);
- }
- if (response_count!=0)
- {
- if (cmd_type!=0)
- {
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- msg(DBG_INF,"misleaded to try ResponseData.\n");
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- return (-22);
- }
- else i=ResponseInfo();
- if (i<0) return (i);
- }
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n");
- if (flags_cmd_out&f_lopsta)
- {
- i=CDi_stat_loop();
- if ((i<0)||!(i&s_attention)) return (-8);
- }
- if (!(flags_cmd_out&f_getsta)) goto LOC_229;
-
- LOC_228:
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n");
- cc_ReadStatus();
-
- LOC_229:
- if (flags_cmd_out&f_ResponseStatus)
- {
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n");
- i=ResponseStatus();
- /* builds status_bits, returns orig. status or p_busy_new */
- if (i<0) return (i);
- if (flags_cmd_out&(f_bit1|f_wait_if_busy))
- {
- if (!st_check)
- {
- if ((flags_cmd_out&f_bit1)&&(i&p_success)) goto LOC_232;
- if ((!(flags_cmd_out&f_wait_if_busy))||(!st_busy)) goto LOC_228;
- }
- }
- }
- LOC_232:
- if (!(flags_cmd_out&f_obey_p_check)) return (0);
- if (!st_check) return (0);
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n");
- i=cc_ReadError();
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n");
- msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i);
- return (i);
-}
-/*==========================================================================*/
-static int cc_Seek(u_int pos, char f_blk_msf)
-{
- int i;
-
- clr_cmdbuf();
- if (f_blk_msf>1) return (-3);
- if (fam0V_drive)
- {
- drvcmd[0]=CMD0_SEEK;
- if (f_blk_msf==1) pos=msf2blk(pos);
- drvcmd[2]=(pos>>16)&0x00FF;
- drvcmd[3]=(pos>>8)&0x00FF;
- drvcmd[4]=pos&0x00FF;
- if (fam0_drive)
- flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
- f_ResponseStatus | f_obey_p_check | f_bit1;
- else
- flags_cmd_out = f_putcmd;
- }
- else if (fam1L_drive)
- {
- drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */
- if (f_blk_msf==0) pos=blk2msf(pos);
- drvcmd[1]=(pos>>16)&0x00FF;
- drvcmd[2]=(pos>>8)&0x00FF;
- drvcmd[3]=pos&0x00FF;
- if (famL_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_SEEK;
- if (f_blk_msf==0) pos=blk2msf(pos);
- drvcmd[2]=(pos>>24)&0x00FF;
- drvcmd[3]=(pos>>16)&0x00FF;
- drvcmd[4]=(pos>>8)&0x00FF;
- drvcmd[5]=pos&0x00FF;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_SEEK;
- if (f_blk_msf==1) pos=msf2blk(pos);
- drvcmd[2]=(pos>>24)&0x00FF;
- drvcmd[3]=(pos>>16)&0x00FF;
- drvcmd[4]=(pos>>8)&0x00FF;
- drvcmd[5]=pos&0x00FF;
- current_drive->n_bytes=1;
- }
- response_count=0;
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_SpinUp(void)
-{
- int i;
-
- msg(DBG_SPI,"SpinUp.\n");
- current_drive->in_SpinUp = 1;
- clr_cmdbuf();
- if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_SPINUP;
- if (fam0L_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
- f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd;
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_SPINUP;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_TRAY_CTL;
- drvcmd[4]=0x01; /* "spinup" */
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_TRAY_CTL;
- drvcmd[4]=0x03; /* "insert", it hopefully spins the drive up */
- }
- response_count=0;
- i=cmd_out();
- current_drive->in_SpinUp = 0;
- return (i);
-}
-/*==========================================================================*/
-static int cc_SpinDown(void)
-{
- int i;
-
- if (fam0_drive) return (0);
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_SPINDOWN;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_TRAY_CTL;
- drvcmd[4]=0x02; /* "eject" */
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famL_drive)
- {
- drvcmd[0]=CMDL_SPINDOWN;
- drvcmd[1]=1;
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (famV_drive)
- {
- drvcmd[0]=CMDV_SPINDOWN;
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_TRAY_CTL;
- drvcmd[4]=0x02; /* "eject" */
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_get_mode_T(void)
-{
- int i;
-
- clr_cmdbuf();
- response_count=10;
- drvcmd[0]=CMDT_GETMODE;
- drvcmd[4]=response_count;
- i=cmd_out_T();
- return (i);
-}
-/*==========================================================================*/
-static int cc_set_mode_T(void)
-{
- int i;
-
- clr_cmdbuf();
- response_count=1;
- drvcmd[0]=CMDT_SETMODE;
- drvcmd[1]=current_drive->speed_byte;
- drvcmd[2]=current_drive->frmsiz>>8;
- drvcmd[3]=current_drive->frmsiz&0x0FF;
- drvcmd[4]=current_drive->f_XA; /* 1: XA */
- drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */
- drvcmd[6]=current_drive->mode_xb_6;
- drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control;
- drvcmd[8]=current_drive->mode_xb_8;
- drvcmd[9]=current_drive->delay;
- i=cmd_out_T();
- return (i);
-}
-/*==========================================================================*/
-static int cc_prep_mode_T(void)
-{
- int i, j;
-
- i=cc_get_mode_T();
- if (i<0) return (i);
- for (i=0;i<10;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
- current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */
- current_drive->frmsiz=make16(infobuf[2],infobuf[3]);
- current_drive->f_XA=infobuf[4];
- if (current_drive->f_XA==0) current_drive->type_byte=0;
- else current_drive->type_byte=1;
- current_drive->mode_xb_6=infobuf[6];
- current_drive->mode_yb_7=1;
- current_drive->mode_xb_8=infobuf[8];
- current_drive->delay=0; /* 0, 1, 2, 3 */
- j=cc_set_mode_T();
- i=cc_get_mode_T();
- for (i=0;i<10;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
- return (j);
-}
-/*==========================================================================*/
-static int cc_SetSpeed(u_char speed, u_char x1, u_char x2)
-{
- int i;
-
- if (fam0LV_drive) return (0);
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_SETMODE;
- drvcmd[1]=0x03;
- drvcmd[2]=speed;
- drvcmd[3]=x1;
- drvcmd[4]=x2;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_SETSPEED;
- if (speed&speed_auto)
- {
- drvcmd[2]=0xFF;
- drvcmd[3]=0xFF;
- }
- else
- {
- drvcmd[2]=0;
- drvcmd[3]=150;
- }
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- return (0);
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_SetVolume(void)
-{
- int i;
- u_char channel0,channel1,volume0,volume1;
- u_char control0,value0,control1,value1;
-
- current_drive->diskstate_flags &= ~volume_bit;
- clr_cmdbuf();
- channel0=current_drive->vol_chan0;
- volume0=current_drive->vol_ctrl0;
- channel1=control1=current_drive->vol_chan1;
- volume1=value1=current_drive->vol_ctrl1;
- control0=value0=0;
-
- if (famV_drive) return (0);
-
- if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211))
- {
- if ((volume0!=0)&&(volume1==0))
- {
- volume1=volume0;
- channel1=channel0;
- }
- else if ((volume0==0)&&(volume1!=0))
- {
- volume0=volume1;
- channel0=channel1;
- }
- }
- if (channel0>1)
- {
- channel0=0;
- volume0=0;
- }
- if (channel1>1)
- {
- channel1=1;
- volume1=0;
- }
-
- if (fam1_drive)
- {
- control0=channel0+1;
- control1=channel1+1;
- value0=(volume0>volume1)?volume0:volume1;
- value1=value0;
- if (volume0==0) control0=0;
- if (volume1==0) control1=0;
- drvcmd[0]=CMD1_SETMODE;
- drvcmd[1]=0x05;
- drvcmd[3]=control0;
- drvcmd[4]=value0;
- drvcmd[5]=control1;
- drvcmd[6]=value1;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- control0=channel0+1;
- control1=channel1+1;
- value0=(volume0>volume1)?volume0:volume1;
- value1=value0;
- if (volume0==0) control0=0;
- if (volume1==0) control1=0;
- drvcmd[0]=CMD2_SETMODE;
- drvcmd[1]=0x0E;
- drvcmd[3]=control0;
- drvcmd[4]=value0;
- drvcmd[5]=control1;
- drvcmd[6]=value1;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famL_drive)
- {
- if ((volume0==0)||(channel0!=0)) control0 |= 0x80;
- if ((volume1==0)||(channel1!=1)) control0 |= 0x40;
- if (volume0|volume1) value0=0x80;
- drvcmd[0]=CMDL_SETMODE;
- drvcmd[1]=0x03;
- drvcmd[4]=control0;
- drvcmd[5]=value0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam0_drive) /* different firmware levels */
- {
- if (current_drive->drv_type>=drv_300)
- {
- control0=volume0&0xFC;
- value0=volume1&0xFC;
- if ((volume0!=0)&&(volume0<4)) control0 |= 0x04;
- if ((volume1!=0)&&(volume1<4)) value0 |= 0x04;
- if (channel0!=0) control0 |= 0x01;
- if (channel1==1) value0 |= 0x01;
- }
- else
- {
- value0=(volume0>volume1)?volume0:volume1;
- if (current_drive->drv_type<drv_211)
- {
- if (channel0!=0)
- {
- i=channel1;
- channel1=channel0;
- channel0=i;
- i=volume1;
- volume1=volume0;
- volume0=i;
- }
- if (channel0==channel1)
- {
- if (channel0==0)
- {
- channel1=1;
- volume1=0;
- volume0=value0;
- }
- else
- {
- channel0=0;
- volume0=0;
- volume1=value0;
- }
- }
- }
-
- if ((volume0!=0)&&(volume1!=0))
- {
- if (volume0==0xFF) volume1=0xFF;
- else if (volume1==0xFF) volume0=0xFF;
- }
- else if (current_drive->drv_type<drv_201) volume0=volume1=value0;
-
- if (current_drive->drv_type>=drv_201)
- {
- if (volume0==0) control0 |= 0x80;
- if (volume1==0) control0 |= 0x40;
- }
- if (current_drive->drv_type>=drv_211)
- {
- if (channel0!=0) control0 |= 0x20;
- if (channel1!=1) control0 |= 0x10;
- }
- }
- drvcmd[0]=CMD0_SETMODE;
- drvcmd[1]=0x83;
- drvcmd[4]=control0;
- drvcmd[5]=value0;
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- current_drive->volume_control=0;
- if (!volume0) current_drive->volume_control|=0x10;
- if (!volume1) current_drive->volume_control|=0x20;
- i=cc_prep_mode_T();
- if (i<0) return (i);
- }
- if (!famT_drive)
- {
- response_count=0;
- i=cmd_out();
- if (i<0) return (i);
- }
- current_drive->diskstate_flags |= volume_bit;
- return (0);
-}
-/*==========================================================================*/
-static int GetStatus(void)
-{
- int i;
-
- if (famT_drive) return (0);
- flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check;
- response_count=0;
- cmd_type=0;
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void)
-{
- int i;
-
- msg(DBG_RES,"cc_DriveReset called.\n");
- clr_cmdbuf();
- response_count=0;
- if (fam0LV_drive) OUT(CDo_reset,0x00);
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_RESET;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_RESET;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- OUT(CDo_reset,0x00);
- }
- else if (famT_drive)
- {
- OUT(CDo_sel_i_d,0);
- OUT(CDo_enable,current_drive->drv_sel);
- OUT(CDo_command,CMDT_RESET);
- for (i=1;i<10;i++) OUT(CDo_command,0);
- }
- if (fam0LV_drive) sbp_sleep(5*HZ); /* wait 5 seconds */
- else sbp_sleep(1*HZ); /* wait a second */
-#if 1
- if (famT_drive)
- {
- msg(DBG_TEA, "================CMDT_RESET given=================.\n");
- sbp_sleep(3*HZ);
- }
-#endif /* 1 */
- flush_status();
- i=GetStatus();
- if (i<0) return i;
- if (!famT_drive)
- if (current_drive->error_byte!=aud_12) return -501;
- return (0);
-}
-
-/*==========================================================================*/
-static int SetSpeed(void)
-{
- int i, speed;
-
- if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0);
- speed=speed_auto;
- if (!(current_drive->drv_options&speed_auto))
- {
- speed |= speed_300;
- if (!(current_drive->drv_options&speed_300)) speed=0;
- }
- i=cc_SetSpeed(speed,0,0);
- return (i);
-}
-
-static void switch_drive(struct sbpcd_drive *);
-
-static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
- struct sbpcd_drive *p = cdi->handle;
- if (p != current_drive)
- switch_drive(p);
-
- return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0);
-}
-
-/*==========================================================================*/
-static int DriveReset(void)
-{
- int i;
-
- i=cc_DriveReset();
- if (i<0) return (-22);
- do
- {
- i=GetStatus();
- if ((i<0)&&(i!=-ERR_DISKCHANGE)) {
- return (-2); /* from sta2err */
- }
- if (!st_caddy_in) break;
- sbp_sleep(1);
- }
- while (!st_diskok);
-#if 000
- current_drive->CD_changed=1;
-#endif
- if ((st_door_closed) && (st_caddy_in))
- {
- i=DiskInfo();
- if (i<0) return (-23);
- }
- return (0);
-}
-
-static int sbpcd_reset(struct cdrom_device_info *cdi)
-{
- struct sbpcd_drive *p = cdi->handle;
- if (p != current_drive)
- switch_drive(p);
- return DriveReset();
-}
-
-/*==========================================================================*/
-static int cc_PlayAudio(int pos_audio_start,int pos_audio_end)
-{
- int i, j, n;
-
- if (current_drive->audio_state==audio_playing) return (-EINVAL);
- clr_cmdbuf();
- response_count=0;
- if (famLV_drive)
- {
- drvcmd[0]=CMDL_PLAY;
- i=msf2blk(pos_audio_start);
- n=msf2blk(pos_audio_end)+1-i;
- drvcmd[1]=(i>>16)&0x00FF;
- drvcmd[2]=(i>>8)&0x00FF;
- drvcmd[3]=i&0x00FF;
- drvcmd[4]=(n>>16)&0x00FF;
- drvcmd[5]=(n>>8)&0x00FF;
- drvcmd[6]=n&0x00FF;
- if (famL_drive)
- flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
- f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
- else
- flags_cmd_out = f_putcmd;
- }
- else
- {
- j=1;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_PLAY_MSF;
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
- f_obey_p_check | f_wait_if_busy;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_PLAY_MSF;
- flags_cmd_out = f_putcmd | f_ResponseStatus | f_obey_p_check;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_PLAY_MSF;
- j=3;
- response_count=1;
- }
- else if (fam0_drive)
- {
- drvcmd[0]=CMD0_PLAY_MSF;
- flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
- f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
- }
- drvcmd[j]=(pos_audio_start>>16)&0x00FF;
- drvcmd[j+1]=(pos_audio_start>>8)&0x00FF;
- drvcmd[j+2]=pos_audio_start&0x00FF;
- drvcmd[j+3]=(pos_audio_end>>16)&0x00FF;
- drvcmd[j+4]=(pos_audio_end>>8)&0x00FF;
- drvcmd[j+5]=pos_audio_end&0x00FF;
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_Pause_Resume(int pau_res)
-{
- int i;
-
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_PAU_RES;
- if (pau_res!=1) drvcmd[1]=0x80;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_PAU_RES;
- if (pau_res!=1) drvcmd[2]=0x01;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_PAU_RES;
- if (pau_res!=1) drvcmd[1]=0x80;
- if (famL_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
- f_obey_p_check|f_bit1;
- else if (famV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
- f_obey_p_check;
- }
- else if (famT_drive)
- {
- if (pau_res==3) return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end));
- else if (pau_res==1) drvcmd[0]=CMDT_PAUSE;
- else return (-56);
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_LockDoor(char lock)
-{
- int i;
-
- if (fam0_drive) return (0);
- msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S);
- msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked);
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_LOCK_CTL;
- if (lock==1) drvcmd[1]=0x01;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_LOCK_CTL;
- if (lock==1) drvcmd[4]=0x01;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_LOCK_CTL;
- if (lock==1) drvcmd[1]=0x01;
- if (famL_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_LOCK_CTL;
- if (lock==1) drvcmd[4]=0x01;
- }
- i=cmd_out();
- msg(DBG_LCS,"p_door_locked bit %d after\n", st_door_locked);
- return (i);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int UnLockDoor(void)
-{
- int i,j;
-
- j=20;
- do
- {
- i=cc_LockDoor(0);
- --j;
- sbp_sleep(1);
- }
- while ((i<0)&&(j));
- if (i<0)
- {
- cc_DriveReset();
- return -84;
- }
- return (0);
-}
-/*==========================================================================*/
-static int LockDoor(void)
-{
- int i,j;
-
- j=20;
- do
- {
- i=cc_LockDoor(1);
- --j;
- sbp_sleep(1);
- }
- while ((i<0)&&(j));
- if (j==0)
- {
- cc_DriveReset();
- j=20;
- do
- {
- i=cc_LockDoor(1);
- --j;
- sbp_sleep(1);
- }
- while ((i<0)&&(j));
- }
- return (i);
-}
-
-static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
- return lock ? LockDoor() : UnLockDoor();
-}
-
-/*==========================================================================*/
-static int cc_CloseTray(void)
-{
- int i;
-
- if (fam0_drive) return (0);
- msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S);
- msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed);
-
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_TRAY_CTL;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_TRAY_CTL;
- drvcmd[1]=0x01;
- drvcmd[4]=0x03; /* "insert" */
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_TRAY_CTL;
- if (famLV_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
- f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_TRAY_CTL;
- drvcmd[4]=0x03; /* "insert" */
- }
- i=cmd_out();
- msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed);
-
- i=cc_ReadError();
- flags_cmd_out |= f_respo2;
- cc_ReadStatus(); /* command: give 1-byte status */
- i=ResponseStatus();
- if (famT_drive&&(i<0))
- {
- cc_DriveReset();
- i=ResponseStatus();
-#if 0
- sbp_sleep(HZ);
-#endif /* 0 */
- i=ResponseStatus();
- }
- if (i<0)
- {
- msg(DBG_INF,"sbpcd cc_CloseTray: ResponseStatus timed out (%d).\n",i);
- }
- if (!(famT_drive))
- {
- if (!st_spinning)
- {
- cc_SpinUp();
- if (st_check) i=cc_ReadError();
- flags_cmd_out |= f_respo2;
- cc_ReadStatus();
- i=ResponseStatus();
- } else {
- }
- }
- i=DiskInfo();
- return (i);
-}
-
-static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
-{
- int retval=0;
- switch_drive(cdi->handle);
- /* DUH! --AJK */
- if(current_drive->CD_changed != 0xFF) {
- current_drive->CD_changed=0xFF;
- current_drive->diskstate_flags &= ~cd_size_bit;
- }
- if (position == 1) {
- cc_SpinDown();
- } else {
- retval=cc_CloseTray();
- }
- return retval;
-}
-
-/*==========================================================================*/
-static int cc_ReadSubQ(void)
-{
- int i,j;
-
- current_drive->diskstate_flags &= ~subq_bit;
- for (j=255;j>0;j--)
- {
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READSUBQ;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- response_count=11;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READSUBQ;
- drvcmd[1]=0x02;
- drvcmd[3]=0x01;
- flags_cmd_out=f_putcmd;
- response_count=10;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_READSUBQ;
- drvcmd[1]=0x02;
- if (famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- response_count=13;
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_READSUBQ;
- drvcmd[1]=0x02;
- drvcmd[2]=0x40;
- drvcmd[3]=0x01;
- drvcmd[8]=response_count;
- }
- i=cmd_out();
- if (i<0) return (i);
- for (i=0;i<response_count;i++)
- {
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_SQ1,"cc_ReadSubQ:%s\n", msgbuf);
- }
- if (famT_drive) break;
- if (infobuf[0]!=0) break;
- if ((!st_spinning) || (j==1))
- {
- current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0;
- current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0;
- return (0);
- }
- }
- if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1];
- else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]);
- current_drive->SubQ_trk=byt2bcd(infobuf[2]);
- current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]);
- if (fam0LV_drive) i=5;
- else if (fam12_drive) i=4;
- else if (famT_drive) i=8;
- current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
- i=7;
- if (fam0LV_drive) i=9;
- else if (fam12_drive) i=7;
- else if (famT_drive) i=4;
- current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
- current_drive->SubQ_whatisthis=infobuf[i+3];
- current_drive->diskstate_flags |= subq_bit;
- return (0);
-}
-/*==========================================================================*/
-static int cc_ModeSense(void)
-{
- int i;
-
- if (fam2_drive) return (0);
- if (famV_drive) return (0);
- current_drive->diskstate_flags &= ~frame_size_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- response_count=5;
- drvcmd[0]=CMD1_GETMODE;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- response_count=2;
- drvcmd[0]=CMD0_GETMODE;
- if (famL_drive) flags_cmd_out=f_putcmd;
- else flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- response_count=10;
- drvcmd[0]=CMDT_GETMODE;
- drvcmd[4]=response_count;
- }
- i=cmd_out();
- if (i<0) return (i);
- i=0;
- current_drive->sense_byte=0;
- if (fam1_drive) current_drive->sense_byte=infobuf[i++];
- else if (famT_drive)
- {
- if (infobuf[4]==0x01) current_drive->xa_byte=0x20;
- else current_drive->xa_byte=0;
- i=2;
- }
- current_drive->frame_size=make16(infobuf[i],infobuf[i+1]);
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf);
-
- current_drive->diskstate_flags |= frame_size_bit;
- return (0);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int cc_ModeSelect(int framesize)
-{
- int i;
-
- if (fam2_drive) return (0);
- if (famV_drive) return (0);
- current_drive->diskstate_flags &= ~frame_size_bit;
- clr_cmdbuf();
- current_drive->frame_size=framesize;
- if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82;
- else current_drive->sense_byte=0x00;
-
- msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n",
- current_drive->sense_byte, current_drive->frame_size);
-
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_SETMODE;
- drvcmd[1]=0x00;
- drvcmd[2]=current_drive->sense_byte;
- drvcmd[3]=(current_drive->frame_size>>8)&0xFF;
- drvcmd[4]=current_drive->frame_size&0xFF;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_SETMODE;
- drvcmd[1]=0x00;
- drvcmd[2]=(current_drive->frame_size>>8)&0xFF;
- drvcmd[3]=current_drive->frame_size&0xFF;
- drvcmd[4]=0x00;
- if(famL_drive)
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- return (-1);
- }
- response_count=0;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->diskstate_flags |= frame_size_bit;
- return (0);
-}
-/*==========================================================================*/
-static int cc_GetVolume(void)
-{
- int i;
- u_char switches;
- u_char chan0=0;
- u_char vol0=0;
- u_char chan1=1;
- u_char vol1=0;
-
- if (famV_drive) return (0);
- current_drive->diskstate_flags &= ~volume_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_GETMODE;
- drvcmd[1]=0x05;
- response_count=5;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_GETMODE;
- drvcmd[1]=0x0E;
- response_count=5;
- flags_cmd_out=f_putcmd;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_GETMODE;
- drvcmd[1]=0x03;
- response_count=2;
- if(famL_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- i=cc_get_mode_T();
- if (i<0) return (i);
- }
- if (!famT_drive)
- {
- i=cmd_out();
- if (i<0) return (i);
- }
- if (fam1_drive)
- {
- chan0=infobuf[1]&0x0F;
- vol0=infobuf[2];
- chan1=infobuf[3]&0x0F;
- vol1=infobuf[4];
- if (chan0==0)
- {
- chan0=1;
- vol0=0;
- }
- if (chan1==0)
- {
- chan1=2;
- vol1=0;
- }
- chan0 >>= 1;
- chan1 >>= 1;
- }
- else if (fam2_drive)
- {
- chan0=infobuf[1];
- vol0=infobuf[2];
- chan1=infobuf[3];
- vol1=infobuf[4];
- }
- else if (famL_drive)
- {
- chan0=0;
- chan1=1;
- vol0=vol1=infobuf[1];
- switches=infobuf[0];
- if ((switches&0x80)!=0) chan0=1;
- if ((switches&0x40)!=0) chan1=0;
- }
- else if (fam0_drive) /* different firmware levels */
- {
- chan0=0;
- chan1=1;
- vol0=vol1=infobuf[1];
- if (current_drive->drv_type>=drv_201)
- {
- if (current_drive->drv_type<drv_300)
- {
- switches=infobuf[0];
- if ((switches&0x80)!=0) vol0=0;
- if ((switches&0x40)!=0) vol1=0;
- if (current_drive->drv_type>=drv_211)
- {
- if ((switches&0x20)!=0) chan0=1;
- if ((switches&0x10)!=0) chan1=0;
- }
- }
- else
- {
- vol0=infobuf[0];
- if ((vol0&0x01)!=0) chan0=1;
- if ((vol1&0x01)==0) chan1=0;
- vol0 &= 0xFC;
- vol1 &= 0xFC;
- if (vol0!=0) vol0 += 3;
- if (vol1!=0) vol1 += 3;
- }
- }
- }
- else if (famT_drive)
- {
- current_drive->volume_control=infobuf[7];
- chan0=0;
- chan1=1;
- if (current_drive->volume_control&0x10) vol0=0;
- else vol0=0xff;
- if (current_drive->volume_control&0x20) vol1=0;
- else vol1=0xff;
- }
- current_drive->vol_chan0=chan0;
- current_drive->vol_ctrl0=vol0;
- current_drive->vol_chan1=chan1;
- current_drive->vol_ctrl1=vol1;
-#if 000
- current_drive->vol_chan2=2;
- current_drive->vol_ctrl2=0xFF;
- current_drive->vol_chan3=3;
- current_drive->vol_ctrl3=0xFF;
-#endif /* 000 */
- current_drive->diskstate_flags |= volume_bit;
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadCapacity(void)
-{
- int i, j;
-
- if (fam2_drive) return (0); /* some firmware lacks this command */
- if (famLV_drive) return (0); /* some firmware lacks this command */
- if (famT_drive) return (0); /* done with cc_ReadTocDescr() */
- current_drive->diskstate_flags &= ~cd_size_bit;
- for (j=3;j>0;j--)
- {
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_CAPACITY;
- response_count=5;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
-#if 00
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_CAPACITY;
- response_count=8;
- flags_cmd_out=f_putcmd;
- }
-#endif
- else if (fam0_drive)
- {
- drvcmd[0]=CMD0_CAPACITY;
- response_count=5;
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- i=cmd_out();
- if (i>=0) break;
- msg(DBG_000,"cc_ReadCapacity: cmd_out: err %d\n", i);
- cc_ReadError();
- }
- if (j==0) return (i);
- if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET;
- else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
-#if 00
- else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3]));
-#endif
- current_drive->diskstate_flags |= cd_size_bit;
- msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm);
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocDescr(void)
-{
- int i;
-
- current_drive->diskstate_flags &= ~toc_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_DISKINFO;
- response_count=6;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_DISKINFO;
- response_count=6;
- if(famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- /* possibly longer timeout periods necessary */
- current_drive->f_multisession=0;
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=0xAB;
- drvcmd[3]=0xFF; /* session */
- response_count=8;
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- current_drive->f_multisession=0;
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=CDROM_LEADOUT;
- drvcmd[8]=response_count;
- drvcmd[9]=0x00;
- }
- i=cmd_out();
- if (i<0) return (i);
- if ((famT_drive)&&(i<response_count)) return (-100-i);
- if ((fam1_drive)||(fam2_drive)||(fam0LV_drive))
- current_drive->xa_byte=infobuf[0];
- if (fam2_drive)
- {
- current_drive->first_session=infobuf[1];
- current_drive->last_session=infobuf[2];
- current_drive->n_first_track=infobuf[3];
- current_drive->n_last_track=infobuf[4];
- if (current_drive->first_session!=current_drive->last_session)
- {
- current_drive->f_multisession=1;
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])));
- }
-#if 0
- if (current_drive->first_session!=current_drive->last_session)
- {
- if (current_drive->last_session<=20)
- zwanzig=current_drive->last_session+1;
- else zwanzig=20;
- for (count=current_drive->first_session;count<zwanzig;count++)
- {
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=0xAB;
- drvcmd[3]=count;
- response_count=8;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]));
- }
- current_drive->diskstate_flags |= multisession_bit;
- }
-#endif
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=0xAA;
- drvcmd[3]=0xFF;
- response_count=5;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4]));
- current_drive->size_blk=msf2blk(current_drive->size_msf);
- current_drive->CDsize_frm=current_drive->size_blk+1;
- }
- else if (famT_drive)
- {
- current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11]));
- current_drive->size_blk=msf2blk(current_drive->size_msf);
- current_drive->CDsize_frm=current_drive->size_blk+1;
- current_drive->n_first_track=infobuf[2];
- current_drive->n_last_track=infobuf[3];
- }
- else
- {
- current_drive->n_first_track=infobuf[1];
- current_drive->n_last_track=infobuf[2];
- current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
- current_drive->size_blk=msf2blk(current_drive->size_msf);
- if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1;
- }
- current_drive->diskstate_flags |= toc_bit;
- msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n",
- current_drive->xa_byte,
- current_drive->n_first_track,
- current_drive->n_last_track,
- current_drive->size_msf,
- current_drive->first_session,
- current_drive->last_session);
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocEntry(int num)
-{
- int i;
-
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READTOC;
- drvcmd[2]=num;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- /* possibly longer timeout periods necessary */
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=num;
- response_count=5;
- flags_cmd_out=f_putcmd;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_READTOC;
- drvcmd[1]=0x02;
- drvcmd[2]=num;
- response_count=8;
- if (famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=num;
- drvcmd[8]=response_count;
- drvcmd[9]=0x00;
- }
- i=cmd_out();
- if (i<0) return (i);
- if ((famT_drive)&&(i<response_count)) return (-100-i);
- if ((fam1_drive)||(fam0LV_drive))
- {
- current_drive->TocEnt_nixbyte=infobuf[0];
- i=1;
- }
- else if (fam2_drive) i=0;
- else if (famT_drive) i=5;
- current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]);
- if ((fam1_drive)||(fam0L_drive))
- {
- current_drive->TocEnt_number=infobuf[i++];
- current_drive->TocEnt_format=infobuf[i];
- }
- else
- {
- current_drive->TocEnt_number=num;
- current_drive->TocEnt_format=0;
- }
- if (fam1_drive) i=4;
- else if (fam0LV_drive) i=5;
- else if (fam2_drive) i=2;
- else if (famT_drive) i=9;
- current_drive->TocEnt_address=make32(make16(0,infobuf[i]),
- make16(infobuf[i+1],infobuf[i+2]));
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"TocEntry:%s\n", msgbuf);
- msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n",
- current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr,
- current_drive->TocEnt_number, current_drive->TocEnt_format,
- current_drive->TocEnt_address);
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadPacket(void)
-{
- int i;
-
- clr_cmdbuf();
- drvcmd[0]=CMD0_PACKET;
- drvcmd[1]=response_count;
- if(famL_drive) flags_cmd_out=f_putcmd;
- else if (fam01_drive)
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- else if (fam2_drive) return (-1); /* not implemented yet */
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int convert_UPC(u_char *p)
-{
- int i;
-
- p++;
- if (fam0L_drive) p[13]=0;
- for (i=0;i<7;i++)
- {
- if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++);
- else if (fam0L_drive)
- {
- current_drive->UPC_buf[i]=((*p++)<<4)&0xFF;
- current_drive->UPC_buf[i] |= *p++;
- }
- else if (famT_drive)
- {
- return (-1);
- }
- else /* CD200 */
- {
- return (-1);
- }
- }
- current_drive->UPC_buf[6] &= 0xF0;
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadUPC(void)
-{
- int i;
-#if TEST_UPC
- int block, checksum;
-#endif /* TEST_UPC */
-
- if (fam2_drive) return (0); /* not implemented yet */
- if (famT_drive) return (0); /* not implemented yet */
- if (famV_drive) return (0); /* not implemented yet */
-#if 1
- if (fam0_drive) return (0); /* but it should work */
-#endif
-
- current_drive->diskstate_flags &= ~upc_bit;
-#if TEST_UPC
- for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++)
- {
-#endif /* TEST_UPC */
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_UPC;
-#if TEST_UPC
- drvcmd[1]=(block>>16)&0xFF;
- drvcmd[2]=(block>>8)&0xFF;
- drvcmd[3]=block&0xFF;
-#endif /* TEST_UPC */
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_READ_UPC;
-#if TEST_UPC
- drvcmd[2]=(block>>16)&0xFF;
- drvcmd[3]=(block>>8)&0xFF;
- drvcmd[4]=block&0xFF;
-#endif /* TEST_UPC */
- response_count=0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam2_drive)
- {
- return (-1);
- }
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
- return (i);
- }
- if (fam0L_drive)
- {
- response_count=16;
- if (famL_drive) flags_cmd_out=f_putcmd;
- i=cc_ReadPacket();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
- return (i);
- }
- }
-#if TEST_UPC
- checksum=0;
-#endif /* TEST_UPC */
- for (i=0;i<(fam1_drive?8:16);i++)
- {
-#if TEST_UPC
- checksum |= infobuf[i];
-#endif /* TEST_UPC */
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- }
- msgbuf[i*3]=0;
- msg(DBG_UPC,"UPC info:%s\n", msgbuf);
-#if TEST_UPC
- if ((checksum&0x7F)!=0) break;
- }
-#endif /* TEST_UPC */
- current_drive->UPC_ctl_adr=0;
- if (fam1_drive) i=0;
- else i=2;
- if ((infobuf[i]&0x80)!=0)
- {
- convert_UPC(&infobuf[i]);
- current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02;
- }
- for (i=0;i<7;i++)
- sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]);
- sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr);
- msgbuf[i*3+5]=0;
- msg(DBG_UPC,"UPC code:%s\n", msgbuf);
- current_drive->diskstate_flags |= upc_bit;
- return (0);
-}
-
-static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
- int i;
- unsigned char *mcnp = mcn->medium_catalog_number;
- unsigned char *resp;
-
- current_drive->diskstate_flags &= ~upc_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_UPC;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_READ_UPC;
- response_count=0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam2_drive)
- {
- return (-1);
- }
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
- return (i);
- }
- if (fam0L_drive)
- {
- response_count=16;
- if (famL_drive) flags_cmd_out=f_putcmd;
- i=cc_ReadPacket();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
- return (i);
- }
- }
- current_drive->UPC_ctl_adr=0;
- if (fam1_drive) i=0;
- else i=2;
-
- resp = infobuf + i;
- if (*resp++ == 0x80) {
- /* packed bcd to single ASCII digits */
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- }
- *mcnp = '\0';
-
- current_drive->diskstate_flags |= upc_bit;
- return (0);
-}
-
-/*==========================================================================*/
-static int cc_CheckMultiSession(void)
-{
- int i;
-
- if (fam2_drive) return (0);
- current_drive->f_multisession=0;
- current_drive->lba_multi=0;
- if (fam0_drive) return (0);
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_MULTISESS;
- response_count=6;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- i=cmd_out();
- if (i<0) return (i);
- if ((infobuf[0]&0x80)!=0)
- {
- current_drive->f_multisession=1;
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]),
- make16(infobuf[2],infobuf[3])));
- }
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_MULTISESS;
- drvcmd[1]=3;
- drvcmd[2]=1;
- response_count=8;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),
- make16(infobuf[6],infobuf[7])));
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=0;
- drvcmd[8]=response_count;
- drvcmd[9]=0x40;
- i=cmd_out();
- if (i<0) return (i);
- if (i<response_count) return (-100-i);
- current_drive->first_session=infobuf[2];
- current_drive->last_session=infobuf[3];
- current_drive->track_of_last_session=infobuf[6];
- if (current_drive->first_session!=current_drive->last_session)
- {
- current_drive->f_multisession=1;
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11])));
- }
- }
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi);
- if (current_drive->lba_multi>200)
- {
- current_drive->f_multisession=1;
- msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi);
- }
- return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-static int cc_SubChanInfo(int frame, int count, u_char *buffer)
- /* "frame" is a RED BOOK (msf-bin) address */
-{
- int i;
-
- if (fam0LV_drive) return (-ENOSYS); /* drive firmware lacks it */
- if (famT_drive)
- {
- return (-1);
- }
-#if 0
- if (current_drive->audio_state!=audio_playing) return (-ENODATA);
-#endif
- clr_cmdbuf();
- drvcmd[0]=CMD1_SUBCHANINF;
- drvcmd[1]=(frame>>16)&0xFF;
- drvcmd[2]=(frame>>8)&0xFF;
- drvcmd[3]=frame&0xFF;
- drvcmd[5]=(count>>8)&0xFF;
- drvcmd[6]=count&0xFF;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- cmd_type=READ_SC;
- current_drive->frame_size=CD_FRAMESIZE_SUB;
- i=cmd_out(); /* which buffer to use? */
- return (i);
-}
-#endif /* FUTURE */
-/*==========================================================================*/
-static void __init check_datarate(void)
-{
- int i=0;
-
- msg(DBG_IOX,"check_datarate entered.\n");
- datarate=0;
-#if TEST_STI
- for (i=0;i<=1000;i++) printk(".");
-#endif
- /* set a timer to make (timed_out_delay!=0) after 1.1 seconds */
-#if 1
- del_timer(&delay_timer);
-#endif
- delay_timer.expires=jiffies+11*HZ/10;
- timed_out_delay=0;
- add_timer(&delay_timer);
-#if 0
- msg(DBG_TIM,"delay timer started (11*HZ/10).\n");
-#endif
- do
- {
- i=inb(CDi_status);
- datarate++;
-#if 1
- if (datarate>0x6FFFFFFF) break;
-#endif
- }
- while (!timed_out_delay);
- del_timer(&delay_timer);
-#if 0
- msg(DBG_TIM,"datarate: %04X\n", datarate);
-#endif
- if (datarate<65536) datarate=65536;
- maxtim16=datarate*16;
- maxtim04=datarate*4;
- maxtim02=datarate*2;
- maxtim_8=datarate/32;
-#if LONG_TIMING
- maxtim_data=datarate/100;
-#else
- maxtim_data=datarate/300;
-#endif /* LONG_TIMING */
-#if 0
- msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", maxtim_8, maxtim_data);
-#endif
-}
-/*==========================================================================*/
-#if 0
-static int c2_ReadError(int fam)
-{
- int i;
-
- clr_cmdbuf();
- response_count=9;
- clr_respo_buf(9);
- if (fam==1)
- {
- drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
- i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus);
- }
- else if (fam==2)
- {
- drvcmd[0]=CMD2_READ_ERR;
- i=do_cmd(f_putcmd);
- }
- else return (-1);
- return (i);
-}
-#endif
-/*==========================================================================*/
-static void __init ask_mail(void)
-{
- int i;
-
- msg(DBG_INF, "please mail the following lines to emoenke@gwdg.de\n");
- msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n");
- msg(DBG_INF, "%s\n", VERSION);
- msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n",
- CDo_command, type, current_drive->drive_model, current_drive->drv_id);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_INF,"infobuf =%s\n", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_INF,"infobuf =%s\n", msgbuf);
-}
-/*==========================================================================*/
-static int __init check_version(void)
-{
- int i, j, l;
- int teac_possible=0;
-
- msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S);
- current_drive->drv_type=0;
-
- /* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */
- /* clear any pending error state */
- clr_cmdbuf();
- drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
- response_count=9;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD0_READ_ERR returns %d (ok anyway).\n",i);
- /* read drive version */
- clr_cmdbuf();
- for (i=0;i<12;i++) infobuf[i]=0;
- drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */
- response_count=12; /* fam1: only 11 */
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %d\n",i);
- if (i==-11) teac_possible++;
- j=0;
- for (i=0;i<12;i++) j+=infobuf[i];
- if (j)
- {
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"infobuf =%s\n", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"infobuf =%s\n", msgbuf);
- }
- for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break;
- if (i==4)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='R';
- current_drive->drive_model[2]='-';
- current_drive->drive_model[3]='5';
- current_drive->drive_model[4]=infobuf[i++];
- current_drive->drive_model[5]=infobuf[i++];
- current_drive->drive_model[6]=0;
- current_drive->drv_type=drv_fam1;
- }
- if (!current_drive->drv_type)
- {
- for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break;
- if (i==8)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='R';
- current_drive->drive_model[2]='-';
- current_drive->drive_model[3]='5';
- current_drive->drive_model[4]='2';
- current_drive->drive_model[5]='x';
- current_drive->drive_model[6]=0;
- current_drive->drv_type=drv_fam0;
- }
- }
- if (!current_drive->drv_type)
- {
- for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break;
- if (i==8)
- {
- for (j=0;j<8;j++)
- current_drive->drive_model[j]=infobuf[j];
- current_drive->drive_model[8]=0;
- current_drive->drv_type=drv_famL;
- }
- }
- if (!current_drive->drv_type)
- {
- for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break;
- if (i==6)
- {
- for (j=0;j<6;j++)
- current_drive->drive_model[j]=infobuf[j];
- current_drive->drive_model[6]=0;
- current_drive->drv_type=drv_famV;
- i+=2; /* 2 blanks before version */
- }
- }
- if (!current_drive->drv_type)
- {
- /* check for CD200 */
- clr_cmdbuf();
- drvcmd[0]=CMD2_READ_ERR;
- response_count=9;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).\n",i);
- if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).\n",i);
- /* read drive version */
- clr_cmdbuf();
- for (i=0;i<12;i++) infobuf[i]=0;
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-#if 0
- OUT(CDo_reset,0);
- sbp_sleep(6*HZ);
- OUT(CDo_enable,current_drive->drv_sel);
-#endif
- drvcmd[0]=CMD2_READ_VER;
- response_count=12;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %d\n",i);
- if (i==-7) teac_possible++;
- j=0;
- for (i=0;i<12;i++) j+=infobuf[i];
- if (j)
- {
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_IDX,"infobuf =%s\n", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_IDX,"infobuf =%s\n", msgbuf);
- }
- if (i>=0)
- {
- for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break;
- if (i==5)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='D';
- current_drive->drive_model[2]='2';
- current_drive->drive_model[3]='0';
- current_drive->drive_model[4]='0';
- current_drive->drive_model[5]=infobuf[i++];
- current_drive->drive_model[6]=infobuf[i++];
- current_drive->drive_model[7]=0;
- current_drive->drv_type=drv_fam2;
- }
- }
- }
- if (!current_drive->drv_type)
- {
- /* check for TEAC CD-55A */
- msg(DBG_TEA,"teac_possible: %d\n",teac_possible);
- for (j=1;j<=((current_drive->drv_id==0)?3:1);j++)
- {
- for (l=1;l<=((current_drive->drv_id==0)?10:1);l++)
- {
- msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l);
- if (sbpro_type==1) OUT(CDo_reset,0);
- else
- {
- OUT(CDo_enable,current_drive->drv_sel);
- OUT(CDo_sel_i_d,0);
- OUT(CDo_command,CMDT_RESET);
- for (i=0;i<9;i++) OUT(CDo_command,0);
- }
- sbp_sleep(5*HZ/10);
- OUT(CDo_enable,current_drive->drv_sel);
- OUT(CDo_sel_i_d,0);
- i=inb(CDi_status);
- msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i);
-#if 0
- if (i&s_not_result_ready) continue; /* drive not present or ready */
-#endif
- i=inb(CDi_info);
- msg(DBG_TEA,"TEAC CDi_info: %02X.\n",i);
- if (i==0x55) break; /* drive found */
- }
- if (i==0x55) break; /* drive found */
- }
- if (i==0x55) /* drive found */
- {
- msg(DBG_TEA,"TEAC drive found.\n");
- clr_cmdbuf();
- flags_cmd_out=f_putcmd;
- response_count=12;
- drvcmd[0]=CMDT_READ_VER;
- drvcmd[4]=response_count;
- for (i=0;i<12;i++) infobuf[i]=0;
- i=cmd_out_T();
- if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.\n",i);
- for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break;
- if (i==6)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='D';
- current_drive->drive_model[2]='-';
- current_drive->drive_model[3]='5';
- current_drive->drive_model[4]='5';
- current_drive->drive_model[5]=0;
- current_drive->drv_type=drv_famT;
- }
- }
- }
- if (!current_drive->drv_type)
- {
- msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id);
- return (-522);
- }
- for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j];
- if (famL_drive)
- {
- u_char lcs_firm_e1[]="A E1";
- u_char lcs_firm_f4[]="A4F4";
-
- for (j=0;j<4;j++)
- if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break;
- if (j==4) current_drive->drv_type=drv_e1;
-
- for (j=0;j<4;j++)
- if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break;
- if (j==4) current_drive->drv_type=drv_f4;
-
- if (current_drive->drv_type==drv_famL) ask_mail();
- }
- else if (famT_drive)
- {
- j=infobuf[4]; /* one-byte version??? - here: 0x15 */
- if (j=='5')
- {
- current_drive->firmware_version[0]=infobuf[7];
- current_drive->firmware_version[1]=infobuf[8];
- current_drive->firmware_version[2]=infobuf[10];
- current_drive->firmware_version[3]=infobuf[11];
- }
- else
- {
- if (j!=0x15) ask_mail();
- current_drive->firmware_version[0]='0';
- current_drive->firmware_version[1]='.';
- current_drive->firmware_version[2]='0'+(j>>4);
- current_drive->firmware_version[3]='0'+(j&0x0f);
- }
- }
- else /* CR-52x, CR-56x, CD200, ECS-AT */
- {
- j = (current_drive->firmware_version[0] & 0x0F) * 100 +
- (current_drive->firmware_version[2] & 0x0F) *10 +
- (current_drive->firmware_version[3] & 0x0F);
- if (fam0_drive)
- {
- if (j<200) current_drive->drv_type=drv_199;
- else if (j<201) current_drive->drv_type=drv_200;
- else if (j<210) current_drive->drv_type=drv_201;
- else if (j<211) current_drive->drv_type=drv_210;
- else if (j<300) current_drive->drv_type=drv_211;
- else if (j>=300) current_drive->drv_type=drv_300;
- }
- else if (fam1_drive)
- {
- if (j<100) current_drive->drv_type=drv_099;
- else
- {
- current_drive->drv_type=drv_100;
- if ((j!=500)&&(j!=102)) ask_mail();
- }
- }
- else if (fam2_drive)
- {
- if (current_drive->drive_model[5]=='F')
- {
- if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210))
- ask_mail(); /* unknown version at time */
- }
- else
- {
- msg(DBG_INF,"this CD200 drive is not fully supported yet - only audio will work.\n");
- if ((j!=101)&&(j!=35))
- ask_mail(); /* unknown version at time */
- }
- }
- else if (famV_drive)
- {
- if ((j==100)||(j==150)) current_drive->drv_type=drv_at;
- ask_mail(); /* hopefully we get some feedback by this */
- }
- }
- msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type);
- msg(DBG_INI,"check_version done.\n");
- return (0);
-}
-/*==========================================================================*/
-static void switch_drive(struct sbpcd_drive *p)
-{
- current_drive = p;
- OUT(CDo_enable,current_drive->drv_sel);
- msg(DBG_DID,"drive %d (ID=%d) activated.\n",
- current_drive - D_S, current_drive->drv_id);
- return;
-}
-/*==========================================================================*/
-#ifdef PATH_CHECK
-/*
- * probe for the presence of an interface card
- */
-static int __init check_card(int port)
-{
-#undef N_RESPO
-#define N_RESPO 20
- int i, j, k;
- u_char response[N_RESPO];
- u_char save_port0;
- u_char save_port3;
-
- msg(DBG_INI,"check_card entered.\n");
- save_port0=inb(port+0);
- save_port3=inb(port+3);
-
- for (j=0;j<NR_SBPCD;j++)
- {
- OUT(port+3,j) ; /* enable drive #j */
- OUT(port+0,CMD0_PATH_CHECK);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=10000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
- OUT(port+0,CMD0_PATH_CHECK);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0xFF;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=10000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
-
- if (response[0]==0xAA)
- if (response[1]==0x55)
- return (0);
- }
- for (j=0;j<NR_SBPCD;j++)
- {
- OUT(port+3,j) ; /* enable drive #j */
- OUT(port+0,CMD2_READ_VER);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=1000000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
- OUT(port+0,CMD2_READ_VER);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0xFF;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=1000000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
- if (response[0]==0xAA)
- if (response[1]==0x55)
- return (0);
- }
- OUT(port+0,save_port0);
- OUT(port+3,save_port3);
- return (0); /* in any case - no real "function" at time */
-}
-#endif /* PATH_CHECK */
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * probe for the presence of drives on the selected controller
- */
-static int __init check_drives(void)
-{
- int i, j;
-
- msg(DBG_INI,"check_drives entered.\n");
- ndrives=0;
- for (j=0;j<max_drives;j++)
- {
- struct sbpcd_drive *p = D_S + ndrives;
- p->drv_id=j;
- if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1;
- else p->drv_sel=j;
- switch_drive(p);
- msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
- msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
- i=check_version();
- if (i<0) msg(DBG_INI,"check_version returns %d.\n",i);
- else
- {
- current_drive->drv_options=drv_pattern[j];
- if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150);
- msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n",
- current_drive - D_S,
- current_drive->drv_id,
- current_drive->drive_model,
- current_drive->firmware_version,
- CDo_command,
- sbpro_type);
- ndrives++;
- }
- }
- for (j=ndrives;j<NR_SBPCD;j++) D_S[j].drv_id=-1;
- if (ndrives==0) return (-1);
- return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- * obtain if requested service disturbs current audio state
- */
-static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc)
-{
- switch (audio_state) /* audio status from controller */
- {
- case aud_11: /* "audio play in progress" */
- case audx11:
- switch (func) /* DOS command code */
- {
- case cmd_07: /* input flush */
- case cmd_0d: /* open device */
- case cmd_0e: /* close device */
- case cmd_0c: /* ioctl output */
- return (1);
- case cmd_03: /* ioctl input */
- switch (subfunc)
- /* DOS ioctl input subfunction */
- {
- case cxi_00:
- case cxi_06:
- case cxi_09:
- return (1);
- default:
- return (ERROR15);
- }
- return (1);
- default:
- return (ERROR15);
- }
- return (1);
- case aud_12: /* "audio play paused" */
- case audx12:
- return (1);
- default:
- return (2);
- }
-}
-/*==========================================================================*/
-/* allowed is only
- * ioctl_o, flush_input, open_device, close_device,
- * tell_address, tell_volume, tell_capabiliti,
- * tell_framesize, tell_CD_changed, tell_audio_posi
- */
-static int check_allowed1(u_char func1, u_char func2)
-{
-#if 000
- if (func1==ioctl_o) return (0);
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1==audio_pause) return (-1);
- if (func1==audio_resume) return (-1);
- if (func1!=ioctl_i) return (0);
- if (func2==tell_SubQ_run_tot) return (-1);
- if (func2==tell_cdsize) return (-1);
- if (func2==tell_TocDescrip) return (-1);
- if (func2==tell_TocEntry) return (-1);
- if (func2==tell_subQ_info) return (-1);
- if (fam1_drive) if (func2==tell_SubChanInfo) return (-1);
- if (func2==tell_UPC) return (-1);
-#else
- return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed2(u_char func1, u_char func2)
-{
-#if 000
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1!=ioctl_o) return (0);
- if (fam1_drive)
- {
- if (func2==EjectDisk) return (-1);
- if (func2==CloseTray) return (-1);
- }
-#else
- return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed3(u_char func1, u_char func2)
-{
-#if 000
- if (func1==ioctl_i)
- {
- if (func2==tell_address) return (0);
- if (func2==tell_capabiliti) return (0);
- if (func2==tell_CD_changed) return (0);
- if (fam0L_drive) if (func2==tell_SubChanInfo) return (0);
- return (-1);
- }
- if (func1==ioctl_o)
- {
- if (func2==DriveReset) return (0);
- if (fam0L_drive)
- {
- if (func2==EjectDisk) return (0);
- if (func2==LockDoor) return (0);
- if (func2==CloseTray) return (0);
- }
- return (-1);
- }
- if (func1==flush_input) return (-1);
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1==audio_pause) return (-1);
- if (func1==audio_resume) return (-1);
-#else
- return (0);
-#endif
-}
-/*==========================================================================*/
-static int seek_pos_audio_end(void)
-{
- int i;
-
- i=msf2blk(current_drive->pos_audio_end)-1;
- if (i<0) return (-1);
- i=cc_Seek(i,0);
- return (i);
-}
-#endif /* FUTURE */
-/*==========================================================================*/
-static int ReadToC(void)
-{
- int i, j;
- current_drive->diskstate_flags &= ~toc_bit;
- current_drive->ored_ctl_adr=0;
- /* special handling of CD-I HE */
- if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) ||
- current_drive->xa_byte == 0x10)
- {
- current_drive->TocBuffer[1].nixbyte=0;
- current_drive->TocBuffer[1].ctl_adr=0x40;
- current_drive->TocBuffer[1].number=1;
- current_drive->TocBuffer[1].format=0;
- current_drive->TocBuffer[1].address=blk2msf(0);
- current_drive->ored_ctl_adr |= 0x40;
- current_drive->n_first_track = 1;
- current_drive->n_last_track = 1;
- current_drive->xa_byte = 0x10;
- j = 2;
- } else
- for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++)
- {
- i=cc_ReadTocEntry(j);
- if (i<0)
- {
- msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i);
- return (i);
- }
- current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte;
- current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr;
- current_drive->TocBuffer[j].number=current_drive->TocEnt_number;
- current_drive->TocBuffer[j].format=current_drive->TocEnt_format;
- current_drive->TocBuffer[j].address=current_drive->TocEnt_address;
- current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr;
- }
- /* fake entry for LeadOut Track */
- current_drive->TocBuffer[j].nixbyte=0;
- current_drive->TocBuffer[j].ctl_adr=0;
- current_drive->TocBuffer[j].number=CDROM_LEADOUT;
- current_drive->TocBuffer[j].format=0;
- current_drive->TocBuffer[j].address=current_drive->size_msf;
-
- current_drive->diskstate_flags |= toc_bit;
- return (0);
-}
-/*==========================================================================*/
-static int DiskInfo(void)
-{
- int i, j;
-
- current_drive->mode=READ_M1;
-
-#undef LOOP_COUNT
-#define LOOP_COUNT 10 /* needed for some "old" drives */
-
- msg(DBG_000,"DiskInfo entered.\n");
- for (j=1;j<LOOP_COUNT;j++)
- {
-#if 0
- i=SetSpeed();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: SetSpeed returns %d\n", i);
- continue;
- }
- i=cc_ModeSense();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_ModeSense returns %d\n", i);
- continue;
- }
-#endif
- i=cc_ReadCapacity();
- if (i>=0) break;
- msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i);
-#if 0
- i=cc_DriveReset();
-#endif
- if (!fam0_drive && j == 2) break;
- }
- if (j==LOOP_COUNT) return (-33); /* give up */
-
- i=cc_ReadTocDescr();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: ReadTocDescr returns %d\n", i);
- return (i);
- }
- i=ReadToC();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: ReadToC returns %d\n", i);
- return (i);
- }
- i=cc_CheckMultiSession();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i);
- return (i);
- }
- if (current_drive->f_multisession) current_drive->sbp_bufsiz=1; /* possibly a weird PhotoCD */
- else current_drive->sbp_bufsiz=buffers;
- i=cc_ReadTocEntry(current_drive->n_first_track);
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i);
- return (i);
- }
- i=cc_ReadUPC();
- if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i);
- if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10))
- {
- /* XA disk with old drive */
- cc_ModeSelect(CD_FRAMESIZE_RAW1);
- cc_ModeSense();
- }
- if (famT_drive) cc_prep_mode_T();
- msg(DBG_000,"DiskInfo done.\n");
- return (0);
-}
-
-static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- struct sbpcd_drive *p = cdi->handle;
- int st;
-
- if (CDSL_CURRENT != slot_nr) {
- /* we have no changer support */
- return -EINVAL;
- }
-
- cc_ReadStatus();
- st=ResponseStatus();
- if (st<0)
- {
- msg(DBG_INF,"sbpcd_drive_status: timeout.\n");
- return (0);
- }
- msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
- msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
- msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
- msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
- msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
- msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
-
-#if 0
- if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN;
- if (p->status_bits & p_disk_ok) return CDS_DISC_OK;
- if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
-
- return CDS_NO_DISC;
-#else
- if (p->status_bits & p_spinning) return CDS_DISC_OK;
-/* return CDS_TRAY_OPEN; */
- return CDS_NO_DISC;
-
-#endif
-
-}
-
-
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- * called always if driver gets entered
- * returns 0 or ERROR2 or ERROR15
- */
-static int prepare(u_char func, u_char subfunc)
-{
- int i;
-
- if (fam0L_drive)
- {
- i=inb(CDi_status);
- if (i&s_attention) GetStatus();
- }
- else if (fam1_drive) GetStatus();
- else if (fam2_drive) GetStatus();
- else if (famT_drive) GetStatus();
- if (current_drive->CD_changed==0xFF)
- {
- current_drive->diskstate_flags=0;
- current_drive->audio_state=0;
- if (!st_diskok)
- {
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- else
- {
- i=check_allowed3(func,subfunc);
- if (i<0)
- {
- current_drive->CD_changed=1;
- return (-15);
- }
- }
- }
- else
- {
- if (!st_diskok)
- {
- current_drive->diskstate_flags=0;
- current_drive->audio_state=0;
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- else
- {
- if (st_busy)
- {
- if (current_drive->audio_state!=audio_pausing)
- {
- i=check_allowed2(func,subfunc);
- if (i<0) return (-2);
- }
- }
- else
- {
- if (current_drive->audio_state==audio_playing) seek_pos_audio_end();
- current_drive->audio_state=0;
- }
- if (!frame_size_valid)
- {
- i=DiskInfo();
- if (i<0)
- {
- current_drive->diskstate_flags=0;
- current_drive->audio_state=0;
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- }
- }
- }
- return (0);
-}
-#endif /* FUTURE */
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * Check the results of the "get status" command.
- */
-static int sbp_status(void)
-{
- int st;
-
- st=ResponseStatus();
- if (st<0)
- {
- msg(DBG_INF,"sbp_status: timeout.\n");
- return (0);
- }
-
- if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n");
-
- if (st_check)
- {
- msg(DBG_INF,"st_check detected - retrying.\n");
- return (0);
- }
- if (!st_door_closed)
- {
- msg(DBG_INF,"door is open - retrying.\n");
- return (0);
- }
- if (!st_caddy_in)
- {
- msg(DBG_INF,"disk removed - retrying.\n");
- return (0);
- }
- if (!st_diskok)
- {
- msg(DBG_INF,"!st_diskok detected - retrying.\n");
- return (0);
- }
- if (st_busy)
- {
- msg(DBG_INF,"st_busy detected - retrying.\n");
- return (0);
- }
- return (1);
-}
-/*==========================================================================*/
-
-static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
-{
- struct sbpcd_drive *p = cdi->handle;
- ms_infp->addr_format = CDROM_LBA;
- ms_infp->addr.lba = p->lba_multi;
- if (p->f_multisession)
- ms_infp->xa_flag=1; /* valid redirection address */
- else
- ms_infp->xa_flag=0; /* invalid redirection address */
-
- return 0;
-}
-
-static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
- void * arg)
-{
- struct sbpcd_drive *p = cdi->handle;
- int i, st, j;
-
- msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg);
- if (p->drv_id==-1) {
- msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
- return (-ENXIO); /* no such drive */
- }
- down(&ioctl_read_sem);
- if (p != current_drive)
- switch_drive(p);
-
- msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
- switch (cmd) /* Sun-compatible */
- {
-
- case CDROMPAUSE: /* Pause the drive */
- msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
- /* pause the drive unit when it is currently in PLAY mode, */
- /* or reset the starting and ending locations when in PAUSED mode. */
- /* If applicable, at the next stopping point it reaches */
- /* the drive will discontinue playing. */
- switch (current_drive->audio_state)
- {
- case audio_playing:
- if (famL_drive) i=cc_ReadSubQ();
- else i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- if (famL_drive) i=cc_Pause_Resume(1);
- else i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- current_drive->pos_audio_start=current_drive->SubQ_run_tot;
- current_drive->audio_state=audio_pausing;
- RETURN_UP(0);
- case audio_pausing:
- i=cc_Seek(current_drive->pos_audio_start,1);
- if (i<0) RETURN_UP(-EIO);
- RETURN_UP(0);
- default:
- RETURN_UP(-EINVAL);
- }
-
- case CDROMRESUME: /* resume paused audio play */
- msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n");
- /* resume playing audio tracks when a previous PLAY AUDIO call has */
- /* been paused with a PAUSE command. */
- /* It will resume playing from the location saved in SubQ_run_tot. */
- if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL);
- if (famL_drive)
- i=cc_PlayAudio(current_drive->pos_audio_start,
- current_drive->pos_audio_end);
- else i=cc_Pause_Resume(3);
- if (i<0) RETURN_UP(-EIO);
- current_drive->audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYMSF:
- msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- if (current_drive->audio_state==audio_playing)
- {
- i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- current_drive->pos_audio_start=current_drive->SubQ_run_tot;
- i=cc_Seek(current_drive->pos_audio_start,1);
- }
- memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
- /* values come as msf-bin */
- current_drive->pos_audio_start = (msf.cdmsf_min0<<16) |
- (msf.cdmsf_sec0<<8) |
- msf.cdmsf_frame0;
- current_drive->pos_audio_end = (msf.cdmsf_min1<<16) |
- (msf.cdmsf_sec1<<8) |
- msf.cdmsf_frame1;
- msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
- current_drive->pos_audio_start,current_drive->pos_audio_end);
- i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
- DriveReset();
- current_drive->audio_state=0;
- RETURN_UP(-EIO);
- }
- current_drive->audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- if (current_drive->audio_state==audio_playing)
- {
- msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
-#if 1
- RETURN_UP(0); /* just let us play on */
-#else
- RETURN_UP(-EINVAL); /* play on, but say "error" */
-#endif
- }
- memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
- msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
- ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
- if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
- if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track;
- current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address;
- current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address;
- i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
- DriveReset();
- current_drive->audio_state=0;
- RETURN_UP(-EIO);
- }
- current_drive->audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
- tochdr.cdth_trk0=current_drive->n_first_track;
- tochdr.cdth_trk1=current_drive->n_last_track;
- memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
- RETURN_UP(0);
-
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
- memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
- i=tocentry.cdte_track;
- if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1;
- else if (i<current_drive->n_first_track||i>current_drive->n_last_track)
- RETURN_UP(-EINVAL);
- tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F;
- tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F;
- tocentry.cdte_datamode=current_drive->TocBuffer[i].format;
- if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
- {
- tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
- tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
- tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
- }
- else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
- tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
- else RETURN_UP(-EINVAL);
- memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
- RETURN_UP(0);
-
- case CDROMSTOP: /* Spin down the drive */
- msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- i=cc_Pause_Resume(1);
- current_drive->audio_state=0;
-#if 0
- cc_DriveReset();
-#endif
- RETURN_UP(i);
-
- case CDROMSTART: /* Spin up the drive */
- msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
- cc_SpinUp();
- current_drive->audio_state=0;
- RETURN_UP(0);
-
- case CDROMVOLCTRL: /* Volume control */
- msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
- memcpy(&volctrl,(char *) arg,sizeof(volctrl));
- current_drive->vol_chan0=0;
- current_drive->vol_ctrl0=volctrl.channel0;
- current_drive->vol_chan1=1;
- current_drive->vol_ctrl1=volctrl.channel1;
- i=cc_SetVolume();
- RETURN_UP(0);
-
- case CDROMVOLREAD: /* read Volume settings from drive */
- msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
- st=cc_GetVolume();
- if (st<0) RETURN_UP(st);
- volctrl.channel0=current_drive->vol_ctrl0;
- volctrl.channel1=current_drive->vol_ctrl1;
- volctrl.channel2=0;
- volctrl.channel2=0;
- memcpy((void *)arg,&volctrl,sizeof(volctrl));
- RETURN_UP(0);
-
- case CDROMSUBCHNL: /* Get subchannel info */
- msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
- /* Bogus, I can do better than this! --AJK
- if ((st_spinning)||(!subq_valid)) {
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- }
- */
- i=cc_ReadSubQ();
- if (i<0) {
- j=cc_ReadError(); /* clear out error status from drive */
- current_drive->audio_state=CDROM_AUDIO_NO_STATUS;
- /* get and set the disk state here,
- probably not the right place, but who cares!
- It makes it work properly! --AJK */
- if (current_drive->CD_changed==0xFF) {
- msg(DBG_000,"Disk changed detect\n");
- current_drive->diskstate_flags &= ~cd_size_bit;
- }
- RETURN_UP(-EIO);
- }
- if (current_drive->CD_changed==0xFF) {
- /* reread the TOC because the disk has changed! --AJK */
- msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n");
- i=DiskInfo();
- if(i==0) {
- current_drive->CD_changed=0x00; /* cd has changed, procede, */
- RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
- } else {
- RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
- }
- }
- memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
- /*
- This virtual crap is very bogus!
- It doesn't detect when the cd is done playing audio!
- Lets do this right with proper hardware register reading!
- */
- cc_ReadStatus();
- i=ResponseStatus();
- msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
- msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
- msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
- msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
- msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
- msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
- /* st_busy indicates if it's _ACTUALLY_ playing audio */
- switch (current_drive->audio_state)
- {
- case audio_playing:
- if(st_busy==0) {
- /* CD has stopped playing audio --AJK */
- current_drive->audio_state=audio_completed;
- SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
- } else {
- SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
- }
- break;
- case audio_pausing:
- SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
- break;
- case audio_completed:
- SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
- break;
- default:
- SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
- break;
- }
- SC.cdsc_adr=current_drive->SubQ_ctl_adr;
- SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4;
- SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk);
- SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx);
- if (SC.cdsc_format==CDROM_LBA)
- {
- SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot);
- SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk);
- }
- else /* not only if (SC.cdsc_format==CDROM_MSF) */
- {
- SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF;
- SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF;
- SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF;
- SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF;
- SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF;
- SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF;
- }
- memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl));
- msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
- SC.cdsc_format,SC.cdsc_audiostatus,
- SC.cdsc_adr,SC.cdsc_ctrl,
- SC.cdsc_trk,SC.cdsc_ind,
- SC.cdsc_absaddr,SC.cdsc_reladdr);
- RETURN_UP(0);
-
- default:
- msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
- RETURN_UP(-EINVAL);
- } /* end switch(cmd) */
-}
-/*==========================================================================*/
-/*
- * Take care of the different block sizes between cdrom and Linux.
- */
-static void sbp_transfer(struct request *req)
-{
- long offs;
-
- while ( (req->nr_sectors > 0) &&
- (req->sector/4 >= current_drive->sbp_first_frame) &&
- (req->sector/4 <= current_drive->sbp_last_frame) )
- {
- offs = (req->sector - current_drive->sbp_first_frame * 4) * 512;
- memcpy(req->buffer, current_drive->sbp_buf + offs, 512);
- req->nr_sectors--;
- req->sector++;
- req->buffer += 512;
- }
-}
-/*==========================================================================*/
-/*
- * special end_request for sbpcd to solve CURRENT==NULL bug. (GTL)
- * GTL = Gonzalo Tornaria <tornaria@cmat.edu.uy>
- *
- * This is a kludge so we don't need to modify end_request.
- * We put the req we take out after INIT_REQUEST in the requests list,
- * so that end_request will discard it.
- *
- * The bug could be present in other block devices, perhaps we
- * should modify INIT_REQUEST and end_request instead, and
- * change every block device..
- *
- * Could be a race here?? Could e.g. a timer interrupt schedule() us?
- * If so, we should copy end_request here, and do it right.. (or
- * modify end_request and the block devices).
- *
- * In any case, the race here would be much small than it was, and
- * I couldn't reproduce..
- *
- * The race could be: suppose CURRENT==NULL. We put our req in the list,
- * and we are scheduled. Other process takes over, and gets into
- * do_sbpcd_request. It sees CURRENT!=NULL (it is == to our req), so
- * proceeds. It ends, so CURRENT is now NULL.. Now we awake somewhere in
- * end_request, but now CURRENT==NULL... oops!
- *
- */
-#undef DEBUG_GTL
-
-/*==========================================================================*/
-/*
- * I/O request routine, called from Linux kernel.
- */
-static void do_sbpcd_request(request_queue_t * q)
-{
- u_int block;
- u_int nsect;
- int status_tries, data_tries;
- struct request *req;
- struct sbpcd_drive *p;
-#ifdef DEBUG_GTL
- static int xx_nr=0;
- int xnr;
-#endif
-
- request_loop:
-#ifdef DEBUG_GTL
- xnr=++xx_nr;
-
- req = elv_next_request(q);
-
- if (!req)
- {
- printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
- xnr, current->pid, jiffies);
- printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n",
- xnr, jiffies);
- return;
- }
-
- printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, current->pid, jiffies);
-#endif
-
- req = elv_next_request(q); /* take out our request so no other */
- if (!req)
- return;
-
- if (req -> sector == -1)
- end_request(req, 0);
- spin_unlock_irq(q->queue_lock);
-
- down(&ioctl_read_sem);
- if (rq_data_dir(elv_next_request(q)) != READ)
- {
- msg(DBG_INF, "bad cmd %d\n", req->cmd[0]);
- goto err_done;
- }
- p = req->rq_disk->private_data;
-#if OLD_BUSY
- while (busy_audio) sbp_sleep(HZ); /* wait a bit */
- busy_data=1;
-#endif /* OLD_BUSY */
-
- if (p->audio_state==audio_playing) goto err_done;
- if (p != current_drive)
- switch_drive(p);
-
- block = req->sector; /* always numbered as 512-byte-pieces */
- nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
-
- msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect);
-#if 0
- msg(DBG_MUL,"read LBA %d\n", block/4);
-#endif
-
- sbp_transfer(req);
- /* if we satisfied the request from the buffer, we're done. */
- if (req->nr_sectors == 0)
- {
-#ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
- up(&ioctl_read_sem);
- spin_lock_irq(q->queue_lock);
- end_request(req, 1);
- goto request_loop;
- }
-
-#ifdef FUTURE
- i=prepare(0,0); /* at moment not really a hassle check, but ... */
- if (i!=0)
- msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i);
-#endif /* FUTURE */
-
- if (!st_spinning) cc_SpinUp();
-
- for (data_tries=n_retries; data_tries > 0; data_tries--)
- {
- for (status_tries=3; status_tries > 0; status_tries--)
- {
- flags_cmd_out |= f_respo3;
- cc_ReadStatus();
- if (sbp_status() != 0) break;
- if (st_check) cc_ReadError();
- sbp_sleep(1); /* wait a bit, try again */
- }
- if (status_tries == 0)
- {
- msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
- break;
- }
-
- sbp_read_cmd(req);
- sbp_sleep(0);
- if (sbp_data(req) != 0)
- {
-#ifdef SAFE_MIXED
- current_drive->has_data=2; /* is really a data disk */
-#endif /* SAFE_MIXED */
-#ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
- up(&ioctl_read_sem);
- spin_lock_irq(q->queue_lock);
- end_request(req, 1);
- goto request_loop;
- }
- }
-
- err_done:
-#if OLD_BUSY
- busy_data=0;
-#endif /* OLD_BUSY */
-#ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
- up(&ioctl_read_sem);
- sbp_sleep(0); /* wait a bit, try again */
- spin_lock_irq(q->queue_lock);
- end_request(req, 0);
- goto request_loop;
-}
-/*==========================================================================*/
-/*
- * build and send the READ command.
- */
-static void sbp_read_cmd(struct request *req)
-{
-#undef OLD
-
- int i;
- int block;
-
- current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */
- current_drive->sbp_current = 0;
- block=req->sector/4;
- if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm)
- current_drive->sbp_read_frames = current_drive->sbp_bufsiz;
- else
- {
- current_drive->sbp_read_frames=current_drive->CDsize_frm-block;
- /* avoid reading past end of data */
- if (current_drive->sbp_read_frames < 1)
- {
- msg(DBG_INF,"requested frame %d, CD size %d ???\n",
- block, current_drive->CDsize_frm);
- current_drive->sbp_read_frames=1;
- }
- }
-
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
- clr_cmdbuf();
- if (famV_drive)
- {
- drvcmd[0]=CMDV_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
- bin2bcdx(&drvcmd[1]);
- bin2bcdx(&drvcmd[2]);
- bin2bcdx(&drvcmd[3]);
- drvcmd[4]=current_drive->sbp_read_frames>>8;
- drvcmd[5]=current_drive->sbp_read_frames&0xff;
- drvcmd[6]=0x02; /* flag "msf-bcd" */
- }
- else if (fam0L_drive)
- {
- flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
- if (current_drive->xa_byte==0x20)
- {
- cmd_type=READ_M2;
- drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
- drvcmd[1]=(block>>16)&0x0ff;
- drvcmd[2]=(block>>8)&0x0ff;
- drvcmd[3]=block&0x0ff;
- drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
- }
- else
- {
- drvcmd[0]=CMD0_READ; /* "read frames", old drives */
- if (current_drive->drv_type>=drv_201)
- {
- lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
- bin2bcdx(&drvcmd[1]);
- bin2bcdx(&drvcmd[2]);
- bin2bcdx(&drvcmd[3]);
- }
- else
- {
- drvcmd[1]=(block>>16)&0x0ff;
- drvcmd[2]=(block>>8)&0x0ff;
- drvcmd[3]=block&0x0ff;
- }
- drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
- drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
- }
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[6]=current_drive->sbp_read_frames&0x0ff;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
- drvcmd[6]=0x02;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_READ;
- drvcmd[2]=(block>>24)&0x0ff;
- drvcmd[3]=(block>>16)&0x0ff;
- drvcmd[4]=(block>>8)&0x0ff;
- drvcmd[5]=block&0x0ff;
- drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[8]=current_drive->sbp_read_frames&0x0ff;
- }
- flags_cmd_out=f_putcmd;
- response_count=0;
- i=cmd_out();
- if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i);
- return;
-}
-/*==========================================================================*/
-/*
- * Check the completion of the read-data command. On success, read
- * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer.
- */
-static int sbp_data(struct request *req)
-{
- int i=0, j=0, l, frame;
- u_int try=0;
- u_long timeout;
- u_char *p;
- u_int data_tries = 0;
- u_int data_waits = 0;
- u_int data_retrying = 0;
- int error_flag;
- int xa_count;
- int max_latency;
- int success;
- int wait;
- int duration;
-
- error_flag=0;
- success=0;
-#if LONG_TIMING
- max_latency=9*HZ;
-#else
- if (current_drive->f_multisession) max_latency=15*HZ;
- else max_latency=5*HZ;
-#endif
- duration=jiffies;
- for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++)
- {
- SBPCD_CLI;
-
- del_timer(&data_timer);
- data_timer.expires=jiffies+max_latency;
- timed_out_data=0;
- add_timer(&data_timer);
- while (!timed_out_data)
- {
- if (current_drive->f_multisession) try=maxtim_data*4;
- else try=maxtim_data;
- msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try);
- for ( ; try!=0;try--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (fam0LV_drive) if (j&s_attention) break;
- }
- if (!(j&s_not_data_ready)) goto data_ready;
- if (try==0)
- {
- if (data_retrying == 0) data_waits++;
- data_retrying = 1;
- msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n");
- sbp_sleep(1);
- try = 1;
- }
- }
- msg(DBG_INF,"sbp_data: CDi_status loop expired.\n");
- data_ready:
- del_timer(&data_timer);
-
- if (timed_out_data)
- {
- msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j);
- error_flag++;
- }
- if (try==0)
- {
- msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j);
- error_flag++;
- }
- if (!(j&s_not_result_ready))
- {
- msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j);
- response_count=20;
- j=ResponseInfo();
- j=inb(CDi_status);
- }
- if (j&s_not_data_ready)
- {
- if ((current_drive->ored_ctl_adr&0x40)==0)
- msg(DBG_INF, "CD contains no data tracks.\n");
- else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j);
- error_flag++;
- }
- SBPCD_STI;
- if (error_flag) break;
-
- msg(DBG_000, "sbp_data: beginning to read.\n");
- p = current_drive->sbp_buf + frame * CD_FRAMESIZE;
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- if (cmd_type==READ_M2) {
- if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1);
- else insb(CDi_data, xa_head_buf, CD_XA_HEAD);
- }
- if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1);
- else insb(CDi_data, p, CD_FRAMESIZE);
- if (cmd_type==READ_M2) {
- if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
- else insb(CDi_data, xa_tail_buf, CD_XA_TAIL);
- }
- current_drive->sbp_current++;
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- if (cmd_type==READ_M2)
- {
- for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++)
- sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]);
- msgbuf[xa_count*3]=0;
- msg(DBG_XA1,"xa head:%s\n", msgbuf);
- }
- data_retrying = 0;
- data_tries++;
- if (data_tries >= 1000)
- {
- msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries);
- data_waits = data_tries = 0;
- }
- }
- duration=jiffies-duration;
- msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration);
- if (famT_drive)
- {
- wait=8;
- do
- {
- if (teac==2)
- {
- if ((i=CDi_stat_loop_T()) == -1) break;
- }
- else
- {
- sbp_sleep(1);
- OUT(CDo_sel_i_d,0);
- i=inb(CDi_status);
- }
- if (!(i&s_not_data_ready))
- {
- OUT(CDo_sel_i_d,1);
- j=0;
- do
- {
- if (do_16bit) i=inw(CDi_data);
- else i=inb(CDi_data);
- j++;
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j);
- }
- if (!(i&s_not_result_ready))
- {
- OUT(CDo_sel_i_d,0);
- l=0;
- do
- {
- infobuf[l++]=inb(CDi_info);
- i=inb(CDi_status);
- }
- while (!(i&s_not_result_ready));
- if (infobuf[0]==0x00) success=1;
-#if 1
- for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf);
-#endif
- if (infobuf[0]==0x02)
- {
- error_flag++;
- do
- {
- ++recursion;
- if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion);
- else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n");
- clr_cmdbuf();
- drvcmd[0]=CMDT_READ_ERR;
- j=cmd_out_T(); /* !!! recursive here !!! */
- --recursion;
- sbp_sleep(1);
- }
- while (j<0);
- current_drive->error_state=infobuf[2];
- current_drive->b3=infobuf[3];
- current_drive->b4=infobuf[4];
- }
- break;
- }
- else
- {
-#if 0
- msg(DBG_TEA, "============= waiting for result=================.\n");
- sbp_sleep(1);
-#endif
- }
- }
- while (wait--);
- }
-
- if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
- {
- msg(DBG_TEA, "================error flag: %d=================.\n", error_flag);
- msg(DBG_INF,"sbp_data: read aborted by drive.\n");
-#if 1
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
-#else
- i=cc_ReadError();
-#endif
- return (0);
- }
-
- if (fam0LV_drive)
- {
- SBPCD_CLI;
- i=maxtim_data;
- for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (j&s_attention) break;
- }
- if (i != 0 || time_after_eq(jiffies, timeout)) break;
- sbp_sleep(0);
- i = 1;
- }
- if (i==0) msg(DBG_INF,"status timeout after READ.\n");
- if (!(j&s_attention))
- {
- msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n");
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- SBPCD_STI;
- return (0);
- }
- SBPCD_STI;
- }
-
-#if 0
- if (!success)
-#endif
- do
- {
- if (fam0LV_drive) cc_ReadStatus();
-#if 1
- if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
-#endif
- i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
-#if 1
- if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
-#endif
- if (i<0)
- {
- msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
- return (0);
- }
- }
- while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success)));
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i);
- return (0);
- }
- if (fatal_err)
- {
- fatal_err=0;
- current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */
- current_drive->sbp_current = 0;
- msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
- return (0);
- }
-
- current_drive->sbp_first_frame = req -> sector / 4;
- current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
- sbp_transfer(req);
- return (1);
-}
-/*==========================================================================*/
-
-static int sbpcd_block_open(struct inode *inode, struct file *file)
-{
- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_open(p->sbpcd_infop, inode, file);
-}
-
-static int sbpcd_block_release(struct inode *inode, struct file *file)
-{
- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_release(p->sbpcd_infop, file);
-}
-
-static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
- struct cdrom_device_info *cdi = p->sbpcd_infop;
- int ret, i;
-
- ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg);
- if (ret != -ENOSYS)
- return ret;
-
- msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg);
- if (p->drv_id==-1) {
- msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
- return (-ENXIO); /* no such drive */
- }
- down(&ioctl_read_sem);
- if (p != current_drive)
- switch_drive(p);
-
- msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
- switch (cmd) /* Sun-compatible */
- {
- case DDIOCSDBG: /* DDI Debug */
- if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
- i=sbpcd_dbg_ioctl(arg,1);
- RETURN_UP(i);
- case CDROMRESET: /* hard reset the drive */
- msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
- i=DriveReset();
- current_drive->audio_state=0;
- RETURN_UP(i);
-
- case CDROMREADMODE1:
- msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- cc_ModeSelect(CD_FRAMESIZE);
- cc_ModeSense();
- current_drive->mode=READ_M1;
- RETURN_UP(0);
-
- case CDROMREADMODE2: /* not usable at the moment */
- msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- cc_ModeSelect(CD_FRAMESIZE_RAW1);
- cc_ModeSense();
- current_drive->mode=READ_M2;
- RETURN_UP(0);
-
- case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
- msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
- if (current_drive->sbp_audsiz>0)
- vfree(current_drive->aud_buf);
- current_drive->aud_buf=NULL;
- current_drive->sbp_audsiz=arg;
-
- if (current_drive->sbp_audsiz>16)
- {
- current_drive->sbp_audsiz = 0;
- RETURN_UP(current_drive->sbp_audsiz);
- }
-
- if (current_drive->sbp_audsiz>0)
- {
- current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
- if (current_drive->aud_buf==NULL)
- {
- msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
- current_drive->sbp_audsiz=0;
- }
- else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
- }
- RETURN_UP(current_drive->sbp_audsiz);
-
- case CDROMREADAUDIO:
- { /* start of CDROMREADAUDIO */
- int i=0, j=0, frame, block=0;
- u_int try=0;
- u_long timeout;
- u_char *p;
- u_int data_tries = 0;
- u_int data_waits = 0;
- u_int data_retrying = 0;
- int status_tries;
- int error_flag;
-
- msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n");
- if (fam0_drive) RETURN_UP(-EINVAL);
- if (famL_drive) RETURN_UP(-EINVAL);
- if (famV_drive) RETURN_UP(-EINVAL);
- if (famT_drive) RETURN_UP(-EINVAL);
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL);
- if (copy_from_user(&read_audio, (void __user *)arg,
- sizeof(struct cdrom_read_audio)))
- RETURN_UP(-EFAULT);
- if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
- if (!access_ok(VERIFY_WRITE, read_audio.buf,
- read_audio.nframes*CD_FRAMESIZE_RAW))
- RETURN_UP(-EFAULT);
-
- if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
- block=msf2lba(&read_audio.addr.msf.minute);
- else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
- block=read_audio.addr.lba;
- else RETURN_UP(-EINVAL);
-#if 000
- i=cc_SetSpeed(speed_150,0,0);
- if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i);
-#endif
- msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
- block, blk2msf(block));
- msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
-#if OLD_BUSY
- while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
- busy_audio=1;
-#endif /* OLD_BUSY */
- error_flag=0;
- for (data_tries=5; data_tries>0; data_tries--)
- {
- msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
- current_drive->mode=READ_AU;
- cc_ModeSelect(CD_FRAMESIZE_RAW);
- cc_ModeSense();
- for (status_tries=3; status_tries > 0; status_tries--)
- {
- flags_cmd_out |= f_respo3;
- cc_ReadStatus();
- if (sbp_status() != 0) break;
- if (st_check) cc_ReadError();
- sbp_sleep(1); /* wait a bit, try again */
- }
- if (status_tries == 0)
- {
- msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
- continue;
- }
- msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
-
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
- if (fam0L_drive)
- {
- flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
- cmd_type=READ_M2;
- drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
- drvcmd[1]=(block>>16)&0x000000ff;
- drvcmd[2]=(block>>8)&0x000000ff;
- drvcmd[3]=block&0x000000ff;
- drvcmd[4]=0;
- drvcmd[5]=read_audio.nframes; /* # of frames */
- drvcmd[6]=0;
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ; /* "read frames", new drives */
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=0;
- drvcmd[5]=0;
- drvcmd[6]=read_audio.nframes; /* # of frames */
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ_XA2;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=0;
- drvcmd[5]=read_audio.nframes; /* # of frames */
- drvcmd[6]=0x11; /* raw mode */
- }
- else if (famT_drive) /* CD-55A: not tested yet */
- {
- }
- msg(DBG_AUD,"read_audio: before giving \"read\" command.\n");
- flags_cmd_out=f_putcmd;
- response_count=0;
- i=cmd_out();
- if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i);
- sbp_sleep(0);
- msg(DBG_AUD,"read_audio: after giving \"read\" command.\n");
- for (frame=1;frame<2 && !error_flag; frame++)
- {
- try=maxtim_data;
- for (timeout=jiffies+9*HZ; ; )
- {
- for ( ; try!=0;try--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (fam0L_drive) if (j&s_attention) break;
- }
- if (try != 0 || time_after_eq(jiffies, timeout)) break;
- if (data_retrying == 0) data_waits++;
- data_retrying = 1;
- sbp_sleep(1);
- try = 1;
- }
- if (try==0)
- {
- msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n");
- error_flag++;
- break;
- }
- msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n");
- if (j&s_not_data_ready)
- {
- msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n");
- error_flag++;
- break;
- }
- msg(DBG_AUD,"read_audio: before reading data.\n");
- error_flag=0;
- p = current_drive->aud_buf;
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- if (do_16bit)
- {
- u_short *p2 = (u_short *) p;
-
- for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
- {
- if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
- /* get one sample */
- *p2++ = inw_p(CDi_data);
- *p2++ = inw_p(CDi_data);
- }
- } else {
- for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
- {
- if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
- /* get one sample */
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- }
- }
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- data_retrying = 0;
- }
- msg(DBG_AUD,"read_audio: after reading data.\n");
- if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
- {
- msg(DBG_AUD,"read_audio: read aborted by drive\n");
-#if 0000
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
-#else
- i=cc_ReadError();
-#endif
- continue;
- }
- if (fam0L_drive)
- {
- i=maxtim_data;
- for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (j&s_attention) break;
- }
- if (i != 0 || time_after_eq(jiffies, timeout)) break;
- sbp_sleep(0);
- i = 1;
- }
- if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ");
- if (!(j&s_attention))
- {
- msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n");
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- continue;
- }
- }
- do
- {
- if (fam0L_drive) cc_ReadStatus();
- i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
- if (i<0) { msg(DBG_AUD,
- "read_audio: cc_ReadStatus error after read: %02X\n",
- current_drive->status_bits);
- continue; /* FIXME */
- }
- }
- while ((fam0L_drive)&&(!st_check)&&(!(i&p_success)));
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i);
- continue;
- }
- if (copy_to_user(read_audio.buf,
- current_drive->aud_buf,
- read_audio.nframes * CD_FRAMESIZE_RAW))
- RETURN_UP(-EFAULT);
- msg(DBG_AUD,"read_audio: copy_to_user done.\n");
- break;
- }
- cc_ModeSelect(CD_FRAMESIZE);
- cc_ModeSense();
- current_drive->mode=READ_M1;
-#if OLD_BUSY
- busy_audio=0;
-#endif /* OLD_BUSY */
- if (data_tries == 0)
- {
- msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
- RETURN_UP(-EIO);
- }
- msg(DBG_AUD,"read_audio: successful return.\n");
- RETURN_UP(0);
- } /* end of CDROMREADAUDIO */
-
- default:
- msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
- RETURN_UP(-EINVAL);
- } /* end switch(cmd) */
-}
-
-static int sbpcd_block_media_changed(struct gendisk *disk)
-{
- struct sbpcd_drive *p = disk->private_data;
- return cdrom_media_changed(p->sbpcd_infop);
-}
-
-static struct block_device_operations sbpcd_bdops =
-{
- .owner = THIS_MODULE,
- .open = sbpcd_block_open,
- .release = sbpcd_block_release,
- .ioctl = sbpcd_block_ioctl,
- .media_changed = sbpcd_block_media_changed,
-};
-/*==========================================================================*/
-/*
- * Open the device special file. Check that a disk is in. Read TOC.
- */
-static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
-{
- struct sbpcd_drive *p = cdi->handle;
-
- down(&ioctl_read_sem);
- switch_drive(p);
-
- /*
- * try to keep an "open" counter here and lock the door if 0->1.
- */
- msg(DBG_LCK,"open_count: %d -> %d\n",
- current_drive->open_count,current_drive->open_count+1);
- if (++current_drive->open_count<=1)
- {
- int i;
- i=LockDoor();
- current_drive->open_count=1;
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n");
- i=DiskInfo();
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n");
- if ((current_drive->ored_ctl_adr&0x40)==0)
- {
- msg(DBG_INF,"CD contains no data tracks.\n");
-#ifdef SAFE_MIXED
- current_drive->has_data=0;
-#endif /* SAFE_MIXED */
- }
-#ifdef SAFE_MIXED
- else if (current_drive->has_data<1) current_drive->has_data=1;
-#endif /* SAFE_MIXED */
- }
- if (!st_spinning) cc_SpinUp();
- RETURN_UP(0);
-}
-/*==========================================================================*/
-/*
- * On close, we flush all sbp blocks from the buffer cache.
- */
-static void sbpcd_release(struct cdrom_device_info * cdi)
-{
- struct sbpcd_drive *p = cdi->handle;
-
- if (p->drv_id==-1) {
- msg(DBG_INF, "release: bad device: %s\n", cdi->name);
- return;
- }
- down(&ioctl_read_sem);
- switch_drive(p);
- /*
- * try to keep an "open" counter here and unlock the door if 1->0.
- */
- msg(DBG_LCK,"open_count: %d -> %d\n",
- p->open_count,p->open_count-1);
- if (p->open_count>-2) /* CDROMEJECT may have been done */
- {
- if (--p->open_count<=0)
- {
- p->sbp_first_frame=p->sbp_last_frame=-1;
- if (p->audio_state!=audio_playing)
- if (p->f_eject) cc_SpinDown();
- p->diskstate_flags &= ~cd_size_bit;
- p->open_count=0;
-#ifdef SAFE_MIXED
- p->has_data=0;
-#endif /* SAFE_MIXED */
- }
- }
- up(&ioctl_read_sem);
- return ;
-}
-/*==========================================================================*/
-/*
- *
- */
-static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr);
-static struct cdrom_device_ops sbpcd_dops = {
- .open = sbpcd_open,
- .release = sbpcd_release,
- .drive_status = sbpcd_drive_status,
- .media_changed = sbpcd_media_changed,
- .tray_move = sbpcd_tray_move,
- .lock_door = sbpcd_lock_door,
- .select_speed = sbpcd_select_speed,
- .get_last_session = sbpcd_get_last_session,
- .get_mcn = sbpcd_get_mcn,
- .reset = sbpcd_reset,
- .audio_ioctl = sbpcd_audio_ioctl,
- .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
- CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
- CDC_MCN | CDC_PLAY_AUDIO,
- .n_minors = 1,
-};
-
-/*==========================================================================*/
-/*
- * accept "kernel command line" parameters
- * (suggested by Peter MacDonald with SLS 1.03)
- *
- * This is only implemented for the first controller. Should be enough to
- * allow installing with a "strange" distribution kernel.
- *
- * use: tell LILO:
- * sbpcd=0x230,SoundBlaster
- * or
- * sbpcd=0x300,LaserMate
- * or
- * sbpcd=0x338,SoundScape
- * or
- * sbpcd=0x2C0,Teac16bit
- *
- * (upper/lower case sensitive here - but all-lowercase is ok!!!).
- *
- * the address value has to be the CDROM PORT ADDRESS -
- * not the soundcard base address.
- * For the SPEA/SoundScape setup, DO NOT specify the "configuration port"
- * address, but the address which is really used for the CDROM (usually 8
- * bytes above).
- *
- */
-
-int sbpcd_setup(char *s)
-{
-#ifndef MODULE
- int p[4];
- (void)get_options(s, ARRAY_SIZE(p), p);
- setup_done++;
- msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s);
- sbpro_type=0; /* default: "LaserMate" */
- if (p[0]>1) sbpro_type=p[2];
- else if (!strcmp(s,str_sb)) sbpro_type=1;
- else if (!strcmp(s,str_sb_l)) sbpro_type=1;
- else if (!strcmp(s,str_sp)) sbpro_type=2;
- else if (!strcmp(s,str_sp_l)) sbpro_type=2;
- else if (!strcmp(s,str_ss)) sbpro_type=2;
- else if (!strcmp(s,str_ss_l)) sbpro_type=2;
- else if (!strcmp(s,str_t16)) sbpro_type=3;
- else if (!strcmp(s,str_t16_l)) sbpro_type=3;
- if (p[0]>0) sbpcd_ioaddr=p[1];
- if (p[0]>2) max_drives=p[3];
-#else
- sbpcd_ioaddr = sbpcd[0];
- sbpro_type = sbpcd[1];
-#endif
-
- CDo_command=sbpcd_ioaddr;
- CDi_info=sbpcd_ioaddr;
- CDi_status=sbpcd_ioaddr+1;
- CDo_sel_i_d=sbpcd_ioaddr+1;
- CDo_reset=sbpcd_ioaddr+2;
- CDo_enable=sbpcd_ioaddr+3;
- f_16bit=0;
- if ((sbpro_type==1)||(sbpro_type==3))
- {
- CDi_data=sbpcd_ioaddr;
- if (sbpro_type==3)
- {
- f_16bit=1;
- sbpro_type=1;
- }
- }
- else CDi_data=sbpcd_ioaddr+2;
-
- return 1;
-}
-
-__setup("sbpcd=", sbpcd_setup);
-
-
-/*==========================================================================*/
-/*
- * Sequoia S-1000 CD-ROM Interface Configuration
- * as used within SPEA Media FX, Ensonic SoundScape and some Reveal cards
- * The soundcard has to get jumpered for the interface type "Panasonic"
- * (not Sony or Mitsumi) and to get soft-configured for
- * -> configuration port address
- * -> CDROM port offset (num_ports): has to be 8 here. Possibly this
- * offset value determines the interface type (none, Panasonic,
- * Mitsumi, Sony).
- * The interface uses a configuration port (0x320, 0x330, 0x340, 0x350)
- * some bytes below the real CDROM address.
- *
- * For the Panasonic style (LaserMate) interface and the configuration
- * port 0x330, we have to use an offset of 8; so, the real CDROM port
- * address is 0x338.
- */
-static int __init config_spea(void)
-{
- /*
- * base address offset between configuration port and CDROM port,
- * this probably defines the interface type
- * 2 (type=??): 0x00
- * 8 (type=LaserMate):0x10
- * 16 (type=??):0x20
- * 32 (type=??):0x30
- */
- int n_ports=0x10;
-
- int irq_number=0; /* off:0x00, 2/9:0x01, 7:0x03, 12:0x05, 15:0x07 */
- int dma_channel=0; /* off: 0x00, 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68 */
- int dack_polarity=0; /* L:0x00, H:0x80 */
- int drq_polarity=0x40; /* L:0x00, H:0x40 */
- int i;
-
-#define SPEA_REG_1 sbpcd_ioaddr-0x08+4
-#define SPEA_REG_2 sbpcd_ioaddr-0x08+5
-
- OUT(SPEA_REG_1,0xFF);
- i=inb(SPEA_REG_1);
- if (i!=0x0F)
- {
- msg(DBG_SEQ,"no SPEA interface at %04X present.\n", sbpcd_ioaddr);
- return (-1); /* no interface found */
- }
- OUT(SPEA_REG_1,0x04);
- OUT(SPEA_REG_2,0xC0);
-
- OUT(SPEA_REG_1,0x05);
- OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity);
-
-#if 1
-#define SPEA_PATTERN 0x80
-#else
-#define SPEA_PATTERN 0x00
-#endif
- OUT(SPEA_REG_1,0x06);
- OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
- OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-
- OUT(SPEA_REG_1,0x09);
- i=(inb(SPEA_REG_2)&0xCF)|n_ports;
- OUT(SPEA_REG_2,i);
-
- sbpro_type = 0; /* acts like a LaserMate interface now */
- msg(DBG_SEQ,"found SoundScape interface at %04X.\n", sbpcd_ioaddr);
- return (0);
-}
-
-/*==========================================================================*/
-/*
- * Test for presence of drive and initialize it.
- * Called once at boot or load time.
- */
-
-/* FIXME: cleanups after failed allocations are too ugly for words */
-#ifdef MODULE
-int __init __sbpcd_init(void)
-#else
-int __init sbpcd_init(void)
-#endif
-{
- int i=0, j=0;
- int addr[2]={1, CDROM_PORT};
- int port_index;
-
- sti();
-
- msg(DBG_INF,"sbpcd.c %s\n", VERSION);
-#ifndef MODULE
-#if DISTRIBUTION
- if (!setup_done)
- {
- msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, Longshine, TEAC CD-ROM drives\n");
- msg(DBG_INF,"= = = = = = = = = = W A R N I N G = = = = = = = = = =\n");
- msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an NE2000 card).\n");
- msg(DBG_INF,"If that happens, you have to reboot and use the\n");
- msg(DBG_INF,"LILO (kernel) command line feature like:\n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x230,SoundBlaster\n");
- msg(DBG_INF,"or like:\n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x300,LaserMate\n");
- msg(DBG_INF,"or like:\n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x338,SoundScape\n");
- msg(DBG_INF,"with your REAL address.\n");
- msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =\n");
- }
-#endif /* DISTRIBUTION */
- sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
- sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */
-#endif /* MODULE */
-
- for (port_index=0;port_index<NUM_PROBE;port_index+=2)
- {
- addr[1]=sbpcd[port_index];
- if (addr[1]==0) break;
- if (check_region(addr[1],4))
- {
- msg(DBG_INF,"check_region: %03X is not free.\n",addr[1]);
- continue;
- }
- if (sbpcd[port_index+1]==2) type=str_sp;
- else if (sbpcd[port_index+1]==1) type=str_sb;
- else if (sbpcd[port_index+1]==3) type=str_t16;
- else type=str_lm;
- sbpcd_setup((char *)type);
-#if DISTRIBUTION
- msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type);
-#endif /* DISTRIBUTION */
- if (sbpcd[port_index+1]==2)
- {
- i=config_spea();
- if (i<0) continue;
- }
-#ifdef PATH_CHECK
- if (check_card(addr[1])) continue;
-#endif /* PATH_CHECK */
- i=check_drives();
- msg(DBG_INI,"check_drives done.\n");
- if (i>=0) break; /* drive found */
- } /* end of cycling through the set of possible I/O port addresses */
-
- if (ndrives==0)
- {
- msg(DBG_INF, "No drive found.\n");
-#ifdef MODULE
- return -EIO;
-#else
- goto init_done;
-#endif /* MODULE */
- }
-
- if (port_index>0)
- {
- msg(DBG_INF, "You should read Documentation/cdrom/sbpcd\n");
- msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n");
- }
- check_datarate();
- msg(DBG_INI,"check_datarate done.\n");
-
- for (j=0;j<NR_SBPCD;j++)
- {
- struct sbpcd_drive *p = D_S + j;
- if (p->drv_id==-1)
- continue;
- switch_drive(p);
-#if 1
- if (!famL_drive) cc_DriveReset();
-#endif
- if (!st_spinning) cc_SpinUp();
- p->sbp_first_frame = -1; /* First frame in buffer */
- p->sbp_last_frame = -1; /* Last frame in buffer */
- p->sbp_read_frames = 0; /* Number of frames being read to buffer */
- p->sbp_current = 0; /* Frame being currently read */
- p->CD_changed=1;
- p->frame_size=CD_FRAMESIZE;
- p->f_eject=0;
-#if EJECT
- if (!fam0_drive) p->f_eject=1;
-#endif /* EJECT */
- cc_ReadStatus();
- i=ResponseStatus(); /* returns orig. status or p_busy_new */
- if (famT_drive) i=ResponseStatus(); /* returns orig. status or p_busy_new */
- if (i<0)
- {
- if (i!=-402)
- msg(DBG_INF,"init: ResponseStatus returns %d.\n",i);
- }
- else
- {
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_INI,"init: cc_ReadError returns %d\n",i);
- }
- }
- msg(DBG_INI,"init: first GetStatus: %d\n",i);
- msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n",
- p->error_byte);
- if (p->error_byte==aud_12)
- {
- timeout=jiffies+2*HZ;
- do
- {
- i=GetStatus();
- msg(DBG_INI,"init: second GetStatus: %02X\n",i);
- msg(DBG_LCS,
- "init: second GetStatus: error_byte=%d\n",
- p->error_byte);
- if (i<0) break;
- if (!st_caddy_in) break;
- }
- while ((!st_diskok)||time_after(jiffies, timeout));
- }
- i=SetSpeed();
- if (i>=0) p->CD_changed=1;
- }
-
- if (!request_region(CDo_command,4,major_name))
- {
- printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command);
- return -EIO;
- }
-
- /*
- * Turn on the CD audio channels.
- * The addresses are obtained from SOUND_BASE (see sbpcd.h).
- */
-#if SOUND_BASE
- OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */
- OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
-#endif /* SOUND_BASE */
-
- if (register_blkdev(MAJOR_NR, major_name)) {
-#ifdef MODULE
- return -EIO;
-#else
- goto init_done;
-#endif /* MODULE */
- }
-
- /*
- * init error handling is broken beyond belief in this driver...
- */
- sbpcd_queue = blk_init_queue(do_sbpcd_request, &sbpcd_lock);
- if (!sbpcd_queue) {
- release_region(CDo_command,4);
- unregister_blkdev(MAJOR_NR, major_name);
- return -ENOMEM;
- }
-
- for (j=0;j<NR_SBPCD;j++)
- {
- struct cdrom_device_info * sbpcd_infop;
- struct gendisk *disk;
- struct sbpcd_drive *p = D_S + j;
-
- if (p->drv_id==-1) continue;
- switch_drive(p);
-#ifdef SAFE_MIXED
- p->has_data=0;
-#endif /* SAFE_MIXED */
- /*
- * allocate memory for the frame buffers
- */
- p->aud_buf=NULL;
- p->sbp_audsiz=0;
- p->sbp_bufsiz=buffers;
- if (p->drv_type&drv_fam1)
- if (READ_AUDIO>0)
- p->sbp_audsiz = READ_AUDIO;
- p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE);
- if (!p->sbp_buf) {
- msg(DBG_INF,"data buffer (%d frames) not available.\n",
- buffers);
- if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
- {
- printk("Can't unregister %s\n", major_name);
- }
- release_region(CDo_command,4);
- blk_cleanup_queue(sbpcd_queue);
- return -EIO;
- }
-#ifdef MODULE
- msg(DBG_INF,"data buffer size: %d frames.\n",buffers);
-#endif /* MODULE */
- if (p->sbp_audsiz>0)
- {
- p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW);
- if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz);
- else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz);
- }
- sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info));
- if (sbpcd_infop == NULL)
- {
- release_region(CDo_command,4);
- blk_cleanup_queue(sbpcd_queue);
- return -ENOMEM;
- }
- memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info));
- sbpcd_infop->ops = &sbpcd_dops;
- sbpcd_infop->speed = 2;
- sbpcd_infop->capacity = 1;
- sprintf(sbpcd_infop->name, "sbpcd%d", j);
- sbpcd_infop->handle = p;
- p->sbpcd_infop = sbpcd_infop;
- disk = alloc_disk(1);
- disk->major = MAJOR_NR;
- disk->first_minor = j;
- disk->fops = &sbpcd_bdops;
- strcpy(disk->disk_name, sbpcd_infop->name);
- disk->flags = GENHD_FL_CD;
- p->disk = disk;
- if (register_cdrom(sbpcd_infop))
- {
- printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
- }
- disk->private_data = p;
- disk->queue = sbpcd_queue;
- add_disk(disk);
- }
- blk_queue_hardsect_size(sbpcd_queue, CD_FRAMESIZE);
-
-#ifndef MODULE
- init_done:
-#endif
- return 0;
-}
-/*==========================================================================*/
-#ifdef MODULE
-static void sbpcd_exit(void)
-{
- int j;
-
- if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
- {
- msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
- return;
- }
- release_region(CDo_command,4);
- blk_cleanup_queue(sbpcd_queue);
- for (j=0;j<NR_SBPCD;j++)
- {
- if (D_S[j].drv_id==-1) continue;
- del_gendisk(D_S[j].disk);
- put_disk(D_S[j].disk);
- vfree(D_S[j].sbp_buf);
- if (D_S[j].sbp_audsiz>0)
- vfree(D_S[j].aud_buf);
- if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
- {
- msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
- return;
- }
- vfree(D_S[j].sbpcd_infop);
- }
- msg(DBG_INF, "%s module released.\n", major_name);
-}
-
-
-module_init(__sbpcd_init) /*HACK!*/;
-module_exit(sbpcd_exit);
-
-
-#endif /* MODULE */
-static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- struct sbpcd_drive *p = cdi->handle;
- msg(DBG_CHK,"media_check (%s) called\n", cdi->name);
-
- if (p->CD_changed==0xFF)
- {
- p->CD_changed=0;
- msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name);
- current_drive->diskstate_flags &= ~toc_bit;
- /* we *don't* need invalidate here, it's done by caller */
- current_drive->diskstate_flags &= ~cd_size_bit;
-#ifdef SAFE_MIXED
- current_drive->has_data=0;
-#endif /* SAFE_MIXED */
-
- return (1);
- }
- else
- return (0);
-}
-
-MODULE_LICENSE("GPL");
-/* FIXME: Old modules.conf claims MATSUSHITA_CDROM2_MAJOR and CDROM3, but
- AFAICT this doesn't support those majors, so why? --RR 30 Jul 2003 */
-MODULE_ALIAS_BLOCKDEV_MAJOR(MATSUSHITA_CDROM_MAJOR);
-
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
-
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
deleted file mode 100644
index 2f2225f13c6..00000000000
--- a/drivers/cdrom/sbpcd.h
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * sbpcd.h Specify interface address and interface type here.
- */
-
-/*
- * Attention! This file contains user-serviceable parts!
- * I recommend to make use of it...
- * If you feel helpless, look into Documentation/cdrom/sbpcd
- * (good idea anyway, at least before mailing me).
- *
- * The definitions for the first controller can get overridden by
- * the kernel command line ("lilo boot option").
- * Examples:
- * sbpcd=0x300,LaserMate
- * or
- * sbpcd=0x230,SoundBlaster
- * or
- * sbpcd=0x338,SoundScape
- * or
- * sbpcd=0x2C0,Teac16bit
- *
- * If sbpcd gets used as a module, you can load it with
- * insmod sbpcd.o sbpcd=0x300,0
- * or
- * insmod sbpcd.o sbpcd=0x230,1
- * or
- * insmod sbpcd.o sbpcd=0x338,2
- * or
- * insmod sbpcd.o sbpcd=0x2C0,3
- * respective to override the configured address and type.
- */
-
-/*
- * define your CDROM port base address as CDROM_PORT
- * and specify the type of your interface card as SBPRO.
- *
- * address:
- * ========
- * SBPRO type addresses typically are 0x0230 (=0x220+0x10), 0x0250, ...
- * LASERMATE type (CI-101P, WDH-7001C) addresses typically are 0x0300, ...
- * SOUNDSCAPE addresses are from the LASERMATE type and range. You have to
- * specify the REAL address here, not the configuration port address. Look
- * at the CDROM driver's invoking line within your DOS CONFIG.SYS, or let
- * sbpcd auto-probe, if you are not firm with the address.
- * There are some soundcards on the market with 0x0630, 0x0650, ...; their
- * type is not obvious (both types are possible).
- *
- * example: if your SBPRO audio address is 0x220, specify 0x230 and SBPRO 1.
- * if your soundcard has its CDROM port above 0x300, specify
- * that address and try SBPRO 0 first.
- * if your SoundScape configuration port is at 0x330, specify
- * 0x338 and SBPRO 2.
- *
- * interface type:
- * ===============
- * set SBPRO to 1 for "true" SoundBlaster card
- * set SBPRO to 0 for "compatible" soundcards and
- * for "poor" (no sound) interface cards.
- * set SBPRO to 2 for Ensonic SoundScape or SPEA Media FX cards
- * set SBPRO to 3 for Teac 16bit interface cards
- *
- * Almost all "compatible" sound boards need to set SBPRO to 0.
- * If SBPRO is set wrong, the drives will get found - but any
- * data access will give errors (audio access will work).
- * The "OmniCD" no-sound interface card from CreativeLabs and most Teac
- * interface cards need SBPRO 1.
- *
- * sound base:
- * ===========
- * The SOUND_BASE definition tells if we should try to turn the CD sound
- * channels on. It will only be of use regarding soundcards with a SbPro
- * compatible mixer.
- *
- * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels
- * #define SOUND_BASE 0 leaves the soundcard untouched
- */
-#define CDROM_PORT 0x340 /* <-----------<< port address */
-#define SBPRO 0 /* <-----------<< interface type */
-#define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */
-#define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0 */
-
-/*
- * some more or less user dependent definitions - service them!
- */
-
-/* Set this to 0 once you have configured your interface definitions right. */
-#define DISTRIBUTION 1
-
-/*
- * Time to wait after giving a message.
- * This gets important if you enable non-standard DBG_xxx flags.
- * You will see what happens if you omit the pause or make it
- * too short. Be warned!
- */
-#define KLOGD_PAUSE 1
-
-/* tray control: eject tray if no disk is in */
-#if DISTRIBUTION
-#define JUKEBOX 0
-#else
-#define JUKEBOX 1
-#endif /* DISTRIBUTION */
-
-/* tray control: eject tray after last use */
-#if DISTRIBUTION
-#define EJECT 0
-#else
-#define EJECT 1
-#endif /* DISTRIBUTION */
-
-/* max. number of audio frames to read with one */
-/* request (allocates n* 2352 bytes kernel memory!) */
-/* may be freely adjusted, f.e. 75 (= 1 sec.), at */
-/* runtime by use of the CDROMAUDIOBUFSIZ ioctl. */
-#define READ_AUDIO 0
-
-/* Optimizations for the Teac CD-55A drive read performance.
- * SBP_TEAC_SPEED can be changed here, or one can set the
- * variable "teac" when loading as a module.
- * Valid settings are:
- * 0 - very slow - the recommended "DISTRIBUTION 1" setup.
- * 1 - 2x performance with little overhead. No busy waiting.
- * 2 - 4x performance with 5ms overhead per read. Busy wait.
- *
- * Setting SBP_TEAC_SPEED or the variable 'teac' to anything
- * other than 0 may cause problems. If you run into them, first
- * change SBP_TEAC_SPEED back to 0 and see if your drive responds
- * normally. If yes, you are "allowed" to report your case - to help
- * me with the driver, not to solve your hassle. Don´t mail if you
- * simply are stuck into your own "tuning" experiments, you know?
- */
-#define SBP_TEAC_SPEED 1
-
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * nothing to change below here if you are not fully aware what you're doing
- */
-#ifndef _LINUX_SBPCD_H
-
-#define _LINUX_SBPCD_H
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * driver's own read_ahead, data mode
- */
-#define SBP_BUFFER_FRAMES 8
-
-#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
-#undef FUTURE
-#undef SAFE_MIXED
-
-#define TEST_UPC 0
-#define SPEA_TEST 0
-#define TEST_STI 0
-#define OLD_BUSY 0
-#undef PATH_CHECK
-#ifndef SOUND_BASE
-#define SOUND_BASE 0
-#endif
-#if DISTRIBUTION
-#undef SBP_TEAC_SPEED
-#define SBP_TEAC_SPEED 0
-#endif
-/*==========================================================================*/
-/*
- * DDI interface definitions
- * "invented" by Fred N. van Kempen..
- */
-#define DDIOCSDBG 0x9000
-
-/*==========================================================================*/
-/*
- * "private" IOCTL functions
- */
-#define CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */
-
-/*==========================================================================*/
-/*
- * Debug output levels
- */
-#define DBG_INF 1 /* necessary information */
-#define DBG_BSZ 2 /* BLOCK_SIZE trace */
-#define DBG_REA 3 /* READ status trace */
-#define DBG_CHK 4 /* MEDIA CHECK trace */
-#define DBG_TIM 5 /* datarate timer test */
-#define DBG_INI 6 /* initialization trace */
-#define DBG_TOC 7 /* tell TocEntry values */
-#define DBG_IOC 8 /* ioctl trace */
-#define DBG_STA 9 /* ResponseStatus() trace */
-#define DBG_ERR 10 /* cc_ReadError() trace */
-#define DBG_CMD 11 /* cmd_out() trace */
-#define DBG_WRN 12 /* give explanation before auto-probing */
-#define DBG_MUL 13 /* multi session code test */
-#define DBG_IDX 14 /* test code for drive_id !=0 */
-#define DBG_IOX 15 /* some special information */
-#define DBG_DID 16 /* drive ID test */
-#define DBG_RES 17 /* drive reset info */
-#define DBG_SPI 18 /* SpinUp test */
-#define DBG_IOS 19 /* ioctl trace: subchannel functions */
-#define DBG_IO2 20 /* ioctl trace: general */
-#define DBG_UPC 21 /* show UPC information */
-#define DBG_XA1 22 /* XA mode debugging */
-#define DBG_LCK 23 /* door (un)lock info */
-#define DBG_SQ1 24 /* dump SubQ frame */
-#define DBG_AUD 25 /* READ AUDIO debugging */
-#define DBG_SEQ 26 /* Sequoia interface configuration trace */
-#define DBG_LCS 27 /* Longshine LCS-7260 debugging trace */
-#define DBG_CD2 28 /* MKE/Funai CD200 debugging trace */
-#define DBG_TEA 29 /* TEAC CD-55A debugging trace */
-#define DBG_ECS 30 /* ECS-AT (Vertos 100) debugging trace */
-#define DBG_000 31 /* unnecessary information */
-
-/*==========================================================================*/
-/*==========================================================================*/
-
-/*
- * bits of flags_cmd_out:
- */
-#define f_respo3 0x100
-#define f_putcmd 0x80
-#define f_respo2 0x40
-#define f_lopsta 0x20
-#define f_getsta 0x10
-#define f_ResponseStatus 0x08
-#define f_obey_p_check 0x04
-#define f_bit1 0x02
-#define f_wait_if_busy 0x01
-
-/*
- * diskstate_flags:
- */
-#define x80_bit 0x80
-#define upc_bit 0x40
-#define volume_bit 0x20
-#define toc_bit 0x10
-#define multisession_bit 0x08
-#define cd_size_bit 0x04
-#define subq_bit 0x02
-#define frame_size_bit 0x01
-
-/*
- * disk states (bits of diskstate_flags):
- */
-#define upc_valid (current_drive->diskstate_flags&upc_bit)
-#define volume_valid (current_drive->diskstate_flags&volume_bit)
-#define toc_valid (current_drive->diskstate_flags&toc_bit)
-#define cd_size_valid (current_drive->diskstate_flags&cd_size_bit)
-#define subq_valid (current_drive->diskstate_flags&subq_bit)
-#define frame_size_valid (current_drive->diskstate_flags&frame_size_bit)
-
-/*
- * the status_bits variable
- */
-#define p_success 0x100
-#define p_door_closed 0x80
-#define p_caddy_in 0x40
-#define p_spinning 0x20
-#define p_check 0x10
-#define p_busy_new 0x08
-#define p_door_locked 0x04
-#define p_disk_ok 0x01
-
-/*
- * LCS-7260 special status result bits:
- */
-#define p_lcs_door_locked 0x02
-#define p_lcs_door_closed 0x01 /* probably disk_in */
-
-/*
- * CR-52x special status result bits:
- */
-#define p_caddin_old 0x40
-#define p_success_old 0x08
-#define p_busy_old 0x04
-#define p_bit_1 0x02 /* hopefully unused now */
-
-/*
- * "generation specific" defs of the status result bits:
- */
-#define p0_door_closed 0x80
-#define p0_caddy_in 0x40
-#define p0_spinning 0x20
-#define p0_check 0x10
-#define p0_success 0x08 /* unused */
-#define p0_busy 0x04
-#define p0_bit_1 0x02 /* unused */
-#define p0_disk_ok 0x01
-
-#define pL_disk_in 0x40
-#define pL_spinning 0x20
-#define pL_check 0x10
-#define pL_success 0x08 /* unused ?? */
-#define pL_busy 0x04
-#define pL_door_locked 0x02
-#define pL_door_closed 0x01
-
-#define pV_door_closed 0x40
-#define pV_spinning 0x20
-#define pV_check 0x10
-#define pV_success 0x08
-#define pV_busy 0x04
-#define pV_door_locked 0x02
-#define pV_disk_ok 0x01
-
-#define p1_door_closed 0x80
-#define p1_disk_in 0x40
-#define p1_spinning 0x20
-#define p1_check 0x10
-#define p1_busy 0x08
-#define p1_door_locked 0x04
-#define p1_bit_1 0x02 /* unused */
-#define p1_disk_ok 0x01
-
-#define p2_disk_ok 0x80
-#define p2_door_locked 0x40
-#define p2_spinning 0x20
-#define p2_busy2 0x10
-#define p2_busy1 0x08
-#define p2_door_closed 0x04
-#define p2_disk_in 0x02
-#define p2_check 0x01
-
-/*
- * used drive states:
- */
-#define st_door_closed (current_drive->status_bits&p_door_closed)
-#define st_caddy_in (current_drive->status_bits&p_caddy_in)
-#define st_spinning (current_drive->status_bits&p_spinning)
-#define st_check (current_drive->status_bits&p_check)
-#define st_busy (current_drive->status_bits&p_busy_new)
-#define st_door_locked (current_drive->status_bits&p_door_locked)
-#define st_diskok (current_drive->status_bits&p_disk_ok)
-
-/*
- * bits of the CDi_status register:
- */
-#define s_not_result_ready 0x04 /* 0: "result ready" */
-#define s_not_data_ready 0x02 /* 0: "data ready" */
-#define s_attention 0x01 /* 1: "attention required" */
-/*
- * usable as:
- */
-#define DRV_ATTN ((inb(CDi_status)&s_attention)!=0)
-#define DATA_READY ((inb(CDi_status)&s_not_data_ready)==0)
-#define RESULT_READY ((inb(CDi_status)&s_not_result_ready)==0)
-
-/*
- * drive families and types (firmware versions):
- */
-#define drv_fam0 0x0100 /* CR-52x family */
-#define drv_199 (drv_fam0+0x01) /* <200 */
-#define drv_200 (drv_fam0+0x02) /* <201 */
-#define drv_201 (drv_fam0+0x03) /* <210 */
-#define drv_210 (drv_fam0+0x04) /* <211 */
-#define drv_211 (drv_fam0+0x05) /* <300 */
-#define drv_300 (drv_fam0+0x06) /* >=300 */
-
-#define drv_fam1 0x0200 /* CR-56x family */
-#define drv_099 (drv_fam1+0x01) /* <100 */
-#define drv_100 (drv_fam1+0x02) /* >=100, only 1.02 and 5.00 known */
-
-#define drv_fam2 0x0400 /* CD200 family */
-
-#define drv_famT 0x0800 /* TEAC CD-55A */
-
-#define drv_famL 0x1000 /* Longshine family */
-#define drv_260 (drv_famL+0x01) /* LCS-7260 */
-#define drv_e1 (drv_famL+0x01) /* LCS-7260, firmware "A E1" */
-#define drv_f4 (drv_famL+0x02) /* LCS-7260, firmware "A4F4" */
-
-#define drv_famV 0x2000 /* ECS-AT (vertos-100) family */
-#define drv_at (drv_famV+0x01) /* ECS-AT, firmware "1.00" */
-
-#define fam0_drive (current_drive->drv_type&drv_fam0)
-#define famL_drive (current_drive->drv_type&drv_famL)
-#define famV_drive (current_drive->drv_type&drv_famV)
-#define fam1_drive (current_drive->drv_type&drv_fam1)
-#define fam2_drive (current_drive->drv_type&drv_fam2)
-#define famT_drive (current_drive->drv_type&drv_famT)
-#define fam0L_drive (current_drive->drv_type&(drv_fam0|drv_famL))
-#define fam0V_drive (current_drive->drv_type&(drv_fam0|drv_famV))
-#define famLV_drive (current_drive->drv_type&(drv_famL|drv_famV))
-#define fam0LV_drive (current_drive->drv_type&(drv_fam0|drv_famL|drv_famV))
-#define fam1L_drive (current_drive->drv_type&(drv_fam1|drv_famL))
-#define fam1V_drive (current_drive->drv_type&(drv_fam1|drv_famV))
-#define fam1LV_drive (current_drive->drv_type&(drv_fam1|drv_famL|drv_famV))
-#define fam01_drive (current_drive->drv_type&(drv_fam0|drv_fam1))
-#define fam12_drive (current_drive->drv_type&(drv_fam1|drv_fam2))
-#define fam2T_drive (current_drive->drv_type&(drv_fam2|drv_famT))
-
-/*
- * audio states:
- */
-#define audio_completed 3 /* Forgot this one! --AJK */
-#define audio_playing 2
-#define audio_pausing 1
-
-/*
- * drv_pattern, drv_options:
- */
-#define speed_auto 0x80
-#define speed_300 0x40
-#define speed_150 0x20
-#define audio_mono 0x04
-
-/*
- * values of cmd_type (0 else):
- */
-#define READ_M1 0x01 /* "data mode 1": 2048 bytes per frame */
-#define READ_M2 0x02 /* "data mode 2": 12+2048+280 bytes per frame */
-#define READ_SC 0x04 /* "subchannel info": 96 bytes per frame */
-#define READ_AU 0x08 /* "audio frame": 2352 bytes per frame */
-
-/*
- * sense_byte:
- *
- * values: 00
- * 01
- * 81
- * 82 "raw audio" mode
- * xx from infobuf[0] after 85 00 00 00 00 00 00
- */
-
-/* audio status (bin) */
-#define aud_00 0x00 /* Audio status byte not supported or not valid */
-#define audx11 0x0b /* Audio play operation in progress */
-#define audx12 0x0c /* Audio play operation paused */
-#define audx13 0x0d /* Audio play operation successfully completed */
-#define audx14 0x0e /* Audio play operation stopped due to error */
-#define audx15 0x0f /* No current audio status to return */
-/* audio status (bcd) */
-#define aud_11 0x11 /* Audio play operation in progress */
-#define aud_12 0x12 /* Audio play operation paused */
-#define aud_13 0x13 /* Audio play operation successfully completed */
-#define aud_14 0x14 /* Audio play operation stopped due to error */
-#define aud_15 0x15 /* No current audio status to return */
-
-/*
- * highest allowed drive number (MINOR+1)
- */
-#define NR_SBPCD 4
-
-/*
- * we try to never disable interrupts - seems to work
- */
-#define SBPCD_DIS_IRQ 0
-
-/*
- * "write byte to port"
- */
-#define OUT(x,y) outb(y,x)
-
-/*==========================================================================*/
-
-#define MIXER_addr SOUND_BASE+4 /* sound card's address register */
-#define MIXER_data SOUND_BASE+5 /* sound card's data register */
-#define MIXER_CD_Volume 0x28 /* internal SB Pro register address */
-
-/*==========================================================================*/
-
-#define MAX_TRACKS 99
-
-#define ERR_DISKCHANGE 615
-
-/*==========================================================================*/
-/*
- * To make conversions easier (machine dependent!)
- */
-typedef union _msf
-{
- u_int n;
- u_char c[4];
-} MSF;
-
-typedef union _blk
-{
- u_int n;
- u_char c[4];
-} BLK;
-
-/*==========================================================================*/
-
-/*============================================================================
-==============================================================================
-
-COMMAND SET of "old" drives like CR-521, CR-522
- (the CR-562 family is different):
-
-No. Command Code
---------------------------------------------
-
-Drive Commands:
- 1 Seek 01
- 2 Read Data 02
- 3 Read XA-Data 03
- 4 Read Header 04
- 5 Spin Up 05
- 6 Spin Down 06
- 7 Diagnostic 07
- 8 Read UPC 08
- 9 Read ISRC 09
-10 Play Audio 0A
-11 Play Audio MSF 0B
-12 Play Audio Track/Index 0C
-
-Status Commands:
-13 Read Status 81
-14 Read Error 82
-15 Read Drive Version 83
-16 Mode Select 84
-17 Mode Sense 85
-18 Set XA Parameter 86
-19 Read XA Parameter 87
-20 Read Capacity 88
-21 Read SUB_Q 89
-22 Read Disc Code 8A
-23 Read Disc Information 8B
-24 Read TOC 8C
-25 Pause/Resume 8D
-26 Read Packet 8E
-27 Read Path Check 00
-
-
-all numbers (lba, msf-bin, msf-bcd, counts) to transfer high byte first
-
-mnemo 7-byte command #bytes response (r0...rn)
-________ ____________________ ____
-
-Read Status:
-status: 81. (1) one-byte command, gives the main
- status byte
-Read Error:
-check1: 82 00 00 00 00 00 00. (6) r1: audio status
-
-Read Packet:
-check2: 8e xx 00 00 00 00 00. (xx) gets xx bytes response, relating
- to commands 01 04 05 07 08 09
-
-Play Audio:
-play: 0a ll-bb-aa nn-nn-nn. (0) play audio, ll-bb-aa: starting block (lba),
- nn-nn-nn: #blocks
-Play Audio MSF:
- 0b mm-ss-ff mm-ss-ff (0) play audio from/to
-
-Play Audio Track/Index:
- 0c ...
-
-Pause/Resume:
-pause: 8d pr 00 00 00 00 00. (0) pause (pr=00)
- resume (pr=80) audio playing
-
-Mode Select:
- 84 00 nn-nn ??.?? 00 (0) nn-nn: 2048 or 2340
- possibly defines transfer size
-
-set_vol: 84 83 00 00 sw le 00. (0) sw(itch): lrxxxxxx (off=1)
- le(vel): min=0, max=FF, else half
- (firmware 2.11)
-
-Mode Sense:
-get_vol: 85 03 00 00 00 00 00. (2) tell current audio volume setting
-
-Read Disc Information:
-tocdesc: 8b 00 00 00 00 00 00. (6) read the toc descriptor ("msf-bin"-format)
-
-Read TOC:
-tocent: 8c fl nn 00 00 00 00. (8) read toc entry #nn
- (fl=0:"lba"-, =2:"msf-bin"-format)
-
-Read Capacity:
-capacit: 88 00 00 00 00 00 00. (5) "read CD-ROM capacity"
-
-
-Read Path Check:
-ping: 00 00 00 00 00 00 00. (2) r0=AA, r1=55
- ("ping" if the drive is connected)
-
-Read Drive Version:
-ident: 83 00 00 00 00 00 00. (12) gives "MATSHITAn.nn"
- (n.nn = 2.01, 2.11., 3.00, ...)
-
-Seek:
-seek: 01 00 ll-bb-aa 00 00. (0)
-seek: 01 02 mm-ss-ff 00 00. (0)
-
-Read Data:
-read: 02 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2048 bytes,
- starting at block xx-xx-xx
- fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read XA-Data:
-read: 03 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2340 bytes,
- starting at block xx-xx-xx
- fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read SUB_Q:
- 89 fl 00 00 00 00 00. (13) r0: audio status, r4-r7: lba/msf,
- fl=0: "lba", fl=2: "msf"
-
-Read Disc Code:
- 8a 00 00 00 00 00 00. (14) possibly extended "check condition"-info
-
-Read Header:
- 04 00 ll-bb-aa 00 00. (0) 4 bytes response with "check2"
- 04 02 mm-ss-ff 00 00. (0) 4 bytes response with "check2"
-
-Spin Up:
- 05 00 ll-bb-aa 00 00. (0) possibly implies a "seek"
-
-Spin Down:
- 06 ...
-
-Diagnostic:
- 07 00 ll-bb-aa 00 00. (2) 2 bytes response with "check2"
- 07 02 mm-ss-ff 00 00. (2) 2 bytes response with "check2"
-
-Read UPC:
- 08 00 ll-bb-aa 00 00. (16)
- 08 02 mm-ss-ff 00 00. (16)
-
-Read ISRC:
- 09 00 ll-bb-aa 00 00. (15) 15 bytes response with "check2"
- 09 02 mm-ss-ff 00 00. (15) 15 bytes response with "check2"
-
-Set XA Parameter:
- 86 ...
-
-Read XA Parameter:
- 87 ...
-
-==============================================================================
-============================================================================*/
-
-/*
- * commands
- *
- * CR-52x: CMD0_
- * CR-56x: CMD1_
- * CD200: CMD2_
- * LCS-7260: CMDL_
- * TEAC CD-55A: CMDT_
- * ECS-AT: CMDV_
- */
-#define CMD1_RESET 0x0a
-#define CMD2_RESET 0x01
-#define CMDT_RESET 0xc0
-
-#define CMD1_LOCK_CTL 0x0c
-#define CMD2_LOCK_CTL 0x1e
-#define CMDT_LOCK_CTL CMD2_LOCK_CTL
-#define CMDL_LOCK_CTL 0x0e
-#define CMDV_LOCK_CTL CMDL_LOCK_CTL
-
-#define CMD1_TRAY_CTL 0x07
-#define CMD2_TRAY_CTL 0x1b
-#define CMDT_TRAY_CTL CMD2_TRAY_CTL
-#define CMDL_TRAY_CTL 0x0d
-#define CMDV_TRAY_CTL CMDL_TRAY_CTL
-
-#define CMD1_MULTISESS 0x8d
-#define CMDL_MULTISESS 0x8c
-#define CMDV_MULTISESS CMDL_MULTISESS
-
-#define CMD1_SUBCHANINF 0x11
-#define CMD2_SUBCHANINF 0x??
-
-#define CMD1_ABORT 0x08
-#define CMD2_ABORT 0x08
-#define CMDT_ABORT 0x08
-
-#define CMD2_x02 0x02
-
-#define CMD2_SETSPEED 0xda
-
-#define CMD0_PATH_CHECK 0x00
-#define CMD1_PATH_CHECK 0x???
-#define CMD2_PATH_CHECK 0x???
-#define CMDT_PATH_CHECK 0x???
-#define CMDL_PATH_CHECK CMD0_PATH_CHECK
-#define CMDV_PATH_CHECK CMD0_PATH_CHECK
-
-#define CMD0_SEEK 0x01
-#define CMD1_SEEK CMD0_SEEK
-#define CMD2_SEEK 0x2b
-#define CMDT_SEEK CMD2_SEEK
-#define CMDL_SEEK CMD0_SEEK
-#define CMDV_SEEK CMD0_SEEK
-
-#define CMD0_READ 0x02
-#define CMD1_READ 0x10
-#define CMD2_READ 0x28
-#define CMDT_READ CMD2_READ
-#define CMDL_READ CMD0_READ
-#define CMDV_READ CMD0_READ
-
-#define CMD0_READ_XA 0x03
-#define CMD2_READ_XA 0xd4
-#define CMD2_READ_XA2 0xd5
-#define CMDL_READ_XA CMD0_READ_XA /* really ?? */
-#define CMDV_READ_XA CMD0_READ_XA
-
-#define CMD0_READ_HEAD 0x04
-
-#define CMD0_SPINUP 0x05
-#define CMD1_SPINUP 0x02
-#define CMD2_SPINUP CMD2_TRAY_CTL
-#define CMDL_SPINUP CMD0_SPINUP
-#define CMDV_SPINUP CMD0_SPINUP
-
-#define CMD0_SPINDOWN 0x06 /* really??? */
-#define CMD1_SPINDOWN 0x06
-#define CMD2_SPINDOWN CMD2_TRAY_CTL
-#define CMDL_SPINDOWN 0x0d
-#define CMDV_SPINDOWN CMD0_SPINDOWN
-
-#define CMD0_DIAG 0x07
-
-#define CMD0_READ_UPC 0x08
-#define CMD1_READ_UPC 0x88
-#define CMD2_READ_UPC 0x???
-#define CMDL_READ_UPC CMD0_READ_UPC
-#define CMDV_READ_UPC 0x8f
-
-#define CMD0_READ_ISRC 0x09
-
-#define CMD0_PLAY 0x0a
-#define CMD1_PLAY 0x???
-#define CMD2_PLAY 0x???
-#define CMDL_PLAY CMD0_PLAY
-#define CMDV_PLAY CMD0_PLAY
-
-#define CMD0_PLAY_MSF 0x0b
-#define CMD1_PLAY_MSF 0x0e
-#define CMD2_PLAY_MSF 0x47
-#define CMDT_PLAY_MSF CMD2_PLAY_MSF
-#define CMDL_PLAY_MSF 0x???
-
-#define CMD0_PLAY_TI 0x0c
-#define CMD1_PLAY_TI 0x0f
-
-#define CMD0_STATUS 0x81
-#define CMD1_STATUS 0x05
-#define CMD2_STATUS 0x00
-#define CMDT_STATUS CMD2_STATUS
-#define CMDL_STATUS CMD0_STATUS
-#define CMDV_STATUS CMD0_STATUS
-#define CMD2_SEEK_LEADIN 0x00
-
-#define CMD0_READ_ERR 0x82
-#define CMD1_READ_ERR CMD0_READ_ERR
-#define CMD2_READ_ERR 0x03
-#define CMDT_READ_ERR CMD2_READ_ERR /* get audio status */
-#define CMDL_READ_ERR CMD0_READ_ERR
-#define CMDV_READ_ERR CMD0_READ_ERR
-
-#define CMD0_READ_VER 0x83
-#define CMD1_READ_VER CMD0_READ_VER
-#define CMD2_READ_VER 0x12
-#define CMDT_READ_VER CMD2_READ_VER /* really ?? */
-#define CMDL_READ_VER CMD0_READ_VER
-#define CMDV_READ_VER CMD0_READ_VER
-
-#define CMD0_SETMODE 0x84
-#define CMD1_SETMODE 0x09
-#define CMD2_SETMODE 0x55
-#define CMDT_SETMODE CMD2_SETMODE
-#define CMDL_SETMODE CMD0_SETMODE
-
-#define CMD0_GETMODE 0x85
-#define CMD1_GETMODE 0x84
-#define CMD2_GETMODE 0x5a
-#define CMDT_GETMODE CMD2_GETMODE
-#define CMDL_GETMODE CMD0_GETMODE
-
-#define CMD0_SET_XA 0x86
-
-#define CMD0_GET_XA 0x87
-
-#define CMD0_CAPACITY 0x88
-#define CMD1_CAPACITY 0x85
-#define CMD2_CAPACITY 0x25
-#define CMDL_CAPACITY CMD0_CAPACITY /* missing in some firmware versions */
-
-#define CMD0_READSUBQ 0x89
-#define CMD1_READSUBQ 0x87
-#define CMD2_READSUBQ 0x42
-#define CMDT_READSUBQ CMD2_READSUBQ
-#define CMDL_READSUBQ CMD0_READSUBQ
-#define CMDV_READSUBQ CMD0_READSUBQ
-
-#define CMD0_DISKCODE 0x8a
-
-#define CMD0_DISKINFO 0x8b
-#define CMD1_DISKINFO CMD0_DISKINFO
-#define CMD2_DISKINFO 0x43
-#define CMDT_DISKINFO CMD2_DISKINFO
-#define CMDL_DISKINFO CMD0_DISKINFO
-#define CMDV_DISKINFO CMD0_DISKINFO
-
-#define CMD0_READTOC 0x8c
-#define CMD1_READTOC CMD0_READTOC
-#define CMD2_READTOC 0x???
-#define CMDL_READTOC CMD0_READTOC
-#define CMDV_READTOC CMD0_READTOC
-
-#define CMD0_PAU_RES 0x8d
-#define CMD1_PAU_RES 0x0d
-#define CMD2_PAU_RES 0x4b
-#define CMDT_PAUSE CMD2_PAU_RES
-#define CMDL_PAU_RES CMD0_PAU_RES
-#define CMDV_PAUSE CMD0_PAU_RES
-
-#define CMD0_PACKET 0x8e
-#define CMD1_PACKET CMD0_PACKET
-#define CMD2_PACKET 0x???
-#define CMDL_PACKET CMD0_PACKET
-#define CMDV_PACKET 0x???
-
-/*==========================================================================*/
-/*==========================================================================*/
-#endif /* _LINUX_SBPCD_H */
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
deleted file mode 100644
index 5409fca5bbf..00000000000
--- a/drivers/cdrom/sjcd.c
+++ /dev/null
@@ -1,1815 +0,0 @@
-/* -- sjcd.c
- *
- * Sanyo CD-ROM device driver implementation, Version 1.6
- * Copyright (C) 1995 Vadim V. Model
- *
- * model@cecmow.enet.dec.com
- * vadim@rbrf.ru
- * vadim@ipsun.ras.ru
- *
- *
- * This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
- * it was developed under use of mcd.c from Martin Harriss, with help of
- * Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl).
- *
- * It is planned to include these routines into sbpcd.c later - to make
- * a "mixed use" on one cable possible for all kinds of drives which use
- * the SoundBlaster/Panasonic style CDROM interface. But today, the
- * ability to install directly from CDROM is more important than flexibility.
- *
- * 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.
- *
- * History:
- * 1.1 First public release with kernel version 1.3.7.
- * Written by Vadim Model.
- * 1.2 Added detection and configuration of cdrom interface
- * on ISP16 soundcard.
- * Allow for command line options: sjcd=<io_base>,<irq>,<dma>
- * 1.3 Some minor changes to README.sjcd.
- * 1.4 MSS Sound support!! Listen to a CD through the speakers.
- * 1.5 Module support and bugfixes.
- * Tray locking.
- * 1.6 Removed ISP16 code from this driver.
- * Allow only to set io base address on command line: sjcd=<io_base>
- * Changes to Documentation/cdrom/sjcd
- * Added cleanup after any error in the initialisation.
- * 1.7 Added code to set the sector size tables to prevent the bug present in
- * the previous version of this driver. Coded added by Anthony Barbachan
- * from bugfix tip originally suggested by Alan Cox.
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- */
-
-#define SJCD_VERSION_MAJOR 1
-#define SJCD_VERSION_MINOR 7
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/blkdev.h>
-#include "sjcd.h"
-
-static int sjcd_present = 0;
-static struct request_queue *sjcd_queue;
-
-#define MAJOR_NR SANYO_CDROM_MAJOR
-#define QUEUE (sjcd_queue)
-#define CURRENT elv_next_request(sjcd_queue)
-
-#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */
-
-/*
- * buffer for block size conversion
- */
-static char sjcd_buf[2048 * SJCD_BUF_SIZ];
-static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn;
-static volatile int sjcd_buf_in, sjcd_buf_out = -1;
-
-/*
- * Status.
- */
-static unsigned short sjcd_status_valid = 0;
-static unsigned short sjcd_door_closed;
-static unsigned short sjcd_door_was_open;
-static unsigned short sjcd_media_is_available;
-static unsigned short sjcd_media_is_changed;
-static unsigned short sjcd_toc_uptodate = 0;
-static unsigned short sjcd_command_failed;
-static volatile unsigned char sjcd_completion_status = 0;
-static volatile unsigned char sjcd_completion_error = 0;
-static unsigned short sjcd_command_is_in_progress = 0;
-static unsigned short sjcd_error_reported = 0;
-static DEFINE_SPINLOCK(sjcd_lock);
-
-static int sjcd_open_count;
-
-static int sjcd_audio_status;
-static struct sjcd_play_msf sjcd_playing;
-
-static int sjcd_base = SJCD_BASE_ADDR;
-
-module_param(sjcd_base, int, 0);
-
-static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq);
-
-/*
- * Data transfer.
- */
-static volatile unsigned short sjcd_transfer_is_active = 0;
-
-enum sjcd_transfer_state {
- SJCD_S_IDLE = 0,
- SJCD_S_START = 1,
- SJCD_S_MODE = 2,
- SJCD_S_READ = 3,
- SJCD_S_DATA = 4,
- SJCD_S_STOP = 5,
- SJCD_S_STOPPING = 6
-};
-static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
-static long sjcd_transfer_timeout = 0;
-static int sjcd_read_count = 0;
-static unsigned char sjcd_mode = 0;
-
-#define SJCD_READ_TIMEOUT 5000
-
-#if defined( SJCD_GATHER_STAT )
-/*
- * Statistic.
- */
-static struct sjcd_stat statistic;
-#endif
-
-/*
- * Timer.
- */
-static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0);
-
-#define SJCD_SET_TIMER( func, tmout ) \
- ( sjcd_delay_timer.expires = jiffies+tmout, \
- sjcd_delay_timer.function = ( void * )func, \
- add_timer( &sjcd_delay_timer ) )
-
-#define CLEAR_TIMER del_timer( &sjcd_delay_timer )
-
-/*
- * Set up device, i.e., use command line data to set
- * base address.
- */
-#ifndef MODULE
-static int __init sjcd_setup(char *str)
-{
- int ints[2];
- (void) get_options(str, ARRAY_SIZE(ints), ints);
- if (ints[0] > 0)
- sjcd_base = ints[1];
-
- return 1;
-}
-
-__setup("sjcd=", sjcd_setup);
-
-#endif
-
-/*
- * Special converters.
- */
-static unsigned char bin2bcd(int bin)
-{
- int u, v;
-
- u = bin % 10;
- v = bin / 10;
- return (u | (v << 4));
-}
-
-static int bcd2bin(unsigned char bcd)
-{
- return ((bcd >> 4) * 10 + (bcd & 0x0F));
-}
-
-static long msf2hsg(struct msf *mp)
-{
- return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75
- + bcd2bin(mp->min) * 4500 - 150);
-}
-
-static void hsg2msf(long hsg, struct msf *msf)
-{
- hsg += 150;
- msf->min = hsg / 4500;
- hsg %= 4500;
- msf->sec = hsg / 75;
- msf->frame = hsg % 75;
- msf->min = bin2bcd(msf->min); /* convert to BCD */
- msf->sec = bin2bcd(msf->sec);
- msf->frame = bin2bcd(msf->frame);
-}
-
-/*
- * Send a command to cdrom. Invalidate status.
- */
-static void sjcd_send_cmd(unsigned char cmd)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_cmd( 0x%x )\n", cmd);
-#endif
- outb(cmd, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with one arg to cdrom. Invalidate status.
- */
-static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a);
-#endif
- outb(cmd, SJCDPORT(0));
- outb(a, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with four args to cdrom. Invalidate status.
- */
-static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a,
- unsigned char b, unsigned char c,
- unsigned char d)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_4_cmd( 0x%x )\n", cmd);
-#endif
- outb(cmd, SJCDPORT(0));
- outb(a, SJCDPORT(0));
- outb(b, SJCDPORT(0));
- outb(c, SJCDPORT(0));
- outb(d, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Send a play or read command to cdrom. Invalidate Status.
- */
-static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_long_cmd( 0x%x )\n", cmd);
-#endif
- outb(cmd, SJCDPORT(0));
- outb(pms->start.min, SJCDPORT(0));
- outb(pms->start.sec, SJCDPORT(0));
- outb(pms->start.frame, SJCDPORT(0));
- outb(pms->end.min, SJCDPORT(0));
- outb(pms->end.sec, SJCDPORT(0));
- outb(pms->end.frame, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Get a value from the data port. Should not block, so we use a little
- * wait for a while. Returns 0 if OK.
- */
-static int sjcd_load_response(void *buf, int len)
-{
- unsigned char *resp = (unsigned char *) buf;
-
- for (; len; --len) {
- int i;
- for (i = 200;
- i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))););
- if (i > 0)
- *resp++ = (unsigned char) inb(SJCDPORT(0));
- else
- break;
- }
- return (len);
-}
-
-/*
- * Load and parse command completion status (drive info byte and maybe error).
- * Sorry, no error classification yet.
- */
-static void sjcd_load_status(void)
-{
- sjcd_media_is_changed = 0;
- sjcd_completion_error = 0;
- sjcd_completion_status = inb(SJCDPORT(0));
- if (sjcd_completion_status & SST_DOOR_OPENED) {
- sjcd_door_closed = sjcd_media_is_available = 0;
- } else {
- sjcd_door_closed = 1;
- if (sjcd_completion_status & SST_MEDIA_CHANGED)
- sjcd_media_is_available = sjcd_media_is_changed =
- 1;
- else if (sjcd_completion_status & 0x0F) {
- /*
- * OK, we seem to catch an error ...
- */
- while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))));
- sjcd_completion_error = inb(SJCDPORT(0));
- if ((sjcd_completion_status & 0x08) &&
- (sjcd_completion_error & 0x40))
- sjcd_media_is_available = 0;
- else
- sjcd_command_failed = 1;
- } else
- sjcd_media_is_available = 1;
- }
- /*
- * Ok, status loaded successfully.
- */
- sjcd_status_valid = 1, sjcd_error_reported = 0;
- sjcd_command_is_in_progress = 0;
-
- /*
- * If the disk is changed, the TOC is not valid.
- */
- if (sjcd_media_is_changed)
- sjcd_toc_uptodate = 0;
-#if defined( SJCD_TRACE )
- printk("SJCD: status %02x.%02x loaded.\n",
- (int) sjcd_completion_status, (int) sjcd_completion_error);
-#endif
-}
-
-/*
- * Read status from cdrom. Check to see if the status is available.
- */
-static int sjcd_check_status(void)
-{
- /*
- * Try to load the response from cdrom into buffer.
- */
- if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) {
- sjcd_load_status();
- return (1);
- } else {
- /*
- * No status is available.
- */
- return (0);
- }
-}
-
-/*
- * This is just timeout counter, and nothing more. Surprised ? :-)
- */
-static volatile long sjcd_status_timeout;
-
-/*
- * We need about 10 seconds to wait. The longest command takes about 5 seconds
- * to probe the disk (usually after tray closed or drive reset). Other values
- * should be thought of for other commands.
- */
-#define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
-
-static void sjcd_status_timer(void)
-{
- if (sjcd_check_status()) {
- /*
- * The command completed and status is loaded, stop waiting.
- */
- wake_up(&sjcd_waitq);
- } else if (--sjcd_status_timeout <= 0) {
- /*
- * We are timed out.
- */
- wake_up(&sjcd_waitq);
- } else {
- /*
- * We have still some time to wait. Try again.
- */
- SJCD_SET_TIMER(sjcd_status_timer, 1);
- }
-}
-
-/*
- * Wait for status for 10 sec approx. Returns non-positive when timed out.
- * Should not be used while reading data CDs.
- */
-static int sjcd_wait_for_status(void)
-{
- sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
- SJCD_SET_TIMER(sjcd_status_timer, 1);
- sleep_on(&sjcd_waitq);
-#if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
- if (sjcd_status_timeout <= 0)
- printk("SJCD: Error Wait For Status.\n");
-#endif
- return (sjcd_status_timeout);
-}
-
-static int sjcd_receive_status(void)
-{
- int i;
-#if defined( SJCD_TRACE )
- printk("SJCD: receive_status\n");
-#endif
- /*
- * Wait a bit for status available.
- */
- for (i = 200; i-- && (sjcd_check_status() == 0););
- if (i < 0) {
-#if defined( SJCD_TRACE )
- printk("SJCD: long wait for status\n");
-#endif
- if (sjcd_wait_for_status() <= 0)
- printk("SJCD: Timeout when read status.\n");
- else
- i = 0;
- }
- return (i);
-}
-
-/*
- * Load the status. Issue get status command and wait for status available.
- */
-static void sjcd_get_status(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: get_status\n");
-#endif
- sjcd_send_cmd(SCMD_GET_STATUS);
- sjcd_receive_status();
-}
-
-/*
- * Check the drive if the disk is changed. Should be revised.
- */
-static int sjcd_disk_change(struct gendisk *disk)
-{
-#if 0
- printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name);
-#endif
- if (!sjcd_command_is_in_progress)
- sjcd_get_status();
- return (sjcd_status_valid ? sjcd_media_is_changed : 0);
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary.
- * We assume that the drive contains no more than 99 toc entries.
- */
-static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS];
-static unsigned char sjcd_first_track_no, sjcd_last_track_no;
-#define sjcd_disk_length sjcd_table_of_contents[0].un.track_msf
-
-static int sjcd_update_toc(void)
-{
- struct sjcd_hw_disk_info info;
- int i;
-#if defined( SJCD_TRACE )
- printk("SJCD: update toc:\n");
-#endif
- /*
- * check to see if we need to do anything
- */
- if (sjcd_toc_uptodate)
- return (0);
-
- /*
- * Get the TOC start information.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK);
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&info, sizeof(info)) != 0) {
- printk
- ("SJCD: cannot load response about TOC start.\n");
- return (-1);
- }
- sjcd_first_track_no = bcd2bin(info.un.track_no);
- } else {
- printk("SJCD: get first failed\n");
- return (-1);
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no);
-#endif
- /*
- * Get the TOC finish information.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK);
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&info, sizeof(info)) != 0) {
- printk
- ("SJCD: cannot load response about TOC finish.\n");
- return (-1);
- }
- sjcd_last_track_no = bcd2bin(info.un.track_no);
- } else {
- printk("SJCD: get last failed\n");
- return (-1);
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no);
-#endif
- for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) {
- /*
- * Get the first track information.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i));
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&sjcd_table_of_contents[i],
- sizeof(struct
- sjcd_hw_disk_info))
- != 0) {
- printk
- ("SJCD: cannot load info for %d track\n",
- i);
- return (-1);
- }
- } else {
- printk("SJCD: get info %d failed\n", i);
- return (-1);
- }
- }
-
- /*
- * Get the disk length info.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE);
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&info, sizeof(info)) != 0) {
- printk
- ("SJCD: cannot load response about disk size.\n");
- return (-1);
- }
- sjcd_disk_length.min = info.un.track_msf.min;
- sjcd_disk_length.sec = info.un.track_msf.sec;
- sjcd_disk_length.frame = info.un.track_msf.frame;
- } else {
- printk("SJCD: get size failed\n");
- return (1);
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min,
- sjcd_disk_length.sec, sjcd_disk_length.frame);
-#endif
- return (0);
-}
-
-/*
- * Load subchannel information.
- */
-static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp)
-{
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: load sub q\n");
-#endif
- sjcd_send_cmd(SCMD_GET_QINFO);
- s = sjcd_receive_status();
- if (s < 0 || sjcd_command_failed || !sjcd_status_valid) {
- sjcd_send_cmd(0xF2);
- s = sjcd_receive_status();
- if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
- return (-1);
- sjcd_send_cmd(SCMD_GET_QINFO);
- s = sjcd_receive_status();
- if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
- return (-1);
- }
- if (sjcd_media_is_available)
- if (sjcd_load_response(qp, sizeof(*qp)) == 0)
- return (0);
- return (-1);
-}
-
-/*
- * Start playing from the specified position.
- */
-static int sjcd_play(struct sjcd_play_msf *mp)
-{
- struct sjcd_play_msf msf;
-
- /*
- * Turn the device to play mode.
- */
- sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY);
- if (sjcd_receive_status() < 0)
- return (-1);
-
- /*
- * Seek to the starting point.
- */
- msf.start = mp->start;
- msf.end.min = msf.end.sec = msf.end.frame = 0x00;
- sjcd_send_6_cmd(SCMD_SEEK, &msf);
- if (sjcd_receive_status() < 0)
- return (-1);
-
- /*
- * Start playing.
- */
- sjcd_send_6_cmd(SCMD_PLAY, mp);
- return (sjcd_receive_status());
-}
-
-/*
- * Tray control functions.
- */
-static int sjcd_tray_close(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_close\n");
-#endif
- sjcd_send_cmd(SCMD_CLOSE_TRAY);
- return (sjcd_receive_status());
-}
-
-static int sjcd_tray_lock(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_lock\n");
-#endif
- sjcd_send_cmd(SCMD_LOCK_TRAY);
- return (sjcd_receive_status());
-}
-
-static int sjcd_tray_unlock(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_unlock\n");
-#endif
- sjcd_send_cmd(SCMD_UNLOCK_TRAY);
- return (sjcd_receive_status());
-}
-
-static int sjcd_tray_open(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_open\n");
-#endif
- sjcd_send_cmd(SCMD_EJECT_TRAY);
- return (sjcd_receive_status());
-}
-
-/*
- * Do some user commands.
- */
-static int sjcd_ioctl(struct inode *ip, struct file *fp,
- unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
-#if defined( SJCD_TRACE )
- printk("SJCD:ioctl\n");
-#endif
-
- sjcd_get_status();
- if (!sjcd_status_valid)
- return (-EIO);
- if (sjcd_update_toc() < 0)
- return (-EIO);
-
- switch (cmd) {
- case CDROMSTART:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: start\n");
-#endif
- return (0);
- }
-
- case CDROMSTOP:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: stop\n");
-#endif
- sjcd_send_cmd(SCMD_PAUSE);
- (void) sjcd_receive_status();
- sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
- return (0);
- }
-
- case CDROMPAUSE:{
- struct sjcd_hw_qinfo q_info;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: pause\n");
-#endif
- if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
- sjcd_send_cmd(SCMD_PAUSE);
- (void) sjcd_receive_status();
- if (sjcd_get_q_info(&q_info) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_NO_STATUS;
- } else {
- sjcd_audio_status =
- CDROM_AUDIO_PAUSED;
- sjcd_playing.start = q_info.abs;
- }
- return (0);
- } else
- return (-EINVAL);
- }
-
- case CDROMRESUME:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: resume\n");
-#endif
- if (sjcd_audio_status == CDROM_AUDIO_PAUSED) {
- /*
- * continue play starting at saved location
- */
- if (sjcd_play(&sjcd_playing) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_ERROR;
- return (-EIO);
- } else {
- sjcd_audio_status =
- CDROM_AUDIO_PLAY;
- return (0);
- }
- } else
- return (-EINVAL);
- }
-
- case CDROMPLAYTRKIND:{
- struct cdrom_ti ti;
- int s = -EFAULT;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: playtrkind\n");
-#endif
- if (!copy_from_user(&ti, argp, sizeof(ti))) {
- s = 0;
- if (ti.cdti_trk0 < sjcd_first_track_no)
- return (-EINVAL);
- if (ti.cdti_trk1 > sjcd_last_track_no)
- ti.cdti_trk1 = sjcd_last_track_no;
- if (ti.cdti_trk0 > ti.cdti_trk1)
- return (-EINVAL);
-
- sjcd_playing.start =
- sjcd_table_of_contents[ti.cdti_trk0].
- un.track_msf;
- sjcd_playing.end =
- (ti.cdti_trk1 <
- sjcd_last_track_no) ?
- sjcd_table_of_contents[ti.cdti_trk1 +
- 1].un.
- track_msf : sjcd_table_of_contents[0].
- un.track_msf;
-
- if (sjcd_play(&sjcd_playing) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_ERROR;
- return (-EIO);
- } else
- sjcd_audio_status =
- CDROM_AUDIO_PLAY;
- }
- return (s);
- }
-
- case CDROMPLAYMSF:{
- struct cdrom_msf sjcd_msf;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: playmsf\n");
-#endif
- if ((s =
- access_ok(VERIFY_READ, argp, sizeof(sjcd_msf))
- ? 0 : -EFAULT) == 0) {
- if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
- sjcd_send_cmd(SCMD_PAUSE);
- (void) sjcd_receive_status();
- sjcd_audio_status =
- CDROM_AUDIO_NO_STATUS;
- }
-
- if (copy_from_user(&sjcd_msf, argp,
- sizeof(sjcd_msf)))
- return (-EFAULT);
-
- sjcd_playing.start.min =
- bin2bcd(sjcd_msf.cdmsf_min0);
- sjcd_playing.start.sec =
- bin2bcd(sjcd_msf.cdmsf_sec0);
- sjcd_playing.start.frame =
- bin2bcd(sjcd_msf.cdmsf_frame0);
- sjcd_playing.end.min =
- bin2bcd(sjcd_msf.cdmsf_min1);
- sjcd_playing.end.sec =
- bin2bcd(sjcd_msf.cdmsf_sec1);
- sjcd_playing.end.frame =
- bin2bcd(sjcd_msf.cdmsf_frame1);
-
- if (sjcd_play(&sjcd_playing) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_ERROR;
- return (-EIO);
- } else
- sjcd_audio_status =
- CDROM_AUDIO_PLAY;
- }
- return (s);
- }
-
- case CDROMREADTOCHDR:{
- struct cdrom_tochdr toc_header;
-#if defined (SJCD_TRACE )
- printk("SJCD: ioctl: readtocheader\n");
-#endif
- toc_header.cdth_trk0 = sjcd_first_track_no;
- toc_header.cdth_trk1 = sjcd_last_track_no;
- if (copy_to_user(argp, &toc_header,
- sizeof(toc_header)))
- return -EFAULT;
- return 0;
- }
-
- case CDROMREADTOCENTRY:{
- struct cdrom_tocentry toc_entry;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: readtocentry\n");
-#endif
- if ((s =
- access_ok(VERIFY_WRITE, argp, sizeof(toc_entry))
- ? 0 : -EFAULT) == 0) {
- struct sjcd_hw_disk_info *tp;
-
- if (copy_from_user(&toc_entry, argp,
- sizeof(toc_entry)))
- return (-EFAULT);
- if (toc_entry.cdte_track == CDROM_LEADOUT)
- tp = &sjcd_table_of_contents[0];
- else if (toc_entry.cdte_track <
- sjcd_first_track_no)
- return (-EINVAL);
- else if (toc_entry.cdte_track >
- sjcd_last_track_no)
- return (-EINVAL);
- else
- tp = &sjcd_table_of_contents
- [toc_entry.cdte_track];
-
- toc_entry.cdte_adr =
- tp->track_control & 0x0F;
- toc_entry.cdte_ctrl =
- tp->track_control >> 4;
-
- switch (toc_entry.cdte_format) {
- case CDROM_LBA:
- toc_entry.cdte_addr.lba =
- msf2hsg(&(tp->un.track_msf));
- break;
- case CDROM_MSF:
- toc_entry.cdte_addr.msf.minute =
- bcd2bin(tp->un.track_msf.min);
- toc_entry.cdte_addr.msf.second =
- bcd2bin(tp->un.track_msf.sec);
- toc_entry.cdte_addr.msf.frame =
- bcd2bin(tp->un.track_msf.
- frame);
- break;
- default:
- return (-EINVAL);
- }
- if (copy_to_user(argp, &toc_entry,
- sizeof(toc_entry)))
- s = -EFAULT;
- }
- return (s);
- }
-
- case CDROMSUBCHNL:{
- struct cdrom_subchnl subchnl;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: subchnl\n");
-#endif
- if ((s =
- access_ok(VERIFY_WRITE, argp, sizeof(subchnl))
- ? 0 : -EFAULT) == 0) {
- struct sjcd_hw_qinfo q_info;
-
- if (copy_from_user(&subchnl, argp,
- sizeof(subchnl)))
- return (-EFAULT);
-
- if (sjcd_get_q_info(&q_info) < 0)
- return (-EIO);
-
- subchnl.cdsc_audiostatus =
- sjcd_audio_status;
- subchnl.cdsc_adr =
- q_info.track_control & 0x0F;
- subchnl.cdsc_ctrl =
- q_info.track_control >> 4;
- subchnl.cdsc_trk =
- bcd2bin(q_info.track_no);
- subchnl.cdsc_ind = bcd2bin(q_info.x);
-
- switch (subchnl.cdsc_format) {
- case CDROM_LBA:
- subchnl.cdsc_absaddr.lba =
- msf2hsg(&(q_info.abs));
- subchnl.cdsc_reladdr.lba =
- msf2hsg(&(q_info.rel));
- break;
- case CDROM_MSF:
- subchnl.cdsc_absaddr.msf.minute =
- bcd2bin(q_info.abs.min);
- subchnl.cdsc_absaddr.msf.second =
- bcd2bin(q_info.abs.sec);
- subchnl.cdsc_absaddr.msf.frame =
- bcd2bin(q_info.abs.frame);
- subchnl.cdsc_reladdr.msf.minute =
- bcd2bin(q_info.rel.min);
- subchnl.cdsc_reladdr.msf.second =
- bcd2bin(q_info.rel.sec);
- subchnl.cdsc_reladdr.msf.frame =
- bcd2bin(q_info.rel.frame);
- break;
- default:
- return (-EINVAL);
- }
- if (copy_to_user(argp, &subchnl,
- sizeof(subchnl)))
- s = -EFAULT;
- }
- return (s);
- }
-
- case CDROMVOLCTRL:{
- struct cdrom_volctrl vol_ctrl;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: volctrl\n");
-#endif
- if ((s =
- access_ok(VERIFY_READ, argp, sizeof(vol_ctrl))
- ? 0 : -EFAULT) == 0) {
- unsigned char dummy[4];
-
- if (copy_from_user(&vol_ctrl, argp,
- sizeof(vol_ctrl)))
- return (-EFAULT);
- sjcd_send_4_cmd(SCMD_SET_VOLUME,
- vol_ctrl.channel0, 0xFF,
- vol_ctrl.channel1, 0xFF);
- if (sjcd_receive_status() < 0)
- return (-EIO);
- (void) sjcd_load_response(dummy, 4);
- }
- return (s);
- }
-
- case CDROMEJECT:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: eject\n");
-#endif
- if (!sjcd_command_is_in_progress) {
- sjcd_tray_unlock();
- sjcd_send_cmd(SCMD_EJECT_TRAY);
- (void) sjcd_receive_status();
- }
- return (0);
- }
-
-#if defined( SJCD_GATHER_STAT )
- case 0xABCD:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: statistic\n");
-#endif
- if (copy_to_user(argp, &statistic, sizeof(statistic)))
- return -EFAULT;
- return 0;
- }
-#endif
-
- default:
- return (-EINVAL);
- }
-}
-
-/*
- * Invalidate internal buffers of the driver.
- */
-static void sjcd_invalidate_buffers(void)
-{
- int i;
- for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1);
- sjcd_buf_out = -1;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-static void sjcd_transfer(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: transfer:\n");
-#endif
- if (current_valid()) {
- while (CURRENT->nr_sectors) {
- int i, bn = CURRENT->sector / 4;
- for (i = 0;
- i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn;
- i++);
- if (i < SJCD_BUF_SIZ) {
- int offs =
- (i * 4 + (CURRENT->sector & 3)) * 512;
- int nr_sectors = 4 - (CURRENT->sector & 3);
- if (sjcd_buf_out != i) {
- sjcd_buf_out = i;
- if (sjcd_buf_bn[i] != bn) {
- sjcd_buf_out = -1;
- continue;
- }
- }
- if (nr_sectors > CURRENT->nr_sectors)
- nr_sectors = CURRENT->nr_sectors;
-#if defined( SJCD_TRACE )
- printk("SJCD: copy out\n");
-#endif
- memcpy(CURRENT->buffer, sjcd_buf + offs,
- nr_sectors * 512);
- CURRENT->nr_sectors -= nr_sectors;
- CURRENT->sector += nr_sectors;
- CURRENT->buffer += nr_sectors * 512;
- } else {
- sjcd_buf_out = -1;
- break;
- }
- }
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: transfer: done\n");
-#endif
-}
-
-static void sjcd_poll(void)
-{
-#if defined( SJCD_GATHER_STAT )
- /*
- * Update total number of ticks.
- */
- statistic.ticks++;
- statistic.tticks[sjcd_transfer_state]++;
-#endif
-
- ReSwitch:switch (sjcd_transfer_state) {
-
- case SJCD_S_IDLE:{
-#if defined( SJCD_GATHER_STAT )
- statistic.idle_ticks++;
-#endif
-#if defined( SJCD_TRACE )
- printk("SJCD_S_IDLE\n");
-#endif
- return;
- }
-
- case SJCD_S_START:{
-#if defined( SJCD_GATHER_STAT )
- statistic.start_ticks++;
-#endif
- sjcd_send_cmd(SCMD_GET_STATUS);
- sjcd_transfer_state =
- sjcd_mode ==
- SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
- sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
- printk("SJCD_S_START: goto SJCD_S_%s mode\n",
- sjcd_transfer_state ==
- SJCD_S_READ ? "READ" : "MODE");
-#endif
- break;
- }
-
- case SJCD_S_MODE:{
- if (sjcd_check_status()) {
- /*
- * Previous command is completed.
- */
- if (!sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- sjcd_mode = 0; /* unknown mode; should not be valid when failed */
- sjcd_send_1_cmd(SCMD_SET_MODE,
- SCMD_MODE_COOKED);
- sjcd_transfer_state = SJCD_S_READ;
- sjcd_transfer_timeout = 1000;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_MODE: goto SJCD_S_READ mode\n");
-#endif
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.mode_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_READ:{
- if (sjcd_status_valid ? 1 : sjcd_check_status()) {
- /*
- * Previous command is completed.
- */
- if (!sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
- if (!sjcd_media_is_available) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
- if (sjcd_mode != SCMD_MODE_COOKED) {
- /*
- * We seem to come from set mode. So discard one byte of result.
- */
- if (sjcd_load_response
- (&sjcd_mode, 1) != 0) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state =
- SJCD_S_STOP;
- goto ReSwitch;
- }
- if (sjcd_mode != SCMD_MODE_COOKED) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state =
- SJCD_S_STOP;
- goto ReSwitch;
- }
- }
-
- if (current_valid()) {
- struct sjcd_play_msf msf;
-
- sjcd_next_bn = CURRENT->sector / 4;
- hsg2msf(sjcd_next_bn, &msf.start);
- msf.end.min = 0;
- msf.end.sec = 0;
- msf.end.frame = sjcd_read_count =
- SJCD_BUF_SIZ;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n",
- msf.start.min, msf.start.sec,
- msf.start.frame, msf.end.min,
- msf.end.sec, msf.end.frame);
- printk
- ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n",
- sjcd_next_bn, sjcd_buf_in,
- sjcd_buf_out,
- sjcd_buf_bn[sjcd_buf_in]);
-#endif
- sjcd_send_6_cmd(SCMD_DATA_READ,
- &msf);
- sjcd_transfer_state = SJCD_S_DATA;
- sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: go to SJCD_S_DATA mode\n");
-#endif
- } else {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.read_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_DATA:{
- unsigned char stat;
-
- sjcd_s_data:stat =
- inb(SJCDPORT
- (1));
-#if defined( SJCD_TRACE )
- printk("SJCD_S_DATA: status = 0x%02x\n", stat);
-#endif
- if (SJCD_STATUS_AVAILABLE(stat)) {
- /*
- * No data is waiting for us in the drive buffer. Status of operation
- * completion is available. Read and parse it.
- */
- sjcd_load_status();
-
- if (!sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD: read block %d failed, maybe audio disk? Giving up\n",
- sjcd_next_bn);
-#endif
- if (current_valid())
- end_request(CURRENT, 0);
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- if (!sjcd_media_is_available) {
- printk
- ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n");
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- sjcd_transfer_state = SJCD_S_READ;
- goto ReSwitch;
- } else if (SJCD_DATA_AVAILABLE(stat)) {
- /*
- * One frame is read into device buffer. We must copy it to our memory.
- * Otherwise cdrom hangs up. Check to see if we have something to copy
- * to.
- */
- if (!current_valid()
- && sjcd_buf_in == sjcd_buf_out) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n");
- printk
- (" ... all the date would be discarded\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- /*
- * Everything seems to be OK. Just read the frame and recalculate
- * indices.
- */
- sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */
- insb(SJCDPORT(2),
- sjcd_buf + 2048 * sjcd_buf_in, 2048);
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
- sjcd_next_bn, sjcd_buf_in,
- sjcd_buf_out,
- sjcd_buf_bn[sjcd_buf_in]);
-#endif
- sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++;
- if (sjcd_buf_out == -1)
- sjcd_buf_out = sjcd_buf_in;
- if (++sjcd_buf_in == SJCD_BUF_SIZ)
- sjcd_buf_in = 0;
-
- /*
- * Only one frame is ready at time. So we should turn over to wait for
- * another frame. If we need that, of course.
- */
- if (--sjcd_read_count == 0) {
- /*
- * OK, request seems to be precessed. Continue transferring...
- */
- if (!sjcd_transfer_is_active) {
- while (current_valid()) {
- /*
- * Continue transferring.
- */
- sjcd_transfer();
- if (CURRENT->
- nr_sectors ==
- 0)
- end_request
- (CURRENT, 1);
- else
- break;
- }
- }
- if (current_valid() &&
- (CURRENT->sector / 4 <
- sjcd_next_bn
- || CURRENT->sector / 4 >
- sjcd_next_bn +
- SJCD_BUF_SIZ)) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state =
- SJCD_S_STOP;
- goto ReSwitch;
- }
- }
- /*
- * Now we should turn around rather than wait for while.
- */
- goto sjcd_s_data;
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.data_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_STOP:{
- sjcd_read_count = 0;
- sjcd_send_cmd(SCMD_STOP);
- sjcd_transfer_state = SJCD_S_STOPPING;
- sjcd_transfer_timeout = 500;
-#if defined( SJCD_GATHER_STAT )
- statistic.stop_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_STOPPING:{
- unsigned char stat;
-
- stat = inb(SJCDPORT(1));
-#if defined( SJCD_TRACE )
- printk("SJCD_S_STOP: status = 0x%02x\n", stat);
-#endif
- if (SJCD_DATA_AVAILABLE(stat)) {
- int i;
-#if defined( SJCD_TRACE )
- printk("SJCD_S_STOP: discard data\n");
-#endif
- /*
- * Discard all the data from the pipe. Foolish method.
- */
- for (i = 2048; i--;
- (void) inb(SJCDPORT(2)));
- sjcd_transfer_timeout = 500;
- } else if (SJCD_STATUS_AVAILABLE(stat)) {
- sjcd_load_status();
- if (sjcd_status_valid
- && sjcd_media_is_changed) {
- sjcd_toc_uptodate = 0;
- sjcd_invalidate_buffers();
- }
- if (current_valid()) {
- if (sjcd_status_valid)
- sjcd_transfer_state =
- SJCD_S_READ;
- else
- sjcd_transfer_state =
- SJCD_S_START;
- } else
- sjcd_transfer_state = SJCD_S_IDLE;
- goto ReSwitch;
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.stopping_ticks++;
-#endif
- break;
- }
-
- default:
- printk("SJCD: poll: invalid state %d\n",
- sjcd_transfer_state);
- return;
- }
-
- if (--sjcd_transfer_timeout == 0) {
- printk("SJCD: timeout in state %d\n", sjcd_transfer_state);
- while (current_valid())
- end_request(CURRENT, 0);
- sjcd_send_cmd(SCMD_STOP);
- sjcd_transfer_state = SJCD_S_IDLE;
- goto ReSwitch;
- }
-
- /*
- * Get back in some time. 1 should be replaced with count variable to
- * avoid unnecessary testings.
- */
- SJCD_SET_TIMER(sjcd_poll, 1);
-}
-
-static void do_sjcd_request(request_queue_t * q)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: do_sjcd_request(%ld+%ld)\n",
- CURRENT->sector, CURRENT->nr_sectors);
-#endif
- sjcd_transfer_is_active = 1;
- while (current_valid()) {
- sjcd_transfer();
- if (CURRENT->nr_sectors == 0)
- end_request(CURRENT, 1);
- else {
- sjcd_buf_out = -1; /* Want to read a block not in buffer */
- if (sjcd_transfer_state == SJCD_S_IDLE) {
- if (!sjcd_toc_uptodate) {
- if (sjcd_update_toc() < 0) {
- printk
- ("SJCD: transfer: discard\n");
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- }
- sjcd_transfer_state = SJCD_S_START;
- SJCD_SET_TIMER(sjcd_poll, HZ / 100);
- }
- break;
- }
- }
- sjcd_transfer_is_active = 0;
-#if defined( SJCD_TRACE )
- printk
- ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
- sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
- sjcd_buf_bn[sjcd_buf_in]);
- printk("do_sjcd_request ends\n");
-#endif
-}
-
-/*
- * Open the device special file. Check disk is in.
- */
-static int sjcd_open(struct inode *ip, struct file *fp)
-{
- /*
- * Check the presence of device.
- */
- if (!sjcd_present)
- return (-ENXIO);
-
- /*
- * Only read operations are allowed. Really? (:-)
- */
- if (fp->f_mode & 2)
- return (-EROFS);
-
- if (sjcd_open_count == 0) {
- int s, sjcd_open_tries;
-/* We don't know that, do we? */
-/*
- sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
-*/
- sjcd_mode = 0;
- sjcd_door_was_open = 0;
- sjcd_transfer_state = SJCD_S_IDLE;
- sjcd_invalidate_buffers();
- sjcd_status_valid = 0;
-
- /*
- * Strict status checking.
- */
- for (sjcd_open_tries = 4; --sjcd_open_tries;) {
- if (!sjcd_status_valid)
- sjcd_get_status();
- if (!sjcd_status_valid) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: open: timed out when check status.\n");
-#endif
- goto err_out;
- } else if (!sjcd_media_is_available) {
-#if defined( SJCD_DIAGNOSTIC )
- printk("SJCD: open: no disk in drive\n");
-#endif
- if (!sjcd_door_closed) {
- sjcd_door_was_open = 1;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD: open: close the tray\n");
-#endif
- s = sjcd_tray_close();
- if (s < 0 || !sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: open: tray close attempt failed\n");
-#endif
- goto err_out;
- }
- continue;
- } else
- goto err_out;
- }
- break;
- }
- s = sjcd_tray_lock();
- if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk("SJCD: open: tray lock attempt failed\n");
-#endif
- goto err_out;
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: open: done\n");
-#endif
- }
-
- ++sjcd_open_count;
- return (0);
-
- err_out:
- return (-EIO);
-}
-
-/*
- * On close, we flush all sjcd blocks from the buffer cache.
- */
-static int sjcd_release(struct inode *inode, struct file *file)
-{
- int s;
-
-#if defined( SJCD_TRACE )
- printk("SJCD: release\n");
-#endif
- if (--sjcd_open_count == 0) {
- sjcd_invalidate_buffers();
- s = sjcd_tray_unlock();
- if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: release: tray unlock attempt failed.\n");
-#endif
- }
- if (sjcd_door_was_open) {
- s = sjcd_tray_open();
- if (s < 0 || !sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: release: tray unload attempt failed.\n");
-#endif
- }
- }
- }
- return 0;
-}
-
-/*
- * A list of file operations allowed for this cdrom.
- */
-static struct block_device_operations sjcd_fops = {
- .owner = THIS_MODULE,
- .open = sjcd_open,
- .release = sjcd_release,
- .ioctl = sjcd_ioctl,
- .media_changed = sjcd_disk_change,
-};
-
-/*
- * Following stuff is intended for initialization of the cdrom. It
- * first looks for presence of device. If the device is present, it
- * will be reset. Then read the version of the drive and load status.
- * The version is two BCD-coded bytes.
- */
-static struct {
- unsigned char major, minor;
-} sjcd_version;
-
-static struct gendisk *sjcd_disk;
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- * Probe cdrom, find out version and status.
- */
-static int __init sjcd_init(void)
-{
- int i;
-
- printk(KERN_INFO
- "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n",
- SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);
-
-#if defined( SJCD_TRACE )
- printk("SJCD: sjcd=0x%x: ", sjcd_base);
-#endif
-
- if (register_blkdev(MAJOR_NR, "sjcd"))
- return -EIO;
-
- sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock);
- if (!sjcd_queue)
- goto out0;
-
- blk_queue_hardsect_size(sjcd_queue, 2048);
-
- sjcd_disk = alloc_disk(1);
- if (!sjcd_disk) {
- printk(KERN_ERR "SJCD: can't allocate disk");
- goto out1;
- }
- sjcd_disk->major = MAJOR_NR,
- sjcd_disk->first_minor = 0,
- sjcd_disk->fops = &sjcd_fops,
- sprintf(sjcd_disk->disk_name, "sjcd");
-
- if (!request_region(sjcd_base, 4,"sjcd")) {
- printk
- ("SJCD: Init failed, I/O port (%X) is already in use\n",
- sjcd_base);
- goto out2;
- }
-
- /*
- * Check for card. Since we are booting now, we can't use standard
- * wait algorithm.
- */
- printk(KERN_INFO "SJCD: Resetting: ");
- sjcd_send_cmd(SCMD_RESET);
- for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
- unsigned long timer;
-
- /*
- * Wait 10ms approx.
- */
- for (timer = jiffies; time_before_eq(jiffies, timer););
- if ((i % 100) == 0)
- printk(".");
- (void) sjcd_check_status();
- }
- if (i == 0 || sjcd_command_failed) {
- printk(" reset failed, no drive found.\n");
- goto out3;
- } else
- printk("\n");
-
- /*
- * Get and print out cdrom version.
- */
- printk(KERN_INFO "SJCD: Getting version: ");
- sjcd_send_cmd(SCMD_GET_VERSION);
- for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
- unsigned long timer;
-
- /*
- * Wait 10ms approx.
- */
- for (timer = jiffies; time_before_eq(jiffies, timer););
- if ((i % 100) == 0)
- printk(".");
- (void) sjcd_check_status();
- }
- if (i == 0 || sjcd_command_failed) {
- printk(" get version failed, no drive found.\n");
- goto out3;
- }
-
- if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {
- printk(" %1x.%02x\n", (int) sjcd_version.major,
- (int) sjcd_version.minor);
- } else {
- printk(" read version failed, no drive found.\n");
- goto out3;
- }
-
- /*
- * Check and print out the tray state. (if it is needed?).
- */
- if (!sjcd_status_valid) {
- printk(KERN_INFO "SJCD: Getting status: ");
- sjcd_send_cmd(SCMD_GET_STATUS);
- for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
- unsigned long timer;
-
- /*
- * Wait 10ms approx.
- */
- for (timer = jiffies;
- time_before_eq(jiffies, timer););
- if ((i % 100) == 0)
- printk(".");
- (void) sjcd_check_status();
- }
- if (i == 0 || sjcd_command_failed) {
- printk(" get status failed, no drive found.\n");
- goto out3;
- } else
- printk("\n");
- }
-
- printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
- sjcd_disk->queue = sjcd_queue;
- add_disk(sjcd_disk);
-
- sjcd_present++;
- return (0);
-out3:
- release_region(sjcd_base, 4);
-out2:
- put_disk(sjcd_disk);
-out1:
- blk_cleanup_queue(sjcd_queue);
-out0:
- if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
- printk("SJCD: cannot unregister device.\n");
- return (-EIO);
-}
-
-static void __exit sjcd_exit(void)
-{
- del_gendisk(sjcd_disk);
- put_disk(sjcd_disk);
- release_region(sjcd_base, 4);
- blk_cleanup_queue(sjcd_queue);
- if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
- printk("SJCD: cannot unregister device.\n");
- printk(KERN_INFO "SJCD: module: removed.\n");
-}
-
-module_init(sjcd_init);
-module_exit(sjcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR);
diff --git a/drivers/cdrom/sjcd.h b/drivers/cdrom/sjcd.h
deleted file mode 100644
index 0aa5e714659..00000000000
--- a/drivers/cdrom/sjcd.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Definitions for a Sanyo CD-ROM interface.
- *
- * Copyright (C) 1995 Vadim V. Model
- * model@cecmow.enet.dec.com
- * vadim@rbrf.msk.su
- * vadim@ipsun.ras.ru
- * Eric van der Maarel
- * H.T.M.v.d.Maarel@marin.nl
- *
- * This information is based on mcd.c from M. Harriss and sjcd102.lst from
- * E. Moenkeberg.
- *
- * 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.
- */
-
-#ifndef __SJCD_H__
-#define __SJCD_H__
-
-/*
- * Change this to set the I/O port address as default. More flexibility
- * come with setup implementation.
- */
-#define SJCD_BASE_ADDR 0x340
-
-/*
- * Change this to set the irq as default. Really SANYO do not use interrupts
- * at all.
- */
-#define SJCD_INTR_NR 0
-
-/*
- * Change this to set the dma as default value. really SANYO does not use
- * direct memory access at all.
- */
-#define SJCD_DMA_NR 0
-
-/*
- * Macros which allow us to find out the status of the drive.
- */
-#define SJCD_STATUS_AVAILABLE( x ) (((x)&0x02)==0)
-#define SJCD_DATA_AVAILABLE( x ) (((x)&0x01)==0)
-
-/*
- * Port access macro. Three ports are available: S-data port (command port),
- * status port (read only) and D-data port (read only).
- */
-#define SJCDPORT( x ) ( sjcd_base + ( x ) )
-#define SJCD_STATUS_PORT SJCDPORT( 1 )
-#define SJCD_S_DATA_PORT SJCDPORT( 0 )
-#define SJCD_COMMAND_PORT SJCDPORT( 0 )
-#define SJCD_D_DATA_PORT SJCDPORT( 2 )
-
-/*
- * Drive info bits. Drive info available as first (mandatory) byte of
- * command completion status.
- */
-#define SST_NOT_READY 0x10 /* no disk in the drive (???) */
-#define SST_MEDIA_CHANGED 0x20 /* disk is changed */
-#define SST_DOOR_OPENED 0x40 /* door is open */
-
-/* commands */
-
-#define SCMD_EJECT_TRAY 0xD0 /* eject tray if not locked */
-#define SCMD_LOCK_TRAY 0xD2 /* lock tray when in */
-#define SCMD_UNLOCK_TRAY 0xD4 /* unlock tray when in */
-#define SCMD_CLOSE_TRAY 0xD6 /* load tray in */
-
-#define SCMD_RESET 0xFA /* soft reset */
-#define SCMD_GET_STATUS 0x80
-#define SCMD_GET_VERSION 0xCC
-
-#define SCMD_DATA_READ 0xA0 /* are the same, depend on mode&args */
-#define SCMD_SEEK 0xA0
-#define SCMD_PLAY 0xA0
-
-#define SCMD_GET_QINFO 0xA8
-
-#define SCMD_SET_MODE 0xC4
-#define SCMD_MODE_PLAY 0xE0
-#define SCMD_MODE_COOKED (0xF8 & ~0x20)
-#define SCMD_MODE_RAW 0xF9
-#define SCMD_MODE_x20_BIT 0x20 /* What is it for ? */
-
-#define SCMD_SET_VOLUME 0xAE
-#define SCMD_PAUSE 0xE0
-#define SCMD_STOP 0xE0
-
-#define SCMD_GET_DISK_INFO 0xAA
-
-/*
- * Some standard arguments for SCMD_GET_DISK_INFO.
- */
-#define SCMD_GET_1_TRACK 0xA0 /* get the first track information */
-#define SCMD_GET_L_TRACK 0xA1 /* get the last track information */
-#define SCMD_GET_D_SIZE 0xA2 /* get the whole disk information */
-
-/*
- * Borrowed from hd.c. Allows to optimize multiple port read commands.
- */
-#define S_READ_DATA( port, buf, nr ) insb( port, buf, nr )
-
-/*
- * We assume that there are no audio disks with TOC length more than this
- * number (I personally have never seen disks with more than 20 fragments).
- */
-#define SJCD_MAX_TRACKS 100
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct sjcd_hw_disk_info {
- unsigned char track_control;
- unsigned char track_no;
- unsigned char x, y, z;
- union {
- unsigned char track_no;
- struct msf track_msf;
- } un;
-};
-
-struct sjcd_hw_qinfo {
- unsigned char track_control;
- unsigned char track_no;
- unsigned char x;
- struct msf rel;
- struct msf abs;
-};
-
-struct sjcd_play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct sjcd_disk_info {
- unsigned char first;
- unsigned char last;
- struct msf disk_length;
- struct msf first_track;
-};
-
-struct sjcd_toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char point_index;
- struct msf track_time;
- struct msf disk_time;
-};
-
-#if defined( SJCD_GATHER_STAT )
-
-struct sjcd_stat {
- int ticks;
- int tticks[ 8 ];
- int idle_ticks;
- int start_ticks;
- int mode_ticks;
- int read_ticks;
- int data_ticks;
- int stop_ticks;
- int stopping_ticks;
-};
-
-#endif
-
-#endif
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
deleted file mode 100644
index f77ada933ea..00000000000
--- a/drivers/cdrom/sonycd535.c
+++ /dev/null
@@ -1,1689 +0,0 @@
-/*
- * Sony CDU-535 interface device driver
- *
- * This is a modified version of the CDU-31A device driver (see below).
- * Changes were made using documentation for the CDU-531 (which Sony
- * assures me is very similar to the 535) and partial disassembly of the
- * DOS driver. I used Minyard's driver and replaced the CDU-31A
- * commands with the CDU-531 commands. This was complicated by a different
- * interface protocol with the drive. The driver is still polled.
- *
- * Data transfer rate is about 110 Kb/sec, theoretical maximum is 150 Kb/sec.
- * I tried polling without the sony_sleep during the data transfers but
- * it did not speed things up any.
- *
- * 1993-05-23 (rgj) changed the major number to 21 to get rid of conflict
- * with CDU-31A driver. This is the also the number from the Linux
- * Device Driver Registry for the Sony Drive. Hope nobody else is using it.
- *
- * 1993-08-29 (rgj) remove the configuring of the interface board address
- * from the top level configuration, you have to modify it in this file.
- *
- * 1995-01-26 Made module-capable (Joel Katz <Stimpson@Panix.COM>)
- *
- * 1995-05-20
- * Modified to support CDU-510/515 series
- * (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- * Fixed to report verify_area() failures
- * (Heiko Eissfeldt <heiko@colossus.escape.de>)
- *
- * 1995-06-01
- * More changes to support CDU-510/515 series
- * (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * September 2003 - Fix SMP support by removing cli/sti calls.
- * Using spinlocks with a wait_queue instead.
- * Felipe Damasio <felipewd@terra.com.br>
- *
- * Things to do:
- * - handle errors and status better, put everything into a single word
- * - use interrupts (code mostly there, but a big hole still missing)
- * - handle multi-session CDs?
- * - use DMA?
- *
- * Known Bugs:
- * -
- *
- * Ken Pizzini (ken@halcyon.com)
- *
- * Original by:
- * Ron Jeppesen (ronj.an@site007.saic.com)
- *
- *
- *------------------------------------------------------------------------
- * Sony CDROM interface device driver.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above)
- *
- * Colossians 3:17
- *
- * The Sony interface device driver handles Sony interface CDROM
- * drives and provides a complete block-level interface as well as an
- * ioctl() interface compatible with the Sun (as specified in
- * include/linux/cdrom.h). With this interface, CDROMs can be
- * accessed and standard audio CDs can be played back normally.
- *
- * This interface is (unfortunately) a polled interface. This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables. Some (like mine) do not even have the capability to
- * handle interrupts or DMA. For this reason you will see a bit of
- * the following:
- *
- * snap = jiffies;
- * while (jiffies-snap < SONY_JIFFIES_TIMEOUT)
- * {
- * if (some_condition())
- * break;
- * sony_sleep();
- * }
- * if (some_condition not met)
- * {
- * return an_error;
- * }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try. (The conditional is written so that jiffies
- * wrap-around is handled properly.)
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk. The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal. A lot of conversion goes on.
- *
- * Copyright (C) 1993 Corey Minyard
- *
- * 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.
- *
- */
-
-
-# include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#define REALLY_SLOW_IO
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/cdrom.h>
-
-#define MAJOR_NR CDU535_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
-#include "sonycd535.h"
-
-/*
- * this is the base address of the interface card for the Sony CDU-535
- * CDROM drive. If your jumpers are set for an address other than
- * this one (the default), change the following line to the
- * proper address.
- */
-#ifndef CDU535_ADDRESS
-# define CDU535_ADDRESS 0x340
-#endif
-#ifndef CDU535_INTERRUPT
-# define CDU535_INTERRUPT 0
-#endif
-#ifndef CDU535_HANDLE
-# define CDU535_HANDLE "cdu535"
-#endif
-#ifndef CDU535_MESSAGE_NAME
-# define CDU535_MESSAGE_NAME "Sony CDU-535"
-#endif
-
-#define CDU535_BLOCK_SIZE 2048
-
-#ifndef MAX_SPINUP_RETRY
-# define MAX_SPINUP_RETRY 3 /* 1 is sufficient for most drives... */
-#endif
-#ifndef RETRY_FOR_BAD_STATUS
-# define RETRY_FOR_BAD_STATUS 100 /* in 10th of second */
-#endif
-
-#ifndef DEBUG
-# define DEBUG 1
-#endif
-
-/*
- * SONY535_BUFFER_SIZE determines the size of internal buffer used
- * by the drive. It must be at least 2K and the larger the buffer
- * the better the transfer rate. It does however take system memory.
- * On my system I get the following transfer rates using dd to read
- * 10 Mb off /dev/cdrom.
- *
- * 8K buffer 43 Kb/sec
- * 16K buffer 66 Kb/sec
- * 32K buffer 91 Kb/sec
- * 64K buffer 111 Kb/sec
- * 128K buffer 123 Kb/sec
- * 512K buffer 123 Kb/sec
- */
-#define SONY535_BUFFER_SIZE (64*1024)
-
-/*
- * if LOCK_DOORS is defined then the eject button is disabled while
- * the device is open.
- */
-#ifndef NO_LOCK_DOORS
-# define LOCK_DOORS
-#endif
-
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int cdu_open(struct inode *inode, struct file *filp);
-static inline unsigned int int_to_bcd(unsigned int val);
-static unsigned int bcd_to_int(unsigned int bcd);
-static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
- Byte * response, int n_response, int ignoreStatusBit7);
-
-/* The base I/O address of the Sony Interface. This is a variable (not a
- #define) so it can be easily changed via some future ioctl() */
-static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
-module_param(sony535_cd_base_io, int, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive. The
- * comment for the base address also applies here.
- */
-static unsigned short select_unit_reg;
-static unsigned short result_reg;
-static unsigned short command_reg;
-static unsigned short read_status_reg;
-static unsigned short data_reg;
-
-static DEFINE_SPINLOCK(sonycd535_lock); /* queue lock */
-static struct request_queue *sonycd535_queue;
-
-static int initialized; /* Has the drive been initialized? */
-static int sony_disc_changed = 1; /* Has the disk been changed
- since the last check? */
-static int sony_toc_read; /* Has the table of contents been
- read? */
-static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead
- buffer. */
-static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of
- the read-ahead buffer. */
-static unsigned int sony_usage; /* How many processes have the
- drive open. */
-
-static int sony_first_block = -1; /* First OS block (512 byte) in
- the read-ahead buffer */
-static int sony_last_block = -1; /* Last OS block (512 byte) in
- the read-ahead buffer */
-
-static struct s535_sony_toc *sony_toc; /* Points to the table of
- contents. */
-
-static struct s535_sony_subcode *last_sony_subcode; /* Points to the last
- subcode address read */
-static Byte **sony_buffer; /* Points to the pointers
- to the sector buffers */
-
-static int sony_inuse; /* is the drive in use? Only one
- open at a time allowed */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play. The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over. This holds the
- * position during a pause so a resume can restart it. It uses the
- * audio status variable above to tell if it is paused.
- * I just kept the CDU-31A driver behavior rather than using the PAUSE
- * command on the CDU-535.
- */
-static Byte cur_pos_msf[3];
-static Byte final_pos_msf[3];
-
-/* What IRQ is the drive using? 0 if none. */
-static int sony535_irq_used = CDU535_INTERRUPT;
-
-/* The interrupt handler will wake this queue up when it gets an interrupt. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
-
-
-/*
- * This routine returns 1 if the disk has been changed since the last
- * check or 0 if it hasn't. Setting flag to 0 resets the changed flag.
- */
-static int
-cdu535_check_media_change(struct gendisk *disk)
-{
- /* if driver is not initialized, always return 0 */
- int retval = initialized ? sony_disc_changed : 0;
- sony_disc_changed = 0;
- return retval;
-}
-
-static inline void
-enable_interrupts(void)
-{
-#ifdef USE_IRQ
- /*
- * This code was taken from cdu31a.c; it will not
- * directly work for the cdu535 as written...
- */
- curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static inline void
-disable_interrupts(void)
-{
-#ifdef USE_IRQ
- /*
- * This code was taken from cdu31a.c; it will not
- * directly work for the cdu535 as written...
- */
- curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static irqreturn_t
-cdu535_interrupt(int irq, void *dev_id)
-{
- disable_interrupts();
- if (waitqueue_active(&cdu535_irq_wait)) {
- wake_up(&cdu535_irq_wait);
- return IRQ_HANDLED;
- }
- printk(CDU535_MESSAGE_NAME
- ": Got an interrupt but nothing was waiting\n");
- return IRQ_NONE;
-}
-
-
-/*
- * Wait a little while.
- */
-static inline void
-sony_sleep(void)
-{
- if (sony535_irq_used <= 0) { /* poll */
- yield();
- } else { /* Interrupt driven */
- DEFINE_WAIT(wait);
-
- spin_lock_irq(&sonycd535_lock);
- enable_interrupts();
- prepare_to_wait(&cdu535_irq_wait, &wait, TASK_INTERRUPTIBLE);
- spin_unlock_irq(&sonycd535_lock);
- schedule();
- finish_wait(&cdu535_irq_wait, &wait);
- }
-}
-
-/*------------------start of SONY CDU535 very specific ---------------------*/
-
-/****************************************************************************
- * void select_unit( int unit_no )
- *
- * Select the specified unit (0-3) so that subsequent commands reference it
- ****************************************************************************/
-static void
-select_unit(int unit_no)
-{
- unsigned int select_mask = ~(1 << unit_no);
- outb(select_mask, select_unit_reg);
-}
-
-/***************************************************************************
- * int read_result_reg( Byte *data_ptr )
- *
- * Read a result byte from the Sony CDU controller, store in location pointed
- * to by data_ptr. Return zero on success, TIME_OUT if we did not receive
- * data.
- ***************************************************************************/
-static int
-read_result_reg(Byte *data_ptr)
-{
- unsigned long snap;
- int read_status;
-
- snap = jiffies;
- while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
- read_status = inb(read_status_reg);
- if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
-#if DEBUG > 1
- printk(CDU535_MESSAGE_NAME
- ": read_result_reg(): readStatReg = 0x%x\n", read_status);
-#endif
- *data_ptr = inb(result_reg);
- return 0;
- } else {
- sony_sleep();
- }
- }
- printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");
- return TIME_OUT;
-}
-
-/****************************************************************************
- * int read_exec_status( Byte status[2] )
- *
- * Read the execution status of the last command and put into status.
- * Handles reading second status word if available. Returns 0 on success,
- * TIME_OUT on failure.
- ****************************************************************************/
-static int
-read_exec_status(Byte status[2])
-{
- status[1] = 0;
- if (read_result_reg(&(status[0])) != 0)
- return TIME_OUT;
- if ((status[0] & 0x80) != 0) { /* byte two follows */
- if (read_result_reg(&(status[1])) != 0)
- return TIME_OUT;
- }
-#if DEBUG > 1
- printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",
- status[0], status[1]);
-#endif
- return 0;
-}
-
-/****************************************************************************
- * int check_drive_status( void )
- *
- * Check the current drive status. Using this before executing a command
- * takes care of the problem of unsolicited drive status-2 messages.
- * Add a check of the audio status if we think the disk is playing.
- ****************************************************************************/
-static int
-check_drive_status(void)
-{
- Byte status, e_status[2];
- int CDD, ATN;
- Byte cmd;
-
- select_unit(0);
- if (sony_audio_status == CDROM_AUDIO_PLAY) { /* check status */
- outb(SONY535_REQUEST_AUDIO_STATUS, command_reg);
- if (read_result_reg(&status) == 0) {
- switch (status) {
- case 0x0:
- break; /* play in progress */
- case 0x1:
- break; /* paused */
- case 0x3: /* audio play completed */
- case 0x5: /* play not requested */
- sony_audio_status = CDROM_AUDIO_COMPLETED;
- read_subcode();
- break;
- case 0x4: /* error during play */
- sony_audio_status = CDROM_AUDIO_ERROR;
- break;
- }
- }
- }
- /* now check drive status */
- outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg);
- if (read_result_reg(&status) != 0)
- return TIME_OUT;
-
-#if DEBUG > 1
- printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status);
-#endif
-
- if (status == 0)
- return 0;
-
- ATN = status & 0xf;
- CDD = (status >> 4) & 0xf;
-
- switch (ATN) {
- case 0x0:
- break; /* go on to CDD stuff */
- case SONY535_ATN_BUSY:
- if (initialized)
- printk(CDU535_MESSAGE_NAME " error: drive busy\n");
- return CD_BUSY;
- case SONY535_ATN_EJECT_IN_PROGRESS:
- printk(CDU535_MESSAGE_NAME " error: eject in progress\n");
- sony_audio_status = CDROM_AUDIO_INVALID;
- return CD_BUSY;
- case SONY535_ATN_RESET_OCCURRED:
- case SONY535_ATN_DISC_CHANGED:
- case SONY535_ATN_RESET_AND_DISC_CHANGED:
-#if DEBUG > 0
- printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n");
-#endif
- sony_disc_changed = 1;
- sony_toc_read = 0;
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- sony_first_block = -1;
- sony_last_block = -1;
- if (initialized) {
- cmd = SONY535_SPIN_UP;
- do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0);
- sony_get_toc();
- }
- return 0;
- default:
- printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN);
- return CD_BUSY;
- }
- switch (CDD) { /* the 531 docs are not helpful in decoding this */
- case 0x0: /* just use the values from the DOS driver */
- case 0x2:
- case 0xa:
- break; /* no error */
- case 0xc:
- printk(CDU535_MESSAGE_NAME
- ": check_drive_status(): CDD = 0xc! Not properly handled!\n");
- return CD_BUSY; /* ? */
- default:
- return CD_BUSY;
- }
- return 0;
-} /* check_drive_status() */
-
-/*****************************************************************************
- * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
- * Byte *response, int n_response, int ignore_status_bit7 )
- *
- * Generic routine for executing commands. The command and its parameters
- * should be placed in the cmd[] array, number of bytes in the command is
- * stored in nCmd. The response from the command will be stored in the
- * response array. The number of bytes you expect back (excluding status)
- * should be passed in n_response. Finally, some
- * commands set bit 7 of the return status even when there is no second
- * status byte, on these commands set ignoreStatusBit7 TRUE.
- * If the command was sent and data received back, then we return 0,
- * else we return TIME_OUT. You still have to check the status yourself.
- * You should call check_drive_status() before calling this routine
- * so that you do not lose notifications of disk changes, etc.
- ****************************************************************************/
-static int
-do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
- Byte * response, int n_response, int ignore_status_bit7)
-{
- int i;
-
- /* write out the command */
- for (i = 0; i < n_cmd; i++)
- outb(cmd[i], command_reg);
-
- /* read back the status */
- if (read_result_reg(status) != 0)
- return TIME_OUT;
- if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) {
- /* get second status byte */
- if (read_result_reg(status + 1) != 0)
- return TIME_OUT;
- } else {
- status[1] = 0;
- }
-#if DEBUG > 2
- printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n",
- *cmd, status[0], status[1]);
-#endif
-
- /* do not know about when I should read set of data and when not to */
- if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0)
- return 0;
-
- /* else, read in rest of data */
- for (i = 0; 0 < n_response; n_response--, i++)
- if (read_result_reg(response + i) != 0)
- return TIME_OUT;
- return 0;
-} /* do_sony_cmd() */
-
-/**************************************************************************
- * int set_drive_mode( int mode, Byte status[2] )
- *
- * Set the drive mode to the specified value (mode=0 is audio, mode=e0
- * is mode-1 CDROM
- **************************************************************************/
-static int
-set_drive_mode(int mode, Byte status[2])
-{
- Byte cmd_buff[2];
- Byte ret_buff[1];
-
- cmd_buff[0] = SONY535_SET_DRIVE_MODE;
- cmd_buff[1] = mode;
- return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1);
-}
-
-/***************************************************************************
- * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
- * Byte *data_buff, int buff_size )
- *
- * Read n_blocks of data from the CDROM starting at position params[0:2],
- * number of blocks in stored in params[3:5] -- both these are already
- * int bcd format.
- * Transfer the data into the buffer pointed at by data_buff. buff_size
- * gives the number of bytes available in the buffer.
- * The routine returns number of bytes read in if successful, otherwise
- * it returns one of the standard error returns.
- ***************************************************************************/
-static int
-seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
- Byte **buff, int buf_size)
-{
- Byte cmd_buff[7];
- int i;
- int read_status;
- unsigned long snap;
- Byte *data_buff;
- int sector_count = 0;
-
- if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
- return NO_ROOM;
-
- set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
-
- /* send command to read the data */
- cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1;
- for (i = 0; i < 6; i++)
- cmd_buff[i + 1] = params[i];
- for (i = 0; i < 7; i++)
- outb(cmd_buff[i], command_reg);
-
- /* read back the data one block at a time */
- while (0 < n_blocks--) {
- /* wait for data to be ready */
- int data_valid = 0;
- snap = jiffies;
- while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
- read_status = inb(read_status_reg);
- if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
- read_exec_status(status);
- return BAD_STATUS;
- }
- if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
- /* data is ready, read it */
- data_buff = buff[sector_count++];
- for (i = 0; i < CDU535_BLOCK_SIZE; i++)
- *data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */
- data_valid = 1;
- break; /* exit the timeout loop */
- }
- sony_sleep(); /* data not ready, sleep a while */
- }
- if (!data_valid)
- return TIME_OUT; /* if we reach this stage */
- }
-
- /* read all the data, now read the status */
- if ((i = read_exec_status(status)) != 0)
- return i;
- return CDU535_BLOCK_SIZE * sector_count;
-} /* seek_and_read_N_blocks() */
-
-/****************************************************************************
- * int request_toc_data( Byte status[2], struct s535_sony_toc *toc )
- *
- * Read in the table of contents data. Converts all the bcd data
- * into integers in the toc structure.
- ****************************************************************************/
-static int
-request_toc_data(Byte status[2], struct s535_sony_toc *toc)
-{
- int to_status;
- int i, j, n_tracks, track_no;
- int first_track_num, last_track_num;
- Byte cmd_no = 0xb2;
- Byte track_address_buffer[5];
-
- /* read the fixed portion of the table of contents */
- if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0)
- return to_status;
-
- /* convert the data into integers so we can use them */
- first_track_num = bcd_to_int(toc->first_track_num);
- last_track_num = bcd_to_int(toc->last_track_num);
- n_tracks = last_track_num - first_track_num + 1;
-
- /* read each of the track address descriptors */
- for (i = 0; i < n_tracks; i++) {
- /* read the descriptor into a temporary buffer */
- for (j = 0; j < 5; j++) {
- if (read_result_reg(track_address_buffer + j) != 0)
- return TIME_OUT;
- if (j == 1) /* need to convert from bcd */
- track_no = bcd_to_int(track_address_buffer[j]);
- }
- /* copy the descriptor to proper location - sonycd.c just fills */
- memcpy(toc->tracks + i, track_address_buffer, 5);
- }
- return 0;
-} /* request_toc_data() */
-
-/***************************************************************************
- * int spin_up_drive( Byte status[2] )
- *
- * Spin up the drive (unless it is already spinning).
- ***************************************************************************/
-static int
-spin_up_drive(Byte status[2])
-{
- Byte cmd;
-
- /* first see if the drive is already spinning */
- cmd = SONY535_REQUEST_DRIVE_STATUS_1;
- if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0)
- return TIME_OUT;
- if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0)
- return 0; /* it's already spinning */
-
- /* otherwise, give the spin-up command */
- cmd = SONY535_SPIN_UP;
- return do_sony_cmd(&cmd, 1, status, NULL, 0, 0);
-}
-
-/*--------------------end of SONY CDU535 very specific ---------------------*/
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int
-int_to_bcd(unsigned int val)
-{
- int retval;
-
- retval = (val / 10) << 4;
- retval = retval | val % 10;
- return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int
-bcd_to_int(unsigned int bcd)
-{
- return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void
-log_to_msf(unsigned int log, Byte *msf)
-{
- log = log + LOG_START_OFFSET;
- msf[0] = int_to_bcd(log / 4500);
- log = log % 4500;
- msf[1] = int_to_bcd(log / 75);
- msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int
-msf_to_log(Byte *msf)
-{
- unsigned int log;
-
-
- log = bcd_to_int(msf[2]);
- log += bcd_to_int(msf[1]) * 75;
- log += bcd_to_int(msf[0]) * 4500;
- log = log - LOG_START_OFFSET;
-
- return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void
-size_to_buf(unsigned int size, Byte *buf)
-{
- buf[0] = size / 65536;
- size = size % 65536;
- buf[1] = size / 256;
- buf[2] = size % 256;
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail. Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations. This especially helps since the OS
- * may use 1024 byte blocks and the drive uses 2048 byte blocks. Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void
-do_cdu535_request(request_queue_t * q)
-{
- struct request *req;
- unsigned int read_size;
- int block;
- int nsect;
- int copyoff;
- int spin_up_retry;
- Byte params[10];
- Byte status[2];
- Byte cmd[2];
-
- while (1) {
- req = elv_next_request(q);
- if (!req)
- return;
-
- block = req->sector;
- nsect = req->nr_sectors;
- if (!blk_fs_request(req)) {
- end_request(req, 0);
- continue;
- }
- if (rq_data_dir(req) == WRITE) {
- end_request(req, 0);
- continue;
- }
- /*
- * If the block address is invalid or the request goes beyond
- * the end of the media, return an error.
- */
- if (sony_toc->lead_out_start_lba <= (block/4)) {
- end_request(req, 0);
- return;
- }
- if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
- end_request(req, 0);
- return;
- }
- while (0 < nsect) {
- /*
- * If the requested sector is not currently in
- * the read-ahead buffer, it must be read in.
- */
- if ((block < sony_first_block) || (sony_last_block < block)) {
- sony_first_block = (block / 4) * 4;
- log_to_msf(block / 4, params);
-
- /*
- * If the full read-ahead would go beyond the end of the media, trim
- * it back to read just till the end of the media.
- */
- if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
- sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
- read_size = sony_toc->lead_out_start_lba - (block / 4);
- } else {
- sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
- read_size = sony_buffer_sectors;
- }
- size_to_buf(read_size, &params[3]);
-
- /*
- * Read the data. If the drive was not spinning,
- * spin it up and try some more.
- */
- for (spin_up_retry=0 ;; ++spin_up_retry) {
- /* This loop has been modified to support the Sony
- * CDU-510/515 series, thanks to Claudio Porfiri
- * <C.Porfiri@nisms.tei.ericsson.se>.
- */
- /*
- * This part is to deal with very slow hardware. We
- * try at most MAX_SPINUP_RETRY times to read the same
- * block. A check for seek_and_read_N_blocks' result is
- * performed; if the result is wrong, the CDROM's engine
- * is restarted and the operation is tried again.
- */
- /*
- * 1995-06-01: The system got problems when downloading
- * from Slackware CDROM, the problem seems to be:
- * seek_and_read_N_blocks returns BAD_STATUS and we
- * should wait for a while before retrying, so a new
- * part was added to discriminate the return value from
- * seek_and_read_N_blocks for the various cases.
- */
- int readStatus = seek_and_read_N_blocks(params, read_size,
- status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
- if (0 <= readStatus) /* Good data; common case, placed first */
- break;
- if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
- /* give up */
- if (readStatus == NO_ROOM)
- printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
- else
- printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
- status[0]);
- sony_first_block = -1;
- sony_last_block = -1;
- end_request(req, 0);
- return;
- }
- if (readStatus == BAD_STATUS) {
- /* Sleep for a while, then retry */
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&sonycd535_lock);
- schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
- spin_lock_irq(&sonycd535_lock);
- }
-#if DEBUG > 0
- printk(CDU535_MESSAGE_NAME
- " debug: calling spin up when reading data!\n");
-#endif
- cmd[0] = SONY535_SPIN_UP;
- do_sony_cmd(cmd, 1, status, NULL, 0, 0);
- }
- }
- /*
- * The data is in memory now, copy it to the buffer and advance to the
- * next block to read.
- */
- copyoff = block - sony_first_block;
- memcpy(req->buffer,
- sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
-
- block += 1;
- nsect -= 1;
- req->buffer += 512;
- }
-
- end_request(req, 1);
- }
-}
-
-/*
- * Read the table of contents from the drive and set sony_toc_read if
- * successful.
- */
-static void
-sony_get_toc(void)
-{
- Byte status[2];
- if (!sony_toc_read) {
- /* do not call check_drive_status() from here since it can call this routine */
- if (request_toc_data(status, sony_toc) < 0)
- return;
- sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
- sony_toc_read = 1;
- }
-}
-
-
-/*
- * Search for a specific track in the table of contents. track is
- * passed in bcd format
- */
-static int
-find_track(int track)
-{
- int i;
- int num_tracks;
-
-
- num_tracks = bcd_to_int(sony_toc->last_track_num) -
- bcd_to_int(sony_toc->first_track_num) + 1;
- for (i = 0; i < num_tracks; i++) {
- if (sony_toc->tracks[i].track == track) {
- return i;
- }
- }
-
- return -1;
-}
-
-/*
- * Read the subcode and put it int last_sony_subcode for future use.
- */
-static int
-read_subcode(void)
-{
- Byte cmd = SONY535_REQUEST_SUB_Q_DATA;
- Byte status[2];
- int dsc_status;
-
- if (check_drive_status() != 0)
- return -EIO;
-
- if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,
- sizeof(struct s535_sony_subcode), 1)) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",
- status[0], dsc_status);
- return -EIO;
- }
- return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing). If the drive is paused or completed, the subcode information has
- * already been stored, just use that. The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int
-sony_get_subchnl_info(void __user *arg)
-{
- struct cdrom_subchnl schi;
-
- /* Get attention stuff */
- if (check_drive_status() != 0)
- return -EIO;
-
- sony_get_toc();
- if (!sony_toc_read) {
- return -EIO;
- }
- if (copy_from_user(&schi, arg, sizeof schi))
- return -EFAULT;
-
- switch (sony_audio_status) {
- case CDROM_AUDIO_PLAY:
- if (read_subcode() < 0) {
- return -EIO;
- }
- break;
-
- case CDROM_AUDIO_PAUSED:
- case CDROM_AUDIO_COMPLETED:
- break;
-
- case CDROM_AUDIO_NO_STATUS:
- schi.cdsc_audiostatus = sony_audio_status;
- if (copy_to_user(arg, &schi, sizeof schi))
- return -EFAULT;
- return 0;
- break;
-
- case CDROM_AUDIO_INVALID:
- case CDROM_AUDIO_ERROR:
- default:
- return -EIO;
- }
-
- schi.cdsc_audiostatus = sony_audio_status;
- schi.cdsc_adr = last_sony_subcode->address;
- schi.cdsc_ctrl = last_sony_subcode->control;
- schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
- schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
- if (schi.cdsc_format == CDROM_MSF) {
- schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
- schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
- schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
-
- schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
- schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
- schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
- } else if (schi.cdsc_format == CDROM_LBA) {
- schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
- schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
- }
- return copy_to_user(arg, &schi, sizeof schi) ? -EFAULT : 0;
-}
-
-
-/*
- * The big ugly ioctl handler.
- */
-static int
-cdu_ioctl(struct inode *inode,
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
-{
- Byte status[2];
- Byte cmd_buff[10], params[10];
- int i;
- int dsc_status;
- void __user *argp = (void __user *)arg;
-
- if (check_drive_status() != 0)
- return -EIO;
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- if (spin_up_drive(status) < 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",
- status[0]);
- return -EIO;
- }
- return 0;
- break;
-
- case CDROMSTOP: /* Spin down the drive */
- cmd_buff[0] = SONY535_HOLD;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
- /*
- * Spin the drive down, ignoring the error if the disk was
- * already not spinning.
- */
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- cmd_buff[0] = SONY535_SPIN_DOWN;
- dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
- if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||
- ((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",
- status[0]);
- return -EIO;
- }
- return 0;
- break;
-
- case CDROMPAUSE: /* Pause the drive */
- cmd_buff[0] = SONY535_HOLD; /* CDU-31 driver uses AUDIO_STOP, not pause */
- if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",
- status[0]);
- return -EIO;
- }
- /* Get the current position and save it for resuming */
- if (read_subcode() < 0) {
- return -EIO;
- }
- cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
- cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
- cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
- sony_audio_status = CDROM_AUDIO_PAUSED;
- return 0;
- break;
-
- case CDROMRESUME: /* Start the drive after being paused */
- set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
- if (sony_audio_status != CDROM_AUDIO_PAUSED) {
- return -EINVAL;
- }
- spin_up_drive(status);
-
- /* Start the drive at the saved position. */
- cmd_buff[0] = SONY535_PLAY_AUDIO;
- cmd_buff[1] = 0; /* play back starting at this address */
- cmd_buff[2] = cur_pos_msf[0];
- cmd_buff[3] = cur_pos_msf[1];
- cmd_buff[4] = cur_pos_msf[2];
- cmd_buff[5] = SONY535_PLAY_AUDIO;
- cmd_buff[6] = 2; /* set ending address */
- cmd_buff[7] = final_pos_msf[0];
- cmd_buff[8] = final_pos_msf[1];
- cmd_buff[9] = final_pos_msf[2];
- if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
- (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",
- status[0]);
- return -EIO;
- }
- sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
- break;
-
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
- if (copy_from_user(params, argp, 6))
- return -EFAULT;
- spin_up_drive(status);
- set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
- /* The parameters are given in int, must be converted */
- for (i = 0; i < 3; i++) {
- cmd_buff[2 + i] = int_to_bcd(params[i]);
- cmd_buff[7 + i] = int_to_bcd(params[i + 3]);
- }
- cmd_buff[0] = SONY535_PLAY_AUDIO;
- cmd_buff[1] = 0; /* play back starting at this address */
- /* cmd_buff[2-4] are filled in for loop above */
- cmd_buff[5] = SONY535_PLAY_AUDIO;
- cmd_buff[6] = 2; /* set ending address */
- /* cmd_buff[7-9] are filled in for loop above */
- if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
- (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",
- status[0]);
- return -EIO;
- }
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = cmd_buff[7];
- final_pos_msf[1] = cmd_buff[8];
- final_pos_msf[2] = cmd_buff[9];
- sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
- break;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- {
- struct cdrom_tochdr __user *hdr = argp;
- struct cdrom_tochdr loc_hdr;
-
- sony_get_toc();
- if (!sony_toc_read)
- return -EIO;
- loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
- loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
- if (copy_to_user(hdr, &loc_hdr, sizeof *hdr))
- return -EFAULT;
- }
- return 0;
- break;
-
- case CDROMREADTOCENTRY: /* Read a given table of contents entry */
- {
- struct cdrom_tocentry __user *entry = argp;
- struct cdrom_tocentry loc_entry;
- int track_idx;
- Byte *msf_val = NULL;
-
- sony_get_toc();
- if (!sony_toc_read) {
- return -EIO;
- }
-
- if (copy_from_user(&loc_entry, entry, sizeof loc_entry))
- return -EFAULT;
-
- /* Lead out is handled separately since it is special. */
- if (loc_entry.cdte_track == CDROM_LEADOUT) {
- loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ;
- loc_entry.cdte_ctrl = sony_toc->control2;
- msf_val = sony_toc->lead_out_start_msf;
- } else {
- track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
- if (track_idx < 0)
- return -EINVAL;
- loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ;
- loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
- msf_val = sony_toc->tracks[track_idx].track_start_msf;
- }
-
- /* Logical buffer address or MSF format requested? */
- if (loc_entry.cdte_format == CDROM_LBA) {
- loc_entry.cdte_addr.lba = msf_to_log(msf_val);
- } else if (loc_entry.cdte_format == CDROM_MSF) {
- loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
- loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
- loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
- }
- if (copy_to_user(entry, &loc_entry, sizeof *entry))
- return -EFAULT;
- }
- return 0;
- break;
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- {
- struct cdrom_ti ti;
- int track_idx;
-
- sony_get_toc();
- if (!sony_toc_read)
- return -EIO;
-
- if (copy_from_user(&ti, argp, sizeof ti))
- return -EFAULT;
- if ((ti.cdti_trk0 < sony_toc->first_track_num)
- || (sony_toc->last_track_num < ti.cdti_trk0)
- || (ti.cdti_trk1 < ti.cdti_trk0)) {
- return -EINVAL;
- }
- track_idx = find_track(int_to_bcd(ti.cdti_trk0));
- if (track_idx < 0)
- return -EINVAL;
- params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
- params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
- params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
- /*
- * If we want to stop after the last track, use the lead-out
- * MSF to do that.
- */
- if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {
- log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,
- &(params[4]));
- } else {
- track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));
- if (track_idx < 0)
- return -EINVAL;
- log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,
- &(params[4]));
- }
- params[0] = 0x03;
-
- spin_up_drive(status);
-
- set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
- /* Start the drive at the saved position. */
- cmd_buff[0] = SONY535_PLAY_AUDIO;
- cmd_buff[1] = 0; /* play back starting at this address */
- cmd_buff[2] = params[1];
- cmd_buff[3] = params[2];
- cmd_buff[4] = params[3];
- cmd_buff[5] = SONY535_PLAY_AUDIO;
- cmd_buff[6] = 2; /* set ending address */
- cmd_buff[7] = params[4];
- cmd_buff[8] = params[5];
- cmd_buff[9] = params[6];
- if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
- (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n",
- status[0]);
- printk("... Params: %x %x %x %x %x %x %x\n",
- params[0], params[1], params[2],
- params[3], params[4], params[5], params[6]);
- return -EIO;
- }
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = params[4];
- final_pos_msf[1] = params[5];
- final_pos_msf[2] = params[6];
- sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
- }
-
- case CDROMSUBCHNL: /* Get subchannel info */
- return sony_get_subchnl_info(argp);
-
- case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
- {
- struct cdrom_volctrl volctrl;
-
- if (copy_from_user(&volctrl, argp, sizeof volctrl))
- return -EFAULT;
- cmd_buff[0] = SONY535_SET_VOLUME;
- cmd_buff[1] = volctrl.channel0;
- cmd_buff[2] = volctrl.channel1;
- if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",
- status[0]);
- return -EIO;
- }
- }
- return 0;
-
- case CDROMEJECT: /* Eject the drive */
- cmd_buff[0] = SONY535_STOP;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
- cmd_buff[0] = SONY535_SPIN_DOWN;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
- sony_audio_status = CDROM_AUDIO_INVALID;
- cmd_buff[0] = SONY535_EJECT_CADDY;
- if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",
- status[0]);
- return -EIO;
- }
- return 0;
- break;
-
- default:
- return -EINVAL;
- }
-}
-
-
-/*
- * Open the drive for operations. Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int
-cdu_open(struct inode *inode,
- struct file *filp)
-{
- Byte status[2], cmd_buff[2];
-
- if (sony_inuse)
- return -EBUSY;
- if (check_drive_status() != 0)
- return -EIO;
- sony_inuse = 1;
-
- if (spin_up_drive(status) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",
- status[0]);
- sony_inuse = 0;
- return -EIO;
- }
- sony_get_toc();
- if (!sony_toc_read) {
- cmd_buff[0] = SONY535_SPIN_DOWN;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
- sony_inuse = 0;
- return -EIO;
- }
- check_disk_change(inode->i_bdev);
- sony_usage++;
-
-#ifdef LOCK_DOORS
- /* disable the eject button while mounted */
- cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-#endif
-
- return 0;
-}
-
-
-/*
- * Close the drive. Spin it down if no task is using it. The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static int
-cdu_release(struct inode *inode,
- struct file *filp)
-{
- Byte status[2], cmd_no;
-
- sony_inuse = 0;
-
- if (0 < sony_usage) {
- sony_usage--;
- }
- if (sony_usage == 0) {
- check_drive_status();
-
- if (sony_audio_status != CDROM_AUDIO_PLAY) {
- cmd_no = SONY535_SPIN_DOWN;
- do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
- }
-#ifdef LOCK_DOORS
- /* enable the eject button after umount */
- cmd_no = SONY535_ENABLE_EJECT_BUTTON;
- do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
-#endif
- }
- return 0;
-}
-
-static struct block_device_operations cdu_fops =
-{
- .owner = THIS_MODULE,
- .open = cdu_open,
- .release = cdu_release,
- .ioctl = cdu_ioctl,
- .media_changed = cdu535_check_media_change,
-};
-
-static struct gendisk *cdu_disk;
-
-/*
- * Initialize the driver.
- */
-static int __init sony535_init(void)
-{
- struct s535_sony_drive_config drive_config;
- Byte cmd_buff[3];
- Byte ret_buff[2];
- Byte status[2];
- unsigned long snap;
- int got_result = 0;
- int tmp_irq;
- int i;
- int err;
-
- /* Setting the base I/O address to 0 will disable it. */
- if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
- return 0;
-
- /* Set up all the register locations */
- result_reg = sony535_cd_base_io;
- command_reg = sony535_cd_base_io;
- data_reg = sony535_cd_base_io + 1;
- read_status_reg = sony535_cd_base_io + 2;
- select_unit_reg = sony535_cd_base_io + 3;
-
-#ifndef USE_IRQ
- sony535_irq_used = 0; /* polling only until this is ready... */
-#endif
- /* we need to poll until things get initialized */
- tmp_irq = sony535_irq_used;
- sony535_irq_used = 0;
-
-#if DEBUG > 0
- printk(KERN_INFO CDU535_MESSAGE_NAME ": probing base address %03X\n",
- sony535_cd_base_io);
-#endif
- /* look for the CD-ROM, follows the procedure in the DOS driver */
- inb(select_unit_reg);
- /* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
- schedule_timeout_interruptible((HZ+17)*40/18);
- inb(result_reg);
-
- outb(0, read_status_reg); /* does a reset? */
- snap = jiffies;
- while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
- select_unit(0);
- if (inb(result_reg) != 0xff) {
- got_result = 1;
- break;
- }
- sony_sleep();
- }
-
- if (!got_result || check_drive_status() == TIME_OUT)
- goto Enodev;
-
- /* CD-ROM drive responded -- get the drive configuration */
- cmd_buff[0] = SONY535_INQUIRY;
- if (do_sony_cmd(cmd_buff, 1, status, (Byte *)&drive_config, 28, 1) != 0)
- goto Enodev;
-
- /* was able to get the configuration,
- * set drive mode as rest of init
- */
-#if DEBUG > 0
- /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
- if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
- printk(CDU535_MESSAGE_NAME
- "Inquiry command returned status = 0x%x\n", status[0]);
-#endif
- /* now ready to use interrupts, if available */
- sony535_irq_used = tmp_irq;
-
- /* A negative sony535_irq_used will attempt an autoirq. */
- if (sony535_irq_used < 0) {
- unsigned long irq_mask, delay;
-
- irq_mask = probe_irq_on();
- enable_interrupts();
- outb(0, read_status_reg); /* does a reset? */
- delay = jiffies + HZ/10;
- while (time_before(jiffies, delay)) ;
-
- sony535_irq_used = probe_irq_off(irq_mask);
- disable_interrupts();
- }
- if (sony535_irq_used > 0) {
- if (request_irq(sony535_irq_used, cdu535_interrupt,
- IRQF_DISABLED, CDU535_HANDLE, NULL)) {
- printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
- " driver; polling instead.\n", sony535_irq_used);
- sony535_irq_used = 0;
- }
- }
- cmd_buff[0] = SONY535_SET_DRIVE_MODE;
- cmd_buff[1] = 0x0; /* default audio */
- if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) != 0)
- goto Enodev_irq;
-
- /* set the drive mode successful, we are set! */
- sony_buffer_size = SONY535_BUFFER_SIZE;
- sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
-
- printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
- drive_config.vendor_id,
- drive_config.product_id,
- drive_config.product_rev_level);
- printk(" base address %03X, ", sony535_cd_base_io);
- if (tmp_irq > 0)
- printk("IRQ%d, ", tmp_irq);
- printk("using %d byte buffer\n", sony_buffer_size);
-
- if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) {
- err = -EIO;
- goto out1;
- }
- sonycd535_queue = blk_init_queue(do_cdu535_request, &sonycd535_lock);
- if (!sonycd535_queue) {
- err = -ENOMEM;
- goto out1a;
- }
-
- blk_queue_hardsect_size(sonycd535_queue, CDU535_BLOCK_SIZE);
- sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
- err = -ENOMEM;
- if (!sony_toc)
- goto out2;
- last_sony_subcode = kmalloc(sizeof(struct s535_sony_subcode), GFP_KERNEL);
- if (!last_sony_subcode)
- goto out3;
- sony_buffer = kmalloc(sizeof(Byte *) * sony_buffer_sectors, GFP_KERNEL);
- if (!sony_buffer)
- goto out4;
- for (i = 0; i < sony_buffer_sectors; i++) {
- sony_buffer[i] = kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
- if (!sony_buffer[i]) {
- while (--i>=0)
- kfree(sony_buffer[i]);
- goto out5;
- }
- }
- initialized = 1;
-
- cdu_disk = alloc_disk(1);
- if (!cdu_disk)
- goto out6;
- cdu_disk->major = MAJOR_NR;
- cdu_disk->first_minor = 0;
- cdu_disk->fops = &cdu_fops;
- sprintf(cdu_disk->disk_name, "cdu");
-
- if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) {
- printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n",
- sony535_cd_base_io);
- goto out7;
- }
- cdu_disk->queue = sonycd535_queue;
- add_disk(cdu_disk);
- return 0;
-
-out7:
- put_disk(cdu_disk);
-out6:
- for (i = 0; i < sony_buffer_sectors; i++)
- kfree(sony_buffer[i]);
-out5:
- kfree(sony_buffer);
-out4:
- kfree(last_sony_subcode);
-out3:
- kfree(sony_toc);
-out2:
- blk_cleanup_queue(sonycd535_queue);
-out1a:
- unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
-out1:
- if (sony535_irq_used)
- free_irq(sony535_irq_used, NULL);
- return err;
-Enodev_irq:
- if (sony535_irq_used)
- free_irq(sony535_irq_used, NULL);
-Enodev:
- printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
- return -EIO;
-}
-
-#ifndef MODULE
-
-/*
- * accept "kernel command line" parameters
- * (added by emoenke@gwdg.de)
- *
- * use: tell LILO:
- * sonycd535=0x320
- *
- * the address value has to be the existing CDROM port address.
- */
-static int __init
-sonycd535_setup(char *strings)
-{
- int ints[3];
- (void)get_options(strings, ARRAY_SIZE(ints), ints);
- /* if IRQ change and default io base desired,
- * then call with io base of 0
- */
- if (ints[0] > 0)
- if (ints[1] != 0)
- sony535_cd_base_io = ints[1];
- if (ints[0] > 1)
- sony535_irq_used = ints[2];
- if ((strings != NULL) && (*strings != '\0'))
- printk(CDU535_MESSAGE_NAME
- ": Warning: Unknown interface type: %s\n", strings);
-
- return 1;
-}
-
-__setup("sonycd535=", sonycd535_setup);
-
-#endif /* MODULE */
-
-static void __exit
-sony535_exit(void)
-{
- int i;
-
- release_region(sony535_cd_base_io, 4);
- for (i = 0; i < sony_buffer_sectors; i++)
- kfree(sony_buffer[i]);
- kfree(sony_buffer);
- kfree(last_sony_subcode);
- kfree(sony_toc);
- del_gendisk(cdu_disk);
- put_disk(cdu_disk);
- blk_cleanup_queue(sonycd535_queue);
- if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
- printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
- else
- printk(KERN_INFO CDU535_HANDLE " module released\n");
-}
-
-module_init(sony535_init);
-module_exit(sony535_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU535_CDROM_MAJOR);
diff --git a/drivers/cdrom/sonycd535.h b/drivers/cdrom/sonycd535.h
deleted file mode 100644
index 5dea1ef168d..00000000000
--- a/drivers/cdrom/sonycd535.h
+++ /dev/null
@@ -1,183 +0,0 @@
-#ifndef SONYCD535_H
-#define SONYCD535_H
-
-/*
- * define all the commands recognized by the CDU-531/5
- */
-#define SONY535_REQUEST_DRIVE_STATUS_1 (0x80)
-#define SONY535_REQUEST_SENSE (0x82)
-#define SONY535_REQUEST_DRIVE_STATUS_2 (0x84)
-#define SONY535_REQUEST_ERROR_STATUS (0x86)
-#define SONY535_REQUEST_AUDIO_STATUS (0x88)
-#define SONY535_INQUIRY (0x8a)
-
-#define SONY535_SET_INACTIVITY_TIME (0x90)
-
-#define SONY535_SEEK_AND_READ_N_BLOCKS_1 (0xa0)
-#define SONY535_SEEK_AND_READ_N_BLOCKS_2 (0xa4)
-#define SONY535_PLAY_AUDIO (0xa6)
-
-#define SONY535_REQUEST_DISC_CAPACITY (0xb0)
-#define SONY535_REQUEST_TOC_DATA (0xb2)
-#define SONY535_REQUEST_SUB_Q_DATA (0xb4)
-#define SONY535_REQUEST_ISRC (0xb6)
-#define SONY535_REQUEST_UPC_EAN (0xb8)
-
-#define SONY535_SET_DRIVE_MODE (0xc0)
-#define SONY535_REQUEST_DRIVE_MODE (0xc2)
-#define SONY535_SET_RETRY_COUNT (0xc4)
-
-#define SONY535_DIAGNOSTIC_1 (0xc6)
-#define SONY535_DIAGNOSTIC_4 (0xcc)
-#define SONY535_DIAGNOSTIC_5 (0xce)
-
-#define SONY535_EJECT_CADDY (0xd0)
-#define SONY535_DISABLE_EJECT_BUTTON (0xd2)
-#define SONY535_ENABLE_EJECT_BUTTON (0xd4)
-
-#define SONY535_HOLD (0xe0)
-#define SONY535_AUDIO_PAUSE_ON_OFF (0xe2)
-#define SONY535_SET_VOLUME (0xe8)
-
-#define SONY535_STOP (0xf0)
-#define SONY535_SPIN_UP (0xf2)
-#define SONY535_SPIN_DOWN (0xf4)
-
-#define SONY535_CLEAR_PARAMETERS (0xf6)
-#define SONY535_CLEAR_ENDING_ADDRESS (0xf8)
-
-/*
- * define some masks
- */
-#define SONY535_DATA_NOT_READY_BIT (0x1)
-#define SONY535_RESULT_NOT_READY_BIT (0x2)
-
-/*
- * drive status 1
- */
-#define SONY535_STATUS1_COMMAND_ERROR (0x1)
-#define SONY535_STATUS1_DATA_ERROR (0x2)
-#define SONY535_STATUS1_SEEK_ERROR (0x4)
-#define SONY535_STATUS1_DISC_TYPE_ERROR (0x8)
-#define SONY535_STATUS1_NOT_SPINNING (0x10)
-#define SONY535_STATUS1_EJECT_BUTTON_PRESSED (0x20)
-#define SONY535_STATUS1_CADDY_NOT_INSERTED (0x40)
-#define SONY535_STATUS1_BYTE_TWO_FOLLOWS (0x80)
-
-/*
- * drive status 2
- */
-#define SONY535_CDD_LOADING_ERROR (0x7)
-#define SONY535_CDD_NO_DISC (0x8)
-#define SONY535_CDD_UNLOADING_ERROR (0x9)
-#define SONY535_CDD_CADDY_NOT_INSERTED (0xd)
-#define SONY535_ATN_RESET_OCCURRED (0x2)
-#define SONY535_ATN_DISC_CHANGED (0x4)
-#define SONY535_ATN_RESET_AND_DISC_CHANGED (0x6)
-#define SONY535_ATN_EJECT_IN_PROGRESS (0xe)
-#define SONY535_ATN_BUSY (0xf)
-
-/*
- * define some parameters
- */
-#define SONY535_AUDIO_DRIVE_MODE (0)
-#define SONY535_CDROM_DRIVE_MODE (0xe0)
-
-#define SONY535_PLAY_OP_PLAYBACK (0)
-#define SONY535_PLAY_OP_ENTER_HOLD (1)
-#define SONY535_PLAY_OP_SET_AUDIO_ENDING_ADDR (2)
-#define SONY535_PLAY_OP_SCAN_FORWARD (3)
-#define SONY535_PLAY_OP_SCAN_BACKWARD (4)
-
-/*
- * convert from msf format to block number
- */
-#define SONY_BLOCK_NUMBER(m,s,f) (((m)*60L+(s))*75L+(f))
-#define SONY_BLOCK_NUMBER_MSF(x) (((x)[0]*60L+(x)[1])*75L+(x)[2])
-
-/*
- * error return values from the doSonyCmd() routines
- */
-#define TIME_OUT (-1)
-#define NO_CDROM (-2)
-#define BAD_STATUS (-3)
-#define CD_BUSY (-4)
-#define NOT_DATA_CD (-5)
-#define NO_ROOM (-6)
-
-#define LOG_START_OFFSET 150 /* Offset of first logical sector */
-
-#define SONY_JIFFIES_TIMEOUT (5*HZ) /* Maximum time
- the drive will wait/try for an
- operation */
-#define SONY_READY_RETRIES (50000) /* How many times to retry a
- spin waiting for a register
- to come ready */
-#define SONY535_FAST_POLLS (10000) /* how many times recheck
- status waiting for a data
- to become ready */
-
-typedef unsigned char Byte;
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s535_sony_drive_config
-{
- char vendor_id[8];
- char product_id[16];
- char product_rev_level[4];
-};
-
-/* The following is returned from the request sub-q data command */
-struct s535_sony_subcode
-{
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track_num;
- unsigned char index_num;
- unsigned char rel_msf[3];
- unsigned char abs_msf[3];
-};
-
-struct s535_sony_disc_capacity
-{
- Byte mFirstTrack, sFirstTrack, fFirstTrack;
- Byte mLeadOut, sLeadOut, fLeadOut;
-};
-
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s535_sony_toc
-{
- unsigned char reserved0 :4;
- unsigned char control0 :4;
- unsigned char point0;
- unsigned char first_track_num;
- unsigned char reserved0a;
- unsigned char reserved0b;
- unsigned char reserved1 :4;
- unsigned char control1 :4;
- unsigned char point1;
- unsigned char last_track_num;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char reserved2 :4;
- unsigned char control2 :4;
- unsigned char point2;
- unsigned char lead_out_start_msf[3];
- struct
- {
- unsigned char reserved :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[100];
-
- unsigned int lead_out_start_lba;
-};
-
-#endif /* SONYCD535_H */
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 1b094509b1d..90965b4def5 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -1005,8 +1005,8 @@ static const unsigned short x86_keycodes[256] =
284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
- 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
- 291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
+ 103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
+ 291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index cc9a9d0df97..bbee97ff355 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -24,7 +24,7 @@
#include <linux/crash_dump.h>
#include <linux/backing-dev.h>
#include <linux/bootmem.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
#include <linux/pfn.h>
#include <asm/uaccess.h>
@@ -75,6 +75,13 @@ static inline int uncached_access(struct file *file, unsigned long addr)
* On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
*/
return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
+#elif defined(CONFIG_MIPS)
+ {
+ extern int __uncached_access(struct file *file,
+ unsigned long addr);
+
+ return __uncached_access(file, addr);
+ }
#else
/*
* Accessing memory above the top the kernel knows about or through a file pointer
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 1da92a689ae..85a23283dff 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2721,9 +2721,9 @@ static void __devexit sx_pci_remove(struct pci_dev *pdev)
its because the standard requires it. So check for SUBVENDOR_ID. */
static struct pci_device_id sx_pci_tbl[] = {
{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
- .subvendor = 0x0200,.subdevice = PCI_ANY_ID },
+ .subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
- .subvendor = 0x0300,.subdevice = PCI_ANY_ID },
+ .subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
{ 0 }
};
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 9eb1edacd82..0aeab3218bb 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -336,8 +336,11 @@ fw_card_bm_work(struct work_struct *work)
}
pick_me:
- /* Now figure out what gap count to set. */
- if (card->topology_type == FW_TOPOLOGY_A &&
+ /*
+ * Pick a gap count from 1394a table E-1. The table doesn't cover
+ * the typically much larger 1394b beta repeater delays though.
+ */
+ if (!card->beta_repeaters_present &&
card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
gap_count = gap_count_table[card->root_node->max_hops];
else
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index dbb76427d52..75388641a7d 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -397,7 +397,7 @@ static int ioctl_send_request(struct client *client, void *buffer)
request->tcode & 0x1f,
device->node->node_id,
request->generation,
- device->node->max_speed,
+ device->max_speed,
request->offset,
response->response.data, request->length,
complete_transaction, response);
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index c1ce465d971..2b658634163 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -401,8 +401,7 @@ static int read_rom(struct fw_device *device, int index, u32 * data)
offset = 0xfffff0000400ULL + index * 4;
fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
- device->node_id,
- device->generation, SCODE_100,
+ device->node_id, device->generation, device->max_speed,
offset, NULL, 4, complete_transaction, &callback_data);
wait_for_completion(&callback_data.done);
@@ -418,6 +417,8 @@ static int read_bus_info_block(struct fw_device *device)
u32 stack[16], sp, key;
int i, end, length;
+ device->max_speed = SCODE_100;
+
/* First read the bus info block. */
for (i = 0; i < 5; i++) {
if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
@@ -434,6 +435,33 @@ static int read_bus_info_block(struct fw_device *device)
return -1;
}
+ device->max_speed = device->node->max_speed;
+
+ /*
+ * Determine the speed of
+ * - devices with link speed less than PHY speed,
+ * - devices with 1394b PHY (unless only connected to 1394a PHYs),
+ * - all devices if there are 1394b repeaters.
+ * Note, we cannot use the bus info block's link_spd as starting point
+ * because some buggy firmwares set it lower than necessary and because
+ * 1394-1995 nodes do not have the field.
+ */
+ if ((rom[2] & 0x7) < device->max_speed ||
+ device->max_speed == SCODE_BETA ||
+ device->card->beta_repeaters_present) {
+ u32 dummy;
+
+ /* for S1600 and S3200 */
+ if (device->max_speed == SCODE_BETA)
+ device->max_speed = device->card->link_speed;
+
+ while (device->max_speed > SCODE_100) {
+ if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
+ break;
+ device->max_speed--;
+ }
+ }
+
/*
* Now parse the config rom. The config rom is a recursive
* directory structure so we parse it using a stack of
@@ -680,8 +708,10 @@ static void fw_device_init(struct work_struct *work)
FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
fw_device_shutdown(&device->work.work);
else
- fw_notify("created new fw device %s (%d config rom retries)\n",
- device->device.bus_id, device->config_rom_retries);
+ fw_notify("created new fw device %s "
+ "(%d config rom retries, S%d00)\n",
+ device->device.bus_id, device->config_rom_retries,
+ 1 << device->max_speed);
/*
* Reschedule the IRM work if we just finished reading the
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index af1723eae4b..d13e6a69707 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -40,6 +40,7 @@ struct fw_device {
struct fw_node *node;
int node_id;
int generation;
+ unsigned max_speed;
struct fw_card *card;
struct device device;
struct list_head link;
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 96c8ac5b86c..41476abc069 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -1934,12 +1934,12 @@ static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
free_irq(pdev->irq, ohci);
err = pci_save_state(pdev);
if (err) {
- fw_error("pci_save_state failed with %d", err);
+ fw_error("pci_save_state failed\n");
return err;
}
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
if (err) {
- fw_error("pci_set_power_state failed with %d", err);
+ fw_error("pci_set_power_state failed\n");
return err;
}
@@ -1955,7 +1955,7 @@ static int pci_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
err = pci_enable_device(pdev);
if (err) {
- fw_error("pci_enable_device failed with %d", err);
+ fw_error("pci_enable_device failed\n");
return err;
}
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index a98d3915e26..7c53be0387f 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -30,10 +30,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/mod_devicetable.h>
#include <linux/device.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
+#include <linux/blkdev.h>
+#include <linux/string.h>
#include <linux/timer.h>
#include <scsi/scsi.h>
@@ -46,6 +49,18 @@
#include "fw-topology.h"
#include "fw-device.h"
+/*
+ * So far only bridges from Oxford Semiconductor are known to support
+ * concurrent logins. Depending on firmware, four or two concurrent logins
+ * are possible on OXFW911 and newer Oxsemi bridges.
+ *
+ * Concurrent logins are useful together with cluster filesystems.
+ */
+static int sbp2_param_exclusive_login = 1;
+module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
+MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
+ "(default = Y, use N for concurrent initiators)");
+
/* I don't know why the SCSI stack doesn't define something like this... */
typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
@@ -154,7 +169,7 @@ struct sbp2_orb {
#define MANAGEMENT_ORB_LUN(v) ((v))
#define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16)
#define MANAGEMENT_ORB_RECONNECT(v) ((v) << 20)
-#define MANAGEMENT_ORB_EXCLUSIVE ((1) << 28)
+#define MANAGEMENT_ORB_EXCLUSIVE(v) ((v) ? 1 << 28 : 0)
#define MANAGEMENT_ORB_REQUEST_FORMAT(v) ((v) << 29)
#define MANAGEMENT_ORB_NOTIFY ((1) << 31)
@@ -205,9 +220,8 @@ struct sbp2_command_orb {
scsi_done_fn_t done;
struct fw_unit *unit;
- struct sbp2_pointer page_table[SG_ALL];
+ struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
dma_addr_t page_table_bus;
- dma_addr_t request_buffer_bus;
};
/*
@@ -347,8 +361,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
spin_unlock_irqrestore(&device->card->lock, flags);
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
- node_id, generation,
- device->node->max_speed, offset,
+ node_id, generation, device->max_speed, offset,
&orb->pointer, sizeof(orb->pointer),
complete_transaction, orb);
}
@@ -383,7 +396,7 @@ static void
complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{
struct sbp2_management_orb *orb =
- (struct sbp2_management_orb *)base_orb;
+ container_of(base_orb, struct sbp2_management_orb, base);
if (status)
memcpy(&orb->status, status, sizeof(*status));
@@ -403,21 +416,11 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
if (orb == NULL)
return -ENOMEM;
- /*
- * The sbp2 device is going to send a block read request to
- * read out the request from host memory, so map it for dma.
- */
- orb->base.request_bus =
- dma_map_single(device->card->device, &orb->request,
- sizeof(orb->request), DMA_TO_DEVICE);
- if (dma_mapping_error(orb->base.request_bus))
- goto out;
-
orb->response_bus =
dma_map_single(device->card->device, &orb->response,
sizeof(orb->response), DMA_FROM_DEVICE);
if (dma_mapping_error(orb->response_bus))
- goto out;
+ goto fail_mapping_response;
orb->request.response.high = 0;
orb->request.response.low = orb->response_bus;
@@ -432,14 +435,9 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
orb->request.status_fifo.high = sd->address_handler.offset >> 32;
orb->request.status_fifo.low = sd->address_handler.offset;
- /*
- * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive
- * login and 1 second reconnect time. The reconnect setting
- * is probably fine, but the exclusive login should be an option.
- */
if (function == SBP2_LOGIN_REQUEST) {
orb->request.misc |=
- MANAGEMENT_ORB_EXCLUSIVE |
+ MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
MANAGEMENT_ORB_RECONNECT(0);
}
@@ -448,6 +446,12 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
init_completion(&orb->done);
orb->base.callback = complete_management_orb;
+ orb->base.request_bus =
+ dma_map_single(device->card->device, &orb->request,
+ sizeof(orb->request), DMA_TO_DEVICE);
+ if (dma_mapping_error(orb->base.request_bus))
+ goto fail_mapping_request;
+
sbp2_send_orb(&orb->base, unit,
node_id, generation, sd->management_agent_address);
@@ -479,9 +483,10 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
out:
dma_unmap_single(device->card->device, orb->base.request_bus,
sizeof(orb->request), DMA_TO_DEVICE);
+ fail_mapping_request:
dma_unmap_single(device->card->device, orb->response_bus,
sizeof(orb->response), DMA_FROM_DEVICE);
-
+ fail_mapping_response:
if (response)
fw_memcpy_from_be32(response,
orb->response, sizeof(orb->response));
@@ -511,7 +516,7 @@ static int sbp2_agent_reset(struct fw_unit *unit)
return -ENOMEM;
fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
- sd->node_id, sd->generation, SCODE_400,
+ sd->node_id, sd->generation, device->max_speed,
sd->command_block_agent_address + SBP2_AGENT_RESET,
&zero, sizeof(zero), complete_agent_reset_write, t);
@@ -521,17 +526,15 @@ static int sbp2_agent_reset(struct fw_unit *unit)
static void sbp2_reconnect(struct work_struct *work);
static struct scsi_host_template scsi_driver_template;
-static void
-release_sbp2_device(struct kref *kref)
+static void release_sbp2_device(struct kref *kref)
{
struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
struct Scsi_Host *host =
container_of((void *)sd, struct Scsi_Host, hostdata[0]);
+ scsi_remove_host(host);
sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
-
- scsi_remove_host(host);
fw_core_remove_address_handler(&sd->address_handler);
fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
put_device(&sd->unit->device);
@@ -833,7 +836,8 @@ sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
static void
complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{
- struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb;
+ struct sbp2_command_orb *orb =
+ container_of(base_orb, struct sbp2_command_orb, base);
struct fw_unit *unit = orb->unit;
struct fw_device *device = fw_device(unit->device.parent);
struct scatterlist *sg;
@@ -880,12 +884,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
if (orb->page_table_bus != 0)
dma_unmap_single(device->card->device, orb->page_table_bus,
- sizeof(orb->page_table_bus), DMA_TO_DEVICE);
-
- if (orb->request_buffer_bus != 0)
- dma_unmap_single(device->card->device, orb->request_buffer_bus,
- sizeof(orb->request_buffer_bus),
- DMA_FROM_DEVICE);
+ sizeof(orb->page_table), DMA_TO_DEVICE);
orb->cmd->result = result;
orb->done(orb->cmd);
@@ -900,7 +899,6 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
struct fw_device *device = fw_device(unit->device.parent);
struct scatterlist *sg;
int sg_len, l, i, j, count;
- size_t size;
dma_addr_t sg_addr;
sg = (struct scatterlist *)orb->cmd->request_buffer;
@@ -935,6 +933,11 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
sg_len = sg_dma_len(sg + i);
sg_addr = sg_dma_address(sg + i);
while (sg_len) {
+ /* FIXME: This won't get us out of the pinch. */
+ if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
+ fw_error("page table overflow\n");
+ goto fail_page_table;
+ }
l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
orb->page_table[j].low = sg_addr;
orb->page_table[j].high = (l << 16);
@@ -944,7 +947,13 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
}
}
- size = sizeof(orb->page_table[0]) * j;
+ fw_memcpy_to_be32(orb->page_table, orb->page_table,
+ sizeof(orb->page_table[0]) * j);
+ orb->page_table_bus =
+ dma_map_single(device->card->device, orb->page_table,
+ sizeof(orb->page_table), DMA_TO_DEVICE);
+ if (dma_mapping_error(orb->page_table_bus))
+ goto fail_page_table;
/*
* The data_descriptor pointer is the one case where we need
@@ -953,20 +962,12 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
* initiator (i.e. us), but data_descriptor can refer to data
* on other nodes so we need to put our ID in descriptor.high.
*/
-
- orb->page_table_bus =
- dma_map_single(device->card->device, orb->page_table,
- size, DMA_TO_DEVICE);
- if (dma_mapping_error(orb->page_table_bus))
- goto fail_page_table;
orb->request.data_descriptor.high = sd->address_high;
orb->request.data_descriptor.low = orb->page_table_bus;
orb->request.misc |=
COMMAND_ORB_PAGE_TABLE_PRESENT |
COMMAND_ORB_DATA_SIZE(j);
- fw_memcpy_to_be32(orb->page_table, orb->page_table, size);
-
return 0;
fail_page_table:
@@ -991,7 +992,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
* transfer direction not handled.
*/
if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
- fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+ fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
cmd->result = DID_ERROR << 16;
done(cmd);
return 0;
@@ -1005,11 +1006,6 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
/* Initialize rcode to something not RCODE_COMPLETE. */
orb->base.rcode = -1;
- orb->base.request_bus =
- dma_map_single(device->card->device, &orb->request,
- sizeof(orb->request), DMA_TO_DEVICE);
- if (dma_mapping_error(orb->base.request_bus))
- goto fail_mapping;
orb->unit = unit;
orb->done = done;
@@ -1024,8 +1020,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
* if we set this to max_speed + 7, we get the right value.
*/
orb->request.misc =
- COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) |
- COMMAND_ORB_SPEED(device->node->max_speed) |
+ COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
+ COMMAND_ORB_SPEED(device->max_speed) |
COMMAND_ORB_NOTIFY;
if (cmd->sc_data_direction == DMA_FROM_DEVICE)
@@ -1036,7 +1032,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0)
- goto fail_map_payload;
+ goto fail_mapping;
fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
@@ -1045,15 +1041,17 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
orb->base.callback = complete_command_orb;
+ orb->base.request_bus =
+ dma_map_single(device->card->device, &orb->request,
+ sizeof(orb->request), DMA_TO_DEVICE);
+ if (dma_mapping_error(orb->base.request_bus))
+ goto fail_mapping;
sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
sd->command_block_agent_address + SBP2_ORB_POINTER);
return 0;
- fail_map_payload:
- dma_unmap_single(device->card->device, orb->base.request_bus,
- sizeof(orb->request), DMA_TO_DEVICE);
fail_mapping:
kfree(orb);
fail_alloc:
@@ -1087,7 +1085,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
sdev->fix_capacity = 1;
}
-
+ if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
+ blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
return 0;
}
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 7aebb8ae0ef..39e5cd12aa5 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -135,17 +135,17 @@ static void update_hop_count(struct fw_node *node)
int i;
for (i = 0; i < node->port_count; i++) {
- if (node->ports[i].node == NULL)
+ if (node->ports[i] == NULL)
continue;
- if (node->ports[i].node->max_hops > max_child_hops)
- max_child_hops = node->ports[i].node->max_hops;
+ if (node->ports[i]->max_hops > max_child_hops)
+ max_child_hops = node->ports[i]->max_hops;
- if (node->ports[i].node->max_depth > depths[0]) {
+ if (node->ports[i]->max_depth > depths[0]) {
depths[1] = depths[0];
- depths[0] = node->ports[i].node->max_depth;
- } else if (node->ports[i].node->max_depth > depths[1])
- depths[1] = node->ports[i].node->max_depth;
+ depths[0] = node->ports[i]->max_depth;
+ } else if (node->ports[i]->max_depth > depths[1])
+ depths[1] = node->ports[i]->max_depth;
}
node->max_depth = depths[0] + 1;
@@ -172,7 +172,8 @@ static struct fw_node *build_tree(struct fw_card *card,
struct list_head stack, *h;
u32 *next_sid, *end, q;
int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
- int gap_count, topology_type;
+ int gap_count;
+ bool beta_repeaters_present;
local_node = NULL;
node = NULL;
@@ -182,7 +183,7 @@ static struct fw_node *build_tree(struct fw_card *card,
phy_id = 0;
irm_node = NULL;
gap_count = SELF_ID_GAP_COUNT(*sid);
- topology_type = 0;
+ beta_repeaters_present = false;
while (sid < end) {
next_sid = count_ports(sid, &port_count, &child_port_count);
@@ -214,7 +215,7 @@ static struct fw_node *build_tree(struct fw_card *card,
node = fw_node_create(q, port_count, card->color);
if (node == NULL) {
- fw_error("Out of memory while building topology.");
+ fw_error("Out of memory while building topology.\n");
return NULL;
}
@@ -224,11 +225,6 @@ static struct fw_node *build_tree(struct fw_card *card,
if (SELF_ID_CONTENDER(q))
irm_node = node;
- if (node->phy_speed == SCODE_BETA)
- topology_type |= FW_TOPOLOGY_B;
- else
- topology_type |= FW_TOPOLOGY_A;
-
parent_count = 0;
for (i = 0; i < port_count; i++) {
@@ -249,12 +245,12 @@ static struct fw_node *build_tree(struct fw_card *card,
break;
case SELFID_PORT_CHILD:
- node->ports[i].node = child;
+ node->ports[i] = child;
/*
* Fix up parent reference for this
* child node.
*/
- child->ports[child->color].node = node;
+ child->ports[child->color] = node;
child->color = card->color;
child = fw_node(child->link.next);
break;
@@ -278,6 +274,10 @@ static struct fw_node *build_tree(struct fw_card *card,
list_add_tail(&node->link, &stack);
stack_depth += 1 - child_port_count;
+ if (node->phy_speed == SCODE_BETA &&
+ parent_count + child_port_count > 1)
+ beta_repeaters_present = true;
+
/*
* If all PHYs does not report the same gap count
* setting, we fall back to 63 which will force a gap
@@ -295,7 +295,7 @@ static struct fw_node *build_tree(struct fw_card *card,
card->root_node = node;
card->irm_node = irm_node;
card->gap_count = gap_count;
- card->topology_type = topology_type;
+ card->beta_repeaters_present = beta_repeaters_present;
return local_node;
}
@@ -321,7 +321,7 @@ for_each_fw_node(struct fw_card *card, struct fw_node *root,
node->color = card->color;
for (i = 0; i < node->port_count; i++) {
- child = node->ports[i].node;
+ child = node->ports[i];
if (!child)
continue;
if (child->color == card->color)
@@ -382,11 +382,11 @@ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
struct fw_node *tree;
int i;
- tree = node1->ports[port].node;
- node0->ports[port].node = tree;
+ tree = node1->ports[port];
+ node0->ports[port] = tree;
for (i = 0; i < tree->port_count; i++) {
- if (tree->ports[i].node == node1) {
- tree->ports[i].node = node0;
+ if (tree->ports[i] == node1) {
+ tree->ports[i] = node0;
break;
}
}
@@ -437,19 +437,17 @@ update_tree(struct fw_card *card, struct fw_node *root)
card->irm_node = node0;
for (i = 0; i < node0->port_count; i++) {
- if (node0->ports[i].node && node1->ports[i].node) {
+ if (node0->ports[i] && node1->ports[i]) {
/*
* This port didn't change, queue the
* connected node for further
* investigation.
*/
- if (node0->ports[i].node->color == card->color)
+ if (node0->ports[i]->color == card->color)
continue;
- list_add_tail(&node0->ports[i].node->link,
- &list0);
- list_add_tail(&node1->ports[i].node->link,
- &list1);
- } else if (node0->ports[i].node) {
+ list_add_tail(&node0->ports[i]->link, &list0);
+ list_add_tail(&node1->ports[i]->link, &list1);
+ } else if (node0->ports[i]) {
/*
* The nodes connected here were
* unplugged; unref the lost nodes and
@@ -457,10 +455,10 @@ update_tree(struct fw_card *card, struct fw_node *root)
* them.
*/
- for_each_fw_node(card, node0->ports[i].node,
+ for_each_fw_node(card, node0->ports[i],
report_lost_node);
- node0->ports[i].node = NULL;
- } else if (node1->ports[i].node) {
+ node0->ports[i] = NULL;
+ } else if (node1->ports[i]) {
/*
* One or more node were connected to
* this port. Move the new nodes into
@@ -468,7 +466,7 @@ update_tree(struct fw_card *card, struct fw_node *root)
* callbacks for them.
*/
move_tree(node0, node1, i);
- for_each_fw_node(card, node0->ports[i].node,
+ for_each_fw_node(card, node0->ports[i],
report_found_node);
}
}
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index 363b6cbcd0b..1b56b4ac7fb 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -20,12 +20,6 @@
#define __fw_topology_h
enum {
- FW_TOPOLOGY_A = 0x01,
- FW_TOPOLOGY_B = 0x02,
- FW_TOPOLOGY_MIXED = 0x03,
-};
-
-enum {
FW_NODE_CREATED = 0x00,
FW_NODE_UPDATED = 0x01,
FW_NODE_DESTROYED = 0x02,
@@ -33,21 +27,16 @@ enum {
FW_NODE_LINK_OFF = 0x04,
};
-struct fw_port {
- struct fw_node *node;
- unsigned speed : 3; /* S100, S200, ... S3200 */
-};
-
struct fw_node {
u16 node_id;
u8 color;
u8 port_count;
- unsigned link_on : 1;
- unsigned initiated_reset : 1;
- unsigned b_path : 1;
- u8 phy_speed : 3; /* As in the self ID packet. */
- u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on
- * the path from the local node to this node. */
+ u8 link_on : 1;
+ u8 initiated_reset : 1;
+ u8 b_path : 1;
+ u8 phy_speed : 2; /* As in the self ID packet. */
+ u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the
+ * local node to this node. */
u8 max_depth : 4; /* Maximum depth to any leaf node */
u8 max_hops : 4; /* Max hops in this sub tree */
atomic_t ref_count;
@@ -58,7 +47,7 @@ struct fw_node {
/* Upper layer specific data. */
void *data;
- struct fw_port ports[0];
+ struct fw_node *ports[0];
};
static inline struct fw_node *
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index acdc3be38c6..5abed193f4a 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -81,7 +81,6 @@
#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args)
static inline void
fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
@@ -246,7 +245,7 @@ struct fw_card {
struct fw_node *irm_node;
int color;
int gap_count;
- int topology_type;
+ bool beta_repeaters_present;
int index;
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 8fbe9fdac12..3b63b0b7812 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1,8 +1,12 @@
#
# HID driver configuration
#
-menu "HID Devices"
+menuconfig HID_SUPPORT
+ bool "HID Devices"
depends on INPUT
+ default y
+
+if HID_SUPPORT
config HID
tristate "Generic HID support"
@@ -24,6 +28,7 @@ config HID
config HID_DEBUG
bool "HID debugging support"
+ default y if !EMBEDDED
depends on HID
---help---
This option lets the HID layer output diagnostics about its internal
@@ -38,5 +43,4 @@ config HID_DEBUG
source "drivers/hid/usbhid/Kconfig"
-endmenu
-
+endif # HID_SUPPORT
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 6ec04e79f68..317cf8a7b63 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -40,6 +40,13 @@
#define DRIVER_DESC "HID core driver"
#define DRIVER_LICENSE "GPL"
+#ifdef CONFIG_HID_DEBUG
+int hid_debug = 0;
+module_param_named(debug, hid_debug, bool, 0600);
+MODULE_PARM_DESC(debug, "Turn HID debugging mode on and off");
+EXPORT_SYMBOL_GPL(hid_debug);
+#endif
+
/*
* Register a new report for a device.
*/
@@ -78,7 +85,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
struct hid_field *field;
if (report->maxfield == HID_MAX_FIELDS) {
- dbg("too many fields in report");
+ dbg_hid("too many fields in report\n");
return NULL;
}
@@ -106,7 +113,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
usage = parser->local.usage[0];
if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
- dbg("collection stack overflow");
+ dbg_hid("collection stack overflow\n");
return -1;
}
@@ -114,7 +121,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
collection = kmalloc(sizeof(struct hid_collection) *
parser->device->collection_size * 2, GFP_KERNEL);
if (collection == NULL) {
- dbg("failed to reallocate collection array");
+ dbg_hid("failed to reallocate collection array\n");
return -1;
}
memcpy(collection, parser->device->collection,
@@ -150,7 +157,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
static int close_collection(struct hid_parser *parser)
{
if (!parser->collection_stack_ptr) {
- dbg("collection stack underflow");
+ dbg_hid("collection stack underflow\n");
return -1;
}
parser->collection_stack_ptr--;
@@ -178,7 +185,7 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
static int hid_add_usage(struct hid_parser *parser, unsigned usage)
{
if (parser->local.usage_index >= HID_MAX_USAGES) {
- dbg("usage index exceeded");
+ dbg_hid("usage index exceeded\n");
return -1;
}
parser->local.usage[parser->local.usage_index] = usage;
@@ -202,12 +209,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
int i;
if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
- dbg("hid_register_report failed");
+ dbg_hid("hid_register_report failed\n");
return -1;
}
if (parser->global.logical_maximum < parser->global.logical_minimum) {
- dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+ dbg_hid("logical range invalid %d %d\n", parser->global.logical_minimum, parser->global.logical_maximum);
return -1;
}
@@ -287,7 +294,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_PUSH:
if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
- dbg("global enviroment stack overflow");
+ dbg_hid("global enviroment stack overflow\n");
return -1;
}
@@ -298,7 +305,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_POP:
if (!parser->global_stack_ptr) {
- dbg("global enviroment stack underflow");
+ dbg_hid("global enviroment stack underflow\n");
return -1;
}
@@ -342,27 +349,27 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
if ((parser->global.report_size = item_udata(item)) > 32) {
- dbg("invalid report_size %d", parser->global.report_size);
+ dbg_hid("invalid report_size %d\n", parser->global.report_size);
return -1;
}
return 0;
case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
- dbg("invalid report_count %d", parser->global.report_count);
+ dbg_hid("invalid report_count %d\n", parser->global.report_count);
return -1;
}
return 0;
case HID_GLOBAL_ITEM_TAG_REPORT_ID:
if ((parser->global.report_id = item_udata(item)) == 0) {
- dbg("report_id 0 is invalid");
+ dbg_hid("report_id 0 is invalid\n");
return -1;
}
return 0;
default:
- dbg("unknown global tag 0x%x", item->tag);
+ dbg_hid("unknown global tag 0x%x\n", item->tag);
return -1;
}
}
@@ -377,7 +384,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
unsigned n;
if (item->size == 0) {
- dbg("item data expected for local item");
+ dbg_hid("item data expected for local item\n");
return -1;
}
@@ -395,14 +402,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
* items and the first delimiter set.
*/
if (parser->local.delimiter_depth != 0) {
- dbg("nested delimiters");
+ dbg_hid("nested delimiters\n");
return -1;
}
parser->local.delimiter_depth++;
parser->local.delimiter_branch++;
} else {
if (parser->local.delimiter_depth < 1) {
- dbg("bogus close delimiter");
+ dbg_hid("bogus close delimiter\n");
return -1;
}
parser->local.delimiter_depth--;
@@ -412,7 +419,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
case HID_LOCAL_ITEM_TAG_USAGE:
if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
+ dbg_hid("alternative usage ignored\n");
return 0;
}
@@ -424,7 +431,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
+ dbg_hid("alternative usage ignored\n");
return 0;
}
@@ -437,7 +444,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
+ dbg_hid("alternative usage ignored\n");
return 0;
}
@@ -446,14 +453,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
for (n = parser->local.usage_minimum; n <= data; n++)
if (hid_add_usage(parser, n)) {
- dbg("hid_add_usage failed\n");
+ dbg_hid("hid_add_usage failed\n");
return -1;
}
return 0;
default:
- dbg("unknown local item tag 0x%x", item->tag);
+ dbg_hid("unknown local item tag 0x%x\n", item->tag);
return 0;
}
return 0;
@@ -487,7 +494,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
break;
default:
- dbg("unknown main item tag 0x%x", item->tag);
+ dbg_hid("unknown main item tag 0x%x\n", item->tag);
ret = 0;
}
@@ -502,7 +509,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
{
- dbg("reserved item type, tag 0x%x", item->tag);
+ dbg_hid("reserved item type, tag 0x%x\n", item->tag);
return 0;
}
@@ -667,14 +674,14 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
while ((start = fetch_item(start, end, &item)) != NULL) {
if (item.format != HID_ITEM_FORMAT_SHORT) {
- dbg("unexpected long global item");
+ dbg_hid("unexpected long global item\n");
hid_free_device(device);
vfree(parser);
return NULL;
}
if (dispatch_type[item.type](parser, &item)) {
- dbg("item %u %u %u %u parsing failed\n",
+ dbg_hid("item %u %u %u %u parsing failed\n",
item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
hid_free_device(device);
vfree(parser);
@@ -683,13 +690,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
if (start == end) {
if (parser->collection_stack_ptr) {
- dbg("unbalanced collection at end of report description");
+ dbg_hid("unbalanced collection at end of report description\n");
hid_free_device(device);
vfree(parser);
return NULL;
}
if (parser->local.delimiter_depth) {
- dbg("unbalanced delimiter at end of report description");
+ dbg_hid("unbalanced delimiter at end of report description\n");
hid_free_device(device);
vfree(parser);
return NULL;
@@ -699,7 +706,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
}
}
- dbg("item fetching failed at offset %d\n", (int)(end - start));
+ dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
hid_free_device(device);
vfree(parser);
return NULL;
@@ -915,13 +922,13 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
hid_dump_input(field->usage + offset, value);
if (offset >= field->report_count) {
- dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
+ dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count);
hid_dump_field(field, 8);
return -1;
}
if (field->logical_minimum < 0) {
if (value != snto32(s32ton(value, size), size)) {
- dbg("value %d is out of range", value);
+ dbg_hid("value %d is out of range\n", value);
return -1;
}
}
@@ -934,19 +941,17 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
{
struct hid_report_enum *report_enum = hid->report_enum + type;
struct hid_report *report;
- int n, rsize;
+ int n, rsize, i;
if (!hid)
return -ENODEV;
if (!size) {
- dbg("empty report");
+ dbg_hid("empty report\n");
return -1;
}
-#ifdef CONFIG_HID_DEBUG
- printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
-#endif
+ dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
n = 0; /* Normally report number is 0 */
if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
@@ -954,25 +959,21 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
size--;
}
-#ifdef CONFIG_HID_DEBUG
- {
- int i;
- printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
- for (i = 0; i < size; i++)
- printk(" %02x", data[i]);
- printk("\n");
- }
-#endif
+ /* dump the report descriptor */
+ dbg_hid("report %d (size %u) = ", n, size);
+ for (i = 0; i < size; i++)
+ dbg_hid_line(" %02x", data[i]);
+ dbg_hid_line("\n");
if (!(report = report_enum->report_id_hash[n])) {
- dbg("undefined report_id %d received", n);
+ dbg_hid("undefined report_id %d received\n", n);
return -1;
}
rsize = ((report->size - 1) >> 3) + 1;
if (size < rsize) {
- dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
+ dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize);
memset(data + size, 0, rsize - size);
}
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 83c4126b37c..a13757b7898 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -347,6 +347,9 @@ static void resolv_usage_page(unsigned page) {
void hid_resolv_usage(unsigned usage) {
const struct hid_usage_entry *p;
+ if (!hid_debug)
+ return;
+
resolv_usage_page(usage >> 16);
printk(".");
for (p = hid_usage_table; p->description; p++)
@@ -369,6 +372,9 @@ __inline__ static void tab(int n) {
void hid_dump_field(struct hid_field *field, int n) {
int j;
+ if (!hid_debug)
+ return;
+
if (field->physical) {
tab(n);
printk("Physical(");
@@ -466,6 +472,9 @@ void hid_dump_device(struct hid_device *device) {
unsigned i,k;
static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
+ if (!hid_debug)
+ return;
+
for (i = 0; i < HID_REPORT_TYPES; i++) {
report_enum = device->report_enum + i;
list = report_enum->report_list.next;
@@ -489,6 +498,9 @@ void hid_dump_device(struct hid_device *device) {
EXPORT_SYMBOL_GPL(hid_dump_device);
void hid_dump_input(struct hid_usage *usage, __s32 value) {
+ if (!hid_debug)
+ return;
+
printk("hid-debug: input ");
hid_resolv_usage(usage->hid);
printk(" = %d\n", value);
@@ -758,6 +770,9 @@ static char **names[EV_MAX + 1] = {
void hid_resolv_event(__u8 type, __u16 code) {
+ if (!hid_debug)
+ return;
+
printk("%s.%s", events[type] ? events[type] : "?",
names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
}
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 7f817897b17..8edbd30cf79 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -60,6 +60,19 @@ static const unsigned char hid_keyboard[256] = {
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};
+/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
+#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
+static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
+ 0,216, 0,213,175,156, 0, 0, 0, 0,
+ 144, 0, 0, 0, 0, 0, 0, 0, 0,212,
+ 174,167,152,161,112, 0, 0, 0,154, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,183,184,185,186,187,
+ 188,189,190,191,192,193,194, 0, 0, 0
+};
+
static const struct {
__s32 x;
__s32 y;
@@ -308,9 +321,7 @@ static int hidinput_setkeycode(struct input_dev *dev, int scancode,
clear_bit(old_keycode, dev->keybit);
set_bit(usage->code, dev->keybit);
-#ifdef CONFIG_HID_DEBUG
- printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
-#endif
+ dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
/* Set the keybit for the old keycode if the old keycode is used
* by another key */
if (hidinput_find_key (hid, 0, old_keycode))
@@ -333,11 +344,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
field->hidinput = hidinput;
-#ifdef CONFIG_HID_DEBUG
- printk(KERN_DEBUG "Mapping: ");
+ dbg_hid("Mapping: ");
hid_resolv_usage(usage->hid);
- printk(" ---> ");
-#endif
+ dbg_hid_line(" ---> ");
if (field->flags & HID_MAIN_ITEM_CONSTANT)
goto ignore;
@@ -378,6 +387,21 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
}
+ /* Special handling for Logitech Cordless Desktop */
+ if (field->application != HID_GD_MOUSE) {
+ if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
+ int hid = usage->hid & HID_USAGE;
+ if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
+ code = logitech_expanded_keymap[hid];
+ }
+ } else {
+ if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
+ int hid = usage->hid & HID_USAGE;
+ if (hid == 7 || hid == 8)
+ goto ignore;
+ }
+ }
+
map_key(code);
break;
@@ -566,6 +590,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
+
+ /* reserved in HUT 1.12. Reported on Petalynx remote */
+ case 0x0f6: map_key_clear(KEY_NEXT); break;
+ case 0x0fa: map_key_clear(KEY_BACK); break;
+
case 0x183: map_key_clear(KEY_CONFIG); break;
case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
case 0x185: map_key_clear(KEY_EDITOR); break;
@@ -598,7 +627,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x21b: map_key_clear(KEY_COPY); break;
case 0x21c: map_key_clear(KEY_CUT); break;
case 0x21d: map_key_clear(KEY_PASTE); break;
- case 0x221: map_key_clear(KEY_FIND); break;
+ case 0x21f: map_key_clear(KEY_FIND); break;
+ case 0x221: map_key_clear(KEY_SEARCH); break;
+ case 0x222: map_key_clear(KEY_GOTO); break;
case 0x223: map_key_clear(KEY_HOMEPAGE); break;
case 0x224: map_key_clear(KEY_BACK); break;
case 0x225: map_key_clear(KEY_FORWARD); break;
@@ -688,7 +719,28 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
break;
case HID_UP_MSVENDOR:
- goto ignore;
+
+ /* special case - Chicony Chicony KU-0418 tactical pad */
+ if (device->vendor == 0x04f2 && device->product == 0x0418) {
+ set_bit(EV_REP, input->evbit);
+ switch(usage->hid & HID_USAGE) {
+ case 0xff01: map_key_clear(BTN_1); break;
+ case 0xff02: map_key_clear(BTN_2); break;
+ case 0xff03: map_key_clear(BTN_3); break;
+ case 0xff04: map_key_clear(BTN_4); break;
+ case 0xff05: map_key_clear(BTN_5); break;
+ case 0xff06: map_key_clear(BTN_6); break;
+ case 0xff07: map_key_clear(BTN_7); break;
+ case 0xff08: map_key_clear(BTN_8); break;
+ case 0xff09: map_key_clear(BTN_9); break;
+ case 0xff0a: map_key_clear(BTN_A); break;
+ case 0xff0b: map_key_clear(BTN_B); break;
+ default: goto ignore;
+ }
+ } else {
+ goto ignore;
+ }
+ break;
case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
@@ -704,10 +756,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
break;
- case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
-
+ case HID_UP_LOGIVENDOR:
set_bit(EV_REP, input->evbit);
switch(usage->hid & HID_USAGE) {
+ /* Reported on Logitech Ultra X Media Remote */
case 0x004: map_key_clear(KEY_AGAIN); break;
case 0x00d: map_key_clear(KEY_HOME); break;
case 0x024: map_key_clear(KEY_SHUFFLE); break;
@@ -725,6 +777,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x04d: map_key_clear(KEY_SUBTITLE); break;
case 0x051: map_key_clear(KEY_RED); break;
case 0x052: map_key_clear(KEY_CLOSE); break;
+
+ /* Reported on Petalynx Maxter remote */
+ case 0x05a: map_key_clear(KEY_TEXT); break;
+ case 0x05b: map_key_clear(KEY_RED); break;
+ case 0x05c: map_key_clear(KEY_GREEN); break;
+ case 0x05d: map_key_clear(KEY_YELLOW); break;
+ case 0x05e: map_key_clear(KEY_BLUE); break;
+
default: goto ignore;
}
break;
@@ -818,16 +878,24 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
field->dpad = usage->code;
}
+ /* for those devices which produce Consumer volume usage as relative,
+ * we emulate pressing volumeup/volumedown appropriate number of times
+ * in hidinput_hid_event()
+ */
+ if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+ (usage->code == ABS_VOLUME)) {
+ set_bit(KEY_VOLUMEUP, input->keybit);
+ set_bit(KEY_VOLUMEDOWN, input->keybit);
+ }
+
hid_resolv_event(usage->type, usage->code);
-#ifdef CONFIG_HID_DEBUG
- printk("\n");
-#endif
+
+ dbg_hid_line("\n");
+
return;
ignore:
-#ifdef CONFIG_HID_DEBUG
- printk("IGNORED\n");
-#endif
+ dbg_hid_line("IGNORED\n");
return;
}
@@ -896,18 +964,33 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
}
if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
- dbg("Maximum Effects - %d",value);
+ dbg_hid("Maximum Effects - %d\n",value);
return;
}
if (usage->hid == (HID_UP_PID | 0x7fUL)) {
- dbg("PID Pool Report\n");
+ dbg_hid("PID Pool Report\n");
return;
}
if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
return;
+ if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+ (usage->code == ABS_VOLUME)) {
+ int count = abs(value);
+ int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ input_event(input, EV_KEY, direction, 1);
+ input_sync(input);
+ input_event(input, EV_KEY, direction, 0);
+ input_sync(input);
+ }
+ return;
+ }
+
input_event(input, usage->type, usage->code, value);
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
@@ -976,7 +1059,7 @@ int hidinput_connect(struct hid_device *hid)
if (IS_INPUT_APPLICATION(hid->collection[i].usage))
break;
- if (i == hid->maxcollection)
+ if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0)
return -1;
if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
@@ -994,7 +1077,7 @@ int hidinput_connect(struct hid_device *hid)
if (!hidinput || !input_dev) {
kfree(hidinput);
input_free_device(input_dev);
- err("Out of memory during hid input probe");
+ err_hid("Out of memory during hid input probe");
return -1;
}
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index d91b9dac6df..3afa4a5035b 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -60,6 +60,12 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
" quirks=vendorID:productID:quirks"
" where vendorID, productID, and quirks are all in"
" 0x-prefixed hex");
+static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
+module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
+MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
+ " rdesc_quirks=vendorID:productID:rdesc_quirks"
+ " where vendorID, productID, and rdesc_quirks are all in"
+ " 0x-prefixed hex");
/*
* Input submission and I/O error handler.
*/
@@ -127,7 +133,7 @@ static void hid_reset(struct work_struct *work)
hid_io_error(hid);
break;
default:
- err("can't reset device, %s-%s/input%d, status %d",
+ err_hid("can't reset device, %s-%s/input%d, status %d",
hid_to_usb_dev(hid)->bus->bus_name,
hid_to_usb_dev(hid)->devpath,
usbhid->ifnum, rc);
@@ -220,7 +226,7 @@ static void hid_irq_in(struct urb *urb)
if (status) {
clear_bit(HID_IN_RUNNING, &usbhid->iofl);
if (status != -EPERM) {
- err("can't resubmit intr, %s-%s/input%d, status %d",
+ err_hid("can't resubmit intr, %s-%s/input%d, status %d",
hid_to_usb_dev(hid)->bus->bus_name,
hid_to_usb_dev(hid)->devpath,
usbhid->ifnum, status);
@@ -240,10 +246,10 @@ static int hid_submit_out(struct hid_device *hid)
usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
usbhid->urbout->dev = hid_to_usb_dev(hid);
- dbg("submitting out urb");
+ dbg_hid("submitting out urb\n");
if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
- err("usb_submit_urb(out) failed");
+ err_hid("usb_submit_urb(out) failed");
return -1;
}
@@ -287,12 +293,12 @@ static int hid_submit_ctrl(struct hid_device *hid)
usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
usbhid->cr->wLength = cpu_to_le16(len);
- dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
+ dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n",
usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
- err("usb_submit_urb(ctrl) failed");
+ err_hid("usb_submit_urb(ctrl) failed");
return -1;
}
@@ -474,7 +480,7 @@ int usbhid_wait_io(struct hid_device *hid)
if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
10*HZ)) {
- dbg("timeout waiting for ctrl or out queue to clear");
+ dbg_hid("timeout waiting for ctrl or out queue to clear\n");
return -1;
}
@@ -633,20 +639,6 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
}
/*
- * Cherry Cymotion keyboard have an invalid HID report descriptor,
- * that needs fixing before we can parse it.
- */
-
-static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
-{
- if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
- info("Fixing up Cherry Cymotion report descriptor");
- rdesc[11] = rdesc[16] = 0xff;
- rdesc[12] = rdesc[17] = 0x03;
- }
-}
-
-/*
* Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
* to "operational". Without this, the ps3 controller will not report any
* events.
@@ -667,51 +659,11 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
USB_CTRL_GET_TIMEOUT);
if (result < 0)
- err("%s failed: %d\n", __func__, result);
+ err_hid("%s failed: %d\n", __func__, result);
kfree(buf);
}
-/*
- * Certain Logitech keyboards send in report #3 keys which are far
- * above the logical maximum described in descriptor. This extends
- * the original value of 0x28c of logical maximum to 0x104d
- */
-static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
-{
- if (rsize >= 90 && rdesc[83] == 0x26
- && rdesc[84] == 0x8c
- && rdesc[85] == 0x02) {
- info("Fixing up Logitech keyboard report descriptor");
- rdesc[84] = rdesc[89] = 0x4d;
- rdesc[85] = rdesc[90] = 0x10;
- }
-}
-
-/*
- * Some USB barcode readers from cypress have usage min and usage max in
- * the wrong order
- */
-static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
-{
- short fixed = 0;
- int i;
-
- for (i = 0; i < rsize - 4; i++) {
- if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
- unsigned char tmp;
-
- rdesc[i] = 0x19; rdesc[i+2] = 0x29;
- tmp = rdesc[i+3];
- rdesc[i+3] = rdesc[i+1];
- rdesc[i+1] = tmp;
- }
- }
-
- if (fixed)
- info("Fixing up Cypress report descriptor");
-}
-
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
struct usb_host_interface *interface = intf->cur_altsetting;
@@ -746,7 +698,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
(!interface->desc.bNumEndpoints ||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
- dbg("class descriptor not present\n");
+ dbg_hid("class descriptor not present\n");
return NULL;
}
@@ -755,41 +707,34 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
- dbg("weird size of report descriptor (%u)", rsize);
+ dbg_hid("weird size of report descriptor (%u)\n", rsize);
return NULL;
}
if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
- dbg("couldn't allocate rdesc memory");
+ dbg_hid("couldn't allocate rdesc memory\n");
return NULL;
}
hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
- dbg("reading report descriptor failed");
+ dbg_hid("reading report descriptor failed\n");
kfree(rdesc);
return NULL;
}
- if ((quirks & HID_QUIRK_CYMOTION))
- hid_fixup_cymotion_descriptor(rdesc, rsize);
+ usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct), rdesc,
+ rsize, rdesc_quirks_param);
- if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
- hid_fixup_logitech_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
- hid_fixup_cypress_descriptor(rdesc, rsize);
-
-#ifdef CONFIG_HID_DEBUG
- printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
+ dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
- printk(" %02x", (unsigned char) rdesc[n]);
- printk("\n");
-#endif
+ dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
+ dbg_hid_line("\n");
if (!(hid = hid_parse_report(rdesc, n))) {
- dbg("parsing report descriptor failed");
+ dbg_hid("parsing report descriptor failed\n");
kfree(rdesc);
return NULL;
}
@@ -861,7 +806,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
}
if (!usbhid->urbin) {
- err("couldn't find an input interrupt endpoint");
+ err_hid("couldn't find an input interrupt endpoint");
goto fail;
}
@@ -956,7 +901,7 @@ static void hid_disconnect(struct usb_interface *intf)
usb_kill_urb(usbhid->urbctrl);
del_timer_sync(&usbhid->io_retry);
- flush_scheduled_work();
+ cancel_work_sync(&usbhid->reset_work);
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(hid);
@@ -978,7 +923,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
int i;
char *c;
- dbg("HID probe called for ifnum %d",
+ dbg_hid("HID probe called for ifnum %d\n",
intf->altsetting->desc.bInterfaceNumber);
if (!(hid = usb_hid_configure(intf)))
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c
index c5cd4107d6a..4b7ab6a46d9 100644
--- a/drivers/hid/usbhid/hid-lgff.c
+++ b/drivers/hid/usbhid/hid-lgff.c
@@ -78,7 +78,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[1] = 0x08;
report->field[0]->value[2] = x;
report->field[0]->value[3] = y;
- dbg("(x, y)=(%04x, %04x)", x, y);
+ dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
@@ -93,7 +93,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[1] = 0x00;
report->field[0]->value[2] = left;
report->field[0]->value[3] = right;
- dbg("(left, right)=(%04x, %04x)", left, right);
+ dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
}
@@ -113,20 +113,20 @@ int hid_lgff_init(struct hid_device* hid)
/* Find the report to use */
if (list_empty(report_list)) {
- err("No output report found");
+ err_hid("No output report found");
return -1;
}
/* Check that the report looks ok */
report = list_entry(report_list->next, struct hid_report, list);
if (!report) {
- err("NULL output report");
+ err_hid("NULL output report");
return -1;
}
field = report->field[0];
if (!field) {
- err("NULL field");
+ err_hid("NULL field");
return -1;
}
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index f5a90e950e6..011326178c0 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -738,6 +738,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
+ pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
pidff->set_effect[PID_START_DELAY].value[0] = 0;
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index f6c4145dc20..775b9f3b8ce 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -105,6 +105,9 @@
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+#define USB_VENDOR_ID_GAMERON 0x0810
+#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
+
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
@@ -196,8 +199,10 @@
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
+#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
+#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
@@ -209,6 +214,13 @@
#define USB_DEVICE_ID_MGE_UPS 0xffff
#define USB_DEVICE_ID_MGE_UPS1 0x0001
+#define USB_VENDOR_ID_MICROSOFT 0x045e
+#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
+
+#define USB_VENDOR_ID_NCR 0x0404
+#define USB_DEVICE_ID_NCR_FIRST 0x0300
+#define USB_DEVICE_ID_NCR_LAST 0x03ff
+
#define USB_VENDOR_ID_NEC 0x073e
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
@@ -220,6 +232,9 @@
#define USB_VENDOR_ID_PANTHERLORD 0x0810
#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
+#define USB_VENDOR_ID_PETALYNX 0x18b1
+#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
+
#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
@@ -278,6 +293,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
+ { USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -285,11 +301,10 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
- { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
-
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
{ USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
@@ -409,9 +424,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
@@ -426,6 +439,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -448,9 +462,28 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
+ { 0, 0 }
+};
+
+/* Quirks for devices which require report descriptor fixup go here */
+static const struct hid_rdesc_blacklist {
+ __u16 idVendor;
+ __u16 idProduct;
+ __u32 quirks;
+} hid_rdesc_blacklist[] = {
+
+ { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
+
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
+
+ { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
+
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
{ 0, 0 }
};
@@ -493,7 +526,7 @@ static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor,
}
if (bl_entry != NULL)
- dbg("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+ dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
bl_entry->quirks, bl_entry->idVendor,
bl_entry->idProduct);
@@ -521,13 +554,13 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
int list_edited = 0;
if (!idVendor) {
- dbg("Cannot add a quirk with idVendor = 0");
+ dbg_hid("Cannot add a quirk with idVendor = 0\n");
return -EINVAL;
}
q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL);
if (!q_new) {
- dbg("Could not allocate quirks_list_struct");
+ dbg_hid("Could not allocate quirks_list_struct\n");
return -ENOMEM;
}
@@ -559,7 +592,6 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
return 0;
}
-
/**
* usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
*
@@ -643,7 +675,7 @@ static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor,
bl_entry = &hid_blacklist[n];
if (bl_entry != NULL)
- dbg("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+ dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
bl_entry->quirks, bl_entry->idVendor,
bl_entry->idProduct);
return bl_entry;
@@ -675,6 +707,12 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
return HID_QUIRK_IGNORE;
+ /* NCR devices must not be queried for reports */
+ if (idVendor == USB_VENDOR_ID_NCR &&
+ idProduct >= USB_DEVICE_ID_NCR_FIRST &&
+ idProduct <= USB_DEVICE_ID_NCR_LAST)
+ return HID_QUIRK_NOGET;
+
down_read(&dquirks_rwsem);
bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
if (!bl_entry)
@@ -686,3 +724,126 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
return quirks;
}
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
+{
+ if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+ printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
+ rdesc[11] = rdesc[16] = 0xff;
+ rdesc[12] = rdesc[17] = 0x03;
+ }
+}
+
+
+/*
+ * Certain Logitech keyboards send in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
+{
+ if (rsize >= 90 && rdesc[83] == 0x26
+ && rdesc[84] == 0x8c
+ && rdesc[85] == 0x02) {
+ printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
+ rdesc[84] = rdesc[89] = 0x4d;
+ rdesc[85] = rdesc[90] = 0x10;
+ }
+}
+
+/* Petalynx Maxter Remote has maximum for consumer page set too low */
+static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
+{
+ if (rsize >= 60 && rdesc[39] == 0x2a
+ && rdesc[40] == 0xf5
+ && rdesc[41] == 0x00
+ && rdesc[59] == 0x26
+ && rdesc[60] == 0xf9
+ && rdesc[61] == 0x00) {
+ printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
+ rdesc[60] = 0xfa;
+ rdesc[40] = 0xfa;
+ }
+}
+
+/*
+ * Some USB barcode readers from cypress have usage min and usage max in
+ * the wrong order
+ */
+static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
+{
+ short fixed = 0;
+ int i;
+
+ for (i = 0; i < rsize - 4; i++) {
+ if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
+ unsigned char tmp;
+
+ rdesc[i] = 0x19; rdesc[i+2] = 0x29;
+ tmp = rdesc[i+3];
+ rdesc[i+3] = rdesc[i+1];
+ rdesc[i+1] = tmp;
+ }
+ }
+
+ if (fixed)
+ printk(KERN_INFO "Fixing up Cypress report descriptor\n");
+}
+
+
+static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
+{
+ if ((quirks & HID_QUIRK_RDESC_CYMOTION))
+ usbhid_fixup_cymotion_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_LOGITECH)
+ usbhid_fixup_logitech_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
+ usbhid_fixup_cypress_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_PETALYNX)
+ usbhid_fixup_petalynx_descriptor(rdesc, rsize);
+}
+
+/**
+ * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
+ *
+ * Description:
+ * Walks the hid_rdesc_blacklist[] array and checks whether the device
+ * is known to have broken report descriptor that needs to be fixed up
+ * prior to entering the HID parser
+ *
+ * Returns: nothing
+ */
+void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
+ char *rdesc, unsigned rsize, char **quirks_param)
+{
+ int n, m;
+ u16 paramVendor, paramProduct;
+ u32 quirks;
+
+ /* static rdesc quirk entries */
+ for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
+ if (hid_rdesc_blacklist[n].idVendor == idVendor &&
+ hid_rdesc_blacklist[n].idProduct == idProduct)
+ __usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
+ rdesc, rsize);
+
+ /* runtime rdesc quirk entries handling */
+ for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
+ m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
+ &paramVendor, &paramProduct, &quirks);
+
+ if (m != 3)
+ printk(KERN_WARNING
+ "Could not parse HID quirk module param %s\n",
+ quirks_param[n]);
+ else if (paramVendor == idVendor && paramProduct == idProduct)
+ __usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
+ }
+
+}
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
index ab5ba6ef891..555bb48b429 100644
--- a/drivers/hid/usbhid/hid-tmff.c
+++ b/drivers/hid/usbhid/hid-tmff.c
@@ -70,7 +70,7 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
tmff->rumble->value[0] = left;
tmff->rumble->value[1] = right;
- dbg("(left,right)=(%08x, %08x)", left, right);
+ dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
return 0;
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c
index a7fbffcdaf3..5a688274f6a 100644
--- a/drivers/hid/usbhid/hid-zpff.c
+++ b/drivers/hid/usbhid/hid-zpff.c
@@ -21,10 +21,6 @@
*/
-/* #define DEBUG */
-
-#define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg)
-
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h>
@@ -49,14 +45,14 @@ static int hid_zpff_play(struct input_dev *dev, void *data,
left = effect->u.rumble.strong_magnitude;
right = effect->u.rumble.weak_magnitude;
- debug("called with 0x%04x 0x%04x", left, right);
+ dbg_hid("called with 0x%04x 0x%04x\n", left, right);
left = left * 0x7f / 0xffff;
right = right * 0x7f / 0xffff;
zpff->report->field[2]->value[0] = left;
zpff->report->field[3]->value[0] = right;
- debug("running with 0x%02x 0x%02x", left, right);
+ dbg_hid("running with 0x%02x 0x%02x\n", left, right);
usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
return 0;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 488d61bdbf2..e793127f971 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -779,7 +779,7 @@ int hiddev_connect(struct hid_device *hid)
retval = usb_register_dev(usbhid->intf, &hiddev_class);
if (retval) {
- err("Not able to get a minor for this device.");
+ err_hid("Not able to get a minor for this device.");
kfree(hiddev);
return -1;
}
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 13097878071..b76b02f7b52 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -125,7 +125,7 @@ static void usb_kbd_irq(struct urb *urb)
resubmit:
i = usb_submit_urb (urb, GFP_ATOMIC);
if (i)
- err ("can't resubmit intr, %s-%s/input0, status %d",
+ err_hid ("can't resubmit intr, %s-%s/input0, status %d",
kbd->usbdev->bus->bus_name,
kbd->usbdev->devpath, i);
}
@@ -151,7 +151,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type,
*(kbd->leds) = kbd->newleds;
kbd->led->dev = kbd->usbdev;
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
- err("usb_submit_urb(leds) failed");
+ err_hid("usb_submit_urb(leds) failed");
return 0;
}
@@ -169,7 +169,7 @@ static void usb_kbd_led(struct urb *urb)
*(kbd->leds) = kbd->newleds;
kbd->led->dev = kbd->usbdev;
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
- err("usb_submit_urb(leds) failed");
+ err_hid("usb_submit_urb(leds) failed");
}
static int usb_kbd_open(struct input_dev *dev)
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 66f826252ae..444a0b84f5b 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -448,23 +448,21 @@ static int icside_dma_test_irq(ide_drive_t *drive)
ICS_ARCIN_V6_INTRSTAT_1)) & 1;
}
-static int icside_dma_timeout(ide_drive_t *drive)
+static void icside_dma_timeout(ide_drive_t *drive)
{
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
if (icside_dma_test_irq(drive))
- return 0;
+ return;
- ide_dump_status(drive, "DMA timeout",
- HWIF(drive)->INB(IDE_STATUS_REG));
+ ide_dump_status(drive, "DMA timeout", HWIF(drive)->INB(IDE_STATUS_REG));
- return icside_dma_end(drive);
+ icside_dma_end(drive);
}
-static int icside_dma_lostirq(ide_drive_t *drive)
+static void icside_dma_lost_irq(ide_drive_t *drive)
{
printk(KERN_ERR "%s: IRQ lost\n", drive->name);
- return 1;
}
static void icside_dma_init(ide_hwif_t *hwif)
@@ -490,8 +488,8 @@ static void icside_dma_init(ide_hwif_t *hwif)
hwif->dma_start = icside_dma_start;
hwif->ide_dma_end = icside_dma_end;
hwif->ide_dma_test_irq = icside_dma_test_irq;
- hwif->ide_dma_timeout = icside_dma_timeout;
- hwif->ide_dma_lostirq = icside_dma_lostirq;
+ hwif->dma_timeout = icside_dma_timeout;
+ hwif->dma_lost_irq = icside_dma_lost_irq;
hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index ca0341c05e5..886091bc7db 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -819,7 +819,7 @@ init_e100_ide (void)
hwif->dma_host_off = &cris_dma_off;
hwif->dma_host_on = &cris_dma_on;
hwif->dma_off_quietly = &cris_dma_off;
- hwif->udma_four = 0;
+ hwif->cbl = ATA_CBL_PATA40;
hwif->ultra_mask = cris_ultra_mask;
hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
hwif->autodma = 1;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 252ab8295ed..1486eb212cc 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -481,7 +481,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
else
printk(" Unknown Error Type: ");
- if (sense->sense_key < ARY_LEN(sense_key_texts))
+ if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
s = sense_key_texts[sense->sense_key];
printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
@@ -491,7 +491,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
sense->ascq);
s = buf;
} else {
- int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
+ int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
unsigned long key = (sense->sense_key << 16);
key |= (sense->asc << 8);
if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
@@ -524,7 +524,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
if (failed_command != NULL) {
- int lo=0, mid, hi= ARY_LEN (packet_command_texts);
+ int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
s = NULL;
while (hi > lo) {
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index ad1f2ed14a3..228b29c5d2e 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -498,8 +498,6 @@ struct cdrom_info {
* Descriptions of ATAPI error codes.
*/
-#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
-
/* This stuff should be in cdrom.h, since it is now generic... */
/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index dc2175c81f5..b1304a7f3e0 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1190,11 +1190,11 @@ static int idedisk_ioctl(struct inode *inode, struct file *file,
return generic_ide_ioctl(drive, file, bdev, cmd, arg);
read_val:
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
err = *val;
spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
return err >= 0 ? put_user(err, (long __user *)arg) : err;
set_val:
@@ -1204,9 +1204,9 @@ set_val:
if (!capable(CAP_SYS_ADMIN))
err = -EACCES;
else {
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
err = setfunc(drive, arg);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
}
return err;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index ead141e2db9..5fe1d72ab45 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -91,45 +91,45 @@
static const struct drive_list_entry drive_whitelist [] = {
- { "Micropolis 2112A" , "ALL" },
- { "CONNER CTMA 4000" , "ALL" },
- { "CONNER CTT8000-A" , "ALL" },
- { "ST34342A" , "ALL" },
+ { "Micropolis 2112A" , NULL },
+ { "CONNER CTMA 4000" , NULL },
+ { "CONNER CTT8000-A" , NULL },
+ { "ST34342A" , NULL },
{ NULL , NULL }
};
static const struct drive_list_entry drive_blacklist [] = {
- { "WDC AC11000H" , "ALL" },
- { "WDC AC22100H" , "ALL" },
- { "WDC AC32500H" , "ALL" },
- { "WDC AC33100H" , "ALL" },
- { "WDC AC31600H" , "ALL" },
+ { "WDC AC11000H" , NULL },
+ { "WDC AC22100H" , NULL },
+ { "WDC AC32500H" , NULL },
+ { "WDC AC33100H" , NULL },
+ { "WDC AC31600H" , NULL },
{ "WDC AC32100H" , "24.09P07" },
{ "WDC AC23200L" , "21.10N21" },
- { "Compaq CRD-8241B" , "ALL" },
- { "CRD-8400B" , "ALL" },
- { "CRD-8480B", "ALL" },
- { "CRD-8482B", "ALL" },
- { "CRD-84" , "ALL" },
- { "SanDisk SDP3B" , "ALL" },
- { "SanDisk SDP3B-64" , "ALL" },
- { "SANYO CD-ROM CRD" , "ALL" },
- { "HITACHI CDR-8" , "ALL" },
- { "HITACHI CDR-8335" , "ALL" },
- { "HITACHI CDR-8435" , "ALL" },
- { "Toshiba CD-ROM XM-6202B" , "ALL" },
- { "TOSHIBA CD-ROM XM-1702BC", "ALL" },
- { "CD-532E-A" , "ALL" },
- { "E-IDE CD-ROM CR-840", "ALL" },
- { "CD-ROM Drive/F5A", "ALL" },
- { "WPI CDD-820", "ALL" },
- { "SAMSUNG CD-ROM SC-148C", "ALL" },
- { "SAMSUNG CD-ROM SC", "ALL" },
- { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" },
- { "_NEC DV5800A", "ALL" },
+ { "Compaq CRD-8241B" , NULL },
+ { "CRD-8400B" , NULL },
+ { "CRD-8480B", NULL },
+ { "CRD-8482B", NULL },
+ { "CRD-84" , NULL },
+ { "SanDisk SDP3B" , NULL },
+ { "SanDisk SDP3B-64" , NULL },
+ { "SANYO CD-ROM CRD" , NULL },
+ { "HITACHI CDR-8" , NULL },
+ { "HITACHI CDR-8335" , NULL },
+ { "HITACHI CDR-8435" , NULL },
+ { "Toshiba CD-ROM XM-6202B" , NULL },
+ { "TOSHIBA CD-ROM XM-1702BC", NULL },
+ { "CD-532E-A" , NULL },
+ { "E-IDE CD-ROM CR-840", NULL },
+ { "CD-ROM Drive/F5A", NULL },
+ { "WPI CDD-820", NULL },
+ { "SAMSUNG CD-ROM SC-148C", NULL },
+ { "SAMSUNG CD-ROM SC", NULL },
+ { "ATAPI CD-ROM DRIVE 40X MAXIMUM", NULL },
+ { "_NEC DV5800A", NULL },
{ "SAMSUNG CD-ROM SN-124", "N001" },
- { "Seagate STT20000A", "ALL" },
+ { "Seagate STT20000A", NULL },
{ NULL , NULL }
};
@@ -147,8 +147,8 @@ int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *driv
{
for ( ; drive_table->id_model ; drive_table++)
if ((!strcmp(drive_table->id_model, id->model)) &&
- ((strstr(id->fw_rev, drive_table->id_firmware)) ||
- (!strcmp(drive_table->id_firmware, "ALL"))))
+ (!drive_table->id_firmware ||
+ strstr(id->fw_rev, drive_table->id_firmware)))
return 1;
return 0;
}
@@ -702,8 +702,22 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
mask = id->dma_mword & hwif->mwdma_mask;
break;
case XFER_SW_DMA_0:
- if (id->field_valid & 2)
+ if (id->field_valid & 2) {
mask = id->dma_1word & hwif->swdma_mask;
+ } else if (id->tDMA) {
+ /*
+ * ide_fix_driveid() doesn't convert ->tDMA to the
+ * CPU endianness so we need to do it here
+ */
+ u8 mode = le16_to_cpu(id->tDMA);
+
+ /*
+ * if the mode is valid convert it to the mask
+ * (the maximum allowed mode is XFER_SW_DMA_2)
+ */
+ if (mode <= 2)
+ mask = ((2 << mode) - 1) & hwif->swdma_mask;
+ }
break;
default:
BUG();
@@ -847,27 +861,27 @@ int ide_set_dma(ide_drive_t *drive)
return rc;
}
-EXPORT_SYMBOL_GPL(ide_set_dma);
-
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-int __ide_dma_lostirq (ide_drive_t *drive)
+void ide_dma_lost_irq (ide_drive_t *drive)
{
printk("%s: DMA interrupt recovery\n", drive->name);
- return 1;
}
-EXPORT_SYMBOL(__ide_dma_lostirq);
+EXPORT_SYMBOL(ide_dma_lost_irq);
-int __ide_dma_timeout (ide_drive_t *drive)
+void ide_dma_timeout (ide_drive_t *drive)
{
+ ide_hwif_t *hwif = HWIF(drive);
+
printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
- if (HWIF(drive)->ide_dma_test_irq(drive))
- return 0;
- return HWIF(drive)->ide_dma_end(drive);
+ if (hwif->ide_dma_test_irq(drive))
+ return;
+
+ hwif->ide_dma_end(drive);
}
-EXPORT_SYMBOL(__ide_dma_timeout);
+EXPORT_SYMBOL(ide_dma_timeout);
/*
* Needed for allowing full modular support of ide-driver
@@ -1018,10 +1032,10 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
hwif->ide_dma_end = &__ide_dma_end;
if (!hwif->ide_dma_test_irq)
hwif->ide_dma_test_irq = &__ide_dma_test_irq;
- if (!hwif->ide_dma_timeout)
- hwif->ide_dma_timeout = &__ide_dma_timeout;
- if (!hwif->ide_dma_lostirq)
- hwif->ide_dma_lostirq = &__ide_dma_lostirq;
+ if (!hwif->dma_timeout)
+ hwif->dma_timeout = &ide_dma_timeout;
+ if (!hwif->dma_lost_irq)
+ hwif->dma_lost_irq = &ide_dma_lost_irq;
if (hwif->chipset != ide_trm290) {
u8 dma_stat = hwif->INB(hwif->dma_status);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index bfe8f1b712b..c5b5011da56 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -1350,7 +1350,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
hwif->INB(IDE_STATUS_REG));
} else {
printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
- (void) hwif->ide_dma_timeout(drive);
+ hwif->dma_timeout(drive);
}
/*
@@ -1466,7 +1466,7 @@ void ide_timer_expiry (unsigned long data)
startstop = handler(drive);
} else if (drive_is_ready(drive)) {
if (drive->waiting_for_dma)
- (void) hwgroup->hwif->ide_dma_lostirq(drive);
+ hwgroup->hwif->dma_lost_irq(drive);
(void)ide_ack_intr(hwif);
printk(KERN_WARNING "%s: lost interrupt\n", drive->name);
startstop = handler(drive);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index f0be5f665a0..92578b6832e 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -574,7 +574,10 @@ u8 eighty_ninty_three (ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
struct hd_driveid *id = drive->id;
- if (hwif->udma_four == 0)
+ if (hwif->cbl == ATA_CBL_PATA40_SHORT)
+ return 1;
+
+ if (hwif->cbl != ATA_CBL_PATA80)
goto no_80w;
/* Check for SATA but only if we are ATA5 or higher */
@@ -600,7 +603,8 @@ no_80w:
printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
"limiting max speed to UDMA33\n",
- drive->name, hwif->udma_four ? "drive" : "host");
+ drive->name,
+ hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
drive->udma33_warned = 1;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index f5ce22c38f8..cc580139946 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -144,7 +144,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
local_irq_enable();
ide_fix_driveid(id);
-#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
+#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
/*
* EATA SCSI controllers do a hardware ATA emulation:
* Ignore them if there is a driver for them available.
@@ -154,7 +154,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
goto err_misc;
}
-#endif /* CONFIG_SCSI_EATA_DMA || CONFIG_SCSI_EATA_PIO */
+#endif /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */
/*
* WIN_IDENTIFY returns little-endian info,
@@ -1025,7 +1025,7 @@ static int init_irq (ide_hwif_t *hwif)
BUG_ON(irqs_disabled());
BUG_ON(hwif == NULL);
- down(&ide_cfg_sem);
+ mutex_lock(&ide_cfg_mtx);
hwif->hwgroup = NULL;
#if MAX_HWIFS > 1
/*
@@ -1154,7 +1154,7 @@ static int init_irq (ide_hwif_t *hwif)
printk(" (%sed with %s)",
hwif->sharing_irq ? "shar" : "serializ", match->name);
printk("\n");
- up(&ide_cfg_sem);
+ mutex_unlock(&ide_cfg_mtx);
return 0;
out_unlink:
spin_lock_irq(&ide_lock);
@@ -1177,7 +1177,7 @@ out_unlink:
}
spin_unlock_irq(&ide_lock);
out_up:
- up(&ide_cfg_sem);
+ mutex_unlock(&ide_cfg_mtx);
return 1;
}
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index ea94c9aa122..fc1d8ae6a80 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -156,7 +156,7 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int d
{
ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
while ((*p) && strcmp((*p)->name, name) < 0)
p = &((*p)->next);
if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
@@ -177,10 +177,10 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int d
if (auto_remove)
setting->auto_remove = 1;
*p = setting;
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
return 0;
abort:
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
kfree(setting);
return -1;
}
@@ -224,7 +224,7 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
*
* Automatically remove all the driver specific settings for this
* drive. This function may not be called from IRQ context. The
- * caller must hold ide_setting_sem.
+ * caller must hold ide_setting_mtx.
*/
static void auto_remove_settings (ide_drive_t *drive)
@@ -269,7 +269,7 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
* @setting: drive setting
*
* Read a drive setting and return the value. The caller
- * must hold the ide_setting_sem when making this call.
+ * must hold the ide_setting_mtx when making this call.
*
* BUGS: the data return and error are the same return value
* so an error -EINVAL and true return of the same value cannot
@@ -306,7 +306,7 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
* @val: value
*
* Write a drive setting if it is possible. The caller
- * must hold the ide_setting_sem when making this call.
+ * must hold the ide_setting_mtx when making this call.
*
* BUGS: the data return and error are the same return value
* so an error -EINVAL and true return of the same value cannot
@@ -367,7 +367,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
* @drive: drive being configured
*
* Add the generic parts of the system settings to the /proc files.
- * The caller must not be holding the ide_setting_sem.
+ * The caller must not be holding the ide_setting_mtx.
*/
void ide_add_generic_settings (ide_drive_t *drive)
@@ -408,7 +408,7 @@ static int proc_ide_read_settings
proc_ide_settings_warn();
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
while(setting) {
@@ -428,7 +428,7 @@ static int proc_ide_read_settings
setting = setting->next;
}
len = out - page;
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
@@ -508,16 +508,16 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
++p;
}
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
setting = ide_find_setting_by_name(drive, name);
if (!setting)
{
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
goto parse_error;
}
if (for_real)
ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
} while (!for_real++);
free_page((unsigned long)buf);
@@ -705,7 +705,7 @@ EXPORT_SYMBOL(ide_proc_register_driver);
* Clean up the driver specific /proc files and IDE settings
* for a given drive.
*
- * Takes ide_setting_sem and ide_lock.
+ * Takes ide_setting_mtx and ide_lock.
* Caller must hold none of the locks.
*/
@@ -715,10 +715,10 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
ide_remove_proc_entries(drive->proc, driver->proc);
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
/*
- * ide_setting_sem protects the settings list
+ * ide_setting_mtx protects the settings list
* ide_lock protects the use of settings
*
* so we need to hold both, ide_settings_sem because we want to
@@ -726,11 +726,11 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
* a setting out that is being used.
*
* OTOH both ide_{read,write}_setting are only ever used under
- * ide_setting_sem.
+ * ide_setting_mtx.
*/
auto_remove_settings(drive);
spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
EXPORT_SYMBOL(ide_proc_unregister_driver);
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index c0864b1e922..e6cb8593b5b 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -102,66 +102,16 @@ static struct ide_timing ide_timing[] = {
#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
#define XFER_MODE 0xf0
-#define XFER_UDMA_133 0x48
-#define XFER_UDMA_100 0x44
-#define XFER_UDMA_66 0x42
-#define XFER_UDMA 0x40
#define XFER_MWDMA 0x20
-#define XFER_SWDMA 0x10
#define XFER_EPIO 0x01
#define XFER_PIO 0x00
-static short ide_find_best_mode(ide_drive_t *drive, int map)
+static short ide_find_best_pio_mode(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
short best = 0;
- if (!id)
- return XFER_PIO_SLOW;
-
- if ((map & XFER_UDMA) && (id->field_valid & 4)) { /* Want UDMA and UDMA bitmap valid */
-
- if ((map & XFER_UDMA_133) == XFER_UDMA_133)
- if ((best = (id->dma_ultra & 0x0040) ? XFER_UDMA_6 : 0)) return best;
-
- if ((map & XFER_UDMA_100) == XFER_UDMA_100)
- if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best;
-
- if ((map & XFER_UDMA_66) == XFER_UDMA_66)
- if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 :
- (id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best;
-
- if ((best = (id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
- (id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
- (id->dma_ultra & 0x0001) ? XFER_UDMA_0 : 0)) return best;
- }
-
- if ((map & XFER_MWDMA) && (id->field_valid & 2)) { /* Want MWDMA and drive has EIDE fields */
-
- if ((best = (id->dma_mword & 0x0004) ? XFER_MW_DMA_2 :
- (id->dma_mword & 0x0002) ? XFER_MW_DMA_1 :
- (id->dma_mword & 0x0001) ? XFER_MW_DMA_0 : 0)) return best;
- }
-
- if (map & XFER_SWDMA) { /* Want SWDMA */
-
- if (id->field_valid & 2) { /* EIDE SWDMA */
-
- if ((best = (id->dma_1word & 0x0004) ? XFER_SW_DMA_2 :
- (id->dma_1word & 0x0002) ? XFER_SW_DMA_1 :
- (id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0)) return best;
- }
-
- if (id->capability & 1) { /* Pre-EIDE style SWDMA */
-
- if ((best = (id->tDMA == 2) ? XFER_SW_DMA_2 :
- (id->tDMA == 1) ? XFER_SW_DMA_1 :
- (id->tDMA == 0) ? XFER_SW_DMA_0 : 0)) return best;
- }
- }
-
-
- if ((map & XFER_EPIO) && (id->field_valid & 2)) { /* EIDE PIO modes */
+ if (id->field_valid & 2) { /* EIDE PIO modes */
if ((best = (drive->id->eide_pio_modes & 4) ? XFER_PIO_5 :
(drive->id->eide_pio_modes & 2) ? XFER_PIO_4 :
@@ -262,7 +212,7 @@ static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing
*/
if ((speed & XFER_MODE) != XFER_PIO) {
- ide_timing_compute(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO), &p, T, UT);
+ ide_timing_compute(drive, ide_find_best_pio_mode(drive), &p, T, UT);
ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 0cd76bf6683..c948a5c17a5 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -169,7 +169,7 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
static int idebus_parameter; /* holds the "idebus=" parameter */
static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
-DECLARE_MUTEX(ide_cfg_sem);
+DEFINE_MUTEX(ide_cfg_mtx);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
@@ -460,6 +460,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->mwdma_mask = tmp_hwif->mwdma_mask;
hwif->swdma_mask = tmp_hwif->swdma_mask;
+ hwif->cbl = tmp_hwif->cbl;
+
hwif->chipset = tmp_hwif->chipset;
hwif->hold = tmp_hwif->hold;
@@ -496,8 +498,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq;
hwif->dma_host_on = tmp_hwif->dma_host_on;
hwif->dma_host_off = tmp_hwif->dma_host_off;
- hwif->ide_dma_lostirq = tmp_hwif->ide_dma_lostirq;
- hwif->ide_dma_timeout = tmp_hwif->ide_dma_timeout;
+ hwif->dma_lost_irq = tmp_hwif->dma_lost_irq;
+ hwif->dma_timeout = tmp_hwif->dma_timeout;
hwif->OUTB = tmp_hwif->OUTB;
hwif->OUTBSYNC = tmp_hwif->OUTBSYNC;
@@ -533,7 +535,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->extra_base = tmp_hwif->extra_base;
hwif->extra_ports = tmp_hwif->extra_ports;
hwif->autodma = tmp_hwif->autodma;
- hwif->udma_four = tmp_hwif->udma_four;
hwif->hwif_data = tmp_hwif->hwif_data;
}
@@ -564,7 +565,7 @@ void ide_unregister(unsigned int index)
{
ide_drive_t *drive;
ide_hwif_t *hwif, *g;
- static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
+ static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */
ide_hwgroup_t *hwgroup;
int irq_count = 0, unit;
@@ -572,7 +573,7 @@ void ide_unregister(unsigned int index)
BUG_ON(in_interrupt());
BUG_ON(irqs_disabled());
- down(&ide_cfg_sem);
+ mutex_lock(&ide_cfg_mtx);
spin_lock_irq(&ide_lock);
hwif = &ide_hwifs[index];
if (!hwif->present)
@@ -679,7 +680,7 @@ void ide_unregister(unsigned int index)
abort:
spin_unlock_irq(&ide_lock);
- up(&ide_cfg_sem);
+ mutex_unlock(&ide_cfg_mtx);
}
EXPORT_SYMBOL(ide_unregister);
@@ -817,9 +818,9 @@ EXPORT_SYMBOL(ide_register_hw);
* Locks for IDE setting functionality
*/
-DECLARE_MUTEX(ide_setting_sem);
+DEFINE_MUTEX(ide_setting_mtx);
-EXPORT_SYMBOL_GPL(ide_setting_sem);
+EXPORT_SYMBOL_GPL(ide_setting_mtx);
/**
* ide_spin_wait_hwgroup - wait for group
@@ -1192,11 +1193,11 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
}
read_val:
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
err = *val;
spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
return err >= 0 ? put_user(err, (long __user *)arg) : err;
set_val:
@@ -1206,9 +1207,9 @@ set_val:
if (!capable(CAP_SYS_ADMIN))
err = -EACCES;
else {
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
err = setfunc(drive, arg);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
}
return err;
@@ -1548,7 +1549,11 @@ static int __init ide_setup(char *s)
goto bad_option;
case -7: /* ata66 */
#ifdef CONFIG_BLK_DEV_IDEPCI
- hwif->udma_four = 1;
+ /*
+ * Use ATA_CBL_PATA40_SHORT so drive side
+ * cable detection is also overriden.
+ */
+ hwif->cbl = ATA_CBL_PATA40_SHORT;
goto obsolete_option;
#else
goto bad_hwif;
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 45ed03591cd..7f4c0a5050a 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -130,7 +130,7 @@ struct hd_i_struct {
#ifdef HD_TYPE
static struct hd_i_struct hd_info[] = { HD_TYPE };
-static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
+static int NR_HD = ARRAY_SIZE(hd_info);
#else
static struct hd_i_struct hd_info[MAX_HD];
static int NR_HD;
@@ -623,7 +623,8 @@ repeat:
cyl = track / disk->head;
#ifdef DEBUG
printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
- req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
+ req->rq_disk->disk_name,
+ req_data_dir(req) == READ ? "read" : "writ",
cyl, head, sec, nsect, req->buffer);
#endif
if (blk_fs_request(req)) {
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index c211fc78345..b557c45a5a9 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -77,15 +77,6 @@ int macide_ack_intr(ide_hwif_t* hwif)
return 0;
}
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
-static void macide_mediabay_interrupt(int irq, void *dev_id)
-{
- int state = baboon->mb_status & 0x04;
-
- printk(KERN_INFO "macide: media bay %s detected\n", state? "removal":"insertion");
-}
-#endif
-
/*
* Probe for a Macintosh IDE interface
*/
@@ -128,11 +119,6 @@ void macide_init(void)
ide_drive_t *drive = &ide_hwifs[index].drives[0];
drive->capacity64 = drive->cyl*drive->head*drive->sect;
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
- request_irq(IRQ_BABOON_2, macide_mediabay_interrupt,
- IRQ_FLG_FAST, "mediabay",
- macide_mediabay_interrupt);
-#endif
}
break;
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
index d1414a75b52..7783745dd16 100644
--- a/drivers/ide/legacy/qd65xx.c
+++ b/drivers/ide/legacy/qd65xx.c
@@ -258,8 +258,7 @@ static void qd6580_tune_drive (ide_drive_t *drive, u8 pio)
int recovery_time = 415; /* worst case values from the dos driver */
if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
- pio = ide_get_best_pio_mode(drive, pio, 255, &d);
- pio = min_t(u8, pio, 4);
+ pio = ide_get_best_pio_mode(drive, pio, 4, &d);
switch (pio) {
case 0: break;
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index ca95e990862..2e7013a2a7f 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -381,9 +381,7 @@ static int auide_dma_setup(ide_drive_t *drive)
static int auide_dma_check(ide_drive_t *drive)
{
- u8 speed;
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ u8 speed = ide_max_dma_mode(drive);
if( dbdma_init_done == 0 ){
auide_hwif.white_list = ide_in_drive_list(drive->id,
@@ -394,7 +392,6 @@ static int auide_dma_check(ide_drive_t *drive)
auide_ddma_init(&auide_hwif);
dbdma_init_done = 1;
}
-#endif
/* Is the drive in our DMA black list? */
@@ -409,8 +406,6 @@ static int auide_dma_check(ide_drive_t *drive)
else
drive->using_dma = 1;
- speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA);
-
if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
return 0;
@@ -456,10 +451,9 @@ static void auide_dma_off_quietly(ide_drive_t *drive)
drive->using_dma = 0;
}
-static int auide_dma_lostirq(ide_drive_t *drive)
+static void auide_dma_lost_irq(ide_drive_t *drive)
{
printk(KERN_ERR "%s: IRQ lost\n", drive->name);
- return 0;
}
static void auide_ddma_tx_callback(int irq, void *param)
@@ -489,16 +483,16 @@ static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 de
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
-static int auide_dma_timeout(ide_drive_t *drive)
+static void auide_dma_timeout(ide_drive_t *drive)
{
-// printk("%s\n", __FUNCTION__);
+ ide_hwif_t *hwif = HWIF(drive);
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
- if (HWIF(drive)->ide_dma_test_irq(drive))
- return 0;
+ if (hwif->ide_dma_test_irq(drive))
+ return;
- return HWIF(drive)->ide_dma_end(drive);
+ hwif->ide_dma_end(drive);
}
@@ -721,7 +715,7 @@ static int au_ide_probe(struct device *dev)
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
hwif->dma_off_quietly = &auide_dma_off_quietly;
- hwif->ide_dma_timeout = &auide_dma_timeout;
+ hwif->dma_timeout = &auide_dma_timeout;
hwif->ide_dma_check = &auide_dma_check;
hwif->dma_exec_cmd = &auide_dma_exec_cmd;
@@ -731,7 +725,7 @@ static int au_ide_probe(struct device *dev)
hwif->ide_dma_test_irq = &auide_dma_test_irq;
hwif->dma_host_off = &auide_dma_host_off;
hwif->dma_host_on = &auide_dma_host_on;
- hwif->ide_dma_lostirq = &auide_dma_lostirq;
+ hwif->dma_lost_irq = &auide_dma_lost_irq;
hwif->ide_dma_on = &auide_dma_on;
hwif->autodma = 1;
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index b173bc66ce1..e5d09367627 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/aec62xx.c Version 0.21 Apr 21, 2007
+ * linux/drivers/ide/pci/aec62xx.c Version 0.24 May 24, 2007
*
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
@@ -140,25 +140,10 @@ static int aec6260_tune_chipset (ide_drive_t *drive, u8 xferspeed)
return(ide_config_drive_speed(drive, speed));
}
-static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed)
-{
- switch (HWIF(drive)->pci_dev->device) {
- case PCI_DEVICE_ID_ARTOP_ATP865:
- case PCI_DEVICE_ID_ARTOP_ATP865R:
- case PCI_DEVICE_ID_ARTOP_ATP860:
- case PCI_DEVICE_ID_ARTOP_ATP860R:
- return ((int) aec6260_tune_chipset(drive, speed));
- case PCI_DEVICE_ID_ARTOP_ATP850UF:
- return ((int) aec6210_tune_chipset(drive, speed));
- default:
- return -1;
- }
-}
-
static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
{
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
- (void) aec62xx_tune_chipset(drive, pio + XFER_PIO_0);
+ (void) HWIF(drive)->speedproc(drive, pio + XFER_PIO_0);
}
static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
@@ -172,12 +157,9 @@ static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
return -1;
}
-static int aec62xx_irq_timeout (ide_drive_t *drive)
+static void aec62xx_dma_lost_irq (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
-
- switch(dev->device) {
+ switch (HWIF(drive)->pci_dev->device) {
case PCI_DEVICE_ID_ARTOP_ATP860:
case PCI_DEVICE_ID_ARTOP_ATP860R:
case PCI_DEVICE_ID_ARTOP_ATP865:
@@ -186,7 +168,6 @@ static int aec62xx_irq_timeout (ide_drive_t *drive)
default:
break;
}
- return 0;
}
static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
@@ -224,64 +205,46 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch
static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = hwif->pci_dev;
+ u8 reg54 = 0, mask = hwif->channel ? 0xf0 : 0x0f;
+ unsigned long flags;
- hwif->autodma = 0;
hwif->tuneproc = &aec62xx_tune_drive;
- hwif->speedproc = &aec62xx_tune_chipset;
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
- hwif->serialized = hwif->channel;
-
- if (hwif->mate)
- hwif->mate->serialized = hwif->serialized;
+ if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+ if(hwif->mate)
+ hwif->mate->serialized = hwif->serialized = 1;
+ hwif->speedproc = &aec6210_tune_chipset;
+ } else
+ hwif->speedproc = &aec6260_tune_chipset;
if (!hwif->dma_base) {
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
+ hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
return;
}
hwif->ultra_mask = hwif->cds->udma_mask;
-
- /* atp865 and atp865r */
- if (hwif->ultra_mask == 0x3f) {
- /* check bit 0x10 of DMA status register */
- if (inb(pci_resource_start(dev, 4) + 2) & 0x10)
- hwif->ultra_mask = 0x7f; /* udma0-6 */
- }
-
hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate;
- hwif->ide_dma_lostirq = &aec62xx_irq_timeout;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
-}
-
-static void __devinit init_dma_aec62xx(ide_hwif_t *hwif, unsigned long dmabase)
-{
- struct pci_dev *dev = hwif->pci_dev;
+ hwif->dma_lost_irq = &aec62xx_dma_lost_irq;
if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
- u8 reg54h = 0;
- unsigned long flags;
-
spin_lock_irqsave(&ide_lock, flags);
- pci_read_config_byte(dev, 0x54, &reg54h);
- pci_write_config_byte(dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
+ pci_read_config_byte (dev, 0x54, &reg54);
+ pci_write_config_byte(dev, 0x54, (reg54 & ~mask));
spin_unlock_irqrestore(&ide_lock, flags);
- } else {
- u8 ata66 = 0;
+ } else if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+ u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
+
pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
- if (!(hwif->udma_four))
- hwif->udma_four = (ata66&(hwif->channel?0x02:0x01))?0:1;
+
+ hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
- ide_setup_dma(hwif, dmabase, 8);
+ if (!noautodma)
+ hwif->autodma = 1;
+ hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d)
@@ -291,16 +254,12 @@ static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d
static int __devinit init_setup_aec6x80(struct pci_dev *dev, ide_pci_device_t *d)
{
- unsigned long bar4reg = pci_resource_start(dev, 4);
-
- if (inb(bar4reg+2) & 0x10) {
- strcpy(d->name, "AEC6880");
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
- strcpy(d->name, "AEC6880R");
- } else {
- strcpy(d->name, "AEC6280");
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
- strcpy(d->name, "AEC6280R");
+ unsigned long dma_base = pci_resource_start(dev, 4);
+
+ if (inb(dma_base + 2) & 0x10) {
+ d->name = (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) ?
+ "AEC6880R" : "AEC6880";
+ d->udma_mask = 0x7f; /* udma0-6 */
}
return ide_setup_pci_device(dev, d);
@@ -312,7 +271,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
.init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -323,7 +281,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
.init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = NOAUTODMA,
.bootable = OFF_BOARD,
@@ -333,28 +290,25 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
.init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.bootable = NEVER_BOARD,
.udma_mask = 0x1f, /* udma0-4 */
},{ /* 3 */
- .name = "AEC6X80",
+ .name = "AEC6280",
.init_setup = init_setup_aec6x80,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.bootable = OFF_BOARD,
.udma_mask = 0x3f, /* udma0-5 */
},{ /* 4 */
- .name = "AEC6X80R",
+ .name = "AEC6280R",
.init_setup = init_setup_aec6x80,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -370,13 +324,16 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
*
* Called when the PCI registration layer (or the IDE initialization)
* finds a device matching our IDE device tables.
+ *
+ * NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R]
+ * chips, pass a local copy of 'struct pci_device_id' down the call chain.
*/
static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &aec62xx_chipsets[id->driver_data];
+ ide_pci_device_t d = aec62xx_chipsets[id->driver_data];
- return d->init_setup(dev, d);
+ return d.init_setup(dev, &d);
}
static struct pci_device_id aec62xx_pci_tbl[] = {
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 27525ec2e19..8a6b27b3bcc 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/alim15x3.c Version 0.21 2007/02/03
+ * linux/drivers/ide/pci/alim15x3.c Version 0.25 Jun 9 2007
*
* Copyright (C) 1998-2000 Michel Aubry, Maintainer
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
@@ -10,6 +10,7 @@
* Copyright (C) 2002 Alan Cox <alan@redhat.com>
* ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
*
* (U)DMA capable version of ali 1533/1543(C), 1535(D)
*
@@ -36,6 +37,7 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
+#include <linux/dmi.h>
#include <asm/io.h>
@@ -583,6 +585,35 @@ out:
return 0;
}
+/*
+ * Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+ {
+ .ident = "HP Pavilion N5430",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_BOARD_NAME, "OmniBook N32N-736"),
+ },
+ },
+ { }
+};
+
+static int ali_cable_override(struct pci_dev *pdev)
+{
+ /* Fujitsu P2000 */
+ if (pdev->subsystem_vendor == 0x10CF &&
+ pdev->subsystem_device == 0x10AF)
+ return 1;
+
+ /* Systems by DMI */
+ if (dmi_check_system(cable_dmi_table))
+ return 1;
+
+ return 0;
+}
+
/**
* ata66_ali15x3 - check for UDMA 66 support
* @hwif: IDE interface
@@ -594,37 +625,31 @@ out:
* FIXME: frobs bits that are not defined on newer ALi devicea
*/
-static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
+static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
- unsigned int ata66 = 0;
- u8 cable_80_pin[2] = { 0, 0 };
-
unsigned long flags;
- u8 tmpbyte;
+ u8 cbl = ATA_CBL_PATA40, tmpbyte;
local_irq_save(flags);
if (m5229_revision >= 0xC2) {
/*
- * Ultra66 cable detection (from Host View)
- * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
- */
- pci_read_config_byte(dev, 0x4a, &tmpbyte);
- /*
- * 0x4a, bit0 is 0 => primary channel
- * has 80-pin (from host view)
- */
- if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1;
- /*
- * 0x4a, bit1 is 0 => secondary channel
- * has 80-pin (from host view)
- */
- if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1;
- /*
- * Allow ata66 if cable of current channel has 80 pins
+ * m5229 80-pin cable detection (from Host View)
+ *
+ * 0x4a bit0 is 0 => primary channel has 80-pin
+ * 0x4a bit1 is 0 => secondary channel has 80-pin
+ *
+ * Certain laptops use short but suitable cables
+ * and don't implement the detect logic.
*/
- ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0];
+ if (ali_cable_override(dev))
+ cbl = ATA_CBL_PATA40_SHORT;
+ else {
+ pci_read_config_byte(dev, 0x4a, &tmpbyte);
+ if ((tmpbyte & (1 << hwif->channel)) == 0)
+ cbl = ATA_CBL_PATA80;
+ }
} else {
/*
* check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
@@ -657,7 +682,7 @@ static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
local_irq_restore(flags);
- return(ata66);
+ return cbl;
}
/**
@@ -708,8 +733,9 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
hwif->dma_setup = &ali15x3_dma_setup;
if (!noautodma)
hwif->autodma = 1;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_ali15x3(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_ali15x3(hwif);
}
hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index a2be65fcf89..84ed30cdb32 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -1,10 +1,11 @@
/*
- * Version 2.16
+ * Version 2.20
*
* AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
* IDE driver for Linux.
*
* Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
*
* Based on the work of:
* Andre Hedrick
@@ -37,11 +38,6 @@
#define AMD_ADDRESS_SETUP (0x0c + amd_config->base)
#define AMD_UDMA_TIMING (0x10 + amd_config->base)
-#define AMD_UDMA 0x07
-#define AMD_UDMA_33 0x01
-#define AMD_UDMA_66 0x02
-#define AMD_UDMA_100 0x03
-#define AMD_UDMA_133 0x04
#define AMD_CHECK_SWDMA 0x08
#define AMD_BAD_SWDMA 0x10
#define AMD_BAD_FIFO 0x20
@@ -53,32 +49,33 @@
static struct amd_ide_chip {
unsigned short id;
- unsigned long base;
- unsigned char flags;
+ u8 base;
+ u8 udma_mask;
+ u8 flags;
} amd_ide_chips[] = {
- { PCI_DEVICE_ID_AMD_COBRA_7401, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA },
- { PCI_DEVICE_ID_AMD_VIPER_7409, 0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA },
- { PCI_DEVICE_ID_AMD_VIPER_7411, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO },
- { PCI_DEVICE_ID_AMD_OPUS_7441, 0x40, AMD_UDMA_100 },
- { PCI_DEVICE_ID_AMD_8111_IDE, 0x40, AMD_UDMA_133 | AMD_CHECK_SERENADE },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x50, AMD_UDMA_100 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 },
+ { PCI_DEVICE_ID_AMD_COBRA_7401, 0x40, ATA_UDMA2, AMD_BAD_SWDMA },
+ { PCI_DEVICE_ID_AMD_VIPER_7409, 0x40, ATA_UDMA4, AMD_CHECK_SWDMA },
+ { PCI_DEVICE_ID_AMD_VIPER_7411, 0x40, ATA_UDMA5, AMD_BAD_FIFO },
+ { PCI_DEVICE_ID_AMD_OPUS_7441, 0x40, ATA_UDMA5, },
+ { PCI_DEVICE_ID_AMD_8111_IDE, 0x40, ATA_UDMA6, AMD_CHECK_SERENADE },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x50, ATA_UDMA5, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, ATA_UDMA5, },
{ 0 }
};
@@ -87,7 +84,7 @@ static ide_pci_device_t *amd_chipset;
static unsigned int amd_80w;
static unsigned int amd_clock;
-static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
/*
@@ -128,7 +125,7 @@ static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count)
pci_read_config_byte(dev, PCI_REVISION_ID, &t);
amd_print("Revision: IDE %#x", t);
- amd_print("Highest DMA rate: %s", amd_dma[amd_config->flags & AMD_UDMA]);
+ amd_print("Highest DMA rate: UDMA%s", amd_dma[fls(amd_config->udma_mask) - 1]);
amd_print("BM-DMA base: %#lx", amd_base);
amd_print("PCI clock: %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10);
@@ -221,12 +218,12 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
- switch (amd_config->flags & AMD_UDMA) {
- case AMD_UDMA_33: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
- case AMD_UDMA_66: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
- case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
- case AMD_UDMA_133: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
- default: return;
+ switch (amd_config->udma_mask) {
+ case ATA_UDMA2: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+ case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
+ case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
+ case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
+ default: return;
}
pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
@@ -248,7 +245,7 @@ static int amd_set_drive(ide_drive_t *drive, u8 speed)
ide_config_drive_speed(drive, speed);
T = 1000000000 / amd_clock;
- UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2);
+ UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
ide_timing_compute(drive, speed, &t, T, UT);
@@ -277,29 +274,19 @@ static int amd_set_drive(ide_drive_t *drive, u8 speed)
static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio)
{
if (pio == 255) {
- amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+ amd_set_drive(drive, ide_find_best_pio_mode(drive));
return;
}
amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
}
-/*
- * amd74xx_dmaproc() is a callback from upper layers that can do
- * a lot, but we use it for DMA/PIO tuning only, delegating everything
- * else to the default ide_dmaproc().
- */
-
static int amd74xx_ide_dma_check(ide_drive_t *drive)
{
- int w80 = HWIF(drive)->udma_four;
+ u8 speed = ide_max_dma_mode(drive);
- u8 speed = ide_find_best_mode(drive,
- XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
- ((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
- (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
- (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0) |
- (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_133 ? XFER_UDMA_133 : 0));
+ if (speed == 0)
+ speed = ide_find_best_pio_mode(drive);
amd_set_drive(drive, speed);
@@ -334,10 +321,10 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
* Check 80-wire cable presence.
*/
- switch (amd_config->flags & AMD_UDMA) {
+ switch (amd_config->udma_mask) {
- case AMD_UDMA_133:
- case AMD_UDMA_100:
+ case ATA_UDMA6:
+ case ATA_UDMA5:
pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
@@ -349,7 +336,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
}
break;
- case AMD_UDMA_66:
+ case ATA_UDMA4:
/* no host side cable detection */
amd_80w = 0x03;
break;
@@ -370,7 +357,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
if ((amd_config->flags & AMD_CHECK_SERENADE) &&
dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
- amd_config->flags = AMD_UDMA_100;
+ amd_config->udma_mask = ATA_UDMA5;
/*
* Determine the system bus clock.
@@ -395,8 +382,9 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
*/
pci_read_config_byte(dev, PCI_REVISION_ID, &t);
- printk(KERN_INFO "%s: %s (rev %02x) %s controller\n",
- amd_chipset->name, pci_name(dev), t, amd_dma[amd_config->flags & AMD_UDMA]);
+ printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
+ amd_chipset->name, pci_name(dev), t,
+ amd_dma[fls(amd_config->udma_mask) - 1]);
/*
* Register /proc/ide/amd74xx entry
@@ -437,12 +425,19 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
return;
hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
- if (!hwif->udma_four)
- hwif->udma_four = (amd_80w >> hwif->channel) & 1;
+ hwif->ultra_mask = amd_config->udma_mask;
+ hwif->mwdma_mask = 0x07;
+ if ((amd_config->flags & AMD_BAD_SWDMA) == 0)
+ hwif->swdma_mask = 0x07;
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+ if ((amd_80w >> hwif->channel) & 1)
+ hwif->cbl = ATA_CBL_PATA80;
+ else
+ hwif->cbl = ATA_CBL_PATA40;
+ }
+
hwif->ide_dma_check = &amd74xx_ide_dma_check;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 8ab33faf6f7..2761510309b 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -264,10 +264,11 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
hwif->swdma_mask = 0x04;
pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+
if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
- hwif->udma_four = 1;
+ hwif->cbl = ATA_CBL_PATA80;
else
- hwif->udma_four = 0;
+ hwif->cbl = ATA_CBL_PATA40;
hwif->dma_host_on = &atiixp_dma_host_on;
hwif->dma_host_off = &atiixp_dma_host_off;
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 7c57dc696f5..8631b6c8aa1 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/cmd64x.c Version 1.47 Mar 19, 2007
+ * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007
*
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Due to massive hardware bugs, UltraDMA is only supported
@@ -52,9 +52,6 @@
#define ARTTIM23_DIS_RA2 0x04
#define ARTTIM23_DIS_RA3 0x08
#define ARTTIM23_INTR_CH1 0x10
-#define ARTTIM2 0x57
-#define ARTTIM3 0x57
-#define DRWTIM23 0x58
#define DRWTIM2 0x58
#define BRST 0x59
#define DRWTIM3 0x5b
@@ -469,71 +466,43 @@ static int cmd646_1_ide_dma_end (ide_drive_t *drive)
static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name)
{
- u32 class_rev = 0;
u8 mrdmode = 0;
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
+ if (dev->device == PCI_DEVICE_ID_CMD_646) {
+ u8 rev = 0;
- switch(dev->device) {
- case PCI_DEVICE_ID_CMD_643:
- break;
- case PCI_DEVICE_ID_CMD_646:
- printk(KERN_INFO "%s: chipset revision 0x%02X, ", name, class_rev);
- switch(class_rev) {
- case 0x07:
- case 0x05:
- printk("UltraDMA Capable");
- break;
- case 0x03:
- printk("MultiWord DMA Force Limited");
- break;
- case 0x01:
- default:
- printk("MultiWord DMA Limited, IRQ workaround enabled");
- break;
- }
- printk("\n");
- break;
- case PCI_DEVICE_ID_CMD_648:
- case PCI_DEVICE_ID_CMD_649:
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+
+ switch (rev) {
+ case 0x07:
+ case 0x05:
+ printk("%s: UltraDMA capable", name);
break;
+ case 0x03:
default:
+ printk("%s: MultiWord DMA force limited", name);
+ break;
+ case 0x01:
+ printk("%s: MultiWord DMA limited, "
+ "IRQ workaround enabled\n", name);
break;
+ }
}
/* Set a good latency timer and cache line size value. */
(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
/* FIXME: pci_set_master() to ensure a good latency timer value */
- /* Setup interrupts. */
- (void) pci_read_config_byte(dev, MRDMODE, &mrdmode);
- mrdmode &= ~(0x30);
- (void) pci_write_config_byte(dev, MRDMODE, mrdmode);
-
- /* Use MEMORY READ LINE for reads.
- * NOTE: Although not mentioned in the PCI0646U specs,
- * these bits are write only and won't be read
- * back as set or not. The PCI0646U2 specs clarify
- * this point.
+ /*
+ * Enable interrupts, select MEMORY READ LINE for reads.
+ *
+ * NOTE: although not mentioned in the PCI0646U specs,
+ * bits 0-1 are write only and won't be read back as
+ * set or not -- PCI0646U2 specs clarify this point.
*/
- (void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02);
-
- /* Set reasonable active/recovery/address-setup values. */
- (void) pci_write_config_byte(dev, ARTTIM0, 0x40);
- (void) pci_write_config_byte(dev, DRWTIM0, 0x3f);
- (void) pci_write_config_byte(dev, ARTTIM1, 0x40);
- (void) pci_write_config_byte(dev, DRWTIM1, 0x3f);
-#ifdef __i386__
- (void) pci_write_config_byte(dev, ARTTIM23, 0x1c);
-#else
- (void) pci_write_config_byte(dev, ARTTIM23, 0x5c);
-#endif
- (void) pci_write_config_byte(dev, DRWTIM23, 0x3f);
- (void) pci_write_config_byte(dev, DRWTIM3, 0x3f);
-#ifdef CONFIG_PPC
- (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0);
-#endif /* CONFIG_PPC */
+ (void) pci_read_config_byte (dev, MRDMODE, &mrdmode);
+ mrdmode &= ~0x30;
+ (void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
@@ -548,29 +517,27 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
return 0;
}
-static unsigned int __devinit ata66_cmd64x(ide_hwif_t *hwif)
+static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
{
- u8 ata66 = 0, mask = (hwif->channel) ? 0x02 : 0x01;
+ struct pci_dev *dev = hwif->pci_dev;
+ u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01;
- switch(hwif->pci_dev->device) {
- case PCI_DEVICE_ID_CMD_643:
- case PCI_DEVICE_ID_CMD_646:
- return ata66;
- default:
- break;
+ switch (dev->device) {
+ case PCI_DEVICE_ID_CMD_648:
+ case PCI_DEVICE_ID_CMD_649:
+ pci_read_config_byte(dev, BMIDECSR, &bmidecsr);
+ return (bmidecsr & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ default:
+ return ATA_CBL_PATA40;
}
- pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66);
- return (ata66 & mask) ? 1 : 0;
}
static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
- unsigned int class_rev;
+ u8 rev = 0;
- hwif->autodma = 0;
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
hwif->tuneproc = &cmd64x_tune_drive;
hwif->speedproc = &cmd64x_tune_chipset;
@@ -580,8 +547,8 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
if (!hwif->dma_base)
return;
- hwif->atapi_dma = 1;
-
+ hwif->atapi_dma = 1;
+ hwif->mwdma_mask = 0x07;
hwif->ultra_mask = hwif->cds->udma_mask;
/*
@@ -596,16 +563,15 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
*
* So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
*/
- if (dev->device == PCI_DEVICE_ID_CMD_646 && class_rev < 5)
+ if (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 5)
hwif->ultra_mask = 0x00;
- hwif->mwdma_mask = 0x07;
-
hwif->ide_dma_check = &cmd64x_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_cmd64x(hwif);
- switch(dev->device) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_cmd64x(hwif);
+
+ switch (dev->device) {
case PCI_DEVICE_ID_CMD_648:
case PCI_DEVICE_ID_CMD_649:
alt_irq_bits:
@@ -614,10 +580,10 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
break;
case PCI_DEVICE_ID_CMD_646:
hwif->chipset = ide_cmd646;
- if (class_rev == 0x01) {
+ if (rev == 0x01) {
hwif->ide_dma_end = &cmd646_1_ide_dma_end;
break;
- } else if (class_rev >= 0x03)
+ } else if (rev >= 0x03)
goto alt_irq_bits;
/* fall thru */
default:
@@ -626,11 +592,9 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
break;
}
-
if (!noautodma)
hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
+ hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 41925c47ef0..10f61f38243 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -187,7 +187,8 @@ static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
/* if a 80 wire cable was detected */
pci_read_config_byte(dev, CS5535_CABLE_DETECT, &bit);
- return (bit & 1);
+
+ return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
/****
@@ -212,8 +213,7 @@ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
hwif->ultra_mask = 0x1F;
hwif->mwdma_mask = 0x07;
-
- hwif->udma_four = cs5535_cable_detect(hwif->pci_dev);
+ hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index c33d0b0f11c..4b6bae8eee8 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 1.06 Jun 27, 2007
+ * linux/drivers/ide/pci/hpt366.c Version 1.10 Jun 29, 2007
*
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
@@ -77,7 +77,7 @@
* since they may tamper with its fields
* - prefix the driver startup messages with the real chip name
* - claim the extra 240 bytes of I/O space for all chips
- * - optimize the rate masking/filtering and the drive list lookup code
+ * - optimize the UltraDMA filtering and the drive list lookup code
* - use pci_get_slot() to get to the function 1 of HPT36x/374
* - cache offset of the channel's misc. control registers (MCRs) being used
* throughout the driver
@@ -99,9 +99,9 @@
* stop duplicating it for each channel by storing the pointer in the pci_dev
* structure: first, at the init_setup stage, point it to a static "template"
* with only the chip type and its specific base DPLL frequency, the highest
- * supported DMA mode, and the chip settings table pointer filled, then, at
- * the init_chipset stage, allocate per-chip instance and fill it with the
- * rest of the necessary information
+ * UltraDMA mode, and the chip settings table pointer filled, then, at the
+ * init_chipset stage, allocate per-chip instance and fill it with the rest
+ * of the necessary information
* - get rid of the constant thresholds in the HPT37x PCI clock detection code,
* switch to calculating PCI clock frequency based on the chip's base DPLL
* frequency
@@ -112,6 +112,7 @@
* also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
* unify HPT36x/37x timing setup code and the speedproc handlers by joining
* the register setting lists into the table indexed by the clock selected
+ * - set the correct hwif->ultra_mask for each individual chip
* Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
*/
@@ -391,7 +392,7 @@ enum ata_clock {
struct hpt_info {
u8 chip_type; /* Chip type */
- u8 max_mode; /* Speeds allowed */
+ u8 max_ultra; /* Max. UltraDMA mode allowed */
u8 dpll_clk; /* DPLL clock in MHz */
u8 pci_clk; /* PCI clock in MHz */
u32 **settings; /* Chipset settings table */
@@ -430,77 +431,77 @@ static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
static struct hpt_info hpt36x __devinitdata = {
.chip_type = HPT36x,
- .max_mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1,
+ .max_ultra = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? 4 : 3) : 2,
.dpll_clk = 0, /* no DPLL */
.settings = hpt36x_settings
};
static struct hpt_info hpt370 __devinitdata = {
.chip_type = HPT370,
- .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2,
+ .max_ultra = HPT370_ALLOW_ATA100_5 ? 5 : 4,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt370a __devinitdata = {
.chip_type = HPT370A,
- .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2,
+ .max_ultra = HPT370_ALLOW_ATA100_5 ? 5 : 4,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt374 __devinitdata = {
.chip_type = HPT374,
- .max_mode = 3,
+ .max_ultra = 5,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt372 __devinitdata = {
.chip_type = HPT372,
- .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 55,
.settings = hpt37x_settings
};
static struct hpt_info hpt372a __devinitdata = {
.chip_type = HPT372A,
- .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt302 __devinitdata = {
.chip_type = HPT302,
- .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt371 __devinitdata = {
.chip_type = HPT371,
- .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT371_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt372n __devinitdata = {
.chip_type = HPT372N,
- .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
static struct hpt_info hpt302n __devinitdata = {
.chip_type = HPT302N,
- .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT302_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
static struct hpt_info hpt371n __devinitdata = {
.chip_type = HPT371N,
- .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT371_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
@@ -523,53 +524,38 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list)
static u8 hpt3xx_udma_filter(ide_drive_t *drive)
{
struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev);
- u8 chip_type = info->chip_type;
- u8 mode = info->max_mode;
u8 mask;
- switch (mode) {
- case 0x04:
- mask = 0x7f;
- break;
- case 0x03:
+ switch (info->chip_type) {
+ case HPT370A:
+ if (!HPT370_ALLOW_ATA100_5 ||
+ check_in_drive_list(drive, bad_ata100_5))
+ return 0x1f;
+ else
+ return 0x3f;
+ case HPT370:
+ if (!HPT370_ALLOW_ATA100_5 ||
+ check_in_drive_list(drive, bad_ata100_5))
+ mask = 0x1f;
+ else
mask = 0x3f;
- if (chip_type >= HPT374)
- break;
- if (!check_in_drive_list(drive, bad_ata100_5))
- goto check_bad_ata33;
- /* fall thru */
- case 0x02:
+ break;
+ case HPT36x:
+ if (!HPT366_ALLOW_ATA66_4 ||
+ check_in_drive_list(drive, bad_ata66_4))
+ mask = 0x0f;
+ else
mask = 0x1f;
- /*
- * CHECK ME, Does this need to be changed to HPT374 ??
- */
- if (chip_type >= HPT370)
- goto check_bad_ata33;
- if (HPT366_ALLOW_ATA66_4 &&
- !check_in_drive_list(drive, bad_ata66_4))
- goto check_bad_ata33;
-
- mask = 0x0f;
- if (HPT366_ALLOW_ATA66_3 &&
- !check_in_drive_list(drive, bad_ata66_3))
- goto check_bad_ata33;
- /* fall thru */
- case 0x01:
+ if (!HPT366_ALLOW_ATA66_3 ||
+ check_in_drive_list(drive, bad_ata66_3))
mask = 0x07;
-
- check_bad_ata33:
- if (chip_type >= HPT370A)
- break;
- if (!check_in_drive_list(drive, bad_ata33))
- break;
- /* fall thru */
- case 0x00:
- default:
- mask = 0x00;
- break;
+ break;
+ default:
+ return 0x7f;
}
- return mask;
+
+ return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
}
static u32 get_speed_setting(u8 speed, struct hpt_info *info)
@@ -737,7 +723,7 @@ static int hpt366_config_drive_xfer_rate(ide_drive_t *drive)
* This is specific to the HPT366 UDMA chipset
* by HighPoint|Triones Technologies, Inc.
*/
-static int hpt366_ide_dma_lostirq(ide_drive_t *drive)
+static void hpt366_dma_lost_irq(ide_drive_t *drive)
{
struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
@@ -749,7 +735,7 @@ static int hpt366_ide_dma_lostirq(ide_drive_t *drive)
drive->name, __FUNCTION__, mcr1, mcr3, scr1);
if (scr1 & 0x10)
pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
- return __ide_dma_lostirq(drive);
+ ide_dma_lost_irq(drive);
}
static void hpt370_clear_engine(ide_drive_t *drive)
@@ -799,10 +785,10 @@ static int hpt370_ide_dma_end(ide_drive_t *drive)
return __ide_dma_end(drive);
}
-static int hpt370_ide_dma_timeout(ide_drive_t *drive)
+static void hpt370_dma_timeout(ide_drive_t *drive)
{
hpt370_irq_timeout(drive);
- return __ide_dma_timeout(drive);
+ ide_dma_timeout(drive);
}
/* returns 1 if DMA IRQ issued, 0 otherwise */
@@ -1150,7 +1136,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
* Select 66 MHz DPLL clock only if UltraATA/133 mode is
* supported/enabled, use 50 MHz DPLL clock otherwise...
*/
- if (info->max_mode == 0x04) {
+ if (info->max_ultra == 6) {
dpll_clk = 66;
clock = ATA_CLOCK_66MHZ;
} else if (dpll_clk) { /* HPT36x chips don't have DPLL */
@@ -1243,7 +1229,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
struct pci_dev *dev = hwif->pci_dev;
struct hpt_info *info = pci_get_drvdata(dev);
int serialize = HPT_SERIALIZE_IO;
- u8 scr1 = 0, ata66 = (hwif->channel) ? 0x01 : 0x02;
+ u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02;
u8 chip_type = info->chip_type;
u8 new_mcr, old_mcr = 0;
@@ -1256,7 +1242,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
hwif->busproc = &hpt3xx_busproc;
- hwif->udma_filter = &hpt3xx_udma_filter;
+
+ if (chip_type <= HPT370A)
+ hwif->udma_filter = &hpt3xx_udma_filter;
/*
* HPT3xxN chips have some complications:
@@ -1305,7 +1293,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
return;
}
- hwif->ultra_mask = 0x7f;
+ hwif->ultra_mask = hwif->cds->udma_mask;
hwif->mwdma_mask = 0x07;
/*
@@ -1342,8 +1330,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
} else
pci_read_config_byte (dev, 0x5a, &scr1);
- if (!hwif->udma_four)
- hwif->udma_four = (scr1 & ata66) ? 0 : 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
@@ -1353,9 +1341,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
} else if (chip_type >= HPT370) {
hwif->dma_start = &hpt370_ide_dma_start;
hwif->ide_dma_end = &hpt370_ide_dma_end;
- hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
+ hwif->dma_timeout = &hpt370_dma_timeout;
} else
- hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
+ hwif->dma_lost_irq = &hpt366_dma_lost_irq;
if (!noautodma)
hwif->autodma = 1;
@@ -1503,9 +1491,35 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
- if (rev > 6)
+ switch (rev) {
+ case 0:
+ case 1:
+ case 2:
+ /*
+ * HPT36x chips have one channel per function and have
+ * both channel enable bits located differently and visible
+ * to both functions -- really stupid design decision... :-(
+ * Bit 4 is for the primary channel, bit 5 for the secondary.
+ */
+ d->channels = 1;
+ d->enablebits[0].mask = d->enablebits[0].val = 0x10;
+
+ d->udma_mask = HPT366_ALLOW_ATA66_3 ?
+ (HPT366_ALLOW_ATA66_4 ? 0x1f : 0x0f) : 0x07;
+ break;
+ case 3:
+ case 4:
+ d->udma_mask = HPT370_ALLOW_ATA100_5 ? 0x3f : 0x1f;
+ break;
+ default:
rev = 6;
-
+ /* fall thru */
+ case 5:
+ case 6:
+ d->udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f;
+ break;
+ }
+
d->name = chipset_names[rev];
pci_set_drvdata(dev, info[rev]);
@@ -1513,15 +1527,6 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
if (rev > 2)
goto init_single;
- /*
- * HPT36x chips have one channel per function and have
- * both channel enable bits located differently and visible
- * to both functions -- really stupid design decision... :-(
- * Bit 4 is for the primary channel, bit 5 for the secondary.
- */
- d->channels = 1;
- d->enablebits[0].mask = d->enablebits[0].val = 0x10;
-
if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
u8 mcr1 = 0, pin1 = 0, pin2 = 0;
int ret;
@@ -1573,6 +1578,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 2 */
@@ -1584,6 +1590,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT302_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 3 */
@@ -1595,6 +1602,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT371_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 4 */
@@ -1606,6 +1614,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2, /* 4 */
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 5 */
@@ -1617,6 +1626,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2, /* 4 */
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
}
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index c04a02687b9..ff48c23e571 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -231,7 +231,7 @@ static int it8213_config_drive_for_dma (ide_drive_t *drive)
static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
{
- u8 reg42h = 0, ata66 = 0;
+ u8 reg42h = 0;
hwif->speedproc = &it8213_tune_chipset;
hwif->tuneproc = &it8213_tuneproc;
@@ -250,11 +250,11 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
hwif->swdma_mask = 0x04;
pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
- ata66 = (reg42h & 0x02) ? 0 : 1;
hwif->ide_dma_check = &it8213_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66;
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
/*
* The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 3aeb7f1b791..8197b653ba1 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -491,10 +491,10 @@ static int it821x_config_drive_for_dma (ide_drive_t *drive)
* the needed logic onboard.
*/
-static unsigned int __devinit ata66_it821x(ide_hwif_t *hwif)
+static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
{
/* The reference driver also only does disk side */
- return 1;
+ return ATA_CBL_PATA80;
}
/**
@@ -662,8 +662,9 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &it821x_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_it821x(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_it821x(hwif);
/*
* The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 76ed2514722..a6008f63e71 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -25,10 +25,10 @@ typedef enum {
* ata66_jmicron - Cable check
* @hwif: IDE port
*
- * Return 1 if the cable is 80pin
+ * Returns the cable type.
*/
-static int __devinit ata66_jmicron(ide_hwif_t *hwif)
+static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
{
struct pci_dev *pdev = hwif->pci_dev;
@@ -70,16 +70,17 @@ static int __devinit ata66_jmicron(ide_hwif_t *hwif)
{
case PORT_PATA0:
if (control & (1 << 3)) /* 40/80 pin primary */
- return 0;
- return 1;
+ return ATA_CBL_PATA40;
+ return ATA_CBL_PATA80;
case PORT_PATA1:
if (control5 & (1 << 19)) /* 40/80 pin secondary */
- return 0;
- return 1;
+ return ATA_CBL_PATA40;
+ return ATA_CBL_PATA80;
case PORT_SATA:
break;
}
- return 1; /* Avoid bogus "control reaches end of non-void function" */
+ /* Avoid bogus "control reaches end of non-void function" */
+ return ATA_CBL_PATA80;
}
static void jmicron_tuneproc (ide_drive_t *drive, byte mode_wanted)
@@ -159,8 +160,9 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &jmicron_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_jmicron(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_jmicron(hwif);
hwif->autodma = 1;
hwif->drives[0].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 0765dce6948..ee5020df005 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -225,7 +225,10 @@ static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio)
static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
{
- return get_indexed_reg(hwif, 0x0b) & 0x04;
+ if (get_indexed_reg(hwif, 0x0b) & 0x04)
+ return ATA_CBL_PATA40;
+ else
+ return ATA_CBL_PATA80;
}
static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
@@ -509,8 +512,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
- if (!hwif->udma_four)
- hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = pdcnew_cable_detect(hwif);
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 23844687dee..41ac4a94959 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -152,8 +152,10 @@ static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio)
static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
{
u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
+
pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
- return (CIS & mask) ? 1 : 0;
+
+ return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
/*
@@ -267,18 +269,24 @@ somebody_else:
return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
}
-static int pdc202xx_ide_dma_lostirq(ide_drive_t *drive)
+static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
{
- if (HWIF(drive)->resetproc != NULL)
- HWIF(drive)->resetproc(drive);
- return __ide_dma_lostirq(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+
+ if (hwif->resetproc != NULL)
+ hwif->resetproc(drive);
+
+ ide_dma_lost_irq(drive);
}
-static int pdc202xx_ide_dma_timeout(ide_drive_t *drive)
+static void pdc202xx_dma_timeout(ide_drive_t *drive)
{
- if (HWIF(drive)->resetproc != NULL)
- HWIF(drive)->resetproc(drive);
- return __ide_dma_timeout(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+
+ if (hwif->resetproc != NULL)
+ hwif->resetproc(drive);
+
+ ide_dma_timeout(drive);
}
static void pdc202xx_reset_host (ide_hwif_t *hwif)
@@ -347,12 +355,13 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
hwif->err_stops_fifo = 1;
hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate;
- hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq;
- hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout;
+ hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
+ hwif->dma_timeout = &pdc202xx_dma_timeout;
if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
- if (!(hwif->udma_four))
- hwif->udma_four = (pdc202xx_old_cable_detect(hwif)) ? 0 : 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = pdc202xx_old_cable_detect(hwif);
+
hwif->dma_start = &pdc202xx_old_ide_dma_start;
hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
}
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 8b219dd6302..2e0b29ef596 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/piix.c Version 0.47 February 8, 2007
+ * linux/drivers/ide/pci/piix.c Version 0.50 Jun 10, 2007
*
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
@@ -394,14 +394,45 @@ static void piix_dma_clear_irq(ide_drive_t *drive)
hwif->OUTB(dma_stat, hwif->dma_status);
}
-static int __devinit piix_cable_detect(ide_hwif_t *hwif)
+struct ich_laptop {
+ u16 device;
+ u16 subvendor;
+ u16 subdevice;
+};
+
+/*
+ * List of laptops that use short cables rather than 80 wire
+ */
+
+static const struct ich_laptop ich_laptop[] = {
+ /* devid, subvendor, subdev */
+ { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
+ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
+ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
+ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
+ /* end marker */
+ { 0, }
+};
+
+static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *pdev = hwif->pci_dev;
+ const struct ich_laptop *lap = &ich_laptop[0];
u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
- pci_read_config_byte(dev, 0x54, &reg54h);
+ /* check for specials */
+ while (lap->device) {
+ if (lap->device == pdev->device &&
+ lap->subvendor == pdev->subsystem_vendor &&
+ lap->subdevice == pdev->subsystem_device) {
+ return ATA_CBL_PATA40_SHORT;
+ }
+ lap++;
+ }
+
+ pci_read_config_byte(pdev, 0x54, &reg54h);
- return (reg54h & mask) ? 1 : 0;
+ return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
/**
@@ -444,8 +475,8 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
hwif->swdma_mask = 0x04;
if (hwif->ultra_mask & 0x78) {
- if (!hwif->udma_four)
- hwif->udma_four = piix_cable_detect(hwif);
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = piix_cable_detect(hwif);
}
if (no_piix_dma)
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 55bc0a32e34..7b87488e3da 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -716,7 +716,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
hwif->atapi_dma = 1;
/* we support 80c cable only. */
- hwif->udma_four = 1;
+ hwif->cbl = ATA_CBL_PATA80;
hwif->autodma = 0;
if (!noautodma)
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index d9c4fd1ae99..1371b5bf6bf 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/serverworks.c Version 0.11 Jun 2 2007
+ * linux/drivers/ide/pci/serverworks.c Version 0.20 Jun 3 2007
*
* Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz
@@ -151,84 +151,11 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 &&
drive->media == ide_disk && speed >= XFER_UDMA_0)
BUG();
-
- pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing);
- pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing);
+
pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
pci_read_config_word(dev, 0x4A, &csb5_pio);
pci_read_config_byte(dev, 0x54, &ultra_enable);
- /* If we are in RAID mode (eg AMI MegaIDE) then we can't it
- turns out trust the firmware configuration */
-
- if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
- goto oem_setup_failed;
-
- /* Per Specified Design by OEM, and ASIC Architect */
- if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
- (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
- if (!drive->init_speed) {
- u8 dma_stat = inb(hwif->dma_status);
-
- if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
- ((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) {
- drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)];
- return 0;
- } else if ((dma_timing) &&
- ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
- u8 dmaspeed;
-
- switch (dma_timing & 0x77) {
- case 0x20:
- dmaspeed = XFER_MW_DMA_2;
- break;
- case 0x21:
- dmaspeed = XFER_MW_DMA_1;
- break;
- case 0x77:
- dmaspeed = XFER_MW_DMA_0;
- break;
- default:
- goto dma_pio;
- }
-
- drive->current_speed = drive->init_speed = dmaspeed;
- return 0;
- }
-dma_pio:
- if (pio_timing) {
- u8 piospeed;
-
- switch (pio_timing & 0x7f) {
- case 0x20:
- piospeed = XFER_PIO_4;
- break;
- case 0x22:
- piospeed = XFER_PIO_3;
- break;
- case 0x34:
- piospeed = XFER_PIO_2;
- break;
- case 0x47:
- piospeed = XFER_PIO_1;
- break;
- case 0x5d:
- piospeed = XFER_PIO_0;
- break;
- default:
- goto oem_setup_failed;
- }
-
- drive->current_speed = drive->init_speed = piospeed;
- return 0;
- }
- }
- }
-
-oem_setup_failed:
-
- pio_timing = 0;
- dma_timing = 0;
ultra_timing &= ~(0x0F << (4*unit));
ultra_enable &= ~(0x01 << drive->dn);
csb5_pio &= ~(0x0F << (4*drive->dn));
@@ -402,9 +329,9 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
return dev->irq;
}
-static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
{
- return 1;
+ return ATA_CBL_PATA80;
}
/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits
@@ -414,7 +341,7 @@ static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
* Bit 14 clear = primary IDE channel does not have 80-pin cable.
* Bit 14 set = primary IDE channel has 80-pin cable.
*/
-static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
@@ -422,8 +349,8 @@ static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
(dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE))
return ((1 << (hwif->channel + 14)) &
- dev->subsystem_device) ? 1 : 0;
- return 0;
+ dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ return ATA_CBL_PATA40;
}
/* Sun Cobalt Alpine hardware avoids the 80-pin cable
@@ -432,18 +359,18 @@ static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
*
* WARNING: this only works on Alpine hardware!
*/
-static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
return ((1 << (hwif->channel + 14)) &
- dev->subsystem_device) ? 1 : 0;
- return 0;
+ dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ return ATA_CBL_PATA40;
}
-static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
@@ -462,9 +389,9 @@ static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
/* Per Specified Design by OEM, and ASIC Architect */
if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
(dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2))
- return 1;
+ return ATA_CBL_PATA80;
- return 0;
+ return ATA_CBL_PATA40;
}
static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
@@ -495,8 +422,8 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
- if (!hwif->udma_four)
- hwif->udma_four = ata66_svwks(hwif);
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_svwks(hwif);
}
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index d3185e29a38..d396b2929ed 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -316,14 +316,6 @@ static void sgiioc4_dma_host_off(ide_drive_t * drive)
sgiioc4_clearirq(drive);
}
-static int
-sgiioc4_ide_dma_lostirq(ide_drive_t * drive)
-{
- HWIF(drive)->resetproc(drive);
-
- return __ide_dma_lostirq(drive);
-}
-
static void
sgiioc4_resetproc(ide_drive_t * drive)
{
@@ -331,6 +323,14 @@ sgiioc4_resetproc(ide_drive_t * drive)
sgiioc4_clearirq(drive);
}
+static void
+sgiioc4_dma_lost_irq(ide_drive_t * drive)
+{
+ sgiioc4_resetproc(drive);
+
+ ide_dma_lost_irq(drive);
+}
+
static u8
sgiioc4_INB(unsigned long port)
{
@@ -607,8 +607,8 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
hwif->dma_host_on = &sgiioc4_dma_host_on;
hwif->dma_host_off = &sgiioc4_dma_host_off;
- hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
- hwif->ide_dma_timeout = &__ide_dma_timeout;
+ hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
+ hwif->dma_timeout = &ide_dma_timeout;
hwif->INB = &sgiioc4_INB;
}
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 1a4444e7226..1c3e3548789 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -933,16 +933,17 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
* interface.
*/
-static unsigned int __devinit ata66_siimage(ide_hwif_t *hwif)
+static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
{
unsigned long addr = siimage_selreg(hwif, 0);
- if (pci_get_drvdata(hwif->pci_dev) == NULL) {
- u8 ata66 = 0;
+ u8 ata66 = 0;
+
+ if (pci_get_drvdata(hwif->pci_dev) == NULL)
pci_read_config_byte(hwif->pci_dev, addr, &ata66);
- return (ata66 & 0x01) ? 1 : 0;
- }
+ else
+ ata66 = hwif->INB(addr);
- return (hwif->INB(addr) & 0x01) ? 1 : 0;
+ return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
/**
@@ -988,8 +989,9 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
hwif->atapi_dma = 1;
hwif->ide_dma_check = &siimage_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_siimage(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_siimage(hwif);
if (hwif->mmio) {
hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index bb6cc4aedd6..f875183ac8d 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/sis5513.c Version 0.20 Mar 4, 2007
+ * linux/drivers/ide/pci/sis5513.c Version 0.25 Jun 10, 2007
*
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
@@ -796,10 +796,33 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
return 0;
}
-static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
+struct sis_laptop {
+ u16 device;
+ u16 subvendor;
+ u16 subdevice;
+};
+
+static const struct sis_laptop sis_laptop[] = {
+ /* devid, subvendor, subdev */
+ { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */
+ /* end marker */
+ { 0, }
+};
+
+static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
{
+ struct pci_dev *pdev = hwif->pci_dev;
+ const struct sis_laptop *lap = &sis_laptop[0];
u8 ata66 = 0;
+ while (lap->device) {
+ if (lap->device == pdev->device &&
+ lap->subvendor == pdev->subsystem_vendor &&
+ lap->subdevice == pdev->subsystem_device)
+ return ATA_CBL_PATA40_SHORT;
+ lap++;
+ }
+
if (chipset_family >= ATA_133) {
u16 regw = 0;
u16 reg_addr = hwif->channel ? 0x52: 0x50;
@@ -811,7 +834,8 @@ static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
ata66 = (reg48h & mask) ? 0 : 1;
}
- return ata66;
+
+ return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
@@ -841,8 +865,8 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
if (!chipset_family)
return;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_sis5513(hwif);
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_sis5513(hwif);
if (chipset_family > ATA_16) {
hwif->ide_dma_check = &sis5513_config_xfer_rate;
@@ -872,6 +896,7 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi
static struct pci_device_id sis5513_pci_tbl[] = {
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5518, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_1180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 7c383d9cc47..487879842af 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -195,7 +195,7 @@ static inline void sl82c105_reset_host(struct pci_dev *dev)
* This function is called when the IDE timer expires, the drive
* indicates that it is READY, and we were waiting for DMA to complete.
*/
-static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
+static void sl82c105_dma_lost_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
@@ -222,9 +222,6 @@ static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
}
sl82c105_reset_host(dev);
-
- /* __ide_dma_lostirq would return 1, so we do as well */
- return 1;
}
/*
@@ -244,15 +241,12 @@ static void sl82c105_dma_start(ide_drive_t *drive)
ide_dma_start(drive);
}
-static int sl82c105_ide_dma_timeout(ide_drive_t *drive)
+static void sl82c105_dma_timeout(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
- DBG(("sl82c105_ide_dma_timeout(drive:%s)\n", drive->name));
-
- sl82c105_reset_host(dev);
- return __ide_dma_timeout(drive);
+ sl82c105_reset_host(HWIF(drive)->pci_dev);
+ ide_dma_timeout(drive);
}
static int sl82c105_ide_dma_on(ide_drive_t *drive)
@@ -441,9 +435,9 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
hwif->ide_dma_check = &sl82c105_ide_dma_check;
hwif->ide_dma_on = &sl82c105_ide_dma_on;
hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
- hwif->ide_dma_lostirq = &sl82c105_ide_dma_lostirq;
+ hwif->dma_lost_irq = &sl82c105_dma_lost_irq;
hwif->dma_start = &sl82c105_dma_start;
- hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout;
+ hwif->dma_timeout = &sl82c105_dma_timeout;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index c40f291f91e..575dbbd8b48 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -199,10 +199,9 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
hwif->mwdma_mask = 0x06;
hwif->swdma_mask = 0x04;
- if (!hwif->udma_four) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
/* bit[0(1)]: 0:80, 1:40 */
- hwif->udma_four = (reg47 & mask) ? 0 : 1;
- }
+ hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate;
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index cee619bb2ea..8de1f8e2249 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -220,13 +220,13 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
hwif->ide_dma_check = &tc86c001_config_drive_xfer_rate;
hwif->dma_start = &tc86c001_dma_start;
- if (!hwif->udma_four) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
/*
* System Control 1 Register bit 13 (PDIAGN):
* 0=80-pin cable, 1=40-pin cable
*/
scr1 = hwif->INW(sc_base + 0x00);
- hwif->udma_four = (scr1 & 0x2000) ? 0 : 1;
+ hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
if (!noautodma)
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index a508550c409..d21dd2e7eeb 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -1,6 +1,6 @@
/*
*
- * Version 3.38
+ * Version 3.45
*
* VIA IDE driver for Linux. Supported southbridges:
*
@@ -9,6 +9,7 @@
* vt8235, vt8237, vt8237a
*
* Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
*
* Based on the work of:
* Michel Aubry
@@ -33,6 +34,8 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
+#include <linux/dmi.h>
+
#include <asm/io.h>
#ifdef CONFIG_PPC_CHRP
@@ -41,8 +44,6 @@
#include "ide-timing.h"
-#define DISPLAY_VIA_TIMINGS
-
#define VIA_IDE_ENABLE 0x40
#define VIA_IDE_CONFIG 0x41
#define VIA_FIFO_CONFIG 0x43
@@ -54,18 +55,12 @@
#define VIA_ADDRESS_SETUP 0x4c
#define VIA_UDMA_TIMING 0x50
-#define VIA_UDMA 0x007
-#define VIA_UDMA_NONE 0x000
-#define VIA_UDMA_33 0x001
-#define VIA_UDMA_66 0x002
-#define VIA_UDMA_100 0x003
-#define VIA_UDMA_133 0x004
-#define VIA_BAD_PREQ 0x010 /* Crashes if PREQ# till DDACK# set */
-#define VIA_BAD_CLK66 0x020 /* 66 MHz clock doesn't work correctly */
-#define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */
-#define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */
-#define VIA_BAD_ID 0x100 /* Has wrong vendor ID (0x1107) */
-#define VIA_BAD_AST 0x200 /* Don't touch Address Setup Timing */
+#define VIA_BAD_PREQ 0x01 /* Crashes if PREQ# till DDACK# set */
+#define VIA_BAD_CLK66 0x02 /* 66 MHz clock doesn't work correctly */
+#define VIA_SET_FIFO 0x04 /* Needs to have FIFO split set */
+#define VIA_NO_UNMASK 0x08 /* Doesn't work with IRQ unmasking on */
+#define VIA_BAD_ID 0x10 /* Has wrong vendor ID (0x1107) */
+#define VIA_BAD_AST 0x20 /* Don't touch Address Setup Timing */
/*
* VIA SouthBridge chips.
@@ -76,36 +71,37 @@ static struct via_isa_bridge {
u16 id;
u8 rev_min;
u8 rev_max;
- u16 flags;
+ u8 udma_mask;
+ u8 flags;
} via_isa_bridges[] = {
- { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 },
- { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 },
- { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
- { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 },
- { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
- { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO },
- { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ },
- { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO },
- { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO },
- { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
- { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK },
- { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
+ { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, ATA_UDMA5, },
+ { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, ATA_UDMA5, },
+ { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, ATA_UDMA5, },
+ { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, ATA_UDMA5, },
+ { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, ATA_UDMA4, },
+ { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+ { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, ATA_UDMA4, },
+ { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, ATA_UDMA2, VIA_SET_FIFO },
+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, ATA_UDMA2, VIA_SET_FIFO | VIA_BAD_PREQ },
+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, ATA_UDMA2, VIA_SET_FIFO },
+ { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, ATA_UDMA2, VIA_SET_FIFO },
+ { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, 0x00, VIA_SET_FIFO },
+ { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK },
+ { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
{ NULL }
};
static unsigned int via_clock;
-static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *via_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
struct via82cxxx_dev
{
@@ -140,12 +136,12 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
- switch (vdev->via_config->flags & VIA_UDMA) {
- case VIA_UDMA_33: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
- case VIA_UDMA_66: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
- case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
- case VIA_UDMA_133: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
- default: return;
+ switch (vdev->via_config->udma_mask) {
+ case ATA_UDMA2: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+ case ATA_UDMA4: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
+ case ATA_UDMA5: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+ case ATA_UDMA6: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+ default: return;
}
pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
@@ -173,12 +169,12 @@ static int via_set_drive(ide_drive_t *drive, u8 speed)
T = 1000000000 / via_clock;
- switch (vdev->via_config->flags & VIA_UDMA) {
- case VIA_UDMA_33: UT = T; break;
- case VIA_UDMA_66: UT = T/2; break;
- case VIA_UDMA_100: UT = T/3; break;
- case VIA_UDMA_133: UT = T/4; break;
- default: UT = T;
+ switch (vdev->via_config->udma_mask) {
+ case ATA_UDMA2: UT = T; break;
+ case ATA_UDMA4: UT = T/2; break;
+ case ATA_UDMA5: UT = T/3; break;
+ case ATA_UDMA6: UT = T/4; break;
+ default: UT = T;
}
ide_timing_compute(drive, speed, &t, T, UT);
@@ -208,8 +204,7 @@ static int via_set_drive(ide_drive_t *drive, u8 speed)
static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
{
if (pio == 255) {
- via_set_drive(drive,
- ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+ via_set_drive(drive, ide_find_best_pio_mode(drive));
return;
}
@@ -226,16 +221,10 @@ static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
static int via82cxxx_ide_dma_check (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
- u16 w80 = hwif->udma_four;
+ u8 speed = ide_max_dma_mode(drive);
- u16 speed = ide_find_best_mode(drive,
- XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
- (vdev->via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
- (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
- (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) |
- (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0));
+ if (speed == 0)
+ speed = ide_find_best_pio_mode(drive);
via_set_drive(drive, speed);
@@ -272,8 +261,8 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
{
int i;
- switch (vdev->via_config->flags & VIA_UDMA) {
- case VIA_UDMA_66:
+ switch (vdev->via_config->udma_mask) {
+ case ATA_UDMA4:
for (i = 24; i >= 0; i -= 8)
if (((u >> (i & 16)) & 8) &&
((u >> i) & 0x20) &&
@@ -286,7 +275,7 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
}
break;
- case VIA_UDMA_100:
+ case ATA_UDMA5:
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
@@ -298,7 +287,7 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
}
break;
- case VIA_UDMA_133:
+ case ATA_UDMA6:
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
@@ -353,7 +342,7 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
via_cable_detect(vdev, u);
- if ((via_config->flags & VIA_UDMA) == VIA_UDMA_66) {
+ if (via_config->udma_mask == ATA_UDMA4) {
/* Enable Clk66 */
pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
} else if (via_config->flags & VIA_BAD_CLK66) {
@@ -416,16 +405,54 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
*/
pci_read_config_byte(isa, PCI_REVISION_ID, &t);
- printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s "
+ printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %sDMA%s "
"controller on pci%s\n",
via_config->name, t,
- via_dma[via_config->flags & VIA_UDMA],
+ via_config->udma_mask ? "U" : "MW",
+ via_dma[via_config->udma_mask ?
+ (fls(via_config->udma_mask) - 1) : 0],
pci_name(dev));
pci_dev_put(isa);
return 0;
}
+/*
+ * Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+ {
+ .ident = "Acer Ferrari 3400",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."),
+ DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"),
+ },
+ },
+ { }
+};
+
+static int via_cable_override(void)
+{
+ /* Systems by DMI */
+ if (dmi_check_system(cable_dmi_table))
+ return 1;
+ return 0;
+}
+
+static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
+{
+ struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
+
+ if (via_cable_override())
+ return ATA_CBL_PATA40_SHORT;
+
+ if ((vdev->via_80w >> hwif->channel) & 1)
+ return ATA_CBL_PATA80;
+ else
+ return ATA_CBL_PATA40;
+}
+
static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
{
struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
@@ -454,12 +481,14 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
return;
hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
+
+ hwif->ultra_mask = vdev->via_config->udma_mask;
hwif->mwdma_mask = 0x07;
hwif->swdma_mask = 0x07;
- if (!hwif->udma_four)
- hwif->udma_four = (vdev->via_80w >> hwif->channel) & 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = via82cxxx_cable_detect(hwif);
+
hwif->ide_dma_check = &via82cxxx_ide_dma_check;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 45fc36f0f21..e46f4720654 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -942,8 +942,8 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
return 1;
case XFER_UDMA_4:
case XFER_UDMA_3:
- if (HWIF(drive)->udma_four == 0)
- return 1;
+ if (drive->hwif->cbl != ATA_CBL_PATA80)
+ return 1;
case XFER_UDMA_2:
case XFER_UDMA_1:
case XFER_UDMA_0:
@@ -1244,7 +1244,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->chipset = ide_pmac;
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay;
hwif->hold = pmif->mediabay;
- hwif->udma_four = pmif->cable_80;
+ hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
hwif->drives[0].unmask = 1;
hwif->drives[1].unmask = 1;
hwif->tuneproc = pmac_ide_tuneproc;
@@ -1821,28 +1821,11 @@ pmac_ide_dma_check(ide_drive_t *drive)
enable = 0;
if (enable) {
- short mode;
-
- map = XFER_MWDMA;
- if (pmif->kind == controller_kl_ata4
- || pmif->kind == controller_un_ata6
- || pmif->kind == controller_k2_ata6
- || pmif->kind == controller_sh_ata6) {
- map |= XFER_UDMA;
- if (pmif->cable_80) {
- map |= XFER_UDMA_66;
- if (pmif->kind == controller_un_ata6 ||
- pmif->kind == controller_k2_ata6 ||
- pmif->kind == controller_sh_ata6)
- map |= XFER_UDMA_100;
- if (pmif->kind == controller_sh_ata6)
- map |= XFER_UDMA_133;
- }
- }
- mode = ide_find_best_mode(drive, map);
- if (mode & XFER_UDMA)
+ u8 mode = ide_max_dma_mode(drive);
+
+ if (mode >= XFER_UDMA_0)
drive->using_dma = pmac_ide_udma_enable(drive, mode);
- else if (mode & XFER_MWDMA)
+ else if (mode >= XFER_MW_DMA_0)
drive->using_dma = pmac_ide_mdma_enable(drive, mode);
hwif->OUTB(0, IDE_CONTROL_REG);
/* Apply settings to controller */
@@ -2004,20 +1987,19 @@ static void pmac_ide_dma_host_on(ide_drive_t *drive)
{
}
-static int
-pmac_ide_dma_lostirq (ide_drive_t *drive)
+static void
+pmac_ide_dma_lost_irq (ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
volatile struct dbdma_regs __iomem *dma;
unsigned long status;
if (pmif == NULL)
- return 0;
+ return;
dma = pmif->dma_regs;
status = readl(&dma->status);
printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
- return 0;
}
/*
@@ -2057,8 +2039,8 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
hwif->dma_host_off = &pmac_ide_dma_host_off;
hwif->dma_host_on = &pmac_ide_dma_host_on;
- hwif->ide_dma_timeout = &__ide_dma_timeout;
- hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
+ hwif->dma_timeout = &ide_dma_timeout;
+ hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
hwif->atapi_dma = 1;
switch(pmif->kind) {
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 20814137761..65722117ab6 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2280,7 +2280,7 @@ static void dv1394_remove_host(struct hpsb_host *host)
} while (video);
if (found_ohci_card)
- class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+ device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
}
@@ -2295,9 +2295,9 @@ static void dv1394_add_host(struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
- class_device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
- NULL, "dv1394-%d", id);
+ device_create(hpsb_protocol_class, NULL, MKDEV(
+ IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+ "dv1394-%d", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 7c13fb3c167..93362eed94e 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -599,9 +599,7 @@ static void ether1394_add_host(struct hpsb_host *host)
}
SET_MODULE_OWNER(dev);
-
- /* This used to be &host->device in Linux 2.6.20 and before. */
- SET_NETDEV_DEV(dev, host->device.parent);
+ SET_NETDEV_DEV(dev, &host->device);
priv = netdev_priv(dev);
INIT_LIST_HEAD(&priv->ip_node_list);
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 83a49331275..b6425469b6e 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -483,37 +483,6 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return retval;
}
-/**
- * hpsb_listen_channel - enable receving a certain isochronous channel
- *
- * Reception is handled through the @hl's iso_receive op.
- */
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel)
-{
- if (channel > 63) {
- HPSB_ERR("%s called with invalid channel", __FUNCTION__);
- return -EINVAL;
- }
- if (host->iso_listen_count[channel]++ == 0)
- return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
- return 0;
-}
-
-/**
- * hpsb_unlisten_channel - disable receving a certain isochronous channel
- */
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel)
-{
- if (channel > 63) {
- HPSB_ERR("%s called with invalid channel", __FUNCTION__);
- return;
- }
- if (--host->iso_listen_count[channel] == 0)
- host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
-}
-
static void init_hpsb_highlevel(struct hpsb_host *host)
{
INIT_LIST_HEAD(&dummy_zero_addr.host_list);
@@ -570,20 +539,6 @@ void highlevel_host_reset(struct hpsb_host *host)
read_unlock_irqrestore(&hl_irqs_lock, flags);
}
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length)
-{
- unsigned long flags;
- struct hpsb_highlevel *hl;
- int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
-
- read_lock_irqsave(&hl_irqs_lock, flags);
- list_for_each_entry(hl, &hl_irqs, irq_list) {
- if (hl->iso_receive)
- hl->iso_receive(host, channel, data, length);
- }
- read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length)
{
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
index 63474f7ee69..eb9fe321e09 100644
--- a/drivers/ieee1394/highlevel.h
+++ b/drivers/ieee1394/highlevel.h
@@ -26,9 +26,7 @@ struct hpsb_address_serve {
struct hpsb_highlevel {
const char *name;
- /* Any of the following pointers can legally be NULL, except for
- * iso_receive which can only be NULL when you don't request
- * channels. */
+ /* Any of the following pointers can legally be NULL. */
/* New host initialized. Will also be called during
* hpsb_register_highlevel for all hosts already installed. */
@@ -43,13 +41,6 @@ struct hpsb_highlevel {
* You can not expect to be able to do stock hpsb_reads. */
void (*host_reset)(struct hpsb_host *host);
- /* An isochronous packet was received. Channel contains the channel
- * number for your convenience, it is also contained in the included
- * packet header (first quadlet, CRCs are missing). You may get called
- * for channel/host combinations you did not request. */
- void (*iso_receive)(struct hpsb_host *host, int channel,
- quadlet_t *data, size_t length);
-
/* A write request was received on either the FCP_COMMAND (direction =
* 0) or the FCP_RESPONSE (direction = 1) register. The cts arg
* contains the cts field (first byte of data). */
@@ -109,7 +100,6 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags);
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length);
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length);
@@ -125,10 +115,6 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
struct hpsb_address_ops *ops, u64 start, u64 end);
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start);
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel);
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel);
void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index bd0755c789c..8dd09d85041 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -154,15 +154,16 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
h->device.parent = dev;
+ set_dev_node(&h->device, dev_to_node(dev));
snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
- h->class_dev.dev = &h->device;
- h->class_dev.class = &hpsb_host_class;
- snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
+ h->host_dev.parent = &h->device;
+ h->host_dev.class = &hpsb_host_class;
+ snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
if (device_register(&h->device))
goto fail;
- if (class_device_register(&h->class_dev)) {
+ if (device_register(&h->host_dev)) {
device_unregister(&h->device);
goto fail;
}
@@ -202,7 +203,7 @@ void hpsb_remove_host(struct hpsb_host *host)
host->driver = &dummy_driver;
highlevel_remove_host(host);
- class_device_unregister(&host->class_dev);
+ device_unregister(&host->host_dev);
device_unregister(&host->device);
}
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index feb55d03229..e4e8aeb4d77 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -28,8 +28,6 @@ struct hpsb_host {
struct timer_list timeout;
unsigned long timeout_interval;
- unsigned char iso_listen_count[64];
-
int node_count; /* number of identified nodes on this bus */
int selfid_count; /* total number of SelfIDs received */
int nodes_active; /* number of nodes with active link layer */
@@ -57,7 +55,7 @@ struct hpsb_host {
struct hpsb_host_driver *driver;
struct pci_dev *pdev;
struct device device;
- struct class_device class_dev;
+ struct device host_dev;
struct delayed_work delayed_reset;
unsigned config_roms:31;
@@ -99,12 +97,6 @@ enum devctl_cmd {
/* Cancel all outstanding async requests without resetting the bus.
* Return void. */
CANCEL_REQUESTS,
-
- /* Start or stop receiving isochronous channel in arg. Return void.
- * This acts as an optimization hint, hosts are not required not to
- * listen on unrequested channels. */
- ISO_LISTEN_CHANNEL,
- ISO_UNLISTEN_CHANNEL
};
enum isoctl_cmd {
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 8f71b6a06aa..0fc8c6e559e 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -1028,11 +1028,6 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
handle_incoming_packet(host, tcode, data, size, write_acked);
break;
-
- case TCODE_ISO_DATA:
- highlevel_iso_receive(host, data, size);
- break;
-
case TCODE_CYCLE_START:
/* simply ignore this packet if it is passed on */
break;
@@ -1316,7 +1311,6 @@ EXPORT_SYMBOL(hpsb_make_streampacket);
EXPORT_SYMBOL(hpsb_make_lockpacket);
EXPORT_SYMBOL(hpsb_make_lock64packet);
EXPORT_SYMBOL(hpsb_make_phypacket);
-EXPORT_SYMBOL(hpsb_make_isopacket);
EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_packet_success);
@@ -1327,8 +1321,6 @@ EXPORT_SYMBOL(hpsb_unregister_highlevel);
EXPORT_SYMBOL(hpsb_register_addrspace);
EXPORT_SYMBOL(hpsb_unregister_addrspace);
EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
-EXPORT_SYMBOL(hpsb_listen_channel);
-EXPORT_SYMBOL(hpsb_unlisten_channel);
EXPORT_SYMBOL(hpsb_get_hostinfo);
EXPORT_SYMBOL(hpsb_create_hostinfo);
EXPORT_SYMBOL(hpsb_destroy_hostinfo);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index ad526523d0e..21d50f73a21 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -24,9 +24,8 @@ struct hpsb_packet {
nodeid_t node_id;
- /* Async and Iso types should be clear, raw means send-as-is, do not
- * CRC! Byte swapping shall still be done in this case. */
- enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
+ /* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */
+ enum { hpsb_async, hpsb_raw } __attribute__((packed)) type;
/* Okay, this is core internal and a no care for hosts.
* queued = queued for sending
@@ -37,7 +36,7 @@ struct hpsb_packet {
hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
} __attribute__((packed)) state;
- /* These are core internal. */
+ /* These are core-internal. */
signed char tlabel;
signed char ack_code;
unsigned char tcode;
@@ -62,11 +61,15 @@ struct hpsb_packet {
/* Store jiffies for implementing bus timeouts. */
unsigned long sendtime;
- /* Sizes are in bytes. *data can be DMA-mapped. */
+ /* Core-internal. */
size_t allocated_data_size; /* as allocated */
+
+ /* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */
size_t data_size; /* as filled in */
size_t header_size; /* as filled in, not counting the CRC */
- quadlet_t *data;
+
+ /* Buffers */
+ quadlet_t *data; /* can be DMA-mapped */
quadlet_t header[5];
quadlet_t embedded_data[0]; /* keep as last member */
};
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 40078ce930c..c39c70a8aa9 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -89,18 +89,6 @@ static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
packet->expect_response = 1;
}
-static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
- int tag, int sync)
-{
- packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
- | (TCODE_ISO_DATA << 4) | sync;
-
- packet->header_size = 4;
- packet->data_size = length;
- packet->type = hpsb_iso;
- packet->tcode = TCODE_ISO_DATA;
-}
-
static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
{
packet->header[0] = data;
@@ -491,24 +479,6 @@ struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
return p;
}
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
- int length, int channel,
- int tag, int sync)
-{
- struct hpsb_packet *p;
-
- p = hpsb_alloc_packet(length);
- if (!p)
- return NULL;
-
- p->host = host;
- fill_iso_packet(p, length, channel, tag, sync);
-
- p->generation = get_hpsb_generation(host);
-
- return p;
-}
-
/*
* FIXME - these functions should probably read from / write to user space to
* avoid in kernel buffers for user space callers
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index 86b8ee692ea..d2d5bc3546d 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -19,8 +19,6 @@ struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
nodeid_t node, u64 addr, int extcode,
octlet_t *data, octlet_t arg);
struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int length,
- int channel, int tag, int sync);
struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
nodeid_t node, u64 addr,
quadlet_t *buffer, size_t length);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 81b3864d2ba..c4d3d4131f0 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -19,6 +19,7 @@
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <asm/atomic.h>
+#include <asm/semaphore.h>
#include "csr.h"
#include "highlevel.h"
@@ -145,8 +146,6 @@ static struct csr1212_bus_ops nodemgr_csr_ops = {
* but now we are much simpler because of the LDM.
*/
-static DEFINE_MUTEX(nodemgr_serialize);
-
struct host_info {
struct hpsb_host *host;
struct list_head list;
@@ -154,7 +153,7 @@ struct host_info {
};
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size);
static void nodemgr_resume_ne(struct node_entry *ne);
static void nodemgr_remove_ne(struct node_entry *ne);
@@ -165,37 +164,38 @@ struct bus_type ieee1394_bus_type = {
.match = nodemgr_bus_match,
};
-static void host_cls_release(struct class_device *class_dev)
+static void host_cls_release(struct device *dev)
{
- put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device);
+ put_device(&container_of((dev), struct hpsb_host, host_dev)->device);
}
struct class hpsb_host_class = {
.name = "ieee1394_host",
- .release = host_cls_release,
+ .dev_release = host_cls_release,
};
-static void ne_cls_release(struct class_device *class_dev)
+static void ne_cls_release(struct device *dev)
{
- put_device(&container_of((class_dev), struct node_entry, class_dev)->device);
+ put_device(&container_of((dev), struct node_entry, node_dev)->device);
}
static struct class nodemgr_ne_class = {
.name = "ieee1394_node",
- .release = ne_cls_release,
+ .dev_release = ne_cls_release,
};
-static void ud_cls_release(struct class_device *class_dev)
+static void ud_cls_release(struct device *dev)
{
- put_device(&container_of((class_dev), struct unit_directory, class_dev)->device);
+ put_device(&container_of((dev), struct unit_directory, unit_dev)->device);
}
/* The name here is only so that unit directory hotplug works with old
- * style hotplug, which only ever did unit directories anyway. */
+ * style hotplug, which only ever did unit directories anyway.
+ */
static struct class nodemgr_ud_class = {
.name = "ieee1394",
- .release = ud_cls_release,
- .uevent = nodemgr_uevent,
+ .dev_release = ud_cls_release,
+ .dev_uevent = nodemgr_uevent,
};
static struct hpsb_highlevel nodemgr_highlevel;
@@ -730,11 +730,11 @@ static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
static void nodemgr_remove_uds(struct node_entry *ne)
{
- struct class_device *cdev;
+ struct device *dev;
struct unit_directory *tmp, *ud;
- /* Iteration over nodemgr_ud_class.children has to be protected by
- * nodemgr_ud_class.sem, but class_device_unregister() will eventually
+ /* Iteration over nodemgr_ud_class.devices has to be protected by
+ * nodemgr_ud_class.sem, but device_unregister() will eventually
* take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
* release the semaphore, and then unregister the ud. Since this code
* may be called from other contexts besides the knodemgrds, protect the
@@ -744,9 +744,9 @@ static void nodemgr_remove_uds(struct node_entry *ne)
for (;;) {
ud = NULL;
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- tmp = container_of(cdev, struct unit_directory,
- class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ tmp = container_of(dev, struct unit_directory,
+ unit_dev);
if (tmp->ne == ne) {
ud = tmp;
break;
@@ -755,7 +755,7 @@ static void nodemgr_remove_uds(struct node_entry *ne)
up(&nodemgr_ud_class.sem);
if (ud == NULL)
break;
- class_device_unregister(&ud->class_dev);
+ device_unregister(&ud->unit_dev);
device_unregister(&ud->device);
}
mutex_unlock(&nodemgr_serialize_remove_uds);
@@ -772,10 +772,9 @@ static void nodemgr_remove_ne(struct node_entry *ne)
HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
-
nodemgr_remove_uds(ne);
- class_device_unregister(&ne->class_dev);
+ device_unregister(&ne->node_dev);
device_unregister(dev);
put_device(dev);
@@ -783,7 +782,9 @@ static void nodemgr_remove_ne(struct node_entry *ne)
static int __nodemgr_remove_host_dev(struct device *dev, void *data)
{
- nodemgr_remove_ne(container_of(dev, struct node_entry, device));
+ if (dev->bus == &ieee1394_bus_type)
+ nodemgr_remove_ne(container_of(dev, struct node_entry,
+ device));
return 0;
}
@@ -850,14 +851,14 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
(unsigned long long)(ne->guid));
- ne->class_dev.dev = &ne->device;
- ne->class_dev.class = &nodemgr_ne_class;
- snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
- (unsigned long long)(ne->guid));
+ ne->node_dev.parent = &ne->device;
+ ne->node_dev.class = &nodemgr_ne_class;
+ snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx",
+ (unsigned long long)(ne->guid));
if (device_register(&ne->device))
goto fail_devreg;
- if (class_device_register(&ne->class_dev))
+ if (device_register(&ne->node_dev))
goto fail_classdevreg;
get_device(&ne->device);
@@ -885,12 +886,12 @@ fail_alloc:
static struct node_entry *find_entry_by_guid(u64 guid)
{
- struct class_device *cdev;
+ struct device *dev;
struct node_entry *ne, *ret_ne = NULL;
down(&nodemgr_ne_class.sem);
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (ne->guid == guid) {
ret_ne = ne;
@@ -906,12 +907,12 @@ static struct node_entry *find_entry_by_guid(u64 guid)
static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
nodeid_t nodeid)
{
- struct class_device *cdev;
+ struct device *dev;
struct node_entry *ne, *ret_ne = NULL;
down(&nodemgr_ne_class.sem);
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (ne->host == host && ne->nodeid == nodeid) {
ret_ne = ne;
@@ -935,14 +936,14 @@ static void nodemgr_register_device(struct node_entry *ne,
snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
ne->device.bus_id, ud->id);
- ud->class_dev.dev = &ud->device;
- ud->class_dev.class = &nodemgr_ud_class;
- snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
+ ud->unit_dev.parent = &ud->device;
+ ud->unit_dev.class = &nodemgr_ud_class;
+ snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u",
ne->device.bus_id, ud->id);
if (device_register(&ud->device))
goto fail_devreg;
- if (class_device_register(&ud->class_dev))
+ if (device_register(&ud->unit_dev))
goto fail_classdevreg;
get_device(&ud->device);
@@ -1159,7 +1160,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
#ifdef CONFIG_HOTPLUG
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct unit_directory *ud;
@@ -1169,10 +1170,10 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
/* ieee1394:venNmoNspNverN */
char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
- if (!cdev)
+ if (!dev)
return -ENODEV;
- ud = container_of(cdev, struct unit_directory, class_dev);
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne->in_limbo || ud->ignore_driver)
return -ENODEV;
@@ -1207,7 +1208,7 @@ do { \
#else
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
return -ENODEV;
@@ -1378,8 +1379,10 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
static void nodemgr_suspend_ne(struct node_entry *ne)
{
- struct class_device *cdev;
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
+ int error;
HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
@@ -1388,15 +1391,24 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- ud = container_of(cdev, struct unit_directory, class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne)
continue;
- if (ud->device.driver &&
- (!ud->device.driver->suspend ||
- ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ error = 1; /* release if suspend is not implemented */
+ if (drv->suspend) {
+ down(&ud->device.sem);
+ error = drv->suspend(&ud->device, PMSG_SUSPEND);
+ up(&ud->device.sem);
+ }
+ if (error)
device_release_driver(&ud->device);
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
}
@@ -1404,20 +1416,29 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
static void nodemgr_resume_ne(struct node_entry *ne)
{
- struct class_device *cdev;
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
ne->in_limbo = 0;
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- ud = container_of(cdev, struct unit_directory, class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne)
continue;
- if (ud->device.driver && ud->device.driver->resume)
- ud->device.driver->resume(&ud->device);
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ if (drv->resume) {
+ down(&ud->device.sem);
+ drv->resume(&ud->device);
+ up(&ud->device.sem);
+ }
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
@@ -1428,23 +1449,32 @@ static void nodemgr_resume_ne(struct node_entry *ne)
static void nodemgr_update_pdrv(struct node_entry *ne)
{
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
struct hpsb_protocol_driver *pdrv;
- struct class_device *cdev;
+ int error;
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- ud = container_of(cdev, struct unit_directory, class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne)
continue;
- if (ud->device.driver) {
- pdrv = container_of(ud->device.driver,
- struct hpsb_protocol_driver,
- driver);
- if (pdrv->update && pdrv->update(ud))
- device_release_driver(&ud->device);
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ error = 0;
+ pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
+ if (pdrv->update) {
+ down(&ud->device.sem);
+ error = pdrv->update(ud);
+ up(&ud->device.sem);
}
+ if (error)
+ device_release_driver(&ud->device);
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
}
@@ -1509,7 +1539,7 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
static void nodemgr_node_probe(struct host_info *hi, int generation)
{
struct hpsb_host *host = hi->host;
- struct class_device *cdev;
+ struct device *dev;
struct node_entry *ne;
/* Do some processing of the nodes we've probed. This pulls them
@@ -1522,13 +1552,13 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
* improvement...) */
down(&nodemgr_ne_class.sem);
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (!ne->needs_probe)
nodemgr_probe_ne(hi, ne, generation);
}
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (ne->needs_probe)
nodemgr_probe_ne(hi, ne, generation);
}
@@ -1686,18 +1716,12 @@ static int nodemgr_host_thread(void *__hi)
if (kthread_should_stop())
goto exit;
- if (mutex_lock_interruptible(&nodemgr_serialize)) {
- if (try_to_freeze())
- continue;
- goto exit;
- }
-
/* Pause for 1/4 second in 1/16 second intervals,
* to make sure things settle down. */
g = get_hpsb_generation(host);
for (i = 0; i < 4 ; i++) {
if (msleep_interruptible(63) || kthread_should_stop())
- goto unlock_exit;
+ goto exit;
/* Now get the generation in which the node ID's we collect
* are valid. During the bus scan we will use this generation
@@ -1715,7 +1739,6 @@ static int nodemgr_host_thread(void *__hi)
if (!nodemgr_check_irm_capability(host, reset_cycles) ||
!nodemgr_do_irm_duties(host, reset_cycles)) {
reset_cycles++;
- mutex_unlock(&nodemgr_serialize);
continue;
}
reset_cycles = 0;
@@ -1732,11 +1755,7 @@ static int nodemgr_host_thread(void *__hi)
/* Update some of our sysfs symlinks */
nodemgr_update_host_dev_links(host);
-
- mutex_unlock(&nodemgr_serialize);
}
-unlock_exit:
- mutex_unlock(&nodemgr_serialize);
exit:
HPSB_VERBOSE("NodeMgr: Exiting thread");
return 0;
@@ -1756,13 +1775,13 @@ exit:
*/
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
{
- struct class_device *cdev;
+ struct device *dev;
struct hpsb_host *host;
int error = 0;
down(&hpsb_host_class.sem);
- list_for_each_entry(cdev, &hpsb_host_class.children, node) {
- host = container_of(cdev, struct hpsb_host, class_dev);
+ list_for_each_entry(dev, &hpsb_host_class.devices, node) {
+ host = container_of(dev, struct hpsb_host, host_dev);
if ((error = cb(host, data)))
break;
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 4530b29d941..919e92e2a95 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -84,7 +84,7 @@ struct unit_directory {
int length; /* Number of quadlets */
struct device device;
- struct class_device class_dev;
+ struct device unit_dev;
struct csr1212_keyval *ud_kv;
u32 lun; /* logical unit number immediate value */
@@ -107,7 +107,7 @@ struct node_entry {
u32 capabilities;
struct device device;
- struct class_device class_dev;
+ struct device node_dev;
/* Means this node is not attached anymore */
int in_limbo;
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 5dadfd296f7..5667c8102ef 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -138,19 +138,6 @@ printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->
#define DBGMSG(fmt, args...) do {} while (0)
#endif
-#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
-#define OHCI_DMA_ALLOC(fmt, args...) \
- HPSB_ERR("%s(%s)alloc(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
- ++global_outstanding_dmas, ## args)
-#define OHCI_DMA_FREE(fmt, args...) \
- HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
- --global_outstanding_dmas, ## args)
-static int global_outstanding_dmas = 0;
-#else
-#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0)
-#define OHCI_DMA_FREE(fmt, args...) do {} while (0)
-#endif
-
/* print general (card independent) information */
#define PRINT_G(level, fmt, args...) \
printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
@@ -170,7 +157,6 @@ static void dma_trm_reset(struct dma_trm_ctx *d);
static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
enum context_type type, int ctx, int num_desc,
int buf_size, int split_buf_size, int context_base);
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d);
static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
@@ -533,9 +519,6 @@ static void ohci_initialize(struct ti_ohci *ohci)
initialize_dma_trm_ctx(&ohci->at_req_context);
initialize_dma_trm_ctx(&ohci->at_resp_context);
- /* Initialize IR Legacy DMA channel mask */
- ohci->ir_legacy_channels = 0;
-
/* Accept AR requests from all nodes */
reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
@@ -733,7 +716,6 @@ static void insert_packet(struct ti_ohci *ohci,
pci_map_single(ohci->dev, packet->data,
packet->data_size,
PCI_DMA_TODEVICE));
- OHCI_DMA_ALLOC("single, block transmit packet");
d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0;
@@ -783,7 +765,6 @@ static void insert_packet(struct ti_ohci *ohci,
d->prg_cpu[idx]->end.address = cpu_to_le32(
pci_map_single(ohci->dev, packet->data,
packet->data_size, PCI_DMA_TODEVICE));
- OHCI_DMA_ALLOC("single, iso transmit packet");
d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0;
@@ -884,36 +865,9 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
return -EOVERFLOW;
}
- /* Decide whether we have an iso, a request, or a response packet */
if (packet->type == hpsb_raw)
d = &ohci->at_req_context;
- else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
- /* The legacy IT DMA context is initialized on first
- * use. However, the alloc cannot be run from
- * interrupt context, so we bail out if that is the
- * case. I don't see anyone sending ISO packets from
- * interrupt context anyway... */
-
- if (ohci->it_legacy_context.ohci == NULL) {
- if (in_interrupt()) {
- PRINT(KERN_ERR,
- "legacy IT context cannot be initialized during interrupt");
- return -EINVAL;
- }
-
- if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
- DMA_CTX_ISO, 0, IT_NUM_DESC,
- OHCI1394_IsoXmitContextBase) < 0) {
- PRINT(KERN_ERR,
- "error initializing legacy IT context");
- return -ENOMEM;
- }
-
- initialize_dma_trm_ctx(&ohci->it_legacy_context);
- }
-
- d = &ohci->it_legacy_context;
- } else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
+ else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
d = &ohci->at_resp_context;
else
d = &ohci->at_req_context;
@@ -932,9 +886,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
{
struct ti_ohci *ohci = host->hostdata;
- int retval = 0;
- unsigned long flags;
- int phy_reg;
+ int retval = 0, phy_reg;
switch (cmd) {
case RESET_BUS:
@@ -1027,117 +979,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
dma_trm_reset(&ohci->at_resp_context);
break;
- case ISO_LISTEN_CHANNEL:
- {
- u64 mask;
- struct dma_rcv_ctx *d = &ohci->ir_legacy_context;
- int ir_legacy_active;
-
- if (arg<0 || arg>63) {
- PRINT(KERN_ERR,
- "%s: IS0 listen channel %d is out of range",
- __FUNCTION__, arg);
- return -EFAULT;
- }
-
- mask = (u64)0x1<<arg;
-
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
- if (ohci->ISO_channel_usage & mask) {
- PRINT(KERN_ERR,
- "%s: IS0 listen channel %d is already used",
- __FUNCTION__, arg);
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- return -EFAULT;
- }
-
- ir_legacy_active = ohci->ir_legacy_channels;
-
- ohci->ISO_channel_usage |= mask;
- ohci->ir_legacy_channels |= mask;
-
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-
- if (!ir_legacy_active) {
- if (ohci1394_register_iso_tasklet(ohci,
- &ohci->ir_legacy_tasklet) < 0) {
- PRINT(KERN_ERR, "No IR DMA context available");
- return -EBUSY;
- }
-
- /* the IR context can be assigned to any DMA context
- * by ohci1394_register_iso_tasklet */
- d->ctx = ohci->ir_legacy_tasklet.context;
- d->ctrlSet = OHCI1394_IsoRcvContextControlSet +
- 32*d->ctx;
- d->ctrlClear = OHCI1394_IsoRcvContextControlClear +
- 32*d->ctx;
- d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
- d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
-
- initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-
- if (printk_ratelimit())
- DBGMSG("IR legacy activated");
- }
-
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
- if (arg>31)
- reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
- 1<<(arg-32));
- else
- reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
- 1<<arg);
-
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- DBGMSG("Listening enabled on channel %d", arg);
- break;
- }
- case ISO_UNLISTEN_CHANNEL:
- {
- u64 mask;
-
- if (arg<0 || arg>63) {
- PRINT(KERN_ERR,
- "%s: IS0 unlisten channel %d is out of range",
- __FUNCTION__, arg);
- return -EFAULT;
- }
-
- mask = (u64)0x1<<arg;
-
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
- if (!(ohci->ISO_channel_usage & mask)) {
- PRINT(KERN_ERR,
- "%s: IS0 unlisten channel %d is not used",
- __FUNCTION__, arg);
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- return -EFAULT;
- }
-
- ohci->ISO_channel_usage &= ~mask;
- ohci->ir_legacy_channels &= ~mask;
-
- if (arg>31)
- reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear,
- 1<<(arg-32));
- else
- reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear,
- 1<<arg);
-
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- DBGMSG("Listening disabled on channel %d", arg);
-
- if (ohci->ir_legacy_channels == 0) {
- stop_dma_rcv_ctx(&ohci->ir_legacy_context);
- DBGMSG("ISO legacy receive context stopped");
- }
-
- break;
- }
default:
PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
cmd);
@@ -2869,12 +2710,10 @@ static void dma_trm_tasklet (unsigned long data)
list_del_init(&packet->driver_list);
hpsb_packet_sent(ohci->host, packet, ack);
- if (datasize) {
+ if (datasize)
pci_unmap_single(ohci->dev,
cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address),
datasize, PCI_DMA_TODEVICE);
- OHCI_DMA_FREE("single Xmit data packet");
- }
d->sent_ind = (d->sent_ind+1)%d->num_desc;
d->free_prgs++;
@@ -2885,22 +2724,6 @@ static void dma_trm_tasklet (unsigned long data)
spin_unlock_irqrestore(&d->lock, flags);
}
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d)
-{
- if (d->ctrlClear) {
- ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
-
- if (d->type == DMA_CTX_ISO) {
- /* disable interrupts */
- reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx);
- ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet);
- } else {
- tasklet_kill(&d->task);
- }
- }
-}
-
-
static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
{
int i;
@@ -2913,23 +2736,19 @@ static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
if (d->buf_cpu) {
for (i=0; i<d->num_desc; i++)
- if (d->buf_cpu[i] && d->buf_bus[i]) {
+ if (d->buf_cpu[i] && d->buf_bus[i])
pci_free_consistent(
ohci->dev, d->buf_size,
d->buf_cpu[i], d->buf_bus[i]);
- OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i);
- }
kfree(d->buf_cpu);
kfree(d->buf_bus);
}
if (d->prg_cpu) {
for (i=0; i<d->num_desc; i++)
- if (d->prg_cpu[i] && d->prg_bus[i]) {
- pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
- OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i);
- }
+ if (d->prg_cpu[i] && d->prg_bus[i])
+ pci_pool_free(d->prg_pool, d->prg_cpu[i],
+ d->prg_bus[i]);
pci_pool_destroy(d->prg_pool);
- OHCI_DMA_FREE("dma_rcv prg pool");
kfree(d->prg_cpu);
kfree(d->prg_bus);
}
@@ -2998,13 +2817,10 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
}
num_allocs++;
- OHCI_DMA_ALLOC("dma_rcv prg pool");
-
for (i=0; i<d->num_desc; i++) {
d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
d->buf_size,
d->buf_bus+i);
- OHCI_DMA_ALLOC("consistent dma_rcv buf[%d]", i);
if (d->buf_cpu[i] != NULL) {
memset(d->buf_cpu[i], 0, d->buf_size);
@@ -3016,7 +2832,6 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
}
d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
- OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i);
if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
@@ -3030,18 +2845,11 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
spin_lock_init(&d->lock);
- if (type == DMA_CTX_ISO) {
- ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
- OHCI_ISO_MULTICHANNEL_RECEIVE,
- dma_rcv_tasklet, (unsigned long) d);
- } else {
- d->ctrlSet = context_base + OHCI1394_ContextControlSet;
- d->ctrlClear = context_base + OHCI1394_ContextControlClear;
- d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-
- tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d);
- }
+ d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+ d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+ d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+ tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d);
return 0;
}
@@ -3057,12 +2865,10 @@ static void free_dma_trm_ctx(struct dma_trm_ctx *d)
if (d->prg_cpu) {
for (i=0; i<d->num_desc; i++)
- if (d->prg_cpu[i] && d->prg_bus[i]) {
- pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
- OHCI_DMA_FREE("pool dma_trm prg[%d]", i);
- }
+ if (d->prg_cpu[i] && d->prg_bus[i])
+ pci_pool_free(d->prg_pool, d->prg_cpu[i],
+ d->prg_bus[i]);
pci_pool_destroy(d->prg_pool);
- OHCI_DMA_FREE("dma_trm prg pool");
kfree(d->prg_cpu);
kfree(d->prg_bus);
}
@@ -3108,11 +2914,8 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
}
num_allocs++;
- OHCI_DMA_ALLOC("dma_rcv prg pool");
-
for (i = 0; i < d->num_desc; i++) {
d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
- OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i);
if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
@@ -3127,28 +2930,10 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
spin_lock_init(&d->lock);
/* initialize tasklet */
- if (type == DMA_CTX_ISO) {
- ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT,
- dma_trm_tasklet, (unsigned long) d);
- if (ohci1394_register_iso_tasklet(ohci,
- &ohci->it_legacy_tasklet) < 0) {
- PRINT(KERN_ERR, "No IT DMA context available");
- free_dma_trm_ctx(d);
- return -EBUSY;
- }
-
- /* IT can be assigned to any context by register_iso_tasklet */
- d->ctx = ohci->it_legacy_tasklet.context;
- d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx;
- d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx;
- d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx;
- } else {
- d->ctrlSet = context_base + OHCI1394_ContextControlSet;
- d->ctrlClear = context_base + OHCI1394_ContextControlClear;
- d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
- tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d);
- }
-
+ d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+ d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+ d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+ tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d);
return 0;
}
@@ -3294,7 +3079,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->csr_config_rom_cpu =
pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
&ohci->csr_config_rom_bus);
- OHCI_DMA_ALLOC("consistent csr_config_rom");
if (ohci->csr_config_rom_cpu == NULL)
FAIL(-ENOMEM, "Failed to allocate buffer config rom");
ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
@@ -3303,8 +3087,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->selfid_buf_cpu =
pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
&ohci->selfid_buf_bus);
- OHCI_DMA_ALLOC("consistent selfid_buf");
-
if (ohci->selfid_buf_cpu == NULL)
FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
@@ -3377,20 +3159,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->ISO_channel_usage = 0;
spin_lock_init(&ohci->IR_channel_lock);
- /* Allocate the IR DMA context right here so we don't have
- * to do it in interrupt path - note that this doesn't
- * waste much memory and avoids the jugglery required to
- * allocate it in IRQ path. */
- if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
- DMA_CTX_ISO, 0, IR_NUM_DESC,
- IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
- OHCI1394_IsoRcvContextBase) < 0) {
- FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context");
- }
-
- /* We hopefully don't have to pre-allocate IT DMA like we did
- * for IR DMA above. Allocate it on-demand and mark inactive. */
- ohci->it_legacy_context.ohci = NULL;
spin_lock_init(&ohci->event_lock);
/*
@@ -3483,20 +3251,16 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
free_dma_rcv_ctx(&ohci->ar_resp_context);
free_dma_trm_ctx(&ohci->at_req_context);
free_dma_trm_ctx(&ohci->at_resp_context);
- free_dma_rcv_ctx(&ohci->ir_legacy_context);
- free_dma_trm_ctx(&ohci->it_legacy_context);
case OHCI_INIT_HAVE_SELFID_BUFFER:
pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
ohci->selfid_buf_cpu,
ohci->selfid_buf_bus);
- OHCI_DMA_FREE("consistent selfid_buf");
case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
ohci->csr_config_rom_cpu,
ohci->csr_config_rom_bus);
- OHCI_DMA_FREE("consistent csr_config_rom");
case OHCI_INIT_HAVE_IOMAPPING:
iounmap(ohci->registers);
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index f1ad539e7c1..4320bf01049 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -190,23 +190,10 @@ struct ti_ohci {
unsigned long ir_multichannel_used; /* ditto */
spinlock_t IR_channel_lock;
- /* iso receive (legacy API) */
- u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage;
- it only accounts for channels listened to
- by the legacy API, so that we can know when
- it is safe to free the legacy API context */
-
- struct dma_rcv_ctx ir_legacy_context;
- struct ohci1394_iso_tasklet ir_legacy_tasklet;
-
/* iso transmit */
int nb_iso_xmit_ctx;
unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
- /* iso transmit (legacy API) */
- struct dma_trm_ctx it_legacy_context;
- struct ohci1394_iso_tasklet it_legacy_tasklet;
-
u64 ISO_channel_usage;
/* IEEE-1394 part follows */
@@ -221,7 +208,6 @@ struct ti_ohci {
/* Tasklets for iso receive and transmit, used by video1394
* and dv1394 */
-
struct list_head iso_tasklet_list;
spinlock_t iso_tasklet_list_lock;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 0742befe922..d1a5bcdb5e0 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -477,7 +477,11 @@ static void send_next(struct ti_lynx *lynx, int what)
struct lynx_send_data *d;
struct hpsb_packet *packet;
+#if 0 /* has been removed from ieee1394 core */
d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
+#else
+ d = &lynx->async;
+#endif
if (!list_empty(&d->pcl_queue)) {
PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
BUG();
@@ -511,9 +515,11 @@ static void send_next(struct ti_lynx *lynx, int what)
case hpsb_async:
pcl.buffer[0].control |= PCL_CMD_XMT;
break;
+#if 0 /* has been removed from ieee1394 core */
case hpsb_iso:
pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
break;
+#endif
case hpsb_raw:
pcl.buffer[0].control |= PCL_CMD_UNFXMT;
break;
@@ -542,9 +548,11 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
case hpsb_raw:
d = &lynx->async;
break;
+#if 0 /* has been removed from ieee1394 core */
case hpsb_iso:
d = &lynx->iso_send;
break;
+#endif
default:
PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
packet->type);
@@ -797,7 +805,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
}
break;
-
+#if 0 /* has been removed from ieee1394 core */
case ISO_LISTEN_CHANNEL:
spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
@@ -819,7 +827,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
break;
-
+#endif
default:
PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
retval = -1;
@@ -1009,11 +1017,11 @@ static irqreturn_t lynx_irq_handler(int irq, void *dev_id)
pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
packet->data_size, PCI_DMA_TODEVICE);
}
-
+#if 0 /* has been removed from ieee1394 core */
if (!list_empty(&lynx->iso_send.queue)) {
send_next(lynx, hpsb_iso);
}
-
+#endif
spin_unlock(&lynx->iso_send.queue_lock);
if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
index 50daabf6e5f..a06aaad5b44 100644
--- a/drivers/ieee1394/raw1394-private.h
+++ b/drivers/ieee1394/raw1394-private.h
@@ -36,11 +36,6 @@ struct file_info {
u8 __user *fcp_buffer;
- /* old ISO API */
- u64 listen_channels;
- quadlet_t __user *iso_buffer;
- size_t iso_buffer_length;
-
u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
/* new rawiso API */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index f1d05eeb9f5..336e5ff4cfc 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -98,21 +98,6 @@ static struct hpsb_address_ops arm_ops = {
static void queue_complete_cb(struct pending_request *req);
-#include <asm/current.h>
-static void print_old_iso_deprecation(void)
-{
- static pid_t p;
-
- if (p == current->pid)
- return;
- p = current->pid;
- printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"
- " isochronous request types which will be removed in a next"
- " kernel release\n", current->comm);
- printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"
- " newer interface\n");
-}
-
static struct pending_request *__alloc_pending_request(gfp_t flags)
{
struct pending_request *req;
@@ -297,67 +282,6 @@ static void host_reset(struct hpsb_host *host)
spin_unlock_irqrestore(&host_info_lock, flags);
}
-static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
- size_t length)
-{
- unsigned long flags;
- struct host_info *hi;
- struct file_info *fi;
- struct pending_request *req, *req_next;
- struct iso_block_store *ibs = NULL;
- LIST_HEAD(reqs);
-
- if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
- HPSB_INFO("dropped iso packet");
- return;
- }
-
- spin_lock_irqsave(&host_info_lock, flags);
- hi = find_host_info(host);
-
- if (hi != NULL) {
- list_for_each_entry(fi, &hi->file_info_list, list) {
- if (!(fi->listen_channels & (1ULL << channel)))
- continue;
-
- req = __alloc_pending_request(GFP_ATOMIC);
- if (!req)
- break;
-
- if (!ibs) {
- ibs = kmalloc(sizeof(*ibs) + length,
- GFP_ATOMIC);
- if (!ibs) {
- kfree(req);
- break;
- }
-
- atomic_add(length, &iso_buffer_size);
- atomic_set(&ibs->refcount, 0);
- ibs->data_size = length;
- memcpy(ibs->data, data, length);
- }
-
- atomic_inc(&ibs->refcount);
-
- req->file_info = fi;
- req->ibs = ibs;
- req->data = ibs->data;
- req->req.type = RAW1394_REQ_ISO_RECEIVE;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = 0;
- req->req.recvb = ptr2int(fi->iso_buffer);
- req->req.length = min(length, fi->iso_buffer_length);
-
- list_add_tail(&req->list, &reqs);
- }
- }
- spin_unlock_irqrestore(&host_info_lock, flags);
-
- list_for_each_entry_safe(req, req_next, &reqs, list)
- queue_complete_req(req);
-}
-
static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
int cts, u8 * data, size_t length)
{
@@ -434,7 +358,11 @@ struct compat_raw1394_req {
__u64 sendb;
__u64 recvb;
-} __attribute__((packed));
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
static const char __user *raw1394_compat_write(const char __user *buf)
{
@@ -459,7 +387,7 @@ static const char __user *raw1394_compat_write(const char __user *buf)
static int
raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
{
- struct compat_raw1394_req __user *cr = (typeof(cr)) r;
+ struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
P(type) ||
P(error) ||
@@ -587,7 +515,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req)
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
static int state_initialized(struct file_info *fi, struct pending_request *req)
@@ -601,7 +529,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
req->req.generation = atomic_read(&internal_generation);
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
switch (req->req.type) {
@@ -673,44 +601,7 @@ out_set_card:
}
queue_complete_req(req);
- return sizeof(struct raw1394_request);
-}
-
-static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
-{
- int channel = req->req.misc;
-
- if ((channel > 63) || (channel < -64)) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- } else if (channel >= 0) {
- /* allocate channel req.misc */
- if (fi->listen_channels & (1ULL << channel)) {
- req->req.error = RAW1394_ERROR_ALREADY;
- } else {
- if (hpsb_listen_channel
- (&raw1394_highlevel, fi->host, channel)) {
- req->req.error = RAW1394_ERROR_ALREADY;
- } else {
- fi->listen_channels |= 1ULL << channel;
- fi->iso_buffer = int2ptr(req->req.recvb);
- fi->iso_buffer_length = req->req.length;
- }
- }
- } else {
- /* deallocate channel (one's complement neg) req.misc */
- channel = ~channel;
-
- if (fi->listen_channels & (1ULL << channel)) {
- hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
- channel);
- fi->listen_channels &= ~(1ULL << channel);
- } else {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- }
- }
-
- req->req.length = 0;
- queue_complete_req(req);
+ return 0;
}
static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
@@ -865,7 +756,7 @@ static int handle_async_request(struct file_info *fi,
if (req->req.error) {
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
hpsb_set_packet_complete_task(packet,
@@ -883,51 +774,7 @@ static int handle_async_request(struct file_info *fi,
hpsb_free_tlabel(packet);
queue_complete_req(req);
}
- return sizeof(struct raw1394_request);
-}
-
-static int handle_iso_send(struct file_info *fi, struct pending_request *req,
- int channel)
-{
- unsigned long flags;
- struct hpsb_packet *packet;
-
- packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
- (req->req.misc >> 16) & 0x3,
- req->req.misc & 0xf);
- if (!packet)
- return -ENOMEM;
-
- packet->speed_code = req->req.address & 0x3;
-
- req->packet = packet;
-
- if (copy_from_user(packet->data, int2ptr(req->req.sendb),
- req->req.length)) {
- req->req.error = RAW1394_ERROR_MEMFAULT;
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- req->req.length = 0;
- hpsb_set_packet_complete_task(packet,
- (void (*)(void *))queue_complete_req,
- req);
-
- spin_lock_irqsave(&fi->reqlists_lock, flags);
- list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
- /* Update the generation of the packet just before sending. */
- packet->generation = req->req.generation;
-
- if (hpsb_send_packet(packet) < 0) {
- req->req.error = RAW1394_ERROR_SEND_ERROR;
- queue_complete_req(req);
- }
-
- return sizeof(struct raw1394_request);
+ return 0;
}
static int handle_async_send(struct file_info *fi, struct pending_request *req)
@@ -943,7 +790,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_INVALID_ARG;
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
data_size = req->req.length - header_length;
@@ -957,7 +804,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
if (copy_from_user
@@ -966,7 +813,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
packet->type = hpsb_async;
@@ -994,7 +841,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
queue_complete_req(req);
}
- return sizeof(struct raw1394_request);
+ return 0;
}
static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
@@ -1869,7 +1716,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
spin_lock_irqsave(&host_info_lock, flags);
list_add_tail(&addr->addr_list, &fi->addr_list);
spin_unlock_irqrestore(&host_info_lock, flags);
- return sizeof(struct raw1394_request);
+ return 0;
}
retval =
hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
@@ -1887,7 +1734,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
return (-EALREADY);
}
free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ return 0;
}
static int arm_unregister(struct file_info *fi, struct pending_request *req)
@@ -1955,7 +1802,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
vfree(addr->addr_space_buffer);
kfree(addr);
free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ return 0;
}
retval =
hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
@@ -1971,7 +1818,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
vfree(addr->addr_space_buffer);
kfree(addr);
free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ return 0;
}
/* Copy data from ARM buffer(s) to user buffer. */
@@ -2013,7 +1860,7 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req)
* queue no response, and therefore nobody
* will free it. */
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
} else {
DBGMSG("arm_get_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2065,7 +1912,7 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req)
* queue no response, and therefore nobody
* will free it. */
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
} else {
DBGMSG("arm_set_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2086,7 +1933,7 @@ static int reset_notification(struct file_info *fi, struct pending_request *req)
(req->req.misc == RAW1394_NOTIFY_ON)) {
fi->notification = (u8) req->req.misc;
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
+ return 0;
}
/* error EINVAL (22) invalid argument */
return (-EINVAL);
@@ -2119,12 +1966,12 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
req->req.length = 0;
queue_complete_req(req);
}
- return sizeof(struct raw1394_request);
+ return 0;
}
static int get_config_rom(struct file_info *fi, struct pending_request *req)
{
- int ret = sizeof(struct raw1394_request);
+ int ret = 0;
quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
int status;
@@ -2154,7 +2001,7 @@ static int get_config_rom(struct file_info *fi, struct pending_request *req)
static int update_config_rom(struct file_info *fi, struct pending_request *req)
{
- int ret = sizeof(struct raw1394_request);
+ int ret = 0;
quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -2221,7 +2068,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
hpsb_update_config_rom_image(fi->host);
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
}
@@ -2286,7 +2133,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
/* we have to free the request, because we queue no response,
* and therefore nobody will free it */
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
} else {
for (dentry =
fi->csr1212_dirs[dr]->value.directory.dentries_head;
@@ -2311,11 +2158,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
case RAW1394_REQ_ECHO:
queue_complete_req(req);
- return sizeof(struct raw1394_request);
-
- case RAW1394_REQ_ISO_SEND:
- print_old_iso_deprecation();
- return handle_iso_send(fi, req, node);
+ return 0;
case RAW1394_REQ_ARM_REGISTER:
return arm_register(fi, req);
@@ -2332,27 +2175,30 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
case RAW1394_REQ_RESET_NOTIFY:
return reset_notification(fi, req);
+ case RAW1394_REQ_ISO_SEND:
case RAW1394_REQ_ISO_LISTEN:
- print_old_iso_deprecation();
- handle_iso_listen(fi, req);
- return sizeof(struct raw1394_request);
+ printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n");
+ req->req.error = RAW1394_ERROR_COMPAT;
+ req->req.misc = RAW1394_KERNELAPI_VERSION;
+ queue_complete_req(req);
+ return 0;
case RAW1394_REQ_FCP_LISTEN:
handle_fcp_listen(fi, req);
- return sizeof(struct raw1394_request);
+ return 0;
case RAW1394_REQ_RESET_BUS:
if (req->req.misc == RAW1394_LONG_RESET) {
DBGMSG("busreset called (type: LONG)");
hpsb_reset_bus(fi->host, LONG_RESET);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
+ return 0;
}
if (req->req.misc == RAW1394_SHORT_RESET) {
DBGMSG("busreset called (type: SHORT)");
hpsb_reset_bus(fi->host, SHORT_RESET);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
+ return 0;
}
/* error EINVAL (22) invalid argument */
return (-EINVAL);
@@ -2371,7 +2217,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
req->req.generation = get_hpsb_generation(fi->host);
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
switch (req->req.type) {
@@ -2384,7 +2230,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
if (req->req.length == 0) {
req->req.error = RAW1394_ERROR_INVALID_ARG;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
return handle_async_request(fi, req, node);
@@ -2395,7 +2241,7 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
{
struct file_info *fi = (struct file_info *)file->private_data;
struct pending_request *req;
- ssize_t retval = 0;
+ ssize_t retval = -EBADFD;
#ifdef CONFIG_COMPAT
if (count == sizeof(struct compat_raw1394_req) &&
@@ -2437,6 +2283,9 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
if (retval < 0) {
free_pending_request(req);
+ } else {
+ BUG_ON(retval);
+ retval = count;
}
return retval;
@@ -2802,6 +2651,103 @@ static int raw1394_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
+#ifdef CONFIG_COMPAT
+struct raw1394_iso_packets32 {
+ __u32 n_packets;
+ compat_uptr_t infos;
+} __attribute__((packed));
+
+struct raw1394_cycle_timer32 {
+ __u32 cycle_timer;
+ __u64 local_time;
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
+
+#define RAW1394_IOC_ISO_RECV_PACKETS32 \
+ _IOW ('#', 0x25, struct raw1394_iso_packets32)
+#define RAW1394_IOC_ISO_XMIT_PACKETS32 \
+ _IOW ('#', 0x27, struct raw1394_iso_packets32)
+#define RAW1394_IOC_GET_CYCLE_TIMER32 \
+ _IOR ('#', 0x30, struct raw1394_cycle_timer32)
+
+static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
+ struct raw1394_iso_packets32 __user *arg)
+{
+ compat_uptr_t infos32;
+ void *infos;
+ long err = -EFAULT;
+ struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));
+
+ if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
+ !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
+ infos = compat_ptr(infos32);
+ if (!copy_to_user(&dst->infos, &infos, sizeof infos))
+ err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst);
+ }
+ return err;
+}
+
+static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
+{
+ struct raw1394_cycle_timer32 ct;
+ int err;
+
+ err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+ if (!err)
+ if (copy_to_user(uaddr, &ct, sizeof(ct)))
+ err = -EFAULT;
+ return err;
+}
+
+static long raw1394_compat_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct file_info *fi = file->private_data;
+ void __user *argp = (void __user *)arg;
+ long err;
+
+ lock_kernel();
+ switch (cmd) {
+ /* These requests have same format as long as 'int' has same size. */
+ case RAW1394_IOC_ISO_RECV_INIT:
+ case RAW1394_IOC_ISO_RECV_START:
+ case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
+ case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
+ case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
+ case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
+ case RAW1394_IOC_ISO_RECV_FLUSH:
+ case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+ case RAW1394_IOC_ISO_XMIT_INIT:
+ case RAW1394_IOC_ISO_XMIT_START:
+ case RAW1394_IOC_ISO_XMIT_SYNC:
+ case RAW1394_IOC_ISO_GET_STATUS:
+ case RAW1394_IOC_ISO_SHUTDOWN:
+ case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+ err = raw1394_ioctl(NULL, file, cmd, arg);
+ break;
+ /* These request have different format. */
+ case RAW1394_IOC_ISO_RECV_PACKETS32:
+ err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
+ break;
+ case RAW1394_IOC_ISO_XMIT_PACKETS32:
+ err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
+ break;
+ case RAW1394_IOC_GET_CYCLE_TIMER32:
+ err = raw1394_read_cycle_timer32(fi, argp);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ unlock_kernel();
+
+ return err;
+}
+#endif
+
static unsigned int raw1394_poll(struct file *file, poll_table * pt)
{
struct file_info *fi = file->private_data;
@@ -2861,14 +2807,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
if (fi->iso_state != RAW1394_ISO_INACTIVE)
raw1394_iso_shutdown(fi);
- for (i = 0; i < 64; i++) {
- if (fi->listen_channels & (1ULL << i)) {
- hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
- }
- }
-
spin_lock_irqsave(&host_info_lock, flags);
- fi->listen_channels = 0;
fail = 0;
/* set address-entries invalid */
@@ -3030,7 +2969,6 @@ static struct hpsb_highlevel raw1394_highlevel = {
.add_host = add_host,
.remove_host = remove_host,
.host_reset = host_reset,
- .iso_receive = iso_receive,
.fcp_request = fcp_request,
};
@@ -3041,7 +2979,9 @@ static const struct file_operations raw1394_fops = {
.write = raw1394_write,
.mmap = raw1394_mmap,
.ioctl = raw1394_ioctl,
- // .compat_ioctl = ... someone needs to do this
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = raw1394_compat_ioctl,
+#endif
.poll = raw1394_poll,
.open = raw1394_open,
.release = raw1394_release,
@@ -3054,9 +2994,9 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
if (IS_ERR
- (class_device_create
- (hpsb_protocol_class, NULL,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+ (device_create(
+ hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
goto out_unreg;
@@ -3083,9 +3023,9 @@ static int __init init_raw1394(void)
goto out;
out_dev:
- class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
out_unreg:
hpsb_unregister_highlevel(&raw1394_highlevel);
out:
@@ -3094,9 +3034,9 @@ static int __init init_raw1394(void)
static void __exit cleanup_raw1394(void)
{
- class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
hpsb_unregister_highlevel(&raw1394_highlevel);
hpsb_unregister_protocol(&raw1394_driver);
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index 7bd22ee1afb..963ac20373d 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -17,11 +17,11 @@
#define RAW1394_REQ_ASYNC_WRITE 101
#define RAW1394_REQ_LOCK 102
#define RAW1394_REQ_LOCK64 103
-#define RAW1394_REQ_ISO_SEND 104
+#define RAW1394_REQ_ISO_SEND 104 /* removed ABI, now a no-op */
#define RAW1394_REQ_ASYNC_SEND 105
#define RAW1394_REQ_ASYNC_STREAM 106
-#define RAW1394_REQ_ISO_LISTEN 200
+#define RAW1394_REQ_ISO_LISTEN 200 /* removed ABI, now a no-op */
#define RAW1394_REQ_FCP_LISTEN 201
#define RAW1394_REQ_RESET_BUS 202
#define RAW1394_REQ_GET_ROM 203
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 3f873cc7e24..e0c385a3b45 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -118,14 +118,13 @@ MODULE_PARM_DESC(max_speed, "Force max speed "
"(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
/*
- * Set serialize_io to 1 if you'd like only one scsi command sent
- * down to us at a time (debugging). This might be necessary for very
- * badly behaved sbp2 devices.
+ * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
+ * This is and always has been buggy in multiple subtle ways. See above TODOs.
*/
static int sbp2_serialize_io = 1;
-module_param_named(serialize_io, sbp2_serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers "
- "(default = 1, faster = 0)");
+module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
+MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
+ "(default = Y, faster but buggy = N)");
/*
* Bump up max_sectors if you'd like to support very large sized
@@ -154,9 +153,9 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
* are possible on OXFW911 and newer Oxsemi bridges.
*/
static int sbp2_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644);
+module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
- "(default = 1)");
+ "(default = Y, use N for concurrent initiators)");
/*
* If any of the following workarounds is required for your device to work,
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 44402b9d82a..333a4bb7674 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -67,7 +67,7 @@ struct sbp2_command_orb {
#define ORB_SET_LUN(v) ((v) & 0xffff)
#define ORB_SET_FUNCTION(v) (((v) & 0xf) << 16)
#define ORB_SET_RECONNECT(v) (((v) & 0xf) << 20)
-#define ORB_SET_EXCLUSIVE(v) (((v) & 0x1) << 28)
+#define ORB_SET_EXCLUSIVE(v) ((v) ? 1 << 28 : 0)
#define ORB_SET_LOGIN_RESP_LENGTH(v) ((v) & 0xffff)
#define ORB_SET_PASSWD_LENGTH(v) (((v) & 0xffff) << 16)
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 87ebd0846c3..bd28adfd7af 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1340,9 +1340,9 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
- class_device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, minor),
- NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+ device_create(hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, minor),
+ "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
@@ -1351,8 +1351,8 @@ static void video1394_remove_host (struct hpsb_host *host)
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
if (ohci)
- class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
+ device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
return;
}
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index be6b93c20f6..ab4b2d9b532 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -30,6 +30,7 @@ struct evdev {
wait_queue_head_t wait;
struct evdev_client *grab;
struct list_head client_list;
+ struct device dev;
};
struct evdev_client {
@@ -94,8 +95,10 @@ static int evdev_flush(struct file *file, fl_owner_t id)
return input_flush_device(&evdev->handle, file);
}
-static void evdev_free(struct evdev *evdev)
+static void evdev_free(struct device *dev)
{
+ struct evdev *evdev = container_of(dev, struct evdev, dev);
+
evdev_table[evdev->minor] = NULL;
kfree(evdev);
}
@@ -114,12 +117,10 @@ static int evdev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--evdev->open) {
- if (evdev->exist)
- input_close_device(&evdev->handle);
- else
- evdev_free(evdev);
- }
+ if (!--evdev->open && evdev->exist)
+ input_close_device(&evdev->handle);
+
+ put_device(&evdev->dev);
return 0;
}
@@ -139,24 +140,32 @@ static int evdev_open(struct inode *inode, struct file *file)
if (!evdev || !evdev->exist)
return -ENODEV;
+ get_device(&evdev->dev);
+
client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_evdev;
+ }
client->evdev = evdev;
list_add_tail(&client->node, &evdev->client_list);
if (!evdev->open++ && evdev->exist) {
error = input_open_device(&evdev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_evdev:
+ put_device(&evdev->dev);
+ return error;
}
#ifdef CONFIG_COMPAT
@@ -625,8 +634,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
- struct class_device *cdev;
- dev_t devt;
int minor;
int error;
@@ -649,38 +656,32 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
evdev->handle.name = evdev->name;
evdev->handle.handler = handler;
evdev->handle.private = evdev;
- sprintf(evdev->name, "event%d", minor);
-
- evdev_table[minor] = evdev;
+ snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
- devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+ snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
+ "event%d", minor);
+ evdev->dev.class = &input_class;
+ evdev->dev.parent = &dev->dev;
+ evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
+ evdev->dev.release = evdev_free;
+ device_initialize(&evdev->dev);
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, evdev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
- goto err_free_evdev;
- }
+ evdev_table[minor] = evdev;
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, evdev->name);
+ error = device_add(&evdev->dev);
if (error)
- goto err_cdev_destroy;
+ goto err_free_evdev;
error = input_register_handle(&evdev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_evdev;
return 0;
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
+ err_delete_evdev:
+ device_del(&evdev->dev);
err_free_evdev:
- kfree(evdev);
- evdev_table[minor] = NULL;
+ put_device(&evdev->dev);
return error;
}
@@ -690,10 +691,8 @@ static void evdev_disconnect(struct input_handle *handle)
struct evdev_client *client;
input_unregister_handle(handle);
+ device_del(&evdev->dev);
- sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
evdev->exist = 0;
if (evdev->open) {
@@ -702,8 +701,9 @@ static void evdev_disconnect(struct input_handle *handle)
list_for_each_entry(client, &evdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&evdev->wait);
- } else
- evdev_free(evdev);
+ }
+
+ put_device(&evdev->dev);
}
static const struct input_device_id evdev_ids[] = {
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccd8abafcb7..75b4d2a83dd 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -442,7 +442,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
printk(KERN_ERR
"input: failed to attach handler %s to device %s, "
"error: %d\n",
- handler->name, kobject_name(&dev->cdev.kobj), error);
+ handler->name, kobject_name(&dev->dev.kobj), error);
return error;
}
@@ -527,7 +527,7 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
static int input_devices_seq_show(struct seq_file *seq, void *v)
{
struct input_dev *dev = container_of(v, struct input_dev, node);
- const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
struct input_handle *handle;
seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
@@ -682,15 +682,17 @@ static inline int input_proc_init(void) { return 0; }
static inline void input_proc_exit(void) { }
#endif
-#define INPUT_DEV_STRING_ATTR_SHOW(name) \
-static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
-{ \
- struct input_dev *input_dev = to_input_dev(dev); \
- \
- return scnprintf(buf, PAGE_SIZE, "%s\n", \
- input_dev->name ? input_dev->name : ""); \
-} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+#define INPUT_DEV_STRING_ATTR_SHOW(name) \
+static ssize_t input_dev_show_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ \
+ return scnprintf(buf, PAGE_SIZE, "%s\n", \
+ input_dev->name ? input_dev->name : ""); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys);
@@ -744,7 +746,9 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
return len;
}
-static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+static ssize_t input_dev_show_modalias(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct input_dev *id = to_input_dev(dev);
ssize_t len;
@@ -753,13 +757,13 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
return min_t(int, len, PAGE_SIZE);
}
-static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
static struct attribute *input_dev_attrs[] = {
- &class_device_attr_name.attr,
- &class_device_attr_phys.attr,
- &class_device_attr_uniq.attr,
- &class_device_attr_modalias.attr,
+ &dev_attr_name.attr,
+ &dev_attr_phys.attr,
+ &dev_attr_uniq.attr,
+ &dev_attr_modalias.attr,
NULL
};
@@ -767,13 +771,15 @@ static struct attribute_group input_dev_attr_group = {
.attrs = input_dev_attrs,
};
-#define INPUT_DEV_ID_ATTR(name) \
-static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
-{ \
- struct input_dev *input_dev = to_input_dev(dev); \
- return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
-} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+#define INPUT_DEV_ID_ATTR(name) \
+static ssize_t input_dev_show_id_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
INPUT_DEV_ID_ATTR(bustype);
INPUT_DEV_ID_ATTR(vendor);
@@ -781,10 +787,10 @@ INPUT_DEV_ID_ATTR(product);
INPUT_DEV_ID_ATTR(version);
static struct attribute *input_dev_id_attrs[] = {
- &class_device_attr_bustype.attr,
- &class_device_attr_vendor.attr,
- &class_device_attr_product.attr,
- &class_device_attr_version.attr,
+ &dev_attr_bustype.attr,
+ &dev_attr_vendor.attr,
+ &dev_attr_product.attr,
+ &dev_attr_version.attr,
NULL
};
@@ -813,15 +819,17 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
return len;
}
-#define INPUT_DEV_CAP_ATTR(ev, bm) \
-static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
-{ \
- struct input_dev *input_dev = to_input_dev(dev); \
- int len = input_print_bitmap(buf, PAGE_SIZE, \
- input_dev->bm##bit, ev##_MAX, 1); \
- return min_t(int, len, PAGE_SIZE); \
-} \
-static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+#define INPUT_DEV_CAP_ATTR(ev, bm) \
+static ssize_t input_dev_show_cap_##bm(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ int len = input_print_bitmap(buf, PAGE_SIZE, \
+ input_dev->bm##bit, ev##_MAX, 1); \
+ return min_t(int, len, PAGE_SIZE); \
+} \
+static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
INPUT_DEV_CAP_ATTR(EV, ev);
INPUT_DEV_CAP_ATTR(KEY, key);
@@ -834,15 +842,15 @@ INPUT_DEV_CAP_ATTR(FF, ff);
INPUT_DEV_CAP_ATTR(SW, sw);
static struct attribute *input_dev_caps_attrs[] = {
- &class_device_attr_ev.attr,
- &class_device_attr_key.attr,
- &class_device_attr_rel.attr,
- &class_device_attr_abs.attr,
- &class_device_attr_msc.attr,
- &class_device_attr_led.attr,
- &class_device_attr_snd.attr,
- &class_device_attr_ff.attr,
- &class_device_attr_sw.attr,
+ &dev_attr_ev.attr,
+ &dev_attr_key.attr,
+ &dev_attr_rel.attr,
+ &dev_attr_abs.attr,
+ &dev_attr_msc.attr,
+ &dev_attr_led.attr,
+ &dev_attr_snd.attr,
+ &dev_attr_ff.attr,
+ &dev_attr_sw.attr,
NULL
};
@@ -858,9 +866,9 @@ static struct attribute_group *input_dev_attr_groups[] = {
NULL
};
-static void input_dev_release(struct class_device *class_dev)
+static void input_dev_release(struct device *device)
{
- struct input_dev *dev = to_input_dev(class_dev);
+ struct input_dev *dev = to_input_dev(device);
input_ff_destroy(dev);
kfree(dev);
@@ -947,10 +955,10 @@ static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_ind
return err; \
} while (0)
-static int input_dev_uevent(struct class_device *cdev, char **envp,
+static int input_dev_uevent(struct device *device, char **envp,
int num_envp, char *buffer, int buffer_size)
{
- struct input_dev *dev = to_input_dev(cdev);
+ struct input_dev *dev = to_input_dev(device);
int i = 0;
int len = 0;
@@ -988,10 +996,14 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
return 0;
}
+static struct device_type input_dev_type = {
+ .groups = input_dev_attr_groups,
+ .release = input_dev_release,
+ .uevent = input_dev_uevent,
+};
+
struct class input_class = {
- .name = "input",
- .release = input_dev_release,
- .uevent = input_dev_uevent,
+ .name = "input",
};
EXPORT_SYMBOL_GPL(input_class);
@@ -1010,9 +1022,9 @@ struct input_dev *input_allocate_device(void)
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
if (dev) {
- dev->cdev.class = &input_class;
- dev->cdev.groups = input_dev_attr_groups;
- class_device_initialize(&dev->cdev);
+ dev->dev.type = &input_dev_type;
+ dev->dev.class = &input_class;
+ device_initialize(&dev->dev);
mutex_init(&dev->mutex);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
@@ -1131,17 +1143,17 @@ int input_register_device(struct input_dev *dev)
list_add_tail(&dev->node, &input_dev_list);
- snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+ snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
"input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
- if (!dev->cdev.dev)
- dev->cdev.dev = dev->dev.parent;
+ if (dev->cdev.dev)
+ dev->dev.parent = dev->cdev.dev;
- error = class_device_add(&dev->cdev);
+ error = device_add(&dev->dev);
if (error)
return error;
- path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
printk(KERN_INFO "input: %s as %s\n",
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
kfree(path);
@@ -1173,7 +1185,7 @@ void input_unregister_device(struct input_dev *dev)
list_del_init(&dev->node);
- class_device_unregister(&dev->cdev);
+ device_unregister(&dev->dev);
input_wakeup_procfs_readers();
}
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 10e3b7bc925..a9a0180bfd4 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,6 +43,8 @@ struct joydev {
struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
+ struct device dev;
+
struct js_corr corr[ABS_MAX + 1];
struct JS_DATA_SAVE_TYPE glue;
int nabs;
@@ -138,8 +140,10 @@ static int joydev_fasync(int fd, struct file *file, int on)
return retval < 0 ? retval : 0;
}
-static void joydev_free(struct joydev *joydev)
+static void joydev_free(struct device *dev)
{
+ struct joydev *joydev = container_of(dev, struct joydev, dev);
+
joydev_table[joydev->minor] = NULL;
kfree(joydev);
}
@@ -154,12 +158,10 @@ static int joydev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--joydev->open) {
- if (joydev->exist)
- input_close_device(&joydev->handle);
- else
- joydev_free(joydev);
- }
+ if (!--joydev->open && joydev->exist)
+ input_close_device(&joydev->handle);
+
+ put_device(&joydev->dev);
return 0;
}
@@ -178,24 +180,32 @@ static int joydev_open(struct inode *inode, struct file *file)
if (!joydev || !joydev->exist)
return -ENODEV;
+ get_device(&joydev->dev);
+
client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_joydev;
+ }
client->joydev = joydev;
list_add_tail(&client->node, &joydev->client_list);
if (!joydev->open++ && joydev->exist) {
error = input_open_device(&joydev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_joydev:
+ put_device(&joydev->dev);
+ return error;
}
static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
@@ -481,8 +491,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct joydev *joydev;
- struct class_device *cdev;
- dev_t devt;
int i, j, t, minor;
int error;
@@ -505,7 +513,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
joydev->handle.name = joydev->name;
joydev->handle.handler = handler;
joydev->handle.private = joydev;
- sprintf(joydev->name, "js%d", minor);
+ snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
for (i = 0; i < ABS_MAX + 1; i++)
if (test_bit(i, dev->absbit)) {
@@ -547,36 +555,30 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
}
- joydev_table[minor] = joydev;
-
- devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+ snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
+ "js%d", minor);
+ joydev->dev.class = &input_class;
+ joydev->dev.parent = &dev->dev;
+ joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
+ joydev->dev.release = joydev_free;
+ device_initialize(&joydev->dev);
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, joydev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
- goto err_free_joydev;
- }
+ joydev_table[minor] = joydev;
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, joydev->name);
+ error = device_add(&joydev->dev);
if (error)
- goto err_cdev_destroy;
+ goto err_free_joydev;
error = input_register_handle(&joydev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_joydev;
return 0;
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
+ err_delete_joydev:
+ device_del(&joydev->dev);
err_free_joydev:
- joydev_table[minor] = NULL;
- kfree(joydev);
+ put_device(&joydev->dev);
return error;
}
@@ -587,9 +589,8 @@ static void joydev_disconnect(struct input_handle *handle)
struct joydev_client *client;
input_unregister_handle(handle);
+ device_del(&joydev->dev);
- sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
- class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
joydev->exist = 0;
if (joydev->open) {
@@ -597,8 +598,9 @@ static void joydev_disconnect(struct input_handle *handle)
list_for_each_entry(client, &joydev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&joydev->wait);
- } else
- joydev_free(joydev);
+ }
+
+ put_device(&joydev->dev);
}
static const struct input_device_id joydev_blacklist[] = {
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index b0023452ec9..12db72d83ea 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -268,4 +268,11 @@ config JOYSTICK_XPAD
To compile this driver as a module, choose M here: the
module will be called xpad.
+config JOYSTICK_XPAD_FF
+ bool "X-Box gamepad rumble support"
+ depends on JOYSTICK_XPAD && INPUT
+ select INPUT_FF_MEMLESS
+ ---help---
+ Say Y here if you want to take advantage of xbox 360 rumble features.
+
endif
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 555319e6378..4ed3a3eadf1 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -320,10 +320,10 @@ static int multiport_io(struct gameport* gameport, int sendflags, int sendcode,
static int dig_mode_start(struct gameport *gameport, u32 *packet)
{
- int i, seq_len = sizeof(init_seq)/sizeof(int);
+ int i;
int flags, tries = 0, bads = 0;
- for (i = 0; i < seq_len; i++) { /* Send magic sequence */
+ for (i = 0; i < ARRAY_SIZE(init_seq); i++) { /* Send magic sequence */
if (init_seq[i])
gameport_trigger(gameport);
udelay(GRIP_INIT_DELAY);
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 8c8cd95a698..244089c5265 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -8,6 +8,7 @@
* Ivan Hawkes <blackhawk@ivanhawkes.com>
* 2005 Dominic Cerquetti <binary1230@yahoo.com>
* 2006 Adam Buchbinder <adam.buchbinder@gmail.com>
+ * 2007 Jan Kratochvil <honza@jikos.cz>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -28,6 +29,7 @@
* - information from http://euc.jp/periphs/xbox-controller.ja.html
* - the iForce driver drivers/char/joystick/iforce.c
* - the skeleton-driver drivers/usb/usb-skeleton.c
+ * - Xbox 360 information http://www.free60.org/wiki/Gamepad
*
* Thanks to:
* - ITO Takayuki for providing essential xpad information on his website
@@ -88,6 +90,9 @@
#define MAP_DPAD_TO_AXES 1
#define MAP_DPAD_UNKNOWN -1
+#define XTYPE_XBOX 0
+#define XTYPE_XBOX360 1
+
static int dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
@@ -97,40 +102,42 @@ static const struct xpad_device {
u16 idProduct;
char *name;
u8 dpad_mapping;
+ u8 xtype;
} xpad_device[] = {
- { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES },
- { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES },
- { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES },
- { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES },
- { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS },
- { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES },
- { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES },
- { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES },
- { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES },
- { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS },
- { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS },
- { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
- { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
- { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES },
- { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES },
- { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES},
- { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES },
- { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES },
- { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES },
- { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES },
- { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS },
- { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS },
- { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES },
- { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN }
+ { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+ { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX }
};
static const signed short xpad_btn[] = {
@@ -146,6 +153,12 @@ static const signed short xpad_btn_pad[] = {
-1 /* terminating entry */
};
+static const signed short xpad360_btn[] = { /* buttons for x360 controller */
+ BTN_TL, BTN_TR, /* Button LB/RB */
+ BTN_MODE, /* The big X button */
+ -1
+};
+
static const signed short xpad_abs[] = {
ABS_X, ABS_Y, /* left stick */
ABS_RX, ABS_RY, /* right stick */
@@ -159,8 +172,12 @@ static const signed short xpad_abs_pad[] = {
-1 /* terminating entry */
};
+/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
+ * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
+ * but we need only one of them. */
static struct usb_device_id xpad_table [] = {
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
+ { USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) }, /* X-Box 360 controller */
{ }
};
@@ -174,9 +191,16 @@ struct usb_xpad {
unsigned char *idata; /* input data */
dma_addr_t idata_dma;
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+ struct urb *irq_out; /* urb for interrupt out report */
+ unsigned char *odata; /* output data */
+ dma_addr_t odata_dma;
+#endif
+
char phys[65]; /* physical device path */
int dpad_mapping; /* map d-pad to buttons or to axes */
+ int xtype; /* type of xbox device */
};
/*
@@ -212,8 +236,8 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
} else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
- input_report_key(dev, BTN_0, data[2] & 0x01); // up
- input_report_key(dev, BTN_1, data[2] & 0x02); // down
+ input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
+ input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
}
/* start/back buttons and stick press left/right */
@@ -235,6 +259,64 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
input_sync(dev);
}
+/*
+ * xpad360_process_packet
+ *
+ * Completes a request by converting the data into events for the
+ * input subsystem. It is version for xbox 360 controller
+ *
+ * The used report descriptor was taken from:
+ * http://www.free60.org/wiki/Gamepad
+ */
+
+static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
+{
+ struct input_dev *dev = xpad->dev;
+
+ /* digital pad */
+ if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
+ input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
+ input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
+ } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
+ /* dpad as buttons (right, left, down, up) */
+ input_report_key(dev, BTN_LEFT, data[2] & 0x04);
+ input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
+ input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
+ input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
+ }
+
+ /* start/back buttons */
+ input_report_key(dev, BTN_START, data[2] & 0x10);
+ input_report_key(dev, BTN_BACK, data[2] & 0x20);
+
+ /* stick press left/right */
+ input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
+ input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
+
+ /* buttons A,B,X,Y,TL,TR and MODE */
+ input_report_key(dev, BTN_A, data[3] & 0x10);
+ input_report_key(dev, BTN_B, data[3] & 0x20);
+ input_report_key(dev, BTN_X, data[3] & 0x40);
+ input_report_key(dev, BTN_Y, data[3] & 0x80);
+ input_report_key(dev, BTN_TL, data[3] & 0x01);
+ input_report_key(dev, BTN_TR, data[3] & 0x02);
+ input_report_key(dev, BTN_MODE, data[3] & 0x04);
+
+ /* left stick */
+ input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6]));
+ input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8]));
+
+ /* right stick */
+ input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10]));
+ input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12]));
+
+ /* triggers left/right */
+ input_report_abs(dev, ABS_Z, data[4]);
+ input_report_abs(dev, ABS_RZ, data[5]);
+
+ input_sync(dev);
+}
+
static void xpad_irq_in(struct urb *urb)
{
struct usb_xpad *xpad = urb->context;
@@ -255,7 +337,10 @@ static void xpad_irq_in(struct urb *urb)
goto exit;
}
- xpad_process_packet(xpad, 0, xpad->idata);
+ if (xpad->xtype == XTYPE_XBOX360)
+ xpad360_process_packet(xpad, 0, xpad->idata);
+ else
+ xpad_process_packet(xpad, 0, xpad->idata);
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -264,7 +349,114 @@ exit:
__FUNCTION__, retval);
}
-static int xpad_open (struct input_dev *dev)
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+static void xpad_irq_out(struct urb *urb)
+{
+ int retval;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, retval);
+}
+
+static int xpad_play_effect(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct usb_xpad *xpad = input_get_drvdata(dev);
+
+ if (effect->type == FF_RUMBLE) {
+ __u16 strong = effect->u.rumble.strong_magnitude;
+ __u16 weak = effect->u.rumble.weak_magnitude;
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x08;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = strong / 256;
+ xpad->odata[4] = weak / 256;
+ xpad->odata[5] = 0x00;
+ xpad->odata[6] = 0x00;
+ xpad->odata[7] = 0x00;
+ usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+ }
+
+ return 0;
+}
+
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad)
+{
+ struct usb_endpoint_descriptor *ep_irq_out;
+ int error = -ENOMEM;
+
+ if (xpad->xtype != XTYPE_XBOX360)
+ return 0;
+
+ xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
+ GFP_ATOMIC, &xpad->odata_dma );
+ if (!xpad->odata)
+ goto fail1;
+
+ xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
+ if (!xpad->irq_out)
+ goto fail2;
+
+ ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
+ usb_fill_int_urb(xpad->irq_out, xpad->udev,
+ usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
+ xpad->odata, XPAD_PKT_LEN,
+ xpad_irq_out, xpad, ep_irq_out->bInterval);
+ xpad->irq_out->transfer_dma = xpad->odata_dma;
+ xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
+
+ error = input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
+ if (error)
+ goto fail2;
+
+ return 0;
+
+ fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
+ fail1: return error;
+}
+
+static void xpad_stop_ff(struct usb_xpad *xpad)
+{
+ if (xpad->xtype == XTYPE_XBOX360)
+ usb_kill_urb(xpad->irq_out);
+}
+
+static void xpad_deinit_ff(struct usb_xpad *xpad)
+{
+ if (xpad->xtype == XTYPE_XBOX360) {
+ usb_free_urb(xpad->irq_out);
+ usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
+ xpad->odata, xpad->odata_dma);
+ }
+}
+
+#else
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
+static void xpad_stop_ff(struct usb_xpad *xpad) { }
+static void xpad_deinit_ff(struct usb_xpad *xpad) { }
+#endif
+
+static int xpad_open(struct input_dev *dev)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
@@ -275,11 +467,12 @@ static int xpad_open (struct input_dev *dev)
return 0;
}
-static void xpad_close (struct input_dev *dev)
+static void xpad_close(struct input_dev *dev)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
usb_kill_urb(xpad->irq_in);
+ xpad_stop_ff(xpad);
}
static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
@@ -335,6 +528,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->udev = udev;
xpad->dpad_mapping = xpad_device[i].dpad_mapping;
+ xpad->xtype = xpad_device[i].xtype;
if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
xpad->dpad_mapping = dpad_to_buttons;
xpad->dev = input_dev;
@@ -356,6 +550,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
/* set up buttons */
for (i = 0; xpad_btn[i] >= 0; i++)
set_bit(xpad_btn[i], input_dev->keybit);
+ if (xpad->xtype == XTYPE_XBOX360)
+ for (i = 0; xpad360_btn[i] >= 0; i++)
+ set_bit(xpad360_btn[i], input_dev->keybit);
if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
for (i = 0; xpad_btn_pad[i] >= 0; i++)
set_bit(xpad_btn_pad[i], input_dev->keybit);
@@ -367,6 +564,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
for (i = 0; xpad_abs_pad[i] >= 0; i++)
xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
+ error = xpad_init_ff(intf, xpad);
+ if (error)
+ goto fail2;
+
ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
usb_fill_int_urb(xpad->irq_in, udev,
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
@@ -396,10 +597,10 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (xpad) {
- usb_kill_urb(xpad->irq_in);
input_unregister_device(xpad->dev);
+ xpad_deinit_ff(xpad);
usb_free_urb(xpad->irq_in);
- usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN,
+ usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
xpad->idata, xpad->idata_dma);
kfree(xpad);
}
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index be1fe46cd30..41fc3d03b6e 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -89,7 +89,7 @@ static unsigned char atkbd_set2_keycode[512] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
- 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
+ 159, 0,115, 0,164, 0, 0,116,158, 0,172,166, 0, 0, 0,142,
157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
@@ -111,7 +111,7 @@ static unsigned char atkbd_set3_keycode[512] = {
82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55,183,
184,185,186,187, 74, 94, 92, 93, 0, 0, 0,125,126,127,112, 0,
- 0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
+ 0,139,172,163,165,115,152,172,166,140,160,154,113,114,167,168,
148,149,147,140
};
@@ -219,7 +219,8 @@ struct atkbd {
unsigned long time;
unsigned long err_count;
- struct work_struct event_work;
+ struct delayed_work event_work;
+ unsigned long event_jiffies;
struct mutex event_mutex;
unsigned long event_mask;
};
@@ -408,9 +409,10 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
goto out;
case ATKBD_RET_ACK:
case ATKBD_RET_NAK:
- printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
- "Some program might be trying access hardware directly.\n",
- data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
+ if (printk_ratelimit())
+ printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
+ "Some program might be trying access hardware directly.\n",
+ data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
goto out;
case ATKBD_RET_HANGEUL:
case ATKBD_RET_HANJA:
@@ -565,7 +567,7 @@ static int atkbd_set_leds(struct atkbd *atkbd)
static void atkbd_event_work(struct work_struct *work)
{
- struct atkbd *atkbd = container_of(work, struct atkbd, event_work);
+ struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);
mutex_lock(&atkbd->event_mutex);
@@ -579,12 +581,30 @@ static void atkbd_event_work(struct work_struct *work)
}
/*
+ * Schedule switch for execution. We need to throttle requests,
+ * otherwise keyboard may become unresponsive.
+ */
+static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)
+{
+ unsigned long delay = msecs_to_jiffies(50);
+
+ if (time_after(jiffies, atkbd->event_jiffies + delay))
+ delay = 0;
+
+ atkbd->event_jiffies = jiffies;
+ set_bit(event_bit, &atkbd->event_mask);
+ wmb();
+ schedule_delayed_work(&atkbd->event_work, delay);
+}
+
+/*
* Event callback from the input module. Events that change the state of
* the hardware are processed here. If action can not be performed in
* interrupt context it is offloaded to atkbd_event_work.
*/
-static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int atkbd_event(struct input_dev *dev,
+ unsigned int type, unsigned int code, int value)
{
struct atkbd *atkbd = input_get_drvdata(dev);
@@ -594,19 +614,12 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
switch (type) {
case EV_LED:
- set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask);
- wmb();
- schedule_work(&atkbd->event_work);
+ atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
return 0;
case EV_REP:
-
- if (!atkbd->softrepeat) {
- set_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask);
- wmb();
- schedule_work(&atkbd->event_work);
- }
-
+ if (!atkbd->softrepeat)
+ atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);
return 0;
}
@@ -940,7 +953,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
- INIT_WORK(&atkbd->event_work, atkbd_event_work);
+ INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
mutex_init(&atkbd->event_mutex);
switch (serio->id.type) {
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
index f9e82c9ca42..ebe5eacf299 100644
--- a/drivers/input/keyboard/pxa27x_keyboard.c
+++ b/drivers/input/keyboard/pxa27x_keyboard.c
@@ -140,7 +140,7 @@ static int pxakbd_resume(struct platform_device *pdev)
KPREC = pdata->reg_kprec;
/* Enable unit clock */
- pxa_set_cken(CKEN19_KEYPAD, 1);
+ pxa_set_cken(CKEN_KEYPAD, 1);
}
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 88e29074ac9..9b26574f146 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -65,9 +65,13 @@ config INPUT_COBALT_BTNS
config INPUT_WISTRON_BTNS
tristate "x86 Wistron laptop button interface"
depends on X86 && !X86_64
+ select INPUT_POLLDEV
+ select NEW_LEDS
+ select LEDS_CLASS
help
Say Y here for support of Winstron laptop button interface, used on
- laptops of various brands, including Acer and Fujitsu-Siemens.
+ laptops of various brands, including Acer and Fujitsu-Siemens. If
+ available, mail and wifi leds will be controlable via /sys/class/leds.
To compile this driver as a module, choose M here: the module will
be called wistron_btns.
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 961aad7a047..60121f10f8d 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -20,37 +20,31 @@
#include <linux/io.h>
#include <linux/dmi.h>
#include <linux/init.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
#include <linux/interrupt.h>
+#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/mc146818rtc.h>
#include <linux/module.h>
#include <linux/preempt.h>
#include <linux/string.h>
-#include <linux/timer.h>
#include <linux/types.h>
#include <linux/platform_device.h>
+#include <linux/leds.h>
-/*
- * Number of attempts to read data from queue per poll;
- * the queue can hold up to 31 entries
- */
-#define MAX_POLL_ITERATIONS 64
-
-#define POLL_FREQUENCY 10 /* Number of polls per second */
-
-#if POLL_FREQUENCY > HZ
-#error "POLL_FREQUENCY too high"
-#endif
+/* How often we poll keys - msecs */
+#define POLL_INTERVAL_DEFAULT 500 /* when idle */
+#define POLL_INTERVAL_BURST 100 /* when a key was recently pressed */
/* BIOS subsystem IDs */
#define WIFI 0x35
#define BLUETOOTH 0x34
+#define MAIL_LED 0x31
MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
MODULE_DESCRIPTION("Wistron laptop button driver");
MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.2");
+MODULE_VERSION("0.3");
static int force; /* = 0; */
module_param(force, bool, 0);
@@ -248,9 +242,10 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
#define FE_WIFI_LED 0x02
#define FE_UNTESTED 0x80
-static const struct key_entry *keymap; /* = NULL; Current key map */
+static struct key_entry *keymap; /* = NULL; Current key map */
static int have_wifi;
static int have_bluetooth;
+static int have_leds;
static int __init dmi_matched(struct dmi_system_id *dmi)
{
@@ -263,6 +258,8 @@ static int __init dmi_matched(struct dmi_system_id *dmi)
else if (key->type == KE_BLUETOOTH)
have_bluetooth = 1;
}
+ have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED);
+
return 1;
}
@@ -966,118 +963,163 @@ static int __init select_keymap(void)
/* Input layer interface */
-static struct input_dev *input_dev;
+static struct input_polled_dev *wistron_idev;
+static unsigned long jiffies_last_press;
+static int wifi_enabled;
+static int bluetooth_enabled;
-static int __devinit setup_input_dev(void)
+static void report_key(struct input_dev *dev, unsigned int keycode)
{
- const struct key_entry *key;
- int error;
+ input_report_key(dev, keycode, 1);
+ input_sync(dev);
+ input_report_key(dev, keycode, 0);
+ input_sync(dev);
+}
- input_dev = input_allocate_device();
- if (!input_dev)
- return -ENOMEM;
+static void report_switch(struct input_dev *dev, unsigned int code, int value)
+{
+ input_report_switch(dev, code, value);
+ input_sync(dev);
+}
- input_dev->name = "Wistron laptop buttons";
- input_dev->phys = "wistron/input0";
- input_dev->id.bustype = BUS_HOST;
- input_dev->cdev.dev = &wistron_device->dev;
- for (key = keymap; key->type != KE_END; key++) {
- switch (key->type) {
- case KE_KEY:
- set_bit(EV_KEY, input_dev->evbit);
- set_bit(key->keycode, input_dev->keybit);
- break;
+ /* led management */
+static void wistron_mail_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0);
+}
- case KE_SW:
- set_bit(EV_SW, input_dev->evbit);
- set_bit(key->sw.code, input_dev->swbit);
- break;
+/* same as setting up wifi card, but for laptops on which the led is managed */
+static void wistron_wifi_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0);
+}
- default:
- ;
- }
- }
+static struct led_classdev wistron_mail_led = {
+ .name = "mail:green",
+ .brightness_set = wistron_mail_led_set,
+};
- /* reads information flags on KE_END */
- if (key->code & FE_UNTESTED)
- printk(KERN_WARNING "Untested laptop multimedia keys, "
- "please report success or failure to eric.piel"
- "@tremplin-utc.net\n");
+static struct led_classdev wistron_wifi_led = {
+ .name = "wifi:red",
+ .brightness_set = wistron_wifi_led_set,
+};
- error = input_register_device(input_dev);
- if (error) {
- input_free_device(input_dev);
- return error;
+static void __devinit wistron_led_init(struct device *parent)
+{
+ if (have_leds & FE_WIFI_LED) {
+ u16 wifi = bios_get_default_setting(WIFI);
+ if (wifi & 1) {
+ wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
+ if (led_classdev_register(parent, &wistron_wifi_led))
+ have_leds &= ~FE_WIFI_LED;
+ else
+ bios_set_state(WIFI, wistron_wifi_led.brightness);
+
+ } else
+ have_leds &= ~FE_WIFI_LED;
}
- return 0;
+ if (have_leds & FE_MAIL_LED) {
+ /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
+ wistron_mail_led.brightness = LED_OFF;
+ if (led_classdev_register(parent, &wistron_mail_led))
+ have_leds &= ~FE_MAIL_LED;
+ else
+ bios_set_state(MAIL_LED, wistron_mail_led.brightness);
+ }
}
-static void report_key(unsigned keycode)
+static void __devexit wistron_led_remove(void)
{
- input_report_key(input_dev, keycode, 1);
- input_sync(input_dev);
- input_report_key(input_dev, keycode, 0);
- input_sync(input_dev);
+ if (have_leds & FE_MAIL_LED)
+ led_classdev_unregister(&wistron_mail_led);
+
+ if (have_leds & FE_WIFI_LED)
+ led_classdev_unregister(&wistron_wifi_led);
}
-static void report_switch(unsigned code, int value)
+static inline void wistron_led_suspend(void)
{
- input_report_switch(input_dev, code, value);
- input_sync(input_dev);
+ if (have_leds & FE_MAIL_LED)
+ led_classdev_suspend(&wistron_mail_led);
+
+ if (have_leds & FE_WIFI_LED)
+ led_classdev_suspend(&wistron_wifi_led);
}
- /* Driver core */
+static inline void wistron_led_resume(void)
+{
+ if (have_leds & FE_MAIL_LED)
+ led_classdev_resume(&wistron_mail_led);
-static int wifi_enabled;
-static int bluetooth_enabled;
+ if (have_leds & FE_WIFI_LED)
+ led_classdev_resume(&wistron_wifi_led);
+}
+
+static struct key_entry *wistron_get_entry_by_scancode(int code)
+{
+ struct key_entry *key;
-static void poll_bios(unsigned long);
+ for (key = keymap; key->type != KE_END; key++)
+ if (code == key->code)
+ return key;
-static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0);
+ return NULL;
+}
-static void handle_key(u8 code)
+static struct key_entry *wistron_get_entry_by_keycode(int keycode)
{
- const struct key_entry *key;
+ struct key_entry *key;
- for (key = keymap; key->type != KE_END; key++) {
- if (code == key->code) {
- switch (key->type) {
- case KE_KEY:
- report_key(key->keycode);
- break;
+ for (key = keymap; key->type != KE_END; key++)
+ if (key->type == KE_KEY && keycode == key->keycode)
+ return key;
- case KE_SW:
- report_switch(key->sw.code, key->sw.value);
- break;
+ return NULL;
+}
- case KE_WIFI:
- if (have_wifi) {
- wifi_enabled = !wifi_enabled;
- bios_set_state(WIFI, wifi_enabled);
- }
- break;
+static void handle_key(u8 code)
+{
+ const struct key_entry *key = wistron_get_entry_by_scancode(code);
- case KE_BLUETOOTH:
- if (have_bluetooth) {
- bluetooth_enabled = !bluetooth_enabled;
- bios_set_state(BLUETOOTH, bluetooth_enabled);
- }
- break;
+ if (key) {
+ switch (key->type) {
+ case KE_KEY:
+ report_key(wistron_idev->input, key->keycode);
+ break;
- case KE_END:
- break;
- default:
- BUG();
+ case KE_SW:
+ report_switch(wistron_idev->input,
+ key->sw.code, key->sw.value);
+ break;
+
+ case KE_WIFI:
+ if (have_wifi) {
+ wifi_enabled = !wifi_enabled;
+ bios_set_state(WIFI, wifi_enabled);
+ }
+ break;
+
+ case KE_BLUETOOTH:
+ if (have_bluetooth) {
+ bluetooth_enabled = !bluetooth_enabled;
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
}
- return;
+ break;
+
+ default:
+ BUG();
}
- }
- printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code);
+ jiffies_last_press = jiffies;
+ } else
+ printk(KERN_NOTICE
+ "wistron_btns: Unknown key code %02X\n", code);
}
-static void poll_bios(unsigned long discard)
+static void poll_bios(bool discard)
{
u8 qlen;
u16 val;
@@ -1090,15 +1132,118 @@ static void poll_bios(unsigned long discard)
if (val != 0 && !discard)
handle_key((u8)val);
}
+}
+
+static void wistron_flush(struct input_polled_dev *dev)
+{
+ /* Flush stale event queue */
+ poll_bios(true);
+}
+
+static void wistron_poll(struct input_polled_dev *dev)
+{
+ poll_bios(false);
+
+ /* Increase poll frequency if user is currently pressing keys (< 2s ago) */
+ if (time_before(jiffies, jiffies_last_press + 2 * HZ))
+ dev->poll_interval = POLL_INTERVAL_BURST;
+ else
+ dev->poll_interval = POLL_INTERVAL_DEFAULT;
+}
+
+static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+ const struct key_entry *key = wistron_get_entry_by_scancode(scancode);
+
+ if (key && key->type == KE_KEY) {
+ *keycode = key->keycode;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+ struct key_entry *key;
+ int old_keycode;
+
+ if (keycode < 0 || keycode > KEY_MAX)
+ return -EINVAL;
+
+ key = wistron_get_entry_by_scancode(scancode);
+ if (key && key->type == KE_KEY) {
+ old_keycode = key->keycode;
+ key->keycode = keycode;
+ set_bit(keycode, dev->keybit);
+ if (!wistron_get_entry_by_keycode(old_keycode))
+ clear_bit(old_keycode, dev->keybit);
+ return 0;
+ }
- mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
+ return -EINVAL;
}
+static int __devinit setup_input_dev(void)
+{
+ const struct key_entry *key;
+ struct input_dev *input_dev;
+ int error;
+
+ wistron_idev = input_allocate_polled_device();
+ if (!wistron_idev)
+ return -ENOMEM;
+
+ wistron_idev->flush = wistron_flush;
+ wistron_idev->poll = wistron_poll;
+ wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
+
+ input_dev = wistron_idev->input;
+ input_dev->name = "Wistron laptop buttons";
+ input_dev->phys = "wistron/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->dev.parent = &wistron_device->dev;
+
+ input_dev->getkeycode = wistron_getkeycode;
+ input_dev->setkeycode = wistron_setkeycode;
+
+ for (key = keymap; key->type != KE_END; key++) {
+ switch (key->type) {
+ case KE_KEY:
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(key->keycode, input_dev->keybit);
+ break;
+
+ case KE_SW:
+ set_bit(EV_SW, input_dev->evbit);
+ set_bit(key->sw.code, input_dev->swbit);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* reads information flags on KE_END */
+ if (key->code & FE_UNTESTED)
+ printk(KERN_WARNING "Untested laptop multimedia keys, "
+ "please report success or failure to eric.piel"
+ "@tremplin-utc.net\n");
+
+ error = input_register_polled_device(wistron_idev);
+ if (error) {
+ input_free_polled_device(wistron_idev);
+ return error;
+ }
+
+ return 0;
+}
+
+/* Driver core */
+
static int __devinit wistron_probe(struct platform_device *dev)
{
- int err = setup_input_dev();
- if (err)
- return err;
+ int err;
bios_attach();
cmos_address = bios_get_cmos_address();
@@ -1125,15 +1270,21 @@ static int __devinit wistron_probe(struct platform_device *dev)
bios_set_state(BLUETOOTH, bluetooth_enabled);
}
- poll_bios(1); /* Flush stale event queue and arm timer */
+ wistron_led_init(&dev->dev);
+ err = setup_input_dev();
+ if (err) {
+ bios_detach();
+ return err;
+ }
return 0;
}
static int __devexit wistron_remove(struct platform_device *dev)
{
- del_timer_sync(&poll_timer);
- input_unregister_device(input_dev);
+ wistron_led_remove();
+ input_unregister_polled_device(wistron_idev);
+ input_free_polled_device(wistron_idev);
bios_detach();
return 0;
@@ -1142,14 +1293,13 @@ static int __devexit wistron_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int wistron_suspend(struct platform_device *dev, pm_message_t state)
{
- del_timer_sync(&poll_timer);
-
if (have_wifi)
bios_set_state(WIFI, 0);
if (have_bluetooth)
bios_set_state(BLUETOOTH, 0);
+ wistron_led_suspend();
return 0;
}
@@ -1161,7 +1311,8 @@ static int wistron_resume(struct platform_device *dev)
if (have_bluetooth)
bios_set_state(BLUETOOTH, bluetooth_enabled);
- poll_bios(1);
+ wistron_led_resume();
+ poll_bios(true);
return 0;
}
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 50e06e8dd05..7bbea097cda 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -216,4 +216,20 @@ config MOUSE_HIL
help
Say Y here to support HIL pointers.
+config MOUSE_GPIO
+ tristate "GPIO mouse"
+ depends on GENERIC_GPIO
+ select INPUT_POLLDEV
+ help
+ This driver simulates a mouse on GPIO lines of various CPUs (and some
+ other chips).
+
+ Say Y here if your device has buttons or a simple joystick connected
+ directly to GPIO lines. Your board-specific setup logic must also
+ provide a platform device and platform data saying which GPIOs are
+ used.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gpio_mouse.
+
endif
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index aa4ba878533..9e6e3633082 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
+obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
psmouse-objs := psmouse-base.o synaptics.o
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
new file mode 100644
index 00000000000..0936d6ba015
--- /dev/null
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -0,0 +1,196 @@
+/*
+ * Driver for simulating a mouse on GPIO lines.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input-polldev.h>
+#include <linux/gpio_mouse.h>
+
+#include <asm/gpio.h>
+
+/*
+ * Timer function which is run every scan_ms ms when the device is opened.
+ * The dev input varaible is set to the the input_dev pointer.
+ */
+static void gpio_mouse_scan(struct input_polled_dev *dev)
+{
+ struct gpio_mouse_platform_data *gpio = dev->private;
+ struct input_dev *input = dev->input;
+ int x, y;
+
+ if (gpio->bleft >= 0)
+ input_report_key(input, BTN_LEFT,
+ gpio_get_value(gpio->bleft) ^ gpio->polarity);
+ if (gpio->bmiddle >= 0)
+ input_report_key(input, BTN_MIDDLE,
+ gpio_get_value(gpio->bmiddle) ^ gpio->polarity);
+ if (gpio->bright >= 0)
+ input_report_key(input, BTN_RIGHT,
+ gpio_get_value(gpio->bright) ^ gpio->polarity);
+
+ x = (gpio_get_value(gpio->right) ^ gpio->polarity)
+ - (gpio_get_value(gpio->left) ^ gpio->polarity);
+ y = (gpio_get_value(gpio->down) ^ gpio->polarity)
+ - (gpio_get_value(gpio->up) ^ gpio->polarity);
+
+ input_report_rel(input, REL_X, x);
+ input_report_rel(input, REL_Y, y);
+ input_sync(input);
+}
+
+static int __init gpio_mouse_probe(struct platform_device *pdev)
+{
+ struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
+ struct input_polled_dev *input_poll;
+ struct input_dev *input;
+ int pin, i;
+ int error;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data\n");
+ error = -ENXIO;
+ goto out;
+ }
+
+ if (pdata->scan_ms < 0) {
+ dev_err(&pdev->dev, "invalid scan time\n");
+ error = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+ pin = pdata->pins[i];
+
+ if (pin < 0) {
+
+ if (i <= GPIO_MOUSE_PIN_RIGHT) {
+ /* Mouse direction is required. */
+ dev_err(&pdev->dev,
+ "missing GPIO for directions\n");
+ error = -EINVAL;
+ goto out_free_gpios;
+ }
+
+ if (i == GPIO_MOUSE_PIN_BLEFT)
+ dev_dbg(&pdev->dev, "no left button defined\n");
+
+ } else {
+ error = gpio_request(pin, "gpio_mouse");
+ if (error) {
+ dev_err(&pdev->dev, "fail %d pin (%d idx)\n",
+ pin, i);
+ goto out_free_gpios;
+ }
+
+ gpio_direction_input(pin);
+ }
+ }
+
+ input_poll = input_allocate_polled_device();
+ if (!input_poll) {
+ dev_err(&pdev->dev, "not enough memory for input device\n");
+ error = -ENOMEM;
+ goto out_free_gpios;
+ }
+
+ platform_set_drvdata(pdev, input_poll);
+
+ /* set input-polldev handlers */
+ input_poll->private = pdata;
+ input_poll->poll = gpio_mouse_scan;
+ input_poll->poll_interval = pdata->scan_ms;
+
+ input = input_poll->input;
+ input->name = pdev->name;
+ input->id.bustype = BUS_HOST;
+ input->dev.parent = &pdev->dev;
+
+ input_set_capability(input, EV_REL, REL_X);
+ input_set_capability(input, EV_REL, REL_Y);
+ if (pdata->bleft >= 0)
+ input_set_capability(input, EV_KEY, BTN_LEFT);
+ if (pdata->bmiddle >= 0)
+ input_set_capability(input, EV_KEY, BTN_MIDDLE);
+ if (pdata->bright >= 0)
+ input_set_capability(input, EV_KEY, BTN_RIGHT);
+
+ error = input_register_polled_device(input_poll);
+ if (error) {
+ dev_err(&pdev->dev, "could not register input device\n");
+ goto out_free_polldev;
+ }
+
+ dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n",
+ pdata->scan_ms,
+ pdata->bleft < 0 ? "" : "left ",
+ pdata->bmiddle < 0 ? "" : "middle ",
+ pdata->bright < 0 ? "" : "right");
+
+ return 0;
+
+ out_free_polldev:
+ input_free_polled_device(input_poll);
+ platform_set_drvdata(pdev, NULL);
+
+ out_free_gpios:
+ while (--i >= 0) {
+ pin = pdata->pins[i];
+ if (pin)
+ gpio_free(pin);
+ }
+ out:
+ return error;
+}
+
+static int __devexit gpio_mouse_remove(struct platform_device *pdev)
+{
+ struct input_polled_dev *input = platform_get_drvdata(pdev);
+ struct gpio_mouse_platform_data *pdata = input->private;
+ int pin, i;
+
+ input_unregister_polled_device(input);
+ input_free_polled_device(input);
+
+ for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+ pin = pdata->pins[i];
+ if (pin >= 0)
+ gpio_free(pin);
+ }
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+struct platform_driver gpio_mouse_device_driver = {
+ .remove = __devexit_p(gpio_mouse_remove),
+ .driver = {
+ .name = "gpio_mouse",
+ }
+};
+
+static int __init gpio_mouse_init(void)
+{
+ return platform_driver_probe(&gpio_mouse_device_driver,
+ gpio_mouse_probe);
+}
+module_init(gpio_mouse_init);
+
+static void __exit gpio_mouse_exit(void)
+{
+ platform_driver_unregister(&gpio_mouse_device_driver);
+}
+module_exit(gpio_mouse_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("GPIO mouse driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index f15f695777f..b9f0fb2530e 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -178,6 +178,15 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
}
/*
+ * Cortron PS2 Trackball reports SIDE button on the 4th bit of the first
+ * byte.
+ */
+ if (psmouse->type == PSMOUSE_CORTRON) {
+ input_report_key(dev, BTN_SIDE, (packet[0] >> 3) & 1);
+ packet[0] |= 0x08;
+ }
+
+/*
* Generic PS/2 Mouse
*/
@@ -539,6 +548,20 @@ static int ps2bare_detect(struct psmouse *psmouse, int set_properties)
return 0;
}
+/*
+ * Cortron PS/2 protocol detection. There's no special way to detect it, so it
+ * must be forced by sysfs protocol writing.
+ */
+static int cortron_detect(struct psmouse *psmouse, int set_properties)
+{
+ if (set_properties) {
+ psmouse->vendor = "Cortron";
+ psmouse->name = "PS/2 Trackball";
+ set_bit(BTN_SIDE, psmouse->dev->keybit);
+ }
+
+ return 0;
+}
/*
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
@@ -740,6 +763,12 @@ static const struct psmouse_protocol psmouse_protocols[] = {
},
#endif
{
+ .type = PSMOUSE_CORTRON,
+ .name = "CortronPS/2",
+ .alias = "cortps",
+ .detect = cortron_detect,
+ },
+ {
.type = PSMOUSE_AUTO,
.name = "auto",
.alias = "any",
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 3964e8acbc5..27a68835b5b 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -88,6 +88,7 @@ enum psmouse_type {
PSMOUSE_LIFEBOOK,
PSMOUSE_TRACKPOINT,
PSMOUSE_TOUCHKIT_PS2,
+ PSMOUSE_CORTRON,
PSMOUSE_AUTO /* This one should always be last */
};
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 3f4866d8d18..9173916b8be 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -64,6 +64,7 @@ struct mousedev {
wait_queue_head_t wait;
struct list_head client_list;
struct input_handle handle;
+ struct device dev;
struct list_head mixdev_node;
int mixdev_open;
@@ -112,7 +113,7 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
static struct input_handler mousedev_handler;
static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
-static struct mousedev mousedev_mix;
+static struct mousedev *mousedev_mix;
static LIST_HEAD(mousedev_mix_list);
#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
@@ -218,10 +219,10 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
if (value) {
set_bit(index, &mousedev->packet.buttons);
- set_bit(index, &mousedev_mix.packet.buttons);
+ set_bit(index, &mousedev_mix->packet.buttons);
} else {
clear_bit(index, &mousedev->packet.buttons);
- clear_bit(index, &mousedev_mix.packet.buttons);
+ clear_bit(index, &mousedev_mix->packet.buttons);
}
}
@@ -287,11 +288,11 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
* motion packet so we won't mess current position.
*/
set_bit(0, &mousedev->packet.buttons);
- set_bit(0, &mousedev_mix.packet.buttons);
- mousedev_notify_readers(mousedev, &mousedev_mix.packet);
- mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
+ set_bit(0, &mousedev_mix->packet.buttons);
+ mousedev_notify_readers(mousedev, &mousedev_mix->packet);
+ mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
clear_bit(0, &mousedev->packet.buttons);
- clear_bit(0, &mousedev_mix.packet.buttons);
+ clear_bit(0, &mousedev_mix->packet.buttons);
}
mousedev->touch = mousedev->pkt_count = 0;
mousedev->frac_dx = 0;
@@ -343,7 +344,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
}
mousedev_notify_readers(mousedev, &mousedev->packet);
- mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
+ mousedev_notify_readers(mousedev_mix, &mousedev->packet);
mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
mousedev->packet.abs_event = 0;
@@ -362,8 +363,10 @@ static int mousedev_fasync(int fd, struct file *file, int on)
return retval < 0 ? retval : 0;
}
-static void mousedev_free(struct mousedev *mousedev)
+static void mousedev_free(struct device *dev)
{
+ struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
+
mousedev_table[mousedev->minor] = NULL;
kfree(mousedev);
}
@@ -372,15 +375,16 @@ static int mixdev_add_device(struct mousedev *mousedev)
{
int error;
- if (mousedev_mix.open) {
+ if (mousedev_mix->open) {
error = input_open_device(&mousedev->handle);
if (error)
return error;
mousedev->open++;
- mousedev->mixdev_open++;
+ mousedev->mixdev_open = 1;
}
+ get_device(&mousedev->dev);
list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
return 0;
@@ -395,36 +399,40 @@ static void mixdev_remove_device(struct mousedev *mousedev)
}
list_del_init(&mousedev->mixdev_node);
+ put_device(&mousedev->dev);
}
static void mixdev_open_devices(void)
{
struct mousedev *mousedev;
+ if (mousedev_mix->open++)
+ return;
+
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
- if (mousedev->exist && !mousedev->open) {
- if (input_open_device(&mousedev->handle))
- continue;
+ if (!mousedev->mixdev_open) {
+ if (!mousedev->open && mousedev->exist)
+ if (input_open_device(&mousedev->handle))
+ continue;
mousedev->open++;
- mousedev->mixdev_open++;
+ mousedev->mixdev_open = 1;
}
}
}
static void mixdev_close_devices(void)
{
- struct mousedev *mousedev, *next;
+ struct mousedev *mousedev;
- list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+ if (--mousedev_mix->open)
+ return;
+
+ list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (mousedev->mixdev_open) {
mousedev->mixdev_open = 0;
- if (!--mousedev->open) {
- if (mousedev->exist)
- input_close_device(&mousedev->handle);
- else
- mousedev_free(mousedev);
- }
+ if (!--mousedev->open && mousedev->exist)
+ input_close_device(&mousedev->handle);
}
}
}
@@ -439,14 +447,12 @@ static int mousedev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--mousedev->open) {
- if (mousedev->minor == MOUSEDEV_MIX)
- mixdev_close_devices();
- else if (mousedev->exist)
- input_close_device(&mousedev->handle);
- else
- mousedev_free(mousedev);
- }
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_close_devices();
+ else if (!--mousedev->open && mousedev->exist)
+ input_close_device(&mousedev->handle);
+
+ put_device(&mousedev->dev);
return 0;
}
@@ -473,9 +479,13 @@ static int mousedev_open(struct inode *inode, struct file *file)
if (!mousedev)
return -ENODEV;
+ get_device(&mousedev->dev);
+
client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_mousedev;
+ }
spin_lock_init(&client->packet_lock);
client->pos_x = xres / 2;
@@ -483,21 +493,23 @@ static int mousedev_open(struct inode *inode, struct file *file)
client->mousedev = mousedev;
list_add_tail(&client->node, &mousedev->client_list);
- if (!mousedev->open++) {
- if (mousedev->minor == MOUSEDEV_MIX)
- mixdev_open_devices();
- else if (mousedev->exist) {
- error = input_open_device(&mousedev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
- }
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_open_devices();
+ else if (!mousedev->open++ && mousedev->exist) {
+ error = input_open_device(&mousedev->handle);
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_mousedev:
+ put_device(&mousedev->dev);
+ return error;
}
static inline int mousedev_limit_delta(int delta, int limit)
@@ -680,57 +692,96 @@ static const struct file_operations mousedev_fops = {
.fasync = mousedev_fasync,
};
-static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
- const struct input_device_id *id)
+static struct mousedev *mousedev_create(struct input_dev *dev,
+ struct input_handler *handler,
+ int minor)
{
struct mousedev *mousedev;
- struct class_device *cdev;
- dev_t devt;
- int minor;
int error;
- for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
- if (minor == MOUSEDEV_MINORS) {
- printk(KERN_ERR "mousedev: no more free mousedev devices\n");
- return -ENFILE;
- }
-
mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
- if (!mousedev)
- return -ENOMEM;
+ if (!mousedev) {
+ error = -ENOMEM;
+ goto err_out;
+ }
INIT_LIST_HEAD(&mousedev->client_list);
INIT_LIST_HEAD(&mousedev->mixdev_node);
init_waitqueue_head(&mousedev->wait);
+ if (minor == MOUSEDEV_MIX)
+ strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
+ else
+ snprintf(mousedev->name, sizeof(mousedev->name),
+ "mouse%d", minor);
+
mousedev->minor = minor;
mousedev->exist = 1;
mousedev->handle.dev = dev;
mousedev->handle.name = mousedev->name;
mousedev->handle.handler = handler;
mousedev->handle.private = mousedev;
- sprintf(mousedev->name, "mouse%d", minor);
- mousedev_table[minor] = mousedev;
+ strlcpy(mousedev->dev.bus_id, mousedev->name,
+ sizeof(mousedev->dev.bus_id));
+ mousedev->dev.class = &input_class;
+ if (dev)
+ mousedev->dev.parent = &dev->dev;
+ mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
+ mousedev->dev.release = mousedev_free;
+ device_initialize(&mousedev->dev);
- devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+ mousedev_table[minor] = mousedev;
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, mousedev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
+ error = device_add(&mousedev->dev);
+ if (error)
goto err_free_mousedev;
+
+ return mousedev;
+
+ err_free_mousedev:
+ put_device(&mousedev->dev);
+ err_out:
+ return ERR_PTR(error);
+}
+
+static void mousedev_destroy(struct mousedev *mousedev)
+{
+ struct mousedev_client *client;
+
+ device_del(&mousedev->dev);
+ mousedev->exist = 0;
+
+ if (mousedev->open) {
+ input_close_device(&mousedev->handle);
+ list_for_each_entry(client, &mousedev->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+ wake_up_interruptible(&mousedev->wait);
}
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, mousedev->name);
- if (error)
- goto err_cdev_destroy;
+ put_device(&mousedev->dev);
+}
+
+static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ struct mousedev *mousedev;
+ int minor;
+ int error;
+
+ for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
+ if (minor == MOUSEDEV_MINORS) {
+ printk(KERN_ERR "mousedev: no more free mousedev devices\n");
+ return -ENFILE;
+ }
+
+ mousedev = mousedev_create(dev, handler, minor);
+ if (IS_ERR(mousedev))
+ return PTR_ERR(mousedev);
error = input_register_handle(&mousedev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_mousedev;
error = mixdev_add_device(mousedev);
if (error)
@@ -740,37 +791,18 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
err_unregister_handle:
input_unregister_handle(&mousedev->handle);
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
- err_free_mousedev:
- mousedev_table[minor] = NULL;
- kfree(mousedev);
+ err_delete_mousedev:
+ device_unregister(&mousedev->dev);
return error;
}
static void mousedev_disconnect(struct input_handle *handle)
{
struct mousedev *mousedev = handle->private;
- struct mousedev_client *client;
-
- input_unregister_handle(handle);
-
- sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
- mousedev->exist = 0;
mixdev_remove_device(mousedev);
-
- if (mousedev->open) {
- input_close_device(handle);
- list_for_each_entry(client, &mousedev->client_list, node)
- kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- wake_up_interruptible(&mousedev->wait);
- } else
- mousedev_free(mousedev);
+ input_unregister_handle(handle);
+ mousedev_destroy(mousedev);
}
static const struct input_device_id mousedev_ids[] = {
@@ -822,25 +854,16 @@ static int psaux_registered;
static int __init mousedev_init(void)
{
- struct class_device *cdev;
int error;
+ mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
+ if (IS_ERR(mousedev_mix))
+ return PTR_ERR(mousedev_mix);
+
error = input_register_handler(&mousedev_handler);
- if (error)
+ if (error) {
+ mousedev_destroy(mousedev_mix);
return error;
-
- memset(&mousedev_mix, 0, sizeof(struct mousedev));
- INIT_LIST_HEAD(&mousedev_mix.client_list);
- init_waitqueue_head(&mousedev_mix.wait);
- mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
- mousedev_mix.exist = 1;
- mousedev_mix.minor = MOUSEDEV_MIX;
-
- cdev = class_device_create(&input_class, NULL,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
- if (IS_ERR(cdev)) {
- input_unregister_handler(&mousedev_handler);
- return PTR_ERR(cdev);
}
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -863,9 +886,8 @@ static void __exit mousedev_exit(void)
if (psaux_registered)
misc_deregister(&psaux_mouse);
#endif
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
input_unregister_handler(&mousedev_handler);
+ mousedev_destroy(mousedev_mix);
}
module_init(mousedev_init);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index f4a2517925e..4fca1e7f267 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -200,6 +200,17 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
},
},
{
+ /*
+ * Like DV4017EA does not raise AUXERR for errors on MUX ports.
+ */
+ .ident = "HP Pavilion ZT1000",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
+ },
+ },
+ {
.ident = "Toshiba P10",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 5895202b972..a8f3bc1dff2 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -769,8 +769,10 @@ static int serio_driver_remove(struct device *dev)
static void serio_cleanup(struct serio *serio)
{
+ mutex_lock(&serio->drv_mutex);
if (serio->drv && serio->drv->cleanup)
serio->drv->cleanup(serio);
+ mutex_unlock(&serio->drv_mutex);
}
static void serio_shutdown(struct device *dev)
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 887357666c6..0403622ae26 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -160,7 +160,7 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t cou
{
struct serio_raw_list *list = file->private_data;
struct serio_raw *serio_raw = list->serio_raw;
- char c;
+ char uninitialized_var(c);
ssize_t retval = 0;
if (!serio_raw->serio)
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index cc0a498763d..94683f58c9e 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -82,8 +82,8 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.5 (May-15-2004)"
-#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio"
+#define DRIVER_VERSION "v2.3 (May 2, 2007)"
+#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio/Cedric Brun/Rene van Paassen"
#define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)"
/*
@@ -112,7 +112,7 @@
* (returned as Report 3 - absolute coordinates from the mouse)
*
* bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
- * byte0 0 0 0 0 0 0 1 0
+ * byte0 0 0 0 0 0 0 1 1
* byte1 X7 X6 X5 X4 X3 X2 X1 X0
* byte2 X15 X14 X13 X12 X11 X10 X9 X8
* byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
@@ -134,7 +134,7 @@
* (returned as Report 5 - macrokeys from the mouse)
*
* bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
- * byte0 0 0 0 0 0 1 0 0
+ * byte0 0 0 0 0 0 1 0 1
* byte1 0 0 0 BS2 BS Tip IR DV
* byte2 0 0 0 0 0 0 1 0
* byte3 0 0 0 K4 K3 K2 K1 K0
@@ -218,15 +218,9 @@
#define AIPTEK_WHEEL_DISABLE (-10101)
/* ToolCode values, which BTW are 0x140 .. 0x14f
- * We have things set up such that if TOOL_BUTTON_FIRED_BIT is
- * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx.
- *
- * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will
- * get reset.
+ * We have things set up such that if the tool button has changed,
+ * the tools get reset.
*/
-#define TOOL_BUTTON(x) ((x) & 0x14f)
-#define TOOL_BUTTON_FIRED(x) ((x) & 0x200)
-#define TOOL_BUTTON_FIRED_BIT 0x200
/* toolMode codes
*/
#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN
@@ -264,9 +258,9 @@
/* Mouse button programming
*/
-#define AIPTEK_MOUSE_LEFT_BUTTON 0x01
-#define AIPTEK_MOUSE_RIGHT_BUTTON 0x02
-#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x04
+#define AIPTEK_MOUSE_LEFT_BUTTON 0x04
+#define AIPTEK_MOUSE_RIGHT_BUTTON 0x08
+#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x10
/* Stylus button programming
*/
@@ -294,7 +288,6 @@ struct aiptek_features {
int modelCode; /* Tablet model code (not unique) */
int firmwareCode; /* prom/eeprom version */
char usbPath[64 + 1]; /* device's physical usb path */
- char inputPath[64 + 1]; /* input device path */
};
struct aiptek_settings {
@@ -327,9 +320,32 @@ struct aiptek {
int inDelay; /* jitter: in jitter delay? */
unsigned long endDelay; /* jitter: time when delay ends */
int previousJitterable; /* jitterable prev value */
+
+ int lastMacro; /* macro key to reset */
+ int previousToolMode; /* pen, pencil, brush, etc. tool */
unsigned char *data; /* incoming packet data */
};
+static const int eventTypes[] = {
+ EV_KEY, EV_ABS, EV_REL, EV_MSC,
+};
+
+static const int absEvents[] = {
+ ABS_X, ABS_Y, ABS_PRESSURE, ABS_TILT_X, ABS_TILT_Y,
+ ABS_WHEEL, ABS_MISC,
+};
+
+static const int relEvents[] = {
+ REL_X, REL_Y, REL_WHEEL,
+};
+
+static const int buttonEvents[] = {
+ BTN_LEFT, BTN_RIGHT, BTN_MIDDLE,
+ BTN_TOOL_PEN, BTN_TOOL_RUBBER, BTN_TOOL_PENCIL, BTN_TOOL_AIRBRUSH,
+ BTN_TOOL_BRUSH, BTN_TOOL_MOUSE, BTN_TOOL_LENS, BTN_TOUCH,
+ BTN_STYLUS, BTN_STYLUS2,
+};
+
/*
* Permit easy lookup of keyboard events to send, versus
* the bitmap which comes from the tablet. This hides the
@@ -345,23 +361,39 @@ static const int macroKeyEvents[] = {
};
/***********************************************************************
- * Relative reports deliver values in 2's complement format to
- * deal with negative offsets.
+ * Map values to strings and back. Every map shoudl have the following
+ * as its last element: { NULL, AIPTEK_INVALID_VALUE }.
*/
-static int aiptek_convert_from_2s_complement(unsigned char c)
+#define AIPTEK_INVALID_VALUE -1
+
+struct aiptek_map {
+ const char *string;
+ int value;
+};
+
+static int map_str_to_val(const struct aiptek_map *map, const char *str, size_t count)
{
- int ret;
- unsigned char b = c;
- int negate = 0;
+ const struct aiptek_map *p;
- if ((b & 0x80) != 0) {
- b = ~b;
- b--;
- negate = 1;
- }
- ret = b;
- ret = (negate == 1) ? -ret : ret;
- return ret;
+ if (str[count - 1] == '\n')
+ count--;
+
+ for (p = map; p->string; p++)
+ if (!strncmp(str, p->string, count))
+ return p->value;
+
+ return AIPTEK_INVALID_VALUE;
+}
+
+static const char *map_val_to_str(const struct aiptek_map *map, int val)
+{
+ const struct aiptek_map *p;
+
+ for (p = map; p->value != AIPTEK_INVALID_VALUE; p++)
+ if (val == p->value)
+ return p->string;
+
+ return "unknown";
}
/***********************************************************************
@@ -385,6 +417,9 @@ static int aiptek_convert_from_2s_complement(unsigned char c)
* Proximity. Why two events? I thought it interesting to know if the
* Proximity event occurred while the tablet was in absolute or relative
* mode.
+ * Update: REL_MISC proved not to be such a good idea. With REL_MISC you
+ * get an event transmitted each time. ABS_MISC works better, since it
+ * can be set and re-set. Thus, only using ABS_MISC from now on.
*
* Other tablets use the notion of a certain minimum stylus pressure
* to infer proximity. While that could have been done, that is yet
@@ -441,8 +476,8 @@ static void aiptek_irq(struct urb *urb)
aiptek->diagnostic =
AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE;
} else {
- x = aiptek_convert_from_2s_complement(data[2]);
- y = aiptek_convert_from_2s_complement(data[3]);
+ x = (signed char) data[2];
+ y = (signed char) data[3];
/* jitterable keeps track of whether any button has been pressed.
* We're also using it to remap the physical mouse button mask
@@ -451,18 +486,20 @@ static void aiptek_irq(struct urb *urb)
* that a non-zero value indicates that one or more
* mouse button was pressed.)
*/
- jitterable = data[5] & 0x07;
+ jitterable = data[1] & 0x07;
- left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
- right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
- middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
+ left = (data[1] & aiptek->curSetting.mouseButtonLeft >> 2) != 0 ? 1 : 0;
+ right = (data[1] & aiptek->curSetting.mouseButtonRight >> 2) != 0 ? 1 : 0;
+ middle = (data[1] & aiptek->curSetting.mouseButtonMiddle >> 2) != 0 ? 1 : 0;
input_report_key(inputdev, BTN_LEFT, left);
input_report_key(inputdev, BTN_MIDDLE, middle);
input_report_key(inputdev, BTN_RIGHT, right);
+
+ input_report_abs(inputdev, ABS_MISC,
+ 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
input_report_rel(inputdev, REL_X, x);
input_report_rel(inputdev, REL_Y, y);
- input_report_rel(inputdev, REL_MISC, 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
/* Wheel support is in the form of a single-event
* firing.
@@ -472,6 +509,11 @@ static void aiptek_irq(struct urb *urb)
aiptek->curSetting.wheel);
aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
}
+ if (aiptek->lastMacro != -1) {
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
input_sync(inputdev);
}
}
@@ -489,8 +531,8 @@ static void aiptek_irq(struct urb *urb)
y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
- p = (data[5] & 0x01) != 0 ? 1 : 0;
- dv = (data[5] & 0x02) != 0 ? 1 : 0;
+ dv = (data[5] & 0x01) != 0 ? 1 : 0;
+ p = (data[5] & 0x02) != 0 ? 1 : 0;
tip = (data[5] & 0x04) != 0 ? 1 : 0;
/* Use jitterable to re-arrange button masks
@@ -505,16 +547,18 @@ static void aiptek_irq(struct urb *urb)
* all 'bad' reports...
*/
if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED
- (aiptek->curSetting.toolMode) == 0) {
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
+ aiptek->curSetting.toolMode,
1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
if (p != 0) {
@@ -550,6 +594,11 @@ static void aiptek_irq(struct urb *urb)
}
}
input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS);
+ if (aiptek->lastMacro != -1) {
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
input_sync(inputdev);
}
}
@@ -568,23 +617,25 @@ static void aiptek_irq(struct urb *urb)
jitterable = data[5] & 0x1c;
- p = (data[5] & 0x01) != 0 ? 1 : 0;
- dv = (data[5] & 0x02) != 0 ? 1 : 0;
+ dv = (data[5] & 0x01) != 0 ? 1 : 0;
+ p = (data[5] & 0x02) != 0 ? 1 : 0;
left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED
- (aiptek->curSetting.toolMode) == 0) {
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
+ aiptek->curSetting.toolMode,
1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
if (p != 0) {
@@ -605,7 +656,12 @@ static void aiptek_irq(struct urb *urb)
aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
}
}
- input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+ input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+ if (aiptek->lastMacro != -1) {
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
input_sync(inputdev);
}
}
@@ -615,98 +671,83 @@ static void aiptek_irq(struct urb *urb)
else if (data[0] == 4) {
jitterable = data[1] & 0x18;
- p = (data[1] & 0x01) != 0 ? 1 : 0;
- dv = (data[1] & 0x02) != 0 ? 1 : 0;
+ dv = (data[1] & 0x01) != 0 ? 1 : 0;
+ p = (data[1] & 0x02) != 0 ? 1 : 0;
tip = (data[1] & 0x04) != 0 ? 1 : 0;
bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0;
pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
- macro = data[3];
+ macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1;
z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
- if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ if (dv) {
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
+ aiptek->curSetting.toolMode,
1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
+ }
- if (p != 0) {
- input_report_key(inputdev, BTN_TOUCH, tip);
- input_report_key(inputdev, BTN_STYLUS, bs);
- input_report_key(inputdev, BTN_STYLUS2, pck);
- input_report_abs(inputdev, ABS_PRESSURE, z);
- }
+ if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+ input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
- /* For safety, we're sending key 'break' codes for the
- * neighboring macro keys.
- */
- if (macro > 0) {
- input_report_key(inputdev,
- macroKeyEvents[macro - 1], 0);
- }
- if (macro < 25) {
- input_report_key(inputdev,
- macroKeyEvents[macro + 1], 0);
- }
- input_report_key(inputdev, macroKeyEvents[macro], p);
- input_report_abs(inputdev, ABS_MISC,
- p | AIPTEK_REPORT_TOOL_STYLUS);
- input_sync(inputdev);
+ if (macro != -1 && macro != aiptek->lastMacro) {
+ input_report_key(inputdev, macroKeyEvents[macro], 1);
+ aiptek->lastMacro = macro;
}
+ input_report_abs(inputdev, ABS_MISC,
+ p | AIPTEK_REPORT_TOOL_STYLUS);
+ input_sync(inputdev);
}
/* Report 5s come from the macro keys when pressed by mouse
*/
else if (data[0] == 5) {
jitterable = data[1] & 0x1c;
- p = (data[1] & 0x01) != 0 ? 1 : 0;
- dv = (data[1] & 0x02) != 0 ? 1 : 0;
+ dv = (data[1] & 0x01) != 0 ? 1 : 0;
+ p = (data[1] & 0x02) != 0 ? 1 : 0;
left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
- macro = data[3];
+ macro = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : 0;
- if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ if (dv) {
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
- input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
- 1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
- }
-
- if (p != 0) {
- input_report_key(inputdev, BTN_LEFT, left);
- input_report_key(inputdev, BTN_MIDDLE, middle);
- input_report_key(inputdev, BTN_RIGHT, right);
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
+ input_report_key(inputdev,
+ aiptek->curSetting.toolMode, 1);
+ aiptek->previousToolMode = aiptek->curSetting.toolMode;
}
+ }
- /* For safety, we're sending key 'break' codes for the
- * neighboring macro keys.
- */
- if (macro > 0) {
- input_report_key(inputdev,
- macroKeyEvents[macro - 1], 0);
- }
- if (macro < 25) {
- input_report_key(inputdev,
- macroKeyEvents[macro + 1], 0);
- }
+ if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+ input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
+ if (macro != -1 && macro != aiptek->lastMacro) {
input_report_key(inputdev, macroKeyEvents[macro], 1);
- input_report_rel(inputdev, ABS_MISC,
- p | AIPTEK_REPORT_TOOL_MOUSE);
- input_sync(inputdev);
+ aiptek->lastMacro = macro;
}
+
+ input_report_abs(inputdev, ABS_MISC,
+ p | AIPTEK_REPORT_TOOL_MOUSE);
+ input_sync(inputdev);
}
/* We have no idea which tool can generate a report 6. Theoretically,
* neither need to, having been given reports 4 & 5 for such use.
@@ -725,15 +766,18 @@ static void aiptek_irq(struct urb *urb)
0);
}
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
- */
- if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+ /* If the selected tool changed, reset the old
+ tool key, and set the new one.
+ */
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.
- toolMode), 1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->curSetting.toolMode,
+ 1);
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
input_report_key(inputdev, macroKeyEvents[macro], 1);
@@ -1007,9 +1051,6 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%dx%d\n",
aiptek->inputdev->absmax[ABS_X] + 1,
aiptek->inputdev->absmax[ABS_Y] + 1);
@@ -1024,117 +1065,35 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL);
/***********************************************************************
- * support routines for the 'product_id' file
- */
-static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "0x%04x\n",
- aiptek->inputdev->id.product);
-}
-
-static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor_id' file
- */
-static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor);
-}
-
-static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor' file
- */
-static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
- int retval;
-
- if (aiptek == NULL)
- return 0;
-
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer);
- return retval;
-}
-
-static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL);
-
-/***********************************************************************
- * support routines for the 'product' file
- */
-static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
- int retval;
-
- if (aiptek == NULL)
- return 0;
-
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product);
- return retval;
-}
-
-static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL);
-
-/***********************************************************************
* support routines for the 'pointer_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
+static struct aiptek_map pointer_mode_map[] = {
+ { "stylus", AIPTEK_POINTER_ONLY_STYLUS_MODE },
+ { "mouse", AIPTEK_POINTER_ONLY_MOUSE_MODE },
+ { "either", AIPTEK_POINTER_EITHER_MODE },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.pointerMode) {
- case AIPTEK_POINTER_ONLY_STYLUS_MODE:
- s = "stylus";
- break;
-
- case AIPTEK_POINTER_ONLY_MOUSE_MODE:
- s = "mouse";
- break;
-
- case AIPTEK_POINTER_EITHER_MODE:
- s = "either";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(pointer_mode_map,
+ aiptek->curSetting.pointerMode));
}
static ssize_t
store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
+ int new_mode = map_str_to_val(pointer_mode_map, buf, count);
- if (strcmp(buf, "stylus") == 0) {
- aiptek->newSetting.pointerMode =
- AIPTEK_POINTER_ONLY_STYLUS_MODE;
- } else if (strcmp(buf, "mouse") == 0) {
- aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE;
- } else if (strcmp(buf, "either") == 0) {
- aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE;
- }
+ if (new_mode == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
+
+ aiptek->newSetting.pointerMode = new_mode;
return count;
}
@@ -1146,44 +1105,32 @@ static DEVICE_ATTR(pointer_mode,
* support routines for the 'coordinate_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
+
+static struct aiptek_map coordinate_mode_map[] = {
+ { "absolute", AIPTEK_COORDINATE_ABSOLUTE_MODE },
+ { "relative", AIPTEK_COORDINATE_RELATIVE_MODE },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.coordinateMode) {
- case AIPTEK_COORDINATE_ABSOLUTE_MODE:
- s = "absolute";
- break;
-
- case AIPTEK_COORDINATE_RELATIVE_MODE:
- s = "relative";
- break;
-
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(coordinate_mode_map,
+ aiptek->curSetting.coordinateMode));
}
static ssize_t
store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
+ int new_mode = map_str_to_val(coordinate_mode_map, buf, count);
- if (strcmp(buf, "absolute") == 0) {
- aiptek->newSetting.pointerMode =
- AIPTEK_COORDINATE_ABSOLUTE_MODE;
- } else if (strcmp(buf, "relative") == 0) {
- aiptek->newSetting.pointerMode =
- AIPTEK_COORDINATE_RELATIVE_MODE;
- }
+ if (new_mode == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
+
+ aiptek->newSetting.coordinateMode = new_mode;
return count;
}
@@ -1195,73 +1142,37 @@ static DEVICE_ATTR(coordinate_mode,
* support routines for the 'tool_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
+
+static struct aiptek_map tool_mode_map[] = {
+ { "mouse", AIPTEK_TOOL_BUTTON_MOUSE_MODE },
+ { "eraser", AIPTEK_TOOL_BUTTON_ERASER_MODE },
+ { "pencil", AIPTEK_TOOL_BUTTON_PENCIL_MODE },
+ { "pen", AIPTEK_TOOL_BUTTON_PEN_MODE },
+ { "brush", AIPTEK_TOOL_BUTTON_BRUSH_MODE },
+ { "airbrush", AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE },
+ { "lens", AIPTEK_TOOL_BUTTON_LENS_MODE },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) {
- case AIPTEK_TOOL_BUTTON_MOUSE_MODE:
- s = "mouse";
- break;
-
- case AIPTEK_TOOL_BUTTON_ERASER_MODE:
- s = "eraser";
- break;
-
- case AIPTEK_TOOL_BUTTON_PENCIL_MODE:
- s = "pencil";
- break;
-
- case AIPTEK_TOOL_BUTTON_PEN_MODE:
- s = "pen";
- break;
-
- case AIPTEK_TOOL_BUTTON_BRUSH_MODE:
- s = "brush";
- break;
-
- case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE:
- s = "airbrush";
- break;
-
- case AIPTEK_TOOL_BUTTON_LENS_MODE:
- s = "lens";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(tool_mode_map,
+ aiptek->curSetting.toolMode));
}
static ssize_t
store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
+ int new_mode = map_str_to_val(tool_mode_map, buf, count);
- if (strcmp(buf, "mouse") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE;
- } else if (strcmp(buf, "eraser") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE;
- } else if (strcmp(buf, "pencil") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE;
- } else if (strcmp(buf, "pen") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE;
- } else if (strcmp(buf, "brush") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE;
- } else if (strcmp(buf, "airbrush") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE;
- } else if (strcmp(buf, "lens") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE;
- }
+ if (new_mode == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
+ aiptek->newSetting.toolMode = new_mode;
return count;
}
@@ -1277,9 +1188,6 @@ static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *att
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
} else {
@@ -1294,9 +1202,6 @@ store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char
struct aiptek *aiptek = dev_get_drvdata(dev);
int x;
- if (aiptek == NULL)
- return 0;
-
if (strcmp(buf, "disable") == 0) {
aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE;
} else {
@@ -1319,9 +1224,6 @@ static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *att
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
} else {
@@ -1336,9 +1238,6 @@ store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char
struct aiptek *aiptek = dev_get_drvdata(dev);
int y;
- if (aiptek == NULL)
- return 0;
-
if (strcmp(buf, "disable") == 0) {
aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE;
} else {
@@ -1361,9 +1260,6 @@ static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribut
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay);
}
@@ -1372,9 +1268,6 @@ store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10);
return count;
}
@@ -1391,9 +1284,6 @@ static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_at
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%d\n",
aiptek->curSetting.programmableDelay);
}
@@ -1403,9 +1293,6 @@ store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr,
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10);
return count;
}
@@ -1415,23 +1302,6 @@ static DEVICE_ATTR(delay,
show_tabletProgrammableDelay, store_tabletProgrammableDelay);
/***********************************************************************
- * support routines for the 'input_path' file. Note that this file
- * only displays current setting.
- */
-static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "/dev/input/%s\n",
- aiptek->features.inputPath);
-}
-
-static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL);
-
-/***********************************************************************
* support routines for the 'event_count' file. Note that this file
* only displays current setting.
*/
@@ -1439,9 +1309,6 @@ static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attri
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount);
}
@@ -1456,9 +1323,6 @@ static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_at
struct aiptek *aiptek = dev_get_drvdata(dev);
char *retMsg;
- if (aiptek == NULL)
- return 0;
-
switch (aiptek->diagnostic) {
case AIPTEK_DIAGNOSTIC_NA:
retMsg = "no errors\n";
@@ -1493,45 +1357,32 @@ static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL);
* support routines for the 'stylus_upper' file. Note that this file
* both displays current setting and allows for setting changing.
*/
+
+static struct aiptek_map stylus_button_map[] = {
+ { "upper", AIPTEK_STYLUS_UPPER_BUTTON },
+ { "lower", AIPTEK_STYLUS_LOWER_BUTTON },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.stylusButtonUpper) {
- case AIPTEK_STYLUS_UPPER_BUTTON:
- s = "upper";
- break;
-
- case AIPTEK_STYLUS_LOWER_BUTTON:
- s = "lower";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(stylus_button_map,
+ aiptek->curSetting.stylusButtonUpper));
}
static ssize_t
store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(stylus_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "upper") == 0) {
- aiptek->newSetting.stylusButtonUpper =
- AIPTEK_STYLUS_UPPER_BUTTON;
- } else if (strcmp(buf, "lower") == 0) {
- aiptek->newSetting.stylusButtonUpper =
- AIPTEK_STYLUS_LOWER_BUTTON;
- }
+ aiptek->newSetting.stylusButtonUpper = new_button;
return count;
}
@@ -1543,45 +1394,26 @@ static DEVICE_ATTR(stylus_upper,
* support routines for the 'stylus_lower' file. Note that this file
* both displays current setting and allows for setting changing.
*/
+
static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.stylusButtonLower) {
- case AIPTEK_STYLUS_UPPER_BUTTON:
- s = "upper";
- break;
-
- case AIPTEK_STYLUS_LOWER_BUTTON:
- s = "lower";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(stylus_button_map,
+ aiptek->curSetting.stylusButtonLower));
}
static ssize_t
store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(stylus_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "upper") == 0) {
- aiptek->newSetting.stylusButtonLower =
- AIPTEK_STYLUS_UPPER_BUTTON;
- } else if (strcmp(buf, "lower") == 0) {
- aiptek->newSetting.stylusButtonLower =
- AIPTEK_STYLUS_LOWER_BUTTON;
- }
+ aiptek->newSetting.stylusButtonLower = new_button;
return count;
}
@@ -1593,49 +1425,33 @@ static DEVICE_ATTR(stylus_lower,
* support routines for the 'mouse_left' file. Note that this file
* both displays current setting and allows for setting changing.
*/
+
+static struct aiptek_map mouse_button_map[] = {
+ { "left", AIPTEK_MOUSE_LEFT_BUTTON },
+ { "middle", AIPTEK_MOUSE_MIDDLE_BUTTON },
+ { "right", AIPTEK_MOUSE_RIGHT_BUTTON },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.mouseButtonLeft) {
- case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
- break;
-
- case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
- break;
-
- case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(mouse_button_map,
+ aiptek->curSetting.mouseButtonLeft));
}
static ssize_t
store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(mouse_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
- aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON;
- }
+ aiptek->newSetting.mouseButtonLeft = new_button;
return count;
}
@@ -1650,48 +1466,22 @@ static DEVICE_ATTR(mouse_left,
static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.mouseButtonMiddle) {
- case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
- break;
-
- case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
- break;
-
- case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
- break;
-
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(mouse_button_map,
+ aiptek->curSetting.mouseButtonMiddle));
}
static ssize_t
store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(mouse_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
- aiptek->newSetting.mouseButtonMiddle =
- AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonMiddle =
- AIPTEK_MOUSE_RIGHT_BUTTON;
- }
+ aiptek->newSetting.mouseButtonMiddle = new_button;
return count;
}
@@ -1706,47 +1496,22 @@ static DEVICE_ATTR(mouse_middle,
static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.mouseButtonRight) {
- case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
- break;
-
- case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
- break;
- case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
- break;
-
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(mouse_button_map,
+ aiptek->curSetting.mouseButtonRight));
}
static ssize_t
store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(mouse_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
- aiptek->newSetting.mouseButtonRight =
- AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON;
- }
+ aiptek->newSetting.mouseButtonRight = new_button;
return count;
}
@@ -1762,9 +1527,6 @@ static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *att
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
} else {
@@ -1778,9 +1540,6 @@ store_tabletWheel(struct device *dev, struct device_attribute *attr, const char
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10);
return count;
}
@@ -1794,11 +1553,6 @@ static DEVICE_ATTR(wheel,
*/
static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
/* There is nothing useful to display, so a one-line manual
* is in order...
*/
@@ -1811,9 +1565,6 @@ store_tabletExecute(struct device *dev, struct device_attribute *attr, const cha
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
/* We do not care what you write to this file. Merely the action
* of writing to this file triggers a tablet reprogramming.
*/
@@ -1837,9 +1588,6 @@ static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *a
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode);
}
@@ -1853,9 +1601,6 @@ static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode);
}
@@ -1869,86 +1614,39 @@ static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *at
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%04x\n",
aiptek->features.firmwareCode);
}
static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);
-/***********************************************************************
- * This routine removes all existing sysfs files managed by this device
- * driver.
- */
-static void aiptek_delete_files(struct device *dev)
-{
- device_remove_file(dev, &dev_attr_size);
- device_remove_file(dev, &dev_attr_product_id);
- device_remove_file(dev, &dev_attr_vendor_id);
- device_remove_file(dev, &dev_attr_vendor);
- device_remove_file(dev, &dev_attr_product);
- device_remove_file(dev, &dev_attr_pointer_mode);
- device_remove_file(dev, &dev_attr_coordinate_mode);
- device_remove_file(dev, &dev_attr_tool_mode);
- device_remove_file(dev, &dev_attr_xtilt);
- device_remove_file(dev, &dev_attr_ytilt);
- device_remove_file(dev, &dev_attr_jitter);
- device_remove_file(dev, &dev_attr_delay);
- device_remove_file(dev, &dev_attr_input_path);
- device_remove_file(dev, &dev_attr_event_count);
- device_remove_file(dev, &dev_attr_diagnostic);
- device_remove_file(dev, &dev_attr_odm_code);
- device_remove_file(dev, &dev_attr_model_code);
- device_remove_file(dev, &dev_attr_firmware_code);
- device_remove_file(dev, &dev_attr_stylus_lower);
- device_remove_file(dev, &dev_attr_stylus_upper);
- device_remove_file(dev, &dev_attr_mouse_left);
- device_remove_file(dev, &dev_attr_mouse_middle);
- device_remove_file(dev, &dev_attr_mouse_right);
- device_remove_file(dev, &dev_attr_wheel);
- device_remove_file(dev, &dev_attr_execute);
-}
-
-/***********************************************************************
- * This routine creates the sysfs files managed by this device
- * driver.
- */
-static int aiptek_add_files(struct device *dev)
-{
- int ret;
+static struct attribute *aiptek_attributes[] = {
+ &dev_attr_size.attr,
+ &dev_attr_pointer_mode.attr,
+ &dev_attr_coordinate_mode.attr,
+ &dev_attr_tool_mode.attr,
+ &dev_attr_xtilt.attr,
+ &dev_attr_ytilt.attr,
+ &dev_attr_jitter.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_event_count.attr,
+ &dev_attr_diagnostic.attr,
+ &dev_attr_odm_code.attr,
+ &dev_attr_model_code.attr,
+ &dev_attr_firmware_code.attr,
+ &dev_attr_stylus_lower.attr,
+ &dev_attr_stylus_upper.attr,
+ &dev_attr_mouse_left.attr,
+ &dev_attr_mouse_middle.attr,
+ &dev_attr_mouse_right.attr,
+ &dev_attr_wheel.attr,
+ &dev_attr_execute.attr,
+ NULL
+};
- if ((ret = device_create_file(dev, &dev_attr_size)) ||
- (ret = device_create_file(dev, &dev_attr_product_id)) ||
- (ret = device_create_file(dev, &dev_attr_vendor_id)) ||
- (ret = device_create_file(dev, &dev_attr_vendor)) ||
- (ret = device_create_file(dev, &dev_attr_product)) ||
- (ret = device_create_file(dev, &dev_attr_pointer_mode)) ||
- (ret = device_create_file(dev, &dev_attr_coordinate_mode)) ||
- (ret = device_create_file(dev, &dev_attr_tool_mode)) ||
- (ret = device_create_file(dev, &dev_attr_xtilt)) ||
- (ret = device_create_file(dev, &dev_attr_ytilt)) ||
- (ret = device_create_file(dev, &dev_attr_jitter)) ||
- (ret = device_create_file(dev, &dev_attr_delay)) ||
- (ret = device_create_file(dev, &dev_attr_input_path)) ||
- (ret = device_create_file(dev, &dev_attr_event_count)) ||
- (ret = device_create_file(dev, &dev_attr_diagnostic)) ||
- (ret = device_create_file(dev, &dev_attr_odm_code)) ||
- (ret = device_create_file(dev, &dev_attr_model_code)) ||
- (ret = device_create_file(dev, &dev_attr_firmware_code)) ||
- (ret = device_create_file(dev, &dev_attr_stylus_lower)) ||
- (ret = device_create_file(dev, &dev_attr_stylus_upper)) ||
- (ret = device_create_file(dev, &dev_attr_mouse_left)) ||
- (ret = device_create_file(dev, &dev_attr_mouse_middle)) ||
- (ret = device_create_file(dev, &dev_attr_mouse_right)) ||
- (ret = device_create_file(dev, &dev_attr_wheel)) ||
- (ret = device_create_file(dev, &dev_attr_execute))) {
- err("aiptek: killing own sysfs device files\n");
- aiptek_delete_files(dev);
- }
- return ret;
-}
+static struct attribute_group aiptek_attribute_group = {
+ .attrs = aiptek_attributes,
+};
/***********************************************************************
* This routine is called when a tablet has been identified. It basically
@@ -1961,8 +1659,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_endpoint_descriptor *endpoint;
struct aiptek *aiptek;
struct input_dev *inputdev;
- struct input_handle *inputhandle;
- struct list_head *node, *next;
int i;
int speeds[] = { 0,
AIPTEK_PROGRAMMABLE_DELAY_50,
@@ -1984,17 +1680,23 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);
inputdev = input_allocate_device();
- if (!aiptek || !inputdev)
+ if (!aiptek || !inputdev) {
+ warn("aiptek: cannot allocate memory or input device");
goto fail1;
+ }
aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
GFP_ATOMIC, &aiptek->data_dma);
- if (!aiptek->data)
+ if (!aiptek->data) {
+ warn("aiptek: cannot allocate usb buffer");
goto fail1;
+ }
aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!aiptek->urb)
+ if (!aiptek->urb) {
+ warn("aiptek: cannot allocate urb");
goto fail2;
+ }
aiptek->inputdev = inputdev;
aiptek->usbdev = usbdev;
@@ -2002,6 +1704,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek->inDelay = 0;
aiptek->endDelay = 0;
aiptek->previousJitterable = 0;
+ aiptek->lastMacro = -1;
/* Set up the curSettings struct. Said struct contains the current
* programmable parameters. The newSetting struct contains changes
@@ -2054,36 +1757,23 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Now program the capacities of the tablet, in terms of being
* an input device.
*/
- inputdev->evbit[0] |= BIT(EV_KEY)
- | BIT(EV_ABS)
- | BIT(EV_REL)
- | BIT(EV_MSC);
-
- inputdev->absbit[0] |= BIT(ABS_MISC);
+ for (i = 0; i < ARRAY_SIZE(eventTypes); ++i)
+ __set_bit(eventTypes[i], inputdev->evbit);
- inputdev->relbit[0] |=
- (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));
+ for (i = 0; i < ARRAY_SIZE(absEvents); ++i)
+ __set_bit(absEvents[i], inputdev->absbit);
- inputdev->keybit[LONG(BTN_LEFT)] |=
- (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));
+ for (i = 0; i < ARRAY_SIZE(relEvents); ++i)
+ __set_bit(relEvents[i], inputdev->relbit);
- inputdev->keybit[LONG(BTN_DIGI)] |=
- (BIT(BTN_TOOL_PEN) |
- BIT(BTN_TOOL_RUBBER) |
- BIT(BTN_TOOL_PENCIL) |
- BIT(BTN_TOOL_AIRBRUSH) |
- BIT(BTN_TOOL_BRUSH) |
- BIT(BTN_TOOL_MOUSE) |
- BIT(BTN_TOOL_LENS) |
- BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));
+ __set_bit(MSC_SERIAL, inputdev->mscbit);
- inputdev->mscbit[0] = BIT(MSC_SERIAL);
+ /* Set up key and button codes */
+ for (i = 0; i < ARRAY_SIZE(buttonEvents); ++i)
+ __set_bit(buttonEvents[i], inputdev->keybit);
- /* Programming the tablet macro keys needs to be done with a for loop
- * as the keycodes are discontiguous.
- */
for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
- set_bit(macroKeyEvents[i], inputdev->keybit);
+ __set_bit(macroKeyEvents[i], inputdev->keybit);
/*
* Program the input device coordinate capacities. We do not yet
@@ -2134,25 +1824,11 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
}
}
- /* Register the tablet as an Input Device
- */
- err = input_register_device(aiptek->inputdev);
- if (err)
+ /* Murphy says that some day someone will have a tablet that fails the
+ above test. That's you, Frederic Rodrigo */
+ if (i == ARRAY_SIZE(speeds)) {
+ info("input: Aiptek tried all speeds, no sane response");
goto fail2;
-
- /* We now will look for the evdev device which is mapped to
- * the tablet. The partial name is kept in the link list of
- * input_handles associated with this input device.
- * What identifies an evdev input_handler is that it begins
- * with 'event', continues with a digit, and that in turn
- * is mapped to input/eventN.
- */
- list_for_each_safe(node, next, &inputdev->h_list) {
- inputhandle = to_handle(node);
- if (strncmp(inputhandle->name, "event", 5) == 0) {
- strcpy(aiptek->features.inputPath, inputhandle->name);
- break;
- }
}
/* Associate this driver's struct with the usb interface.
@@ -2161,18 +1837,27 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Set up the sysfs files
*/
- aiptek_add_files(&intf->dev);
+ err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group);
+ if (err) {
+ warn("aiptek: cannot create sysfs group err: %d", err);
+ goto fail3;
+ }
- /* Make sure the evdev module is loaded. Assuming evdev IS a module :-)
+ /* Register the tablet as an Input Device
*/
- if (request_module("evdev") != 0)
- info("aiptek: error loading 'evdev' module");
-
+ err = input_register_device(aiptek->inputdev);
+ if (err) {
+ warn("aiptek: input_register_device returned err: %d", err);
+ goto fail4;
+ }
return 0;
+ fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
+ fail3: usb_free_urb(aiptek->urb);
fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
aiptek->data_dma);
- fail1: input_free_device(inputdev);
+ fail1: usb_set_intfdata(intf, NULL);
+ input_free_device(inputdev);
kfree(aiptek);
return err;
}
@@ -2192,7 +1877,7 @@ static void aiptek_disconnect(struct usb_interface *intf)
*/
usb_kill_urb(aiptek->urb);
input_unregister_device(aiptek->inputdev);
- aiptek_delete_files(&intf->dev);
+ sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
usb_free_urb(aiptek->urb);
usb_buffer_free(interface_to_usbdev(intf),
AIPTEK_PACKET_LENGTH,
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index ef01a807ec0..6542edb6f76 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -11,7 +11,7 @@
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
- * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002-2007 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -62,8 +62,9 @@
* - Minor data report fix
* v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
* - where wacom_sys.c deals with system specific code,
- * - and wacom_wac.c deals with Wacom specific code
+ * - and wacom_wac.c deals with Wacom specific code
* - Support Intuos3 4x6
+ * v1.47 (pc) - Added support for Bamboo
*/
/*
@@ -84,7 +85,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.46"
+#define DRIVER_VERSION "v1.47"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -123,6 +124,7 @@ extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wa
extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern __u16 wacom_le16_to_cpu(unsigned char *data);
extern __u16 wacom_be16_to_cpu(unsigned char *data);
extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 83bddef6606..064e123c9b7 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -138,6 +138,12 @@ static void wacom_close(struct input_dev *dev)
usb_kill_urb(wacom->irq);
}
+void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_1) | BIT(BTN_5);
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+}
+
void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->evbit[0] |= BIT(EV_MSC);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 7661f03a2db..fc03ba256f4 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -178,7 +178,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
case 2: /* Mouse with wheel */
wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
- if (wacom->features->type == WACOM_G4) {
+ if (wacom->features->type == WACOM_G4 ||
+ wacom->features->type == WACOM_MO) {
rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
wacom_report_rel(wcombo, REL_WHEEL, -rw);
} else
@@ -190,7 +191,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
id = CURSOR_DEVICE_ID;
wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
- if (wacom->features->type == WACOM_G4)
+ if (wacom->features->type == WACOM_G4 ||
+ wacom->features->type == WACOM_MO)
wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);
else
wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
@@ -226,7 +228,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
}
/* send pad data */
- if (wacom->features->type == WACOM_G4) {
+ switch (wacom->features->type) {
+ case WACOM_G4:
if (data[7] & 0xf8) {
wacom_input_sync(wcombo); /* sync last event */
wacom->id[1] = 1;
@@ -247,6 +250,33 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_abs(wcombo, ABS_MISC, 0);
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
}
+ break;
+ case WACOM_MO:
+ if ((data[7] & 0xf8) || (data[8] & 0x80)) {
+ wacom_input_sync(wcombo); /* sync last event */
+ wacom->id[1] = 1;
+ wacom->serial[1] = (data[7] & 0xf8);
+ wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+ wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+ wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+ wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+ wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+ wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+ wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+ wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+ } else if (wacom->id[1]) {
+ wacom_input_sync(wcombo); /* sync last event */
+ wacom->id[1] = 0;
+ wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+ wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+ wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+ wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+ wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+ wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+ wacom_report_abs(wcombo, ABS_MISC, 0);
+ wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+ }
+ break;
}
return 1;
}
@@ -331,7 +361,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_EXTRA, 0);
wacom_report_abs(wcombo, ABS_THROTTLE, 0);
wacom_report_abs(wcombo, ABS_RZ, 0);
- } else {
+ } else {
wacom_report_abs(wcombo, ABS_PRESSURE, 0);
wacom_report_abs(wcombo, ABS_TILT_X, 0);
wacom_report_abs(wcombo, ABS_TILT_Y, 0);
@@ -423,9 +453,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
return result-1;
/* Only large I3 and I1 & I2 support Lense Cursor */
- if((wacom->tool[idx] == BTN_TOOL_LENS)
+ if ((wacom->tool[idx] == BTN_TOOL_LENS)
&& ((wacom->features->type == INTUOS3)
- || (wacom->features->type == INTUOS3S)))
+ || (wacom->features->type == INTUOS3S)))
return 0;
/* Cintiq doesn't send data when RDY bit isn't set */
@@ -517,6 +547,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
break;
case WACOM_G4:
case GRAPHIRE:
+ case WACOM_MO:
return (wacom_graphire_irq(wacom_wac, wcombo));
break;
case PTU:
@@ -538,6 +569,8 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
switch (wacom_wac->features->type) {
+ case WACOM_MO:
+ input_dev_mo(input_dev, wacom_wac);
case WACOM_G4:
input_dev_g4(input_dev, wacom_wac);
/* fall through */
@@ -579,6 +612,7 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
{ "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE },
{ "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE },
+ { "Wacom Bamboo", 9, 14760, 9225, 511, 63, WACOM_MO },
{ "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS },
{ "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
{ "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS },
@@ -627,6 +661,7 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index a5e12e8756d..a302e229bb8 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -25,6 +25,7 @@ enum {
INTUOS3,
INTUOS3L,
CINTIQ,
+ WACOM_MO,
MAX_TYPE
};
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index e5cca9bd040..69371779806 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -177,6 +177,7 @@ config TOUCHSCREEN_USB_COMPOSITE
- some other eTurboTouch
- Gunze AHL61
- DMC TSC-10/25
+ - IRTOUCHSYSTEMS/UNITOP
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
@@ -219,4 +220,9 @@ config TOUCHSCREEN_USB_DMC_TSC10
bool "DMC TSC-10/25 device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE
+config TOUCHSCREEN_USB_IRTOUCH
+ default y
+ bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
+ depends on TOUCHSCREEN_USB_COMPOSITE
+
endif
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index e3f22852bd0..b407028ffc5 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -9,6 +9,7 @@
* - eTurboTouch
* - Gunze AHL61
* - DMC TSC-10/25
+ * - IRTOUCHSYSTEMS/UNITOP
*
* Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -110,6 +111,7 @@ enum {
DEVTYPE_ETURBO,
DEVTYPE_GUNZE,
DEVTYPE_DMC_TSC10,
+ DEVTYPE_IRTOUCH,
};
static struct usb_device_id usbtouch_devices[] = {
@@ -150,6 +152,11 @@ static struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
#endif
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+ {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+ {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+#endif
+
{}
};
@@ -416,6 +423,21 @@ static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
/*****************************************************************************
+ * IRTOUCH Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+ dev->x = (pkt[3] << 8) | pkt[2];
+ dev->y = (pkt[5] << 8) | pkt[4];
+ dev->touch = (pkt[1] & 0x03) ? 1 : 0;
+
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
* the different device descriptors
*/
static struct usbtouch_device_info usbtouch_dev_info[] = {
@@ -504,6 +526,17 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.read_data = dmc_tsc10_read_data,
},
#endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+ [DEVTYPE_IRTOUCH] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0fff,
+ .min_yc = 0x0,
+ .max_yc = 0x0fff,
+ .rept_size = 8,
+ .read_data = irtouch_read_data,
+ },
+#endif
};
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 2db364898e1..d2f882e98e5 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -109,9 +109,11 @@ struct tsdev {
int open;
int minor;
char name[8];
+ struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
- struct input_handle handle;
+ struct device dev;
+
int x, y, pressure;
struct ts_calibration cal;
};
@@ -163,9 +165,13 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (!tsdev || !tsdev->exist)
return -ENODEV;
+ get_device(&tsdev->dev);
+
client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_tsdev;
+ }
client->tsdev = tsdev;
client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
@@ -173,19 +179,25 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (!tsdev->open++ && tsdev->exist) {
error = input_open_device(&tsdev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_tsdev:
+ put_device(&tsdev->dev);
+ return error;
}
-static void tsdev_free(struct tsdev *tsdev)
+static void tsdev_free(struct device *dev)
{
+ struct tsdev *tsdev = container_of(dev, struct tsdev, dev);
+
tsdev_table[tsdev->minor] = NULL;
kfree(tsdev);
}
@@ -200,12 +212,10 @@ static int tsdev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--tsdev->open) {
- if (tsdev->exist)
- input_close_device(&tsdev->handle);
- else
- tsdev_free(tsdev);
- }
+ if (!--tsdev->open && tsdev->exist)
+ input_close_device(&tsdev->handle);
+
+ put_device(&tsdev->dev);
return 0;
}
@@ -361,7 +371,7 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
int x, y, tmp;
do_gettimeofday(&time);
- client->event[client->head].millisecs = time.tv_usec / 100;
+ client->event[client->head].millisecs = time.tv_usec / 1000;
client->event[client->head].pressure = tsdev->pressure;
x = tsdev->x;
@@ -388,8 +398,6 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct tsdev *tsdev;
- struct class_device *cdev;
- dev_t devt;
int minor, delta;
int error;
@@ -407,14 +415,13 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
INIT_LIST_HEAD(&tsdev->client_list);
init_waitqueue_head(&tsdev->wait);
- sprintf(tsdev->name, "ts%d", minor);
-
tsdev->exist = 1;
tsdev->minor = minor;
tsdev->handle.dev = dev;
tsdev->handle.name = tsdev->name;
tsdev->handle.handler = handler;
tsdev->handle.private = tsdev;
+ snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
/* Precompute the rough calibration matrix */
delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
@@ -429,36 +436,30 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
tsdev->cal.yscale = (yres << 8) / delta;
tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
- tsdev_table[minor] = tsdev;
-
- devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+ snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id),
+ "ts%d", minor);
+ tsdev->dev.class = &input_class;
+ tsdev->dev.parent = &dev->dev;
+ tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor);
+ tsdev->dev.release = tsdev_free;
+ device_initialize(&tsdev->dev);
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, tsdev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
- goto err_free_tsdev;
- }
+ tsdev_table[minor] = tsdev;
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, tsdev->name);
+ error = device_add(&tsdev->dev);
if (error)
- goto err_cdev_destroy;
+ goto err_free_tsdev;
error = input_register_handle(&tsdev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_tsdev;
return 0;
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
+ err_delete_tsdev:
+ device_del(&tsdev->dev);
err_free_tsdev:
- tsdev_table[minor] = NULL;
- kfree(tsdev);
+ put_device(&tsdev->dev);
return error;
}
@@ -468,10 +469,8 @@ static void tsdev_disconnect(struct input_handle *handle)
struct tsdev_client *client;
input_unregister_handle(handle);
+ device_del(&tsdev->dev);
- sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
tsdev->exist = 0;
if (tsdev->open) {
@@ -479,8 +478,9 @@ static void tsdev_disconnect(struct input_handle *handle)
list_for_each_entry(client, &tsdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&tsdev->wait);
- } else
- tsdev_free(tsdev);
+ }
+
+ put_device(&tsdev->dev);
}
static const struct input_device_id tsdev_ids[] = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2f2fbffafbe..bd601efa7bd 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -34,6 +34,11 @@ config PHANTOM
If you choose to build module, its name will be phantom. If unsure,
say N here.
+config EEPROM_93CX6
+ tristate "EEPROM 93CX6 support"
+ ---help---
+ This is a driver for the EEPROM chipsets 93c46 and 93c66.
+ The driver supports both read as well as write commands.
If unsure, say N.
@@ -187,13 +192,4 @@ config THINKPAD_ACPI_BAY
If you are not sure, say Y here.
-config BLINK
- tristate "Keyboard blink driver"
- help
- Driver that when loaded will blink the keyboard LEDs continuously.
- This is useful for debugging and for kernels that cannot necessarily
- output something to the screen like kexec kernels to give the user
- a visual indication that the kernel is doing something.
-
-
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5b6d46de005..b5ce0e3dba8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/
obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
-obj-$(CONFIG_BLINK) += blink.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
@@ -15,3 +14,4 @@ obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
+obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/blink.c b/drivers/misc/blink.c
deleted file mode 100644
index 97f7253ce2d..00000000000
--- a/drivers/misc/blink.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-
-static void do_blink(unsigned long data);
-
-static DEFINE_TIMER(blink_timer, do_blink, 0 ,0);
-
-static void do_blink(unsigned long data)
-{
- static long count;
- if (panic_blink)
- panic_blink(count++);
- blink_timer.expires = jiffies + msecs_to_jiffies(1);
- add_timer(&blink_timer);
-}
-
-static int blink_panic_event(struct notifier_block *blk,
- unsigned long event, void *arg)
-{
- do_blink(0);
- return 0;
-}
-
-static struct notifier_block blink_notify = {
- .notifier_call = blink_panic_event,
-};
-
-static __init int blink_init(void)
-{
- printk(KERN_INFO "Enabling keyboard blinking\n");
- atomic_notifier_chain_register(&panic_notifier_list, &blink_notify);
- return 0;
-}
-
-static __exit void blink_remove(void)
-{
- del_timer_sync(&blink_timer);
- atomic_notifier_chain_unregister(&panic_notifier_list, &blink_notify);
-}
-
-module_init(blink_init);
-module_exit(blink_remove);
-
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
new file mode 100644
index 00000000000..ea55654e594
--- /dev/null
+++ b/drivers/misc/eeprom_93cx6.c
@@ -0,0 +1,241 @@
+/*
+ Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.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.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Module: eeprom_93cx6
+ Abstract: EEPROM reader routines for 93cx6 chipsets.
+ Supported chipsets: 93c46 & 93c66.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/eeprom_93cx6.h>
+
+MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
+MODULE_LICENSE("GPL");
+
+static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
+{
+ eeprom->reg_data_clock = 1;
+ eeprom->register_write(eeprom);
+
+ /*
+ * Add a short delay for the pulse to work.
+ * According to the specifications the "maximum minimum"
+ * time should be 450ns.
+ */
+ ndelay(450);
+}
+
+static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
+{
+ eeprom->reg_data_clock = 0;
+ eeprom->register_write(eeprom);
+
+ /*
+ * Add a short delay for the pulse to work.
+ * According to the specifications the "maximum minimum"
+ * time should be 450ns.
+ */
+ ndelay(450);
+}
+
+static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
+{
+ /*
+ * Clear all flags, and enable chip select.
+ */
+ eeprom->register_read(eeprom);
+ eeprom->reg_data_in = 0;
+ eeprom->reg_data_out = 0;
+ eeprom->reg_data_clock = 0;
+ eeprom->reg_chip_select = 1;
+ eeprom->register_write(eeprom);
+
+ /*
+ * kick a pulse.
+ */
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
+{
+ /*
+ * Clear chip_select and data_in flags.
+ */
+ eeprom->register_read(eeprom);
+ eeprom->reg_data_in = 0;
+ eeprom->reg_chip_select = 0;
+ eeprom->register_write(eeprom);
+
+ /*
+ * kick a pulse.
+ */
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
+ const u16 data, const u16 count)
+{
+ unsigned int i;
+
+ eeprom->register_read(eeprom);
+
+ /*
+ * Clear data flags.
+ */
+ eeprom->reg_data_in = 0;
+ eeprom->reg_data_out = 0;
+
+ /*
+ * Start writing all bits.
+ */
+ for (i = count; i > 0; i--) {
+ /*
+ * Check if this bit needs to be set.
+ */
+ eeprom->reg_data_in = !!(data & (1 << (i - 1)));
+
+ /*
+ * Write the bit to the eeprom register.
+ */
+ eeprom->register_write(eeprom);
+
+ /*
+ * Kick a pulse.
+ */
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
+ eeprom->reg_data_in = 0;
+ eeprom->register_write(eeprom);
+}
+
+static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
+ u16 *data, const u16 count)
+{
+ unsigned int i;
+ u16 buf = 0;
+
+ eeprom->register_read(eeprom);
+
+ /*
+ * Clear data flags.
+ */
+ eeprom->reg_data_in = 0;
+ eeprom->reg_data_out = 0;
+
+ /*
+ * Start reading all bits.
+ */
+ for (i = count; i > 0; i--) {
+ eeprom_93cx6_pulse_high(eeprom);
+
+ eeprom->register_read(eeprom);
+
+ /*
+ * Clear data_in flag.
+ */
+ eeprom->reg_data_in = 0;
+
+ /*
+ * Read if the bit has been set.
+ */
+ if (eeprom->reg_data_out)
+ buf |= (1 << (i - 1));
+
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
+ *data = buf;
+}
+
+/**
+ * eeprom_93cx6_read - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ *
+ * This function will read the eeprom data as host-endian word
+ * into the given data pointer.
+ */
+void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
+ u16 *data)
+{
+ u16 command;
+
+ /*
+ * Initialize the eeprom register
+ */
+ eeprom_93cx6_startup(eeprom);
+
+ /*
+ * Select the read opcode and the word to be read.
+ */
+ command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
+ eeprom_93cx6_write_bits(eeprom, command,
+ PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+
+ /*
+ * Read the requested 16 bits.
+ */
+ eeprom_93cx6_read_bits(eeprom, data, 16);
+
+ /*
+ * Cleanup eeprom register.
+ */
+ eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
+
+/**
+ * eeprom_93cx6_multiread - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ * @words: Number of words that should be read.
+ *
+ * This function will read all requested words from the eeprom,
+ * this is done by calling eeprom_93cx6_read() multiple times.
+ * But with the additional change that while the eeprom_93cx6_read
+ * will return host ordered bytes, this method will return little
+ * endian words.
+ */
+void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
+ __le16 *data, const u16 words)
+{
+ unsigned int i;
+ u16 tmp;
+
+ for (i = 0; i < words; i++) {
+ tmp = 0;
+ eeprom_93cx6_read(eeprom, word + i, &tmp);
+ data[i] = cpu_to_le16(tmp);
+ }
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
+
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 9320a8c7323..a49cb9737cd 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -14,3 +14,21 @@ config MMC_BLOCK
mount the filesystem. Almost everyone wishing MMC support
should say Y or M here.
+config MMC_BLOCK_BOUNCE
+ bool "Use bounce buffer for simple hosts"
+ depends on MMC_BLOCK
+ default y
+ help
+ SD/MMC is a high latency protocol where it is crucial to
+ send large requests in order to get high performance. Many
+ controllers, however, are restricted to continuous memory
+ (i.e. they can't do scatter-gather), something the kernel
+ rarely can provide.
+
+ Say Y here to help these restricted hosts by bouncing
+ requests back and forth from a large buffer. You will get
+ a big performance gain at the cost of up to 64 KiB of
+ physical memory.
+
+ If unsure, say Y here.
+
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 540ff4bea54..cbd4b6e3e17 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -262,7 +262,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
}
brq.data.sg = mq->sg;
- brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
+ brq.data.sg_len = mmc_queue_map_sg(mq);
+
+ mmc_queue_bounce_pre(mq);
if (brq.data.blocks !=
(req->nr_sectors >> (md->block_bits - 9))) {
@@ -279,6 +281,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
}
mmc_wait_for_req(card->host, &brq.mrq);
+
+ mmc_queue_bounce_post(mq);
+
if (brq.cmd.error) {
printk(KERN_ERR "%s: error %d sending read/write command\n",
req->rq_disk->disk_name, brq.cmd.error);
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index dd97bc79840..4fb2089dc69 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -17,6 +17,8 @@
#include <linux/mmc/host.h>
#include "queue.h"
+#define MMC_QUEUE_BOUNCESZ 65536
+
#define MMC_QUEUE_SUSPENDED (1 << 0)
/*
@@ -118,6 +120,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
struct mmc_host *host = card->host;
u64 limit = BLK_BOUNCE_HIGH;
int ret;
+ unsigned int bouncesz;
if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
limit = *mmc_dev(host)->dma_mask;
@@ -127,21 +130,61 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
if (!mq->queue)
return -ENOMEM;
- blk_queue_prep_rq(mq->queue, mmc_prep_request);
- blk_queue_bounce_limit(mq->queue, limit);
- blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
- blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
- blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
- blk_queue_max_segment_size(mq->queue, host->max_seg_size);
-
mq->queue->queuedata = mq;
mq->req = NULL;
- mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
- GFP_KERNEL);
- if (!mq->sg) {
- ret = -ENOMEM;
- goto cleanup_queue;
+ blk_queue_prep_rq(mq->queue, mmc_prep_request);
+
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+ if (host->max_hw_segs == 1) {
+ bouncesz = MMC_QUEUE_BOUNCESZ;
+
+ if (bouncesz > host->max_req_size)
+ bouncesz = host->max_req_size;
+ if (bouncesz > host->max_seg_size)
+ bouncesz = host->max_seg_size;
+
+ mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+ if (!mq->bounce_buf) {
+ printk(KERN_WARNING "%s: unable to allocate "
+ "bounce buffer\n", mmc_card_name(card));
+ } else {
+ blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
+ blk_queue_max_sectors(mq->queue, bouncesz / 512);
+ blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
+ blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
+ blk_queue_max_segment_size(mq->queue, bouncesz);
+
+ mq->sg = kmalloc(sizeof(struct scatterlist),
+ GFP_KERNEL);
+ if (!mq->sg) {
+ ret = -ENOMEM;
+ goto free_bounce_buf;
+ }
+
+ mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
+ bouncesz / 512, GFP_KERNEL);
+ if (!mq->bounce_sg) {
+ ret = -ENOMEM;
+ goto free_sg;
+ }
+ }
+ }
+#endif
+
+ if (!mq->bounce_buf) {
+ blk_queue_bounce_limit(mq->queue, limit);
+ blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
+ blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
+ blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
+ blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+
+ mq->sg = kmalloc(sizeof(struct scatterlist) *
+ host->max_phys_segs, GFP_KERNEL);
+ if (!mq->sg) {
+ ret = -ENOMEM;
+ goto cleanup_queue;
+ }
}
init_MUTEX(&mq->thread_sem);
@@ -149,14 +192,21 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
if (IS_ERR(mq->thread)) {
ret = PTR_ERR(mq->thread);
- goto free_sg;
+ goto free_bounce_sg;
}
return 0;
-
+ free_bounce_sg:
+ if (mq->bounce_sg)
+ kfree(mq->bounce_sg);
+ mq->bounce_sg = NULL;
free_sg:
kfree(mq->sg);
mq->sg = NULL;
+ free_bounce_buf:
+ if (mq->bounce_buf)
+ kfree(mq->bounce_buf);
+ mq->bounce_buf = NULL;
cleanup_queue:
blk_cleanup_queue(mq->queue);
return ret;
@@ -178,9 +228,17 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
/* Then terminate our worker thread */
kthread_stop(mq->thread);
+ if (mq->bounce_sg)
+ kfree(mq->bounce_sg);
+ mq->bounce_sg = NULL;
+
kfree(mq->sg);
mq->sg = NULL;
+ if (mq->bounce_buf)
+ kfree(mq->bounce_buf);
+ mq->bounce_buf = NULL;
+
blk_cleanup_queue(mq->queue);
mq->card = NULL;
@@ -231,3 +289,108 @@ void mmc_queue_resume(struct mmc_queue *mq)
}
}
+static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
+ struct scatterlist *src, unsigned int src_len)
+{
+ unsigned int chunk;
+ char *dst_buf, *src_buf;
+ unsigned int dst_size, src_size;
+
+ dst_buf = NULL;
+ src_buf = NULL;
+ dst_size = 0;
+ src_size = 0;
+
+ while (src_len) {
+ BUG_ON(dst_len == 0);
+
+ if (dst_size == 0) {
+ dst_buf = page_address(dst->page) + dst->offset;
+ dst_size = dst->length;
+ }
+
+ if (src_size == 0) {
+ src_buf = page_address(src->page) + src->offset;
+ src_size = src->length;
+ }
+
+ chunk = min(dst_size, src_size);
+
+ memcpy(dst_buf, src_buf, chunk);
+
+ dst_buf += chunk;
+ src_buf += chunk;
+ dst_size -= chunk;
+ src_size -= chunk;
+
+ if (dst_size == 0) {
+ dst++;
+ dst_len--;
+ }
+
+ if (src_size == 0) {
+ src++;
+ src_len--;
+ }
+ }
+}
+
+unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
+{
+ unsigned int sg_len;
+
+ if (!mq->bounce_buf)
+ return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
+
+ BUG_ON(!mq->bounce_sg);
+
+ sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);
+
+ mq->bounce_sg_len = sg_len;
+
+ /*
+ * Shortcut in the event we only get a single entry.
+ */
+ if (sg_len == 1) {
+ memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
+ return 1;
+ }
+
+ mq->sg[0].page = virt_to_page(mq->bounce_buf);
+ mq->sg[0].offset = offset_in_page(mq->bounce_buf);
+ mq->sg[0].length = 0;
+
+ while (sg_len) {
+ mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
+ sg_len--;
+ }
+
+ return 1;
+}
+
+void mmc_queue_bounce_pre(struct mmc_queue *mq)
+{
+ if (!mq->bounce_buf)
+ return;
+
+ if (mq->bounce_sg_len == 1)
+ return;
+ if (rq_data_dir(mq->req) != WRITE)
+ return;
+
+ copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len);
+}
+
+void mmc_queue_bounce_post(struct mmc_queue *mq)
+{
+ if (!mq->bounce_buf)
+ return;
+
+ if (mq->bounce_sg_len == 1)
+ return;
+ if (rq_data_dir(mq->req) != READ)
+ return;
+
+ copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1);
+}
+
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 1590b3f3f1f..64e66e0d499 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -14,6 +14,9 @@ struct mmc_queue {
void *data;
struct request_queue *queue;
struct scatterlist *sg;
+ char *bounce_buf;
+ struct scatterlist *bounce_sg;
+ unsigned int bounce_sg_len;
};
extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
@@ -21,4 +24,8 @@ extern void mmc_cleanup_queue(struct mmc_queue *);
extern void mmc_queue_suspend(struct mmc_queue *);
extern void mmc_queue_resume(struct mmc_queue *);
+extern unsigned int mmc_queue_map_sg(struct mmc_queue *);
+extern void mmc_queue_bounce_pre(struct mmc_queue *);
+extern void mmc_queue_bounce_post(struct mmc_queue *);
+
#endif
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 1075b02ae75..3fdd08c7f14 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -7,5 +7,6 @@ ifeq ($(CONFIG_MMC_DEBUG),y)
endif
obj-$(CONFIG_MMC) += mmc_core.o
-mmc_core-y := core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o
+mmc_core-y := core.o sysfs.o bus.o host.o \
+ mmc.o mmc_ops.o sd.o sd_ops.o
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
new file mode 100644
index 00000000000..348b566bf4f
--- /dev/null
+++ b/drivers/mmc/core/bus.c
@@ -0,0 +1,253 @@
+/*
+ * linux/drivers/mmc/core/bus.c
+ *
+ * Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright (C) 2007 Pierre Ossman
+ *
+ * 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.
+ *
+ * MMC card bus driver model
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include "sysfs.h"
+#include "core.h"
+#include "bus.h"
+
+#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev)
+#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
+
+static ssize_t mmc_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mmc_card *card = dev_to_mmc_card(dev);
+
+ switch (card->type) {
+ case MMC_TYPE_MMC:
+ return sprintf(buf, "MMC\n");
+ case MMC_TYPE_SD:
+ return sprintf(buf, "SD\n");
+ default:
+ return -EFAULT;
+ }
+}
+
+static struct device_attribute mmc_dev_attrs[] = {
+ MMC_ATTR_RO(type),
+ __ATTR_NULL,
+};
+
+/*
+ * This currently matches any MMC driver to any MMC card - drivers
+ * themselves make the decision whether to drive this card in their
+ * probe method.
+ */
+static int mmc_bus_match(struct device *dev, struct device_driver *drv)
+{
+ return 1;
+}
+
+static int
+mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
+ int buf_size)
+{
+ struct mmc_card *card = dev_to_mmc_card(dev);
+ int retval = 0, i = 0, length = 0;
+
+#define add_env(fmt,val) do { \
+ retval = add_uevent_var(envp, num_envp, &i, \
+ buf, buf_size, &length, \
+ fmt, val); \
+ if (retval) \
+ return retval; \
+} while (0);
+
+ switch (card->type) {
+ case MMC_TYPE_MMC:
+ add_env("MMC_TYPE=%s", "MMC");
+ break;
+ case MMC_TYPE_SD:
+ add_env("MMC_TYPE=%s", "SD");
+ break;
+ }
+
+ add_env("MMC_NAME=%s", mmc_card_name(card));
+
+#undef add_env
+
+ envp[i] = NULL;
+
+ return 0;
+}
+
+static int mmc_bus_probe(struct device *dev)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = dev_to_mmc_card(dev);
+
+ return drv->probe(card);
+}
+
+static int mmc_bus_remove(struct device *dev)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = dev_to_mmc_card(dev);
+
+ drv->remove(card);
+
+ return 0;
+}
+
+static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = dev_to_mmc_card(dev);
+ int ret = 0;
+
+ if (dev->driver && drv->suspend)
+ ret = drv->suspend(card, state);
+ return ret;
+}
+
+static int mmc_bus_resume(struct device *dev)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = dev_to_mmc_card(dev);
+ int ret = 0;
+
+ if (dev->driver && drv->resume)
+ ret = drv->resume(card);
+ return ret;
+}
+
+static struct bus_type mmc_bus_type = {
+ .name = "mmc",
+ .dev_attrs = mmc_dev_attrs,
+ .match = mmc_bus_match,
+ .uevent = mmc_bus_uevent,
+ .probe = mmc_bus_probe,
+ .remove = mmc_bus_remove,
+ .suspend = mmc_bus_suspend,
+ .resume = mmc_bus_resume,
+};
+
+int mmc_register_bus(void)
+{
+ return bus_register(&mmc_bus_type);
+}
+
+void mmc_unregister_bus(void)
+{
+ bus_unregister(&mmc_bus_type);
+}
+
+/**
+ * mmc_register_driver - register a media driver
+ * @drv: MMC media driver
+ */
+int mmc_register_driver(struct mmc_driver *drv)
+{
+ drv->drv.bus = &mmc_bus_type;
+ return driver_register(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_register_driver);
+
+/**
+ * mmc_unregister_driver - unregister a media driver
+ * @drv: MMC media driver
+ */
+void mmc_unregister_driver(struct mmc_driver *drv)
+{
+ drv->drv.bus = &mmc_bus_type;
+ driver_unregister(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_unregister_driver);
+
+static void mmc_release_card(struct device *dev)
+{
+ struct mmc_card *card = dev_to_mmc_card(dev);
+
+ kfree(card);
+}
+
+/*
+ * Allocate and initialise a new MMC card structure.
+ */
+struct mmc_card *mmc_alloc_card(struct mmc_host *host)
+{
+ struct mmc_card *card;
+
+ card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+ if (!card)
+ return ERR_PTR(-ENOMEM);
+
+ memset(card, 0, sizeof(struct mmc_card));
+
+ card->host = host;
+
+ device_initialize(&card->dev);
+
+ card->dev.parent = mmc_classdev(host);
+ card->dev.bus = &mmc_bus_type;
+ card->dev.release = mmc_release_card;
+
+ return card;
+}
+
+/*
+ * Register a new MMC card with the driver model.
+ */
+int mmc_add_card(struct mmc_card *card)
+{
+ int ret;
+
+ snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+ "%s:%04x", mmc_hostname(card->host), card->rca);
+
+ card->dev.uevent_suppress = 1;
+
+ ret = device_add(&card->dev);
+ if (ret)
+ return ret;
+
+ if (card->host->bus_ops->sysfs_add) {
+ ret = card->host->bus_ops->sysfs_add(card->host, card);
+ if (ret) {
+ device_del(&card->dev);
+ return ret;
+ }
+ }
+
+ card->dev.uevent_suppress = 0;
+
+ kobject_uevent(&card->dev.kobj, KOBJ_ADD);
+
+ mmc_card_set_present(card);
+
+ return 0;
+}
+
+/*
+ * Unregister a new MMC card with the driver model, and
+ * (eventually) free it.
+ */
+void mmc_remove_card(struct mmc_card *card)
+{
+ if (mmc_card_present(card)) {
+ if (card->host->bus_ops->sysfs_remove)
+ card->host->bus_ops->sysfs_remove(card->host, card);
+ device_del(&card->dev);
+ }
+
+ put_device(&card->dev);
+}
+
diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h
new file mode 100644
index 00000000000..4f35431116a
--- /dev/null
+++ b/drivers/mmc/core/bus.h
@@ -0,0 +1,22 @@
+/*
+ * linux/drivers/mmc/core/bus.h
+ *
+ * Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright 2007 Pierre Ossman
+ *
+ * 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.
+ */
+#ifndef _MMC_CORE_BUS_H
+#define _MMC_CORE_BUS_H
+
+struct mmc_card *mmc_alloc_card(struct mmc_host *host);
+int mmc_add_card(struct mmc_card *card);
+void mmc_remove_card(struct mmc_card *card);
+
+int mmc_register_bus(void);
+void mmc_unregister_bus(void);
+
+#endif
+
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7385acfa1dd..b5d8a6d90cc 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -27,7 +27,8 @@
#include <linux/mmc/sd.h>
#include "core.h"
-#include "sysfs.h"
+#include "bus.h"
+#include "host.h"
#include "mmc_ops.h"
#include "sd_ops.h"
@@ -35,6 +36,25 @@
extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
+static struct workqueue_struct *workqueue;
+
+/*
+ * Internal function. Schedule delayed work in the MMC work queue.
+ */
+static int mmc_schedule_delayed_work(struct delayed_work *work,
+ unsigned long delay)
+{
+ return queue_delayed_work(workqueue, work, delay);
+}
+
+/*
+ * Internal function. Flush all scheduled work from the MMC work queue.
+ */
+static void mmc_flush_scheduled_work(void)
+{
+ flush_workqueue(workqueue);
+}
+
/**
* mmc_request_done - finish processing an MMC request
* @host: MMC host which completed request
@@ -369,22 +389,6 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing)
}
/*
- * Allocate a new MMC card
- */
-struct mmc_card *mmc_alloc_card(struct mmc_host *host)
-{
- struct mmc_card *card;
-
- card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
- if (!card)
- return ERR_PTR(-ENOMEM);
-
- mmc_init_card(card, host);
-
- return card;
-}
-
-/*
* Apply power to the MMC stack. This is a two-stage process.
* First, we enable power to the card without the clock running.
* We then wait a bit for the power to stabilise. Finally,
@@ -512,7 +516,7 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay)
EXPORT_SYMBOL(mmc_detect_change);
-static void mmc_rescan(struct work_struct *work)
+void mmc_rescan(struct work_struct *work)
{
struct mmc_host *host =
container_of(work, struct mmc_host, detect.work);
@@ -561,69 +565,13 @@ static void mmc_rescan(struct work_struct *work)
}
}
-
-/**
- * mmc_alloc_host - initialise the per-host structure.
- * @extra: sizeof private data structure
- * @dev: pointer to host device model structure
- *
- * Initialise the per-host structure.
- */
-struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+void mmc_start_host(struct mmc_host *host)
{
- struct mmc_host *host;
-
- host = mmc_alloc_host_sysfs(extra, dev);
- if (host) {
- spin_lock_init(&host->lock);
- init_waitqueue_head(&host->wq);
- INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-
- /*
- * By default, hosts do not support SGIO or large requests.
- * They have to set these according to their abilities.
- */
- host->max_hw_segs = 1;
- host->max_phys_segs = 1;
- host->max_seg_size = PAGE_CACHE_SIZE;
-
- host->max_req_size = PAGE_CACHE_SIZE;
- host->max_blk_size = 512;
- host->max_blk_count = PAGE_CACHE_SIZE / 512;
- }
-
- return host;
-}
-
-EXPORT_SYMBOL(mmc_alloc_host);
-
-/**
- * mmc_add_host - initialise host hardware
- * @host: mmc host
- */
-int mmc_add_host(struct mmc_host *host)
-{
- int ret;
-
- ret = mmc_add_host_sysfs(host);
- if (ret == 0) {
- mmc_power_off(host);
- mmc_detect_change(host, 0);
- }
-
- return ret;
+ mmc_power_off(host);
+ mmc_detect_change(host, 0);
}
-EXPORT_SYMBOL(mmc_add_host);
-
-/**
- * mmc_remove_host - remove host hardware
- * @host: mmc host
- *
- * Unregister and remove all cards associated with this host,
- * and power down the MMC bus.
- */
-void mmc_remove_host(struct mmc_host *host)
+void mmc_stop_host(struct mmc_host *host)
{
#ifdef CONFIG_MMC_DEBUG
unsigned long flags;
@@ -648,24 +596,8 @@ void mmc_remove_host(struct mmc_host *host)
BUG_ON(host->card);
mmc_power_off(host);
- mmc_remove_host_sysfs(host);
}
-EXPORT_SYMBOL(mmc_remove_host);
-
-/**
- * mmc_free_host - free the host structure
- * @host: mmc host
- *
- * Free the host once all references to it have been dropped.
- */
-void mmc_free_host(struct mmc_host *host)
-{
- mmc_free_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_free_host);
-
#ifdef CONFIG_PM
/**
@@ -726,4 +658,31 @@ EXPORT_SYMBOL(mmc_resume_host);
#endif
+static int __init mmc_init(void)
+{
+ int ret;
+
+ workqueue = create_singlethread_workqueue("kmmcd");
+ if (!workqueue)
+ return -ENOMEM;
+
+ ret = mmc_register_bus();
+ if (ret == 0) {
+ ret = mmc_register_host_class();
+ if (ret)
+ mmc_unregister_bus();
+ }
+ return ret;
+}
+
+static void __exit mmc_exit(void)
+{
+ mmc_unregister_host_class();
+ mmc_unregister_bus();
+ destroy_workqueue(workqueue);
+}
+
+module_init(mmc_init);
+module_exit(mmc_exit);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 177264d090a..ae006b30dd8 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -18,6 +18,8 @@
struct mmc_bus_ops {
void (*remove)(struct mmc_host *);
void (*detect)(struct mmc_host *);
+ int (*sysfs_add)(struct mmc_host *, struct mmc_card *card);
+ void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card);
void (*suspend)(struct mmc_host *);
void (*resume)(struct mmc_host *);
};
@@ -54,8 +56,6 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
void mmc_set_timing(struct mmc_host *host, unsigned int timing);
-struct mmc_card *mmc_alloc_card(struct mmc_host *host);
-
static inline void mmc_delay(unsigned int ms)
{
if (ms < 1000 / HZ) {
@@ -66,5 +66,9 @@ static inline void mmc_delay(unsigned int ms)
}
}
+void mmc_rescan(struct work_struct *work);
+void mmc_start_host(struct mmc_host *host);
+void mmc_stop_host(struct mmc_host *host);
+
#endif
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
new file mode 100644
index 00000000000..1433d95c40b
--- /dev/null
+++ b/drivers/mmc/core/host.c
@@ -0,0 +1,156 @@
+/*
+ * linux/drivers/mmc/core/host.c
+ *
+ * Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright (C) 2007 Pierre Ossman
+ *
+ * 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.
+ *
+ * MMC host class device management
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/idr.h>
+#include <linux/pagemap.h>
+
+#include <linux/mmc/host.h>
+
+#include "core.h"
+#include "host.h"
+
+#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
+
+static void mmc_host_classdev_release(struct device *dev)
+{
+ struct mmc_host *host = cls_dev_to_mmc_host(dev);
+ kfree(host);
+}
+
+static struct class mmc_host_class = {
+ .name = "mmc_host",
+ .dev_release = mmc_host_classdev_release,
+};
+
+int mmc_register_host_class(void)
+{
+ return class_register(&mmc_host_class);
+}
+
+void mmc_unregister_host_class(void)
+{
+ class_unregister(&mmc_host_class);
+}
+
+static DEFINE_IDR(mmc_host_idr);
+static DEFINE_SPINLOCK(mmc_host_lock);
+
+/**
+ * mmc_alloc_host - initialise the per-host structure.
+ * @extra: sizeof private data structure
+ * @dev: pointer to host device model structure
+ *
+ * Initialise the per-host structure.
+ */
+struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+{
+ struct mmc_host *host;
+
+ host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+ if (!host)
+ return NULL;
+
+ memset(host, 0, sizeof(struct mmc_host) + extra);
+
+ host->parent = dev;
+ host->class_dev.parent = dev;
+ host->class_dev.class = &mmc_host_class;
+ device_initialize(&host->class_dev);
+
+ spin_lock_init(&host->lock);
+ init_waitqueue_head(&host->wq);
+ INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+
+ /*
+ * By default, hosts do not support SGIO or large requests.
+ * They have to set these according to their abilities.
+ */
+ host->max_hw_segs = 1;
+ host->max_phys_segs = 1;
+ host->max_seg_size = PAGE_CACHE_SIZE;
+
+ host->max_req_size = PAGE_CACHE_SIZE;
+ host->max_blk_size = 512;
+ host->max_blk_count = PAGE_CACHE_SIZE / 512;
+
+ return host;
+}
+
+EXPORT_SYMBOL(mmc_alloc_host);
+
+/**
+ * mmc_add_host - initialise host hardware
+ * @host: mmc host
+ */
+int mmc_add_host(struct mmc_host *host)
+{
+ int err;
+
+ if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+ return -ENOMEM;
+
+ spin_lock(&mmc_host_lock);
+ err = idr_get_new(&mmc_host_idr, host, &host->index);
+ spin_unlock(&mmc_host_lock);
+ if (err)
+ return err;
+
+ snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
+ "mmc%d", host->index);
+
+ err = device_add(&host->class_dev);
+ if (err)
+ return err;
+
+ mmc_start_host(host);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(mmc_add_host);
+
+/**
+ * mmc_remove_host - remove host hardware
+ * @host: mmc host
+ *
+ * Unregister and remove all cards associated with this host,
+ * and power down the MMC bus.
+ */
+void mmc_remove_host(struct mmc_host *host)
+{
+ mmc_stop_host(host);
+
+ device_del(&host->class_dev);
+
+ spin_lock(&mmc_host_lock);
+ idr_remove(&mmc_host_idr, host->index);
+ spin_unlock(&mmc_host_lock);
+}
+
+EXPORT_SYMBOL(mmc_remove_host);
+
+/**
+ * mmc_free_host - free the host structure
+ * @host: mmc host
+ *
+ * Free the host once all references to it have been dropped.
+ */
+void mmc_free_host(struct mmc_host *host)
+{
+ put_device(&host->class_dev);
+}
+
+EXPORT_SYMBOL(mmc_free_host);
+
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
new file mode 100644
index 00000000000..c2dc3d2d9f9
--- /dev/null
+++ b/drivers/mmc/core/host.h
@@ -0,0 +1,18 @@
+/*
+ * linux/drivers/mmc/core/host.h
+ *
+ * Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright 2007 Pierre Ossman
+ *
+ * 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.
+ */
+#ifndef _MMC_CORE_HOST_H
+#define _MMC_CORE_HOST_H
+
+int mmc_register_host_class(void);
+void mmc_unregister_host_class(void);
+
+#endif
+
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 42cc2867ed7..66f85bfa8db 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -18,6 +18,7 @@
#include "core.h"
#include "sysfs.h"
+#include "bus.h"
#include "mmc_ops.h"
static const unsigned int tran_exp[] = {
@@ -236,7 +237,7 @@ out:
* In the case of a resume, "curcard" will contain the card
* we're trying to reinitialise.
*/
-static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+static int mmc_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard)
{
struct mmc_card *card;
@@ -413,8 +414,7 @@ static void mmc_detect(struct mmc_host *host)
mmc_release_host(host);
if (err != MMC_ERR_NONE) {
- mmc_remove_card(host->card);
- host->card = NULL;
+ mmc_remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
@@ -422,6 +422,53 @@ static void mmc_detect(struct mmc_host *host)
}
}
+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+ card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+ card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
+
+static struct device_attribute mmc_dev_attrs[] = {
+ MMC_ATTR_RO(cid),
+ MMC_ATTR_RO(csd),
+ MMC_ATTR_RO(date),
+ MMC_ATTR_RO(fwrev),
+ MMC_ATTR_RO(hwrev),
+ MMC_ATTR_RO(manfid),
+ MMC_ATTR_RO(name),
+ MMC_ATTR_RO(oemid),
+ MMC_ATTR_RO(serial),
+ __ATTR_NULL,
+};
+
+/*
+ * Adds sysfs entries as relevant.
+ */
+static int mmc_sysfs_add(struct mmc_host *host, struct mmc_card *card)
+{
+ int ret;
+
+ ret = mmc_add_attrs(card, mmc_dev_attrs);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * Removes the sysfs entries added by mmc_sysfs_add().
+ */
+static void mmc_sysfs_remove(struct mmc_host *host, struct mmc_card *card)
+{
+ mmc_remove_attrs(card, mmc_dev_attrs);
+}
+
#ifdef CONFIG_MMC_UNSAFE_RESUME
/*
@@ -453,11 +500,9 @@ static void mmc_resume(struct mmc_host *host)
mmc_claim_host(host);
- err = mmc_sd_init_card(host, host->ocr, host->card);
+ err = mmc_init_card(host, host->ocr, host->card);
if (err != MMC_ERR_NONE) {
- mmc_remove_card(host->card);
- host->card = NULL;
-
+ mmc_remove(host);
mmc_detach_bus(host);
}
@@ -474,6 +519,8 @@ static void mmc_resume(struct mmc_host *host)
static const struct mmc_bus_ops mmc_ops = {
.remove = mmc_remove,
.detect = mmc_detect,
+ .sysfs_add = mmc_sysfs_add,
+ .sysfs_remove = mmc_sysfs_remove,
.suspend = mmc_suspend,
.resume = mmc_resume,
};
@@ -512,13 +559,13 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
/*
* Detect and init the card.
*/
- err = mmc_sd_init_card(host, host->ocr, NULL);
+ err = mmc_init_card(host, host->ocr, NULL);
if (err != MMC_ERR_NONE)
goto err;
mmc_release_host(host);
- err = mmc_register_card(host->card);
+ err = mmc_add_card(host->card);
if (err)
goto reclaim_host;
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 918477c490b..1240684083f 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -19,11 +19,10 @@
#include "core.h"
#include "sysfs.h"
+#include "bus.h"
#include "mmc_ops.h"
#include "sd_ops.h"
-#include "core.h"
-
static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000,
0, 0, 0, 0
@@ -487,8 +486,7 @@ static void mmc_sd_detect(struct mmc_host *host)
mmc_release_host(host);
if (err != MMC_ERR_NONE) {
- mmc_remove_card(host->card);
- host->card = NULL;
+ mmc_sd_remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
@@ -496,6 +494,55 @@ static void mmc_sd_detect(struct mmc_host *host)
}
}
+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+ card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+ card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR_FN(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
+
+static struct device_attribute mmc_sd_dev_attrs[] = {
+ MMC_ATTR_RO(cid),
+ MMC_ATTR_RO(csd),
+ MMC_ATTR_RO(scr),
+ MMC_ATTR_RO(date),
+ MMC_ATTR_RO(fwrev),
+ MMC_ATTR_RO(hwrev),
+ MMC_ATTR_RO(manfid),
+ MMC_ATTR_RO(name),
+ MMC_ATTR_RO(oemid),
+ MMC_ATTR_RO(serial),
+ __ATTR_NULL,
+};
+
+/*
+ * Adds sysfs entries as relevant.
+ */
+static int mmc_sd_sysfs_add(struct mmc_host *host, struct mmc_card *card)
+{
+ int ret;
+
+ ret = mmc_add_attrs(card, mmc_sd_dev_attrs);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * Removes the sysfs entries added by mmc_sysfs_add().
+ */
+static void mmc_sd_sysfs_remove(struct mmc_host *host, struct mmc_card *card)
+{
+ mmc_remove_attrs(card, mmc_sd_dev_attrs);
+}
+
#ifdef CONFIG_MMC_UNSAFE_RESUME
/*
@@ -529,9 +576,7 @@ static void mmc_sd_resume(struct mmc_host *host)
err = mmc_sd_init_card(host, host->ocr, host->card);
if (err != MMC_ERR_NONE) {
- mmc_remove_card(host->card);
- host->card = NULL;
-
+ mmc_sd_remove(host);
mmc_detach_bus(host);
}
@@ -548,6 +593,8 @@ static void mmc_sd_resume(struct mmc_host *host)
static const struct mmc_bus_ops mmc_sd_ops = {
.remove = mmc_sd_remove,
.detect = mmc_sd_detect,
+ .sysfs_add = mmc_sd_sysfs_add,
+ .sysfs_remove = mmc_sd_sysfs_remove,
.suspend = mmc_sd_suspend,
.resume = mmc_sd_resume,
};
@@ -599,7 +646,7 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
mmc_release_host(host);
- err = mmc_register_card(host->card);
+ err = mmc_add_card(host->card);
if (err)
goto reclaim_host;
diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c
index 843b1fbba55..00a97e70f91 100644
--- a/drivers/mmc/core/sysfs.c
+++ b/drivers/mmc/core/sysfs.c
@@ -2,6 +2,7 @@
* linux/drivers/mmc/core/sysfs.c
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright 2007 Pierre Ossman
*
* 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
@@ -9,352 +10,34 @@
*
* MMC sysfs/driver model support.
*/
-#include <linux/module.h>
-#include <linux/init.h>
#include <linux/device.h>
-#include <linux/idr.h>
-#include <linux/workqueue.h>
#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
#include "sysfs.h"
-#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev)
-#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
-#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
-
-#define MMC_ATTR(name, fmt, args...) \
-static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct mmc_card *card = dev_to_mmc_card(dev); \
- return sprintf(buf, fmt, args); \
-}
-
-MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
- card->raw_cid[2], card->raw_cid[3]);
-MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
- card->raw_csd[2], card->raw_csd[3]);
-MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
-MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
-MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
-MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
-MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
-MMC_ATTR(name, "%s\n", card->cid.prod_name);
-MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
-MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
-
-#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
-
-static struct device_attribute mmc_dev_attrs[] = {
- MMC_ATTR_RO(cid),
- MMC_ATTR_RO(csd),
- MMC_ATTR_RO(date),
- MMC_ATTR_RO(fwrev),
- MMC_ATTR_RO(hwrev),
- MMC_ATTR_RO(manfid),
- MMC_ATTR_RO(name),
- MMC_ATTR_RO(oemid),
- MMC_ATTR_RO(serial),
- __ATTR_NULL
-};
-
-static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
-
-
-static void mmc_release_card(struct device *dev)
-{
- struct mmc_card *card = dev_to_mmc_card(dev);
-
- kfree(card);
-}
-
-/*
- * This currently matches any MMC driver to any MMC card - drivers
- * themselves make the decision whether to drive this card in their
- * probe method.
- */
-static int mmc_bus_match(struct device *dev, struct device_driver *drv)
-{
- return 1;
-}
-
-static int
-mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
- int buf_size)
-{
- struct mmc_card *card = dev_to_mmc_card(dev);
- char ccc[13];
- int retval = 0, i = 0, length = 0;
-
-#define add_env(fmt,val) do { \
- retval = add_uevent_var(envp, num_envp, &i, \
- buf, buf_size, &length, \
- fmt, val); \
- if (retval) \
- return retval; \
-} while (0);
-
- for (i = 0; i < 12; i++)
- ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
- ccc[12] = '\0';
-
- add_env("MMC_CCC=%s", ccc);
- add_env("MMC_MANFID=%06x", card->cid.manfid);
- add_env("MMC_NAME=%s", mmc_card_name(card));
- add_env("MMC_OEMID=%04x", card->cid.oemid);
-#undef add_env
- envp[i] = NULL;
-
- return 0;
-}
-
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
-{
- struct mmc_driver *drv = to_mmc_driver(dev->driver);
- struct mmc_card *card = dev_to_mmc_card(dev);
- int ret = 0;
-
- if (dev->driver && drv->suspend)
- ret = drv->suspend(card, state);
- return ret;
-}
-
-static int mmc_bus_resume(struct device *dev)
-{
- struct mmc_driver *drv = to_mmc_driver(dev->driver);
- struct mmc_card *card = dev_to_mmc_card(dev);
- int ret = 0;
-
- if (dev->driver && drv->resume)
- ret = drv->resume(card);
- return ret;
-}
-
-static int mmc_bus_probe(struct device *dev)
-{
- struct mmc_driver *drv = to_mmc_driver(dev->driver);
- struct mmc_card *card = dev_to_mmc_card(dev);
-
- return drv->probe(card);
-}
-
-static int mmc_bus_remove(struct device *dev)
-{
- struct mmc_driver *drv = to_mmc_driver(dev->driver);
- struct mmc_card *card = dev_to_mmc_card(dev);
-
- drv->remove(card);
-
- return 0;
-}
-
-static struct bus_type mmc_bus_type = {
- .name = "mmc",
- .dev_attrs = mmc_dev_attrs,
- .match = mmc_bus_match,
- .uevent = mmc_bus_uevent,
- .probe = mmc_bus_probe,
- .remove = mmc_bus_remove,
- .suspend = mmc_bus_suspend,
- .resume = mmc_bus_resume,
-};
-
-/**
- * mmc_register_driver - register a media driver
- * @drv: MMC media driver
- */
-int mmc_register_driver(struct mmc_driver *drv)
-{
- drv->drv.bus = &mmc_bus_type;
- return driver_register(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_register_driver);
-
-/**
- * mmc_unregister_driver - unregister a media driver
- * @drv: MMC media driver
- */
-void mmc_unregister_driver(struct mmc_driver *drv)
-{
- drv->drv.bus = &mmc_bus_type;
- driver_unregister(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_unregister_driver);
-
-
-/*
- * Internal function. Initialise a MMC card structure.
- */
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
-{
- memset(card, 0, sizeof(struct mmc_card));
- card->host = host;
- device_initialize(&card->dev);
- card->dev.parent = mmc_classdev(host);
- card->dev.bus = &mmc_bus_type;
- card->dev.release = mmc_release_card;
-}
-
-/*
- * Internal function. Register a new MMC card with the driver model.
- */
-int mmc_register_card(struct mmc_card *card)
+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs)
{
- int ret;
+ int error = 0;
+ int i;
- snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
- "%s:%04x", mmc_hostname(card->host), card->rca);
-
- ret = device_add(&card->dev);
- if (ret == 0) {
- if (mmc_card_sd(card)) {
- ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
- if (ret)
- device_del(&card->dev);
+ for (i = 0; attr_name(attrs[i]); i++) {
+ error = device_create_file(&card->dev, &attrs[i]);
+ if (error) {
+ while (--i >= 0)
+ device_remove_file(&card->dev, &attrs[i]);
+ break;
}
}
- if (ret == 0)
- mmc_card_set_present(card);
- return ret;
-}
-
-/*
- * Internal function. Unregister a new MMC card with the
- * driver model, and (eventually) free it.
- */
-void mmc_remove_card(struct mmc_card *card)
-{
- if (mmc_card_present(card)) {
- if (mmc_card_sd(card))
- device_remove_file(&card->dev, &mmc_dev_attr_scr);
-
- device_del(&card->dev);
- }
-
- put_device(&card->dev);
-}
-
-
-static void mmc_host_classdev_release(struct device *dev)
-{
- struct mmc_host *host = cls_dev_to_mmc_host(dev);
- kfree(host);
-}
-
-static struct class mmc_host_class = {
- .name = "mmc_host",
- .dev_release = mmc_host_classdev_release,
-};
-
-static DEFINE_IDR(mmc_host_idr);
-static DEFINE_SPINLOCK(mmc_host_lock);
-
-/*
- * Internal function. Allocate a new MMC host.
- */
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
-{
- struct mmc_host *host;
-
- host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
- if (host) {
- memset(host, 0, sizeof(struct mmc_host) + extra);
-
- host->parent = dev;
- host->class_dev.parent = dev;
- host->class_dev.class = &mmc_host_class;
- device_initialize(&host->class_dev);
- }
- return host;
+ return error;
}
-/*
- * Internal function. Register a new MMC host with the MMC class.
- */
-int mmc_add_host_sysfs(struct mmc_host *host)
+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs)
{
- int err;
-
- if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
- return -ENOMEM;
-
- spin_lock(&mmc_host_lock);
- err = idr_get_new(&mmc_host_idr, host, &host->index);
- spin_unlock(&mmc_host_lock);
- if (err)
- return err;
-
- snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
- "mmc%d", host->index);
-
- return device_add(&host->class_dev);
-}
+ int i;
-/*
- * Internal function. Unregister a MMC host with the MMC class.
- */
-void mmc_remove_host_sysfs(struct mmc_host *host)
-{
- device_del(&host->class_dev);
-
- spin_lock(&mmc_host_lock);
- idr_remove(&mmc_host_idr, host->index);
- spin_unlock(&mmc_host_lock);
-}
-
-/*
- * Internal function. Free a MMC host.
- */
-void mmc_free_host_sysfs(struct mmc_host *host)
-{
- put_device(&host->class_dev);
-}
-
-static struct workqueue_struct *workqueue;
-
-/*
- * Internal function. Schedule delayed work in the MMC work queue.
- */
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
-{
- return queue_delayed_work(workqueue, work, delay);
-}
-
-/*
- * Internal function. Flush all scheduled work from the MMC work queue.
- */
-void mmc_flush_scheduled_work(void)
-{
- flush_workqueue(workqueue);
-}
-
-static int __init mmc_init(void)
-{
- int ret;
-
- workqueue = create_singlethread_workqueue("kmmcd");
- if (!workqueue)
- return -ENOMEM;
-
- ret = bus_register(&mmc_bus_type);
- if (ret == 0) {
- ret = class_register(&mmc_host_class);
- if (ret)
- bus_unregister(&mmc_bus_type);
- }
- return ret;
-}
-
-static void __exit mmc_exit(void)
-{
- class_unregister(&mmc_host_class);
- bus_unregister(&mmc_bus_type);
- destroy_workqueue(workqueue);
+ for (i = 0; attr_name(attrs[i]); i++)
+ device_remove_file(&card->dev, &attrs[i]);
}
-module_init(mmc_init);
-module_exit(mmc_exit);
diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h
index 80e29b35828..4b8f670bd10 100644
--- a/drivers/mmc/core/sysfs.h
+++ b/drivers/mmc/core/sysfs.h
@@ -11,17 +11,16 @@
#ifndef _MMC_CORE_SYSFS_H
#define _MMC_CORE_SYSFS_H
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
-int mmc_register_card(struct mmc_card *card);
-void mmc_remove_card(struct mmc_card *card);
+#define MMC_ATTR_FN(name, fmt, args...) \
+static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct mmc_card *card = container_of(dev, struct mmc_card, dev);\
+ return sprintf(buf, fmt, args); \
+}
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
-int mmc_add_host_sysfs(struct mmc_host *host);
-void mmc_remove_host_sysfs(struct mmc_host *host);
-void mmc_free_host_sysfs(struct mmc_host *host);
+#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
-int mmc_schedule_work(struct work_struct *work);
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
-void mmc_flush_scheduled_work(void);
+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs);
+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs);
#endif
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 5b00c194b62..28c881895ab 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -78,8 +78,6 @@
#define DRIVER_NAME "at91_mci"
-#undef SUPPORT_4WIRE
-
#define FL_SENT_COMMAND (1 << 0)
#define FL_SENT_STOP (1 << 1)
@@ -131,7 +129,7 @@ struct at91mci_host
/*
* Copy from sg to a dma block - used for transfers
*/
-static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
+static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
{
unsigned int len, i, size;
unsigned *dmabuf = host->buffer;
@@ -180,7 +178,7 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
/*
* Prepare a dma read
*/
-static void at91mci_pre_dma_read(struct at91mci_host *host)
+static void at91_mci_pre_dma_read(struct at91mci_host *host)
{
int i;
struct scatterlist *sg;
@@ -248,7 +246,7 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
/*
* Handle after a dma read
*/
-static void at91mci_post_dma_read(struct at91mci_host *host)
+static void at91_mci_post_dma_read(struct at91mci_host *host)
{
struct mmc_command *cmd;
struct mmc_data *data;
@@ -268,8 +266,6 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
}
while (host->in_use_index < host->transfer_index) {
- unsigned int *buffer;
-
struct scatterlist *sg;
pr_debug("finishing index %d\n", host->in_use_index);
@@ -280,29 +276,31 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
- /* Swap the contents of the buffer */
- buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
- pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
-
data->bytes_xfered += sg->length;
if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
+ unsigned int *buffer;
int index;
+ /* Swap the contents of the buffer */
+ buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+ pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
+
for (index = 0; index < (sg->length / 4); index++)
buffer[index] = swab32(buffer[index]);
+
+ kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
}
- kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
flush_dcache_page(sg->page);
}
/* Is there another transfer to trigger? */
if (host->transfer_index < data->sg_len)
- at91mci_pre_dma_read(host);
+ at91_mci_pre_dma_read(host);
else {
+ at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
}
pr_debug("post dma read done\n");
@@ -323,7 +321,6 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
/* Now wait for cmd ready */
at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
cmd = host->cmd;
if (!cmd) return;
@@ -331,18 +328,53 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
data = cmd->data;
if (!data) return;
+ if (cmd->data->flags & MMC_DATA_MULTI) {
+ pr_debug("multiple write : wait for BLKE...\n");
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
+ } else
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
+
data->bytes_xfered = host->total_length;
}
+/*Handle after command sent ready*/
+static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
+{
+ if (!host->cmd)
+ return 1;
+ else if (!host->cmd->data) {
+ if (host->flags & FL_SENT_STOP) {
+ /*After multi block write, we must wait for NOTBUSY*/
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
+ } else return 1;
+ } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
+ /*After sendding multi-block-write command, start DMA transfer*/
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE);
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
+ }
+
+ /* command not completed, have to wait */
+ return 0;
+}
+
+
/*
* Enable the controller
*/
static void at91_mci_enable(struct at91mci_host *host)
{
+ unsigned int mr;
+
at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
- at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
+ mr = AT91_MCI_PDCMODE | 0x34a;
+
+ if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+ mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
+
+ at91_mci_write(host, AT91_MCI_MR, mr);
/* use Slot A or B (only one at same time) */
at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
@@ -358,9 +390,8 @@ static void at91_mci_disable(struct at91mci_host *host)
/*
* Send a command
- * return the interrupts to enable
*/
-static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
+static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
{
unsigned int cmdr, mr;
unsigned int block_length;
@@ -371,8 +402,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
host->cmd = cmd;
- /* Not sure if this is needed */
-#if 0
+ /* Needed for leaving busy state before CMD1 */
if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
pr_debug("Clearing timeout\n");
at91_mci_write(host, AT91_MCI_ARGR, 0);
@@ -382,7 +412,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
}
}
-#endif
+
cmdr = cmd->opcode;
if (mmc_resp_type(cmd) == MMC_RSP_NONE)
@@ -439,50 +469,48 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
at91_mci_write(host, ATMEL_PDC_TCR, 0);
at91_mci_write(host, ATMEL_PDC_TNPR, 0);
at91_mci_write(host, ATMEL_PDC_TNCR, 0);
+ ier = AT91_MCI_CMDRDY;
+ } else {
+ /* zero block length and PDC mode */
+ mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
+ at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
- at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
- at91_mci_write(host, AT91_MCI_CMDR, cmdr);
- return AT91_MCI_CMDRDY;
- }
-
- mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
- at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
-
- /*
- * Disable the PDC controller
- */
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
- if (cmdr & AT91_MCI_TRCMD_START) {
- data->bytes_xfered = 0;
- host->transfer_index = 0;
- host->in_use_index = 0;
- if (cmdr & AT91_MCI_TRDIR) {
- /*
- * Handle a read
- */
- host->buffer = NULL;
- host->total_length = 0;
-
- at91mci_pre_dma_read(host);
- ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
- }
- else {
- /*
- * Handle a write
- */
- host->total_length = block_length * blocks;
- host->buffer = dma_alloc_coherent(NULL,
- host->total_length,
- &host->physical_address, GFP_KERNEL);
-
- at91mci_sg_to_dma(host, data);
-
- pr_debug("Transmitting %d bytes\n", host->total_length);
+ /*
+ * Disable the PDC controller
+ */
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
- at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
- at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
- ier = AT91_MCI_TXBUFE;
+ if (cmdr & AT91_MCI_TRCMD_START) {
+ data->bytes_xfered = 0;
+ host->transfer_index = 0;
+ host->in_use_index = 0;
+ if (cmdr & AT91_MCI_TRDIR) {
+ /*
+ * Handle a read
+ */
+ host->buffer = NULL;
+ host->total_length = 0;
+
+ at91_mci_pre_dma_read(host);
+ ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
+ }
+ else {
+ /*
+ * Handle a write
+ */
+ host->total_length = block_length * blocks;
+ host->buffer = dma_alloc_coherent(NULL,
+ host->total_length,
+ &host->physical_address, GFP_KERNEL);
+
+ at91_mci_sg_to_dma(host, data);
+
+ pr_debug("Transmitting %d bytes\n", host->total_length);
+
+ at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
+ at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
+ ier = AT91_MCI_CMDRDY;
+ }
}
}
@@ -497,39 +525,24 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
if (cmdr & AT91_MCI_TRCMD_START) {
if (cmdr & AT91_MCI_TRDIR)
at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
- else
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
}
- return ier;
-}
-
-/*
- * Wait for a command to complete
- */
-static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
-{
- unsigned int ier;
-
- ier = at91_mci_send_command(host, cmd);
-
- pr_debug("setting ier to %08X\n", ier);
- /* Stop on errors or the required value */
+ /* Enable selected interrupts */
at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
}
/*
* Process the next step in the request
*/
-static void at91mci_process_next(struct at91mci_host *host)
+static void at91_mci_process_next(struct at91mci_host *host)
{
if (!(host->flags & FL_SENT_COMMAND)) {
host->flags |= FL_SENT_COMMAND;
- at91mci_process_command(host, host->request->cmd);
+ at91_mci_send_command(host, host->request->cmd);
}
else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
host->flags |= FL_SENT_STOP;
- at91mci_process_command(host, host->request->stop);
+ at91_mci_send_command(host, host->request->stop);
}
else
mmc_request_done(host->mmc, host->request);
@@ -538,7 +551,7 @@ static void at91mci_process_next(struct at91mci_host *host)
/*
* Handle a command that has been completed
*/
-static void at91mci_completed_command(struct at91mci_host *host)
+static void at91_mci_completed_command(struct at91mci_host *host)
{
struct mmc_command *cmd = host->cmd;
unsigned int status;
@@ -583,7 +596,7 @@ static void at91mci_completed_command(struct at91mci_host *host)
else
cmd->error = MMC_ERR_NONE;
- at91mci_process_next(host);
+ at91_mci_process_next(host);
}
/*
@@ -595,7 +608,7 @@ static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
host->request = mrq;
host->flags = 0;
- at91mci_process_next(host);
+ at91_mci_process_next(host);
}
/*
@@ -698,29 +711,33 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
at91_mci_handle_transmitted(host);
}
+ if (int_status & AT91_MCI_ENDRX) {
+ pr_debug("ENDRX\n");
+ at91_mci_post_dma_read(host);
+ }
+
if (int_status & AT91_MCI_RXBUFF) {
pr_debug("RX buffer full\n");
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+ at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
+ completed = 1;
}
if (int_status & AT91_MCI_ENDTX)
pr_debug("Transmit has ended\n");
- if (int_status & AT91_MCI_ENDRX) {
- pr_debug("Receive has ended\n");
- at91mci_post_dma_read(host);
- }
-
if (int_status & AT91_MCI_NOTBUSY) {
pr_debug("Card is ready\n");
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+ completed = 1;
}
if (int_status & AT91_MCI_DTIP)
pr_debug("Data transfer in progress\n");
- if (int_status & AT91_MCI_BLKE)
+ if (int_status & AT91_MCI_BLKE) {
pr_debug("Block transfer has ended\n");
+ completed = 1;
+ }
if (int_status & AT91_MCI_TXRDY)
pr_debug("Ready to transmit\n");
@@ -730,14 +747,14 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
if (int_status & AT91_MCI_CMDRDY) {
pr_debug("Command ready\n");
- completed = 1;
+ completed = at91_mci_handle_cmdrdy(host);
}
}
if (completed) {
pr_debug("Completed command\n");
at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
- at91mci_completed_command(host);
+ at91_mci_completed_command(host);
} else
at91_mci_write(host, AT91_MCI_IDR, int_status);
@@ -830,11 +847,11 @@ static int __init at91_mci_probe(struct platform_device *pdev)
host->bus_mode = 0;
host->board = pdev->dev.platform_data;
if (host->board->wire4) {
-#ifdef SUPPORT_4WIRE
- mmc->caps |= MMC_CAP_4_BIT_DATA;
-#else
- printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
-#endif
+ if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+ else
+ printk("AT91 MMC: 4 wire bus mode not supported"
+ " - using 1 wire\n");
}
/*
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a359efdd77e..10d15c39d00 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -70,6 +70,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
.driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE,
},
+ {
+ .vendor = PCI_VENDOR_ID_ENE,
+ .device = PCI_DEVICE_ID_ENE_CB712_SD_2,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE,
+ },
+
{ /* Generic SD host controller */
PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
},
@@ -1022,7 +1030,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
}
- intmask &= SDHCI_INT_BUS_POWER;
+ intmask &= ~SDHCI_INT_BUS_POWER;
if (intmask) {
printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index 78872c3f376..b96ac8e119d 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -84,7 +84,7 @@ static unsigned long __initdata doc_locations[] = {
#elif defined(CONFIG_MOMENCO_OCELOT)
0x2f000000,
0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
##else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index b665e4ac220..f88ebc5b685 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -258,12 +258,6 @@ config MTD_TSUNAMI
help
Support for the flash chip on Tsunami TIG bus.
-config MTD_LASAT
- tristate "LASAT flash device"
- depends on LASAT && MTD_CFI
- help
- Support for the flash chips on the Lasat 100 and 200 boards.
-
config MTD_NETtel
tristate "CFI flash device on SnapGear/SecureEdge"
depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 3acbb5d01ca..970b189271a 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -47,7 +47,6 @@ obj-$(CONFIG_MTD_OCELOT) += ocelot.o
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
obj-$(CONFIG_MTD_PCI) += pci.o
obj-$(CONFIG_MTD_ALCHEMY) += alchemy-flash.o
-obj-$(CONFIG_MTD_LASAT) += lasat.o
obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_IMPA7) += impa7.o
diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c
deleted file mode 100644
index e3437632105..00000000000
--- a/drivers/mtd/maps/lasat.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Flash device on Lasat 100 and 200 boards
- *
- * (C) 2002 Brian Murphy <brian@murphy.dk>
- *
- * 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.
- *
- * $Id: lasat.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/lasat/lasat.h>
-
-static struct mtd_info *lasat_mtd;
-
-static struct mtd_partition partition_info[LASAT_MTD_LAST];
-static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
-
-static void lasat_set_vpp(struct map_info *map, int vpp)
-{
- if (vpp)
- *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
- else
- *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
-}
-
-static struct map_info lasat_map = {
- .name = "LASAT flash",
- .bankwidth = 4,
- .set_vpp = lasat_set_vpp
-};
-
-static int __init init_lasat(void)
-{
- int i;
- /* since we use AMD chips and set_vpp is not implimented
- * for these (yet) we still have to permanently enable flash write */
- printk(KERN_NOTICE "Unprotecting flash\n");
- ENABLE_VPP((&lasat_map));
-
- lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
- lasat_map.virt = ioremap_nocache(
- lasat_map.phys, lasat_board_info.li_flash_size);
- lasat_map.size = lasat_board_info.li_flash_size;
-
- simple_map_init(&lasat_map);
-
- for (i=0; i < LASAT_MTD_LAST; i++)
- partition_info[i].name = lasat_mtd_partnames[i];
-
- lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
-
- if (!lasat_mtd)
- lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
-
- if (lasat_mtd) {
- u32 size, offset = 0;
-
- lasat_mtd->owner = THIS_MODULE;
-
- for (i=0; i < LASAT_MTD_LAST; i++) {
- size = lasat_flash_partition_size(i);
- partition_info[i].size = size;
- partition_info[i].offset = offset;
- offset += size;
- }
-
- add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
- return 0;
- }
-
- iounmap(lasat_map.virt);
- return -ENXIO;
-}
-
-static void __exit cleanup_lasat(void)
-{
- if (lasat_mtd) {
- del_mtd_partitions(lasat_mtd);
- map_destroy(lasat_mtd);
- }
- if (lasat_map.virt) {
- iounmap(lasat_map.virt);
- lasat_map.virt = 0;
- }
-}
-
-module_init(init_lasat);
-module_exit(cleanup_lasat);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Brian Murphy <brian@murphy.dk>");
-MODULE_DESCRIPTION("Lasat Safepipe/Masquerade MTD map driver");
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 595208f965a..17c868034aa 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -59,7 +59,7 @@ static unsigned long __initdata doc_locations[] = {
#elif defined(CONFIG_MOMENCO_OCELOT)
0x2f000000,
0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index f26ca331615..6deb20fc7a0 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -324,7 +324,7 @@ static struct vortex_chip_info {
{"3c980C Python-T",
PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
{"3cSOHO100-TX Hurricane",
- PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+ PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
{"3c555 Laptop Hurricane",
PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, },
{"3c556 Laptop Tornado",
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index a804965e654..58bbc3e6d0d 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -107,11 +107,6 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered mu
#define PFX DRV_NAME ": "
-#ifndef TRUE
-#define FALSE 0
-#define TRUE (!FALSE)
-#endif
-
#define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \
NETIF_MSG_PROBE | \
NETIF_MSG_LINK)
@@ -661,7 +656,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
if (status & (TxOK | TxErr | TxEmpty | SWInt))
cp_tx(cp);
if (status & LinkChg)
- mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
spin_unlock(&cp->lock);
@@ -1188,7 +1183,7 @@ static int cp_open (struct net_device *dev)
goto err_out_hw;
netif_carrier_off(dev);
- mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE);
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
netif_start_queue(dev);
return 0;
@@ -2050,7 +2045,7 @@ static int cp_resume (struct pci_dev *pdev)
spin_lock_irqsave (&cp->lock, flags);
- mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
spin_unlock_irqrestore (&cp->lock, flags);
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 414de5bd228..04ddec0f4c6 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -73,6 +73,9 @@ struct ei_device {
u32 *reg_offset; /* Register mapping table */
spinlock_t page_lock; /* Page register locks */
unsigned long priv; /* Private field to store bus IDs etc. */
+#ifdef AX88796_PLATFORM
+ unsigned char rxcr_base; /* default value for RXCR */
+#endif
};
/* The maximum number of 8390 interrupt service routines called per IRQ. */
@@ -86,11 +89,19 @@ struct ei_device {
/* Some generic ethernet register configurations. */
#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */
#define E8390_RX_IRQ_MASK 0x5
+
+#ifdef AX88796_PLATFORM
+#define E8390_RXCONFIG (ei_status.rxcr_base | 0x04)
+#define E8390_RXOFF (ei_status.rxcr_base | 0x20)
+#else
#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */
#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */
+#endif
+
#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */
#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */
+
/* Register accessed at EN_CMD, the 8390 base addr. */
#define E8390_STOP 0x01 /* Stop and reset the chip */
#define E8390_START 0x02 /* Start the chip, clear reset */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 7d57f4a25dc..b941c74a06c 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3,10 +3,7 @@
# Network device configuration
#
-menu "Network device support"
- depends on NET
-
-config NETDEVICES
+menuconfig NETDEVICES
default y if UML
bool "Network device support"
---help---
@@ -151,11 +148,9 @@ source "drivers/net/phy/Kconfig"
# Ethernet
#
-menu "Ethernet (10 or 100Mbit)"
- depends on !UML
-
-config NET_ETHERNET
+menuconfig NET_ETHERNET
bool "Ethernet (10 or 100Mbit)"
+ depends on !UML
---help---
Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
type of Local Area Network (LAN) in universities and companies.
@@ -180,9 +175,10 @@ config NET_ETHERNET
kernel: saying N will just cause the configurator to skip all
the questions about Ethernet network cards. If unsure, say N.
+if NET_ETHERNET
+
config MII
tristate "Generic Media Independent Interface device support"
- depends on NET_ETHERNET
help
Most ethernet controllers have MII transceiver either as an external
or internal device. It is safe to say Y or M here even if your
@@ -190,7 +186,7 @@ config MII
config MACB
tristate "Atmel MACB support"
- depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263)
+ depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263
select MII
help
The Atmel MACB ethernet interface is found on many AT32 and AT91
@@ -201,9 +197,18 @@ config MACB
source "drivers/net/arm/Kconfig"
+config AX88796
+ tristate "ASIX AX88796 NE2000 clone support"
+ depends on ARM || MIPS
+ select CRC32
+ select MII
+ help
+ AX88796 driver, using platform bus to provide
+ chip detection and resources
+
config MACE
tristate "MACE (Power Mac ethernet) support"
- depends on NET_ETHERNET && PPC_PMAC && PPC32
+ depends on PPC_PMAC && PPC32
select CRC32
help
Power Macintoshes and clones with Ethernet built-in on the
@@ -226,7 +231,7 @@ config MACE_AAUI_PORT
config BMAC
tristate "BMAC (G3 ethernet) support"
- depends on NET_ETHERNET && PPC_PMAC && PPC32
+ depends on PPC_PMAC && PPC32
select CRC32
help
Say Y for support of BMAC Ethernet interfaces. These are used on G3
@@ -237,7 +242,7 @@ config BMAC
config ARIADNE
tristate "Ariadne support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
help
If you have a Village Tronic Ariadne Ethernet adapter, say Y.
Otherwise, say N.
@@ -247,7 +252,7 @@ config ARIADNE
config A2065
tristate "A2065 support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
select CRC32
help
If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
@@ -258,7 +263,7 @@ config A2065
config HYDRA
tristate "Hydra support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
select CRC32
help
If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
@@ -268,7 +273,7 @@ config HYDRA
config ZORRO8390
tristate "Zorro NS8390-based Ethernet support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
select CRC32
help
This driver is for Zorro Ethernet cards using an NS8390-compatible
@@ -281,7 +286,7 @@ config ZORRO8390
config APNE
tristate "PCMCIA NE2000 support"
- depends on NET_ETHERNET && AMIGA_PCMCIA
+ depends on AMIGA_PCMCIA
select CRC32
help
If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
@@ -292,7 +297,7 @@ config APNE
config APOLLO_ELPLUS
tristate "Apollo 3c505 support"
- depends on NET_ETHERNET && APOLLO
+ depends on APOLLO
help
Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
If you don't have one made for Apollos, you can use one from a PC,
@@ -301,7 +306,7 @@ config APOLLO_ELPLUS
config MAC8390
bool "Macintosh NS 8390 based ethernet cards"
- depends on NET_ETHERNET && MAC
+ depends on MAC
select CRC32
help
If you want to include a driver to support Nubus or LC-PDS
@@ -311,7 +316,7 @@ config MAC8390
config MAC89x0
tristate "Macintosh CS89x0 based ethernet cards"
- depends on NET_ETHERNET && MAC
+ depends on MAC
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
Nubus or LC-PDS network (Ethernet) card of this type, say Y and
@@ -324,7 +329,7 @@ config MAC89x0
config MACSONIC
tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
- depends on NET_ETHERNET && MAC
+ depends on MAC
---help---
Support for NatSemi SONIC based Ethernet devices. This includes
the onboard Ethernet in many Quadras as well as some LC-PDS,
@@ -338,7 +343,7 @@ config MACSONIC
config MACMACE
bool "Macintosh (AV) onboard MACE ethernet"
- depends on NET_ETHERNET && MAC
+ depends on MAC
select CRC32
help
Support for the onboard AMD 79C940 MACE Ethernet controller used in
@@ -348,7 +353,7 @@ config MACMACE
config MVME147_NET
tristate "MVME147 (Lance) Ethernet support"
- depends on NET_ETHERNET && MVME147
+ depends on MVME147
select CRC32
help
Support for the on-board Ethernet interface on the Motorola MVME147
@@ -358,7 +363,7 @@ config MVME147_NET
config MVME16x_NET
tristate "MVME16x Ethernet support"
- depends on NET_ETHERNET && MVME16x
+ depends on MVME16x
help
This is the driver for the Ethernet interface on the Motorola
MVME162, 166, 167, 172 and 177 boards. Say Y here to include the
@@ -367,7 +372,7 @@ config MVME16x_NET
config BVME6000_NET
tristate "BVME6000 Ethernet support"
- depends on NET_ETHERNET && BVME6000
+ depends on BVME6000
help
This is the driver for the Ethernet interface on BVME4000 and
BVME6000 VME boards. Say Y here to include the driver for this chip
@@ -376,7 +381,7 @@ config BVME6000_NET
config ATARILANCE
tristate "Atari Lance support"
- depends on NET_ETHERNET && ATARI
+ depends on ATARI
help
Say Y to include support for several Atari Ethernet adapters based
on the AMD Lance chipset: RieblCard (with or without battery), or
@@ -384,7 +389,7 @@ config ATARILANCE
config ATARI_BIONET
tristate "BioNet-100 support"
- depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
+ depends on ATARI && ATARI_ACSI && BROKEN
help
Say Y to include support for BioData's BioNet-100 Ethernet adapter
for the ACSI port. The driver works (has to work...) with a polled
@@ -392,7 +397,7 @@ config ATARI_BIONET
config ATARI_PAMSNET
tristate "PAMsNet support"
- depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
+ depends on ATARI && ATARI_ACSI && BROKEN
help
Say Y to include support for the PAMsNet Ethernet adapter for the
ACSI port ("ACSI node"). The driver works (has to work...) with a
@@ -400,7 +405,7 @@ config ATARI_PAMSNET
config SUN3LANCE
tristate "Sun3/Sun3x on-board LANCE support"
- depends on NET_ETHERNET && (SUN3 || SUN3X)
+ depends on SUN3 || SUN3X
help
Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
featured an AMD Lance 10Mbit Ethernet controller on board; say Y
@@ -413,7 +418,7 @@ config SUN3LANCE
config SUN3_82586
bool "Sun3 on-board Intel 82586 support"
- depends on NET_ETHERNET && SUN3
+ depends on SUN3
help
This driver enables support for the on-board Intel 82586 based
Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note
@@ -422,7 +427,7 @@ config SUN3_82586
config HPLANCE
bool "HP on-board LANCE support"
- depends on NET_ETHERNET && DIO
+ depends on DIO
select CRC32
help
If you want to use the builtin "LANCE" Ethernet controller on an
@@ -430,21 +435,28 @@ config HPLANCE
config LASI_82596
tristate "Lasi ethernet"
- depends on NET_ETHERNET && GSC
+ depends on GSC
help
Say Y here to support the builtin Intel 82596 ethernet controller
found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
+config SNI_82596
+ tristate "SNI RM ethernet"
+ depends on NET_ETHERNET && SNI_RM
+ help
+ Say Y here to support the on-board Intel 82596 ethernet controller
+ built into SNI RM machines.
+
config MIPS_JAZZ_SONIC
tristate "MIPS JAZZ onboard SONIC Ethernet support"
- depends on NET_ETHERNET && MACH_JAZZ
+ depends on MACH_JAZZ
help
This is the driver for the onboard card of MIPS Magnum 4000,
Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
config MIPS_AU1X00_ENET
bool "MIPS AU1000 Ethernet support"
- depends on NET_ETHERNET && SOC_AU1X00
+ depends on SOC_AU1X00
select PHYLIB
select CRC32
help
@@ -453,11 +465,11 @@ config MIPS_AU1X00_ENET
config NET_SB1250_MAC
tristate "SB1250 Ethernet support"
- depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC
+ depends on SIBYTE_SB1xxx_SOC
config SGI_IOC3_ETH
bool "SGI IOC3 Ethernet"
- depends on NET_ETHERNET && PCI && SGI_IP27
+ depends on PCI && SGI_IP27
select CRC32
select MII
help
@@ -487,7 +499,7 @@ config SGI_IOC3_ETH_HW_TX_CSUM
config MIPS_SIM_NET
tristate "MIPS simulator Network device"
- depends on NET_ETHERNET && MIPS_SIM
+ depends on MIPS_SIM
help
The MIPSNET device is a simple Ethernet network device which is
emulated by the MIPS Simulator.
@@ -495,11 +507,11 @@ config MIPS_SIM_NET
config SGI_O2MACE_ETH
tristate "SGI O2 MACE Fast Ethernet support"
- depends on NET_ETHERNET && SGI_IP32=y
+ depends on SGI_IP32=y
config STNIC
tristate "National DP83902AV support"
- depends on NET_ETHERNET && SUPERH
+ depends on SUPERH
select CRC32
help
Support for cards based on the National Semiconductor DP83902AV
@@ -511,7 +523,7 @@ config STNIC
config SUNLANCE
tristate "Sun LANCE support"
- depends on NET_ETHERNET && SBUS
+ depends on SBUS
select CRC32
help
This driver supports the "le" interface present on all 32-bit Sparc
@@ -524,7 +536,7 @@ config SUNLANCE
config HAPPYMEAL
tristate "Sun Happy Meal 10/100baseT support"
- depends on NET_ETHERNET && (SBUS || PCI)
+ depends on SBUS || PCI
select CRC32
help
This driver supports the "hme" interface present on most Ultra
@@ -537,7 +549,7 @@ config HAPPYMEAL
config SUNBMAC
tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
- depends on NET_ETHERNET && SBUS && EXPERIMENTAL
+ depends on SBUS && EXPERIMENTAL
select CRC32
help
This driver supports the "be" interface available as an Sbus option.
@@ -548,7 +560,7 @@ config SUNBMAC
config SUNQE
tristate "Sun QuadEthernet support"
- depends on NET_ETHERNET && SBUS
+ depends on SBUS
select CRC32
help
This driver supports the "qe" 10baseT Ethernet device, available as
@@ -560,7 +572,7 @@ config SUNQE
config SUNGEM
tristate "Sun GEM support"
- depends on NET_ETHERNET && PCI
+ depends on PCI
select CRC32
help
Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
@@ -568,7 +580,7 @@ config SUNGEM
config CASSINI
tristate "Sun Cassini support"
- depends on NET_ETHERNET && PCI
+ depends on PCI
select CRC32
help
Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
@@ -576,7 +588,7 @@ config CASSINI
config NET_VENDOR_3COM
bool "3COM cards"
- depends on NET_ETHERNET && (ISA || EISA || MCA || PCI)
+ depends on ISA || EISA || MCA || PCI
help
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -736,7 +748,7 @@ config TYPHOON
config LANCE
tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
- depends on NET_ETHERNET && ISA && ISA_DMA_API
+ depends on ISA && ISA_DMA_API
help
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
@@ -748,7 +760,7 @@ config LANCE
config NET_VENDOR_SMC
bool "Western Digital/SMC cards"
- depends on NET_ETHERNET && (ISA || MCA || EISA || MAC)
+ depends on ISA || MCA || EISA || MAC
help
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -818,11 +830,27 @@ config ULTRA32
<file:Documentation/networking/net-modules.txt>. The module
will be called smc-ultra32.
+config SMC9194
+ tristate "SMC 9194 support"
+ depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
+ select CRC32
+ ---help---
+ This is support for the SMC9xxx based Ethernet cards. Choose this
+ option if you have a DELL laptop with the docking station, or
+ another SMC9192/9194 based chipset. Say Y if you want it compiled
+ into the kernel, and read the file
+ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module
+ will be called smc9194.
+
config SMC91X
tristate "SMC 91C9x/91C1xxx support"
select CRC32
select MII
- depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN)
+ depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN
help
This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -836,26 +864,10 @@ config SMC91X
module, say M here and read <file:Documentation/kbuild/modules.txt>
as well as <file:Documentation/networking/net-modules.txt>.
-config SMC9194
- tristate "SMC 9194 support"
- depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
- select CRC32
- ---help---
- This is support for the SMC9xxx based Ethernet cards. Choose this
- option if you have a DELL laptop with the docking station, or
- another SMC9192/9194 based chipset. Say Y if you want it compiled
- into the kernel, and read the file
- <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
- will be called smc9194.
-
config NET_NETX
tristate "NetX Ethernet support"
select MII
- depends on NET_ETHERNET && ARCH_NETX
+ depends on ARCH_NETX
help
This is support for the Hilscher netX builtin Ethernet ports
@@ -865,7 +877,7 @@ config NET_NETX
config DM9000
tristate "DM9000 support"
- depends on (ARM || MIPS) && NET_ETHERNET
+ depends on ARM || MIPS
select CRC32
select MII
---help---
@@ -879,7 +891,7 @@ config SMC911X
tristate "SMSC LAN911[5678] support"
select CRC32
select MII
- depends on NET_ETHERNET && ARCH_PXA
+ depends on ARCH_PXA
help
This is a driver for SMSC's LAN911x series of Ethernet chipsets
including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@ -893,7 +905,7 @@ config SMC911X
config NET_VENDOR_RACAL
bool "Racal-Interlan (Micom) NI cards"
- depends on NET_ETHERNET && ISA
+ depends on ISA
help
If you have a network (Ethernet) card belonging to this class, such
as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
@@ -945,7 +957,7 @@ source "drivers/net/tulip/Kconfig"
config AT1700
tristate "AT1700/1720 support (EXPERIMENTAL)"
- depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL
+ depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
@@ -958,7 +970,7 @@ config AT1700
config DEPCA
tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
- depends on NET_ETHERNET && (ISA || EISA || MCA)
+ depends on ISA || EISA || MCA
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
@@ -972,7 +984,7 @@ config DEPCA
config HP100
tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
- depends on NET_ETHERNET && (ISA || EISA || PCI)
+ depends on ISA || EISA || PCI
help
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
@@ -984,7 +996,7 @@ config HP100
config NET_ISA
bool "Other ISA cards"
- depends on NET_ETHERNET && ISA
+ depends on ISA
---help---
If your network (Ethernet) card hasn't been mentioned yet and its
bus system (that's the way the cards talks to the other components
@@ -1147,7 +1159,7 @@ config SEEQ8005
config NE2_MCA
tristate "NE/2 (ne2000 MCA version) support"
- depends on NET_ETHERNET && MCA_LEGACY
+ depends on MCA_LEGACY
select CRC32
help
If you have a network (Ethernet) card of this type, say Y and read
@@ -1160,7 +1172,7 @@ config NE2_MCA
config IBMLANA
tristate "IBM LAN Adapter/A support"
- depends on NET_ETHERNET && MCA && MCA_LEGACY
+ depends on MCA && MCA_LEGACY
---help---
This is a Micro Channel Ethernet adapter. You need to set
CONFIG_MCA to use this driver. It is both available as an in-kernel
@@ -1176,7 +1188,7 @@ config IBMLANA
config IBMVETH
tristate "IBM LAN Virtual Ethernet support"
- depends on NET_ETHERNET && PPC_PSERIES
+ depends on PPC_PSERIES
---help---
This driver supports virtual ethernet adapters on newer IBM iSeries
and pSeries systems.
@@ -1187,7 +1199,7 @@ config IBMVETH
config IBM_EMAC
tristate "PowerPC 4xx on-chip Ethernet support"
- depends on 4xx
+ depends on 4xx && !PPC_MERGE
help
This driver supports the PowerPC 4xx EMAC family of on-chip
Ethernet controllers.
@@ -1257,7 +1269,7 @@ config IBM_EMAC_TAH
config NET_PCI
bool "EISA, VLB, PCI and on board controllers"
- depends on NET_ETHERNET && (ISA || EISA || PCI)
+ depends on ISA || EISA || PCI
help
This is another class of network cards which attach directly to the
bus. If you have one of those, say Y and read the Ethernet-HOWTO,
@@ -1313,6 +1325,7 @@ config AMD8111_ETH
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module
will be called amd8111e.
+
config AMD8111E_NAPI
bool "Enable NAPI support"
depends on AMD8111_ETH
@@ -1778,7 +1791,7 @@ config SC92031
config NET_POCKET
bool "Pocket and portable adapters"
- depends on NET_ETHERNET && PARPORT
+ depends on PARPORT
---help---
Cute little network (Ethernet) devices which attach to the parallel
port ("pocket adapters"), commonly used with laptops. If you have
@@ -1847,14 +1860,14 @@ config DE620
config SGISEEQ
tristate "SGI Seeq ethernet controller support"
- depends on NET_ETHERNET && SGI_IP22
+ depends on SGI_IP22
help
Say Y here if you have an Seeq based Ethernet network card. This is
used in many Silicon Graphics machines.
config DECLANCE
tristate "DEC LANCE ethernet controller support"
- depends on NET_ETHERNET && MACH_DECSTATION
+ depends on MACH_DECSTATION
select CRC32
help
This driver is for the series of Ethernet controllers produced by
@@ -1884,7 +1897,7 @@ config FEC2
config NE_H8300
tristate "NE2000 compatible support for H8/300"
- depends on H8300 && NET_ETHERNET
+ depends on H8300
help
Say Y here if you want to use the NE2000 compatible
controller on the Renesas H8/300 processor.
@@ -1892,7 +1905,7 @@ config NE_H8300
source "drivers/net/fec_8xx/Kconfig"
source "drivers/net/fs_enet/Kconfig"
-endmenu
+endif # NET_ETHERNET
#
# Gigabit Ethernet
@@ -2101,7 +2114,7 @@ config SKGE
with better performance and more complete ethtool support.
It does not support the link failover and network management
- features that "portable" vendor supplied sk98lin driver does.
+ features available in the hardware.
This driver supports adapters based on the original Yukon chipset:
Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
@@ -2114,7 +2127,7 @@ config SKGE
will be called skge. This is recommended.
config SKY2
- tristate "SysKonnect Yukon2 support (EXPERIMENTAL)"
+ tristate "SysKonnect Yukon2 support"
depends on PCI
select CRC32
---help---
@@ -2129,92 +2142,15 @@ config SKY2
To compile this driver as a module, choose M here: the module
will be called sky2. This is recommended.
-config SK98LIN
- tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
- depends on PCI
- ---help---
- Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
- compliant Gigabit Ethernet Adapter.
-
- This driver supports the original Yukon chipset. This driver is
- deprecated and will be removed from the kernel in the near future,
- it has been replaced by the skge driver. skge is cleaner and
- seems to work better.
+config SKY2_DEBUG
+ bool "Debugging interface"
+ depends on SKY2 && DEBUG_FS
+ help
+ This option adds the ability to dump driver state for debugging.
+ The file debugfs/sky2/ethX displays the state of the internal
+ transmit and receive rings.
- This driver does not support the newer Yukon2 chipset. A separate
- driver, sky2, is provided to support Yukon2-based adapters.
-
- The following adapters are supported by this driver:
- - 3Com 3C940 Gigabit LOM Ethernet Adapter
- - 3Com 3C941 Gigabit LOM Ethernet Adapter
- - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2971T Gigabit Ethernet Adapter
- - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
- - EG1032 v2 Instant Gigabit Network Adapter
- - EG1064 v2 Instant Gigabit Network Adapter
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
- - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
- - Marvell RDK-8001 Adapter
- - Marvell RDK-8002 Adapter
- - Marvell RDK-8003 Adapter
- - Marvell RDK-8004 Adapter
- - Marvell RDK-8006 Adapter
- - Marvell RDK-8007 Adapter
- - Marvell RDK-8008 Adapter
- - Marvell RDK-8009 Adapter
- - Marvell RDK-8010 Adapter
- - Marvell RDK-8011 Adapter
- - Marvell RDK-8012 Adapter
- - Marvell RDK-8052 Adapter
- - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
- - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
- - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
- - SK-9521 10/100/1000Base-T Adapter
- - SK-9521 V2.0 10/100/1000Base-T Adapter
- - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
- - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
- - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
- - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
- - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
- - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
- - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
- - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
- - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
- - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
- - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
- - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
- - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
- - SMC EZ Card 1000 (SMC9452TXV.2)
-
- The adapters support Jumbo Frames.
- The dual link adapters support link-failover and dual port features.
- Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support
- the scatter-gather functionality with sendfile(). Please refer to
- <file:Documentation/networking/sk98lin.txt> for more information about
- optional driver parameters.
- Questions concerning this driver may be addressed to:
- <linux@syskonnect.de>
-
- If you want to compile this driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/kbuild/modules.txt>. The module will
- be called sk98lin. This is recommended.
+ If unsure, say N.
config VIA_VELOCITY
tristate "VIA Velocity support"
@@ -2264,6 +2200,16 @@ config TSI108_ETH
To compile this driver as a module, choose M here: the module
will be called tsi108_eth.
+config GELIC_NET
+ tristate "PS3 Gigabit Ethernet driver"
+ depends on PPC_PS3
+ help
+ This driver supports the network device on the PS3 game
+ console. This driver has built-in support for Ethernet.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ps3_gelic.
+
config GIANFAR
tristate "Gianfar Ethernet"
depends on 85xx || 83xx || PPC_86xx
@@ -2303,7 +2249,7 @@ config UGETH_TX_ON_DEMAND
config MV643XX_ETH
tristate "MV-643XX Ethernet support"
- depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MV64X60 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32)
+ depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32)
select MII
help
This driver supports the gigabit Ethernet on the Marvell MV643XX
@@ -2948,8 +2894,6 @@ config NETCONSOLE
If you want to log kernel messages over the network, enable this.
See <file:Documentation/networking/netconsole.txt> for details.
-endif #NETDEVICES
-
config NETPOLL
def_bool NETCONSOLE
@@ -2961,4 +2905,4 @@ config NETPOLL_TRAP
config NET_POLL_CONTROLLER
def_bool NETPOLL
-endmenu
+endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a77affa4f6e..1bbcbedad04 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -60,10 +60,11 @@ obj-$(CONFIG_TIGON3) += tg3.o
obj-$(CONFIG_BNX2) += bnx2.o
spidernet-y += spider_net.o spider_net_ethtool.o
obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o
+obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
+ps3_gelic-objs += ps3_gelic_net.o
obj-$(CONFIG_TC35815) += tc35815.o
obj-$(CONFIG_SKGE) += skge.o
obj-$(CONFIG_SKY2) += sky2.o
-obj-$(CONFIG_SK98LIN) += sk98lin/
obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
@@ -107,6 +108,7 @@ obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o
obj-$(CONFIG_B44) += b44.o
obj-$(CONFIG_FORCEDETH) += forcedeth.o
obj-$(CONFIG_NE_H8300) += ne-h8300.o
+obj-$(CONFIG_AX88796) += ax88796.o
obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
@@ -157,6 +159,7 @@ obj-$(CONFIG_ELPLUS) += 3c505.o
obj-$(CONFIG_AC3200) += ac3200.o 8390.o
obj-$(CONFIG_APRICOT) += 82596.o
obj-$(CONFIG_LASI_82596) += lasi_82596.o
+obj-$(CONFIG_SNI_82596) += sni_82596.o
obj-$(CONFIG_MVME16x_NET) += 82596.o
obj-$(CONFIG_BVME6000_NET) += 82596.o
obj-$(CONFIG_SC92031) += sc92031.o
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 04382f979c9..b78a4e5ceeb 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -159,10 +159,6 @@ static struct pci_device_id acenic_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
-#ifndef SET_NETDEV_DEV
-#define SET_NETDEV_DEV(net, pdev) do{} while(0)
-#endif
-
#define ace_sync_irq(irq) synchronize_irq(irq)
#ifndef offset_in_page
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 678e4f48d36..5bf2d33887a 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -4,7 +4,7 @@
#
config ARM_AM79C961A
bool "ARM EBSA110 AM79C961A support"
- depends on NET_ETHERNET && ARM && ARCH_EBSA110
+ depends on ARM && ARCH_EBSA110
select CRC32
help
If you wish to compile a kernel for the EBSA-110, then you should
@@ -12,21 +12,21 @@ config ARM_AM79C961A
config ARM_ETHER1
tristate "Acorn Ether1 support"
- depends on NET_ETHERNET && ARM && ARCH_ACORN
+ depends on ARM && ARCH_ACORN
help
If you have an Acorn system with one of these (AKA25) network cards,
you should say Y to this option if you wish to use it with Linux.
config ARM_ETHER3
tristate "Acorn/ANT Ether3 support"
- depends on NET_ETHERNET && ARM && ARCH_ACORN
+ depends on ARM && ARCH_ACORN
help
If you have an Acorn system with one of these network cards, you
should say Y to this option if you wish to use it with Linux.
config ARM_ETHERH
tristate "I-cubed EtherH/ANT EtherM support"
- depends on NET_ETHERNET && ARM && ARCH_ACORN
+ depends on ARM && ARCH_ACORN
select CRC32
help
If you have an Acorn system with one of these network cards, you
@@ -34,7 +34,7 @@ config ARM_ETHERH
config ARM_AT91_ETHER
tristate "AT91RM9200 Ethernet support"
- depends on NET_ETHERNET && ARM && ARCH_AT91RM9200
+ depends on ARM && ARCH_AT91RM9200
select MII
help
If you wish to compile a kernel for the AT91RM9200 and enable
@@ -42,7 +42,7 @@ config ARM_AT91_ETHER
config EP93XX_ETH
tristate "EP93xx Ethernet support"
- depends on NET_ETHERNET && ARM && ARCH_EP93XX
+ depends on ARM && ARCH_EP93XX
help
This is a driver for the ethernet hardware included in EP93xx CPUs.
Say Y if you are building a kernel for EP93xx based devices.
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 8f0d7ce503c..2143eeb7a2b 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -634,7 +634,7 @@ static void am79c961_poll_controller(struct net_device *dev)
{
unsigned long flags;
local_irq_save(flags);
- am79c961_interrupt(dev->irq, dev, NULL);
+ am79c961_interrupt(dev->irq, dev);
local_irq_restore(flags);
}
#endif
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index 54714409a09..f7356374a2e 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -295,10 +295,7 @@ int if_up = 0;
/* Setup the DMA counter */
static void
-setup_dma (address, rw_flag, num_blocks)
- void *address;
- unsigned rw_flag;
- int num_blocks;
+setup_dma (void *address, unsigned rw_flag, int num_blocks)
{
WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI |
A1);
@@ -317,9 +314,7 @@ setup_dma (address, rw_flag, num_blocks)
/* Send the first byte of an command block */
static int
-send_first (target, byte)
- int target;
- unsigned char byte;
+send_first (int target, unsigned char byte)
{
rw = READ;
acsi_delay_end(COMMAND_DELAY);
@@ -338,10 +333,7 @@ send_first (target, byte)
/* Send the rest of an command block */
static int
-send_1_5 (lun, command, dma)
- int lun;
- unsigned char *command;
- int dma;
+send_1_5 (int lun, unsigned char *command, int dma)
{
int i, j;
@@ -371,8 +363,7 @@ get_status (void)
/* Calculate the number of received bytes */
static int
-calc_received (start_address)
- void *start_address;
+calc_received (void *start_address)
{
return (int)(
(((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW)
@@ -384,8 +375,7 @@ calc_received (start_address)
/* start() starts the PAM's DMA adaptor */
static void
-start (target)
- int target;
+start (int target)
{
send_first(target, START);
}
@@ -393,8 +383,7 @@ start (target)
/* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */
static int
-stop (target)
- int target;
+stop (int target)
{
int ret = -1;
unsigned char cmd_buffer[5];
@@ -415,8 +404,7 @@ bad:
/* testpkt() returns the number of received packets waiting in the queue */
static int
-testpkt(target)
- int target;
+testpkt(int target)
{
int ret = -1;
@@ -431,9 +419,7 @@ bad:
/* Please note: The buffer is for internal use only but must be defined! */
static int
-inquiry (target, buffer)
- int target;
- unsigned char *buffer;
+inquiry (int target, unsigned char *buffer)
{
int ret = -1;
unsigned char *vbuffer = phys_to_virt((unsigned long)buffer);
@@ -468,9 +454,7 @@ bad:
*/
static HADDR
-*read_hw_addr(target, buffer)
- int target;
- unsigned char *buffer;
+*read_hw_addr(int target, unsigned char *buffer)
{
HADDR *ret = 0;
unsigned char cmd_buffer[5];
@@ -491,9 +475,7 @@ bad:
}
static irqreturn_t
-pamsnet_intr(irq, data, fp)
- int irq;
- void *data;
+pamsnet_intr(int irq, void *data)
{
return IRQ_HANDLED;
}
@@ -501,9 +483,7 @@ pamsnet_intr(irq, data, fp)
/* receivepkt() loads a packet to a given buffer and returns its length */
static int
-receivepkt (target, buffer)
- int target;
- unsigned char *buffer;
+receivepkt (int target, unsigned char *buffer)
{
int ret = -1;
unsigned char cmd_buffer[5];
@@ -526,10 +506,7 @@ bad:
successfully */
static int
-sendpkt (target, buffer, length)
- int target;
- unsigned char *buffer;
- int length;
+sendpkt (int target, unsigned char *buffer, int length)
{
int ret = -1;
unsigned char cmd_buffer[5];
@@ -665,7 +642,8 @@ struct net_device * __init pamsnet_probe (int unit)
there is non-reboot way to recover if something goes wrong.
*/
static int
-pamsnet_open(struct net_device *dev) {
+pamsnet_open(struct net_device *dev)
+{
struct net_local *lp = netdev_priv(dev);
if (pamsnet_debug > 0)
@@ -694,7 +672,8 @@ pamsnet_open(struct net_device *dev) {
}
static int
-pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
+pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
struct net_local *lp = netdev_priv(dev);
unsigned long flags;
@@ -741,7 +720,8 @@ pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
/* We have a good packet(s), get it/them out of the buffers.
*/
static void
-pamsnet_poll_rx(struct net_device *dev) {
+pamsnet_poll_rx(struct net_device *dev)
+{
struct net_local *lp = netdev_priv(dev);
int boguscount;
int pkt_len;
@@ -816,7 +796,8 @@ pamsnet_poll_rx(struct net_device *dev) {
* passes them to the higher layers and restarts the timer.
*/
static void
-pamsnet_tick(unsigned long data) {
+pamsnet_tick(unsigned long data)
+{
struct net_device *dev = (struct net_device *)data;
struct net_local *lp = netdev_priv(dev);
@@ -832,7 +813,8 @@ pamsnet_tick(unsigned long data) {
/* The inverse routine to pamsnet_open().
*/
static int
-pamsnet_close(struct net_device *dev) {
+pamsnet_close(struct net_device *dev)
+{
struct net_local *lp = netdev_priv(dev);
if (pamsnet_debug > 0)
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
index 6862c11ff86..3bb40dd4a41 100644
--- a/drivers/net/atl1/atl1_main.c
+++ b/drivers/net/atl1/atl1_main.c
@@ -634,14 +634,13 @@ static void atl1_intr_tx(struct atl1_adapter *adapter)
struct atl1_buffer *buffer_info;
u16 sw_tpd_next_to_clean;
u16 cmb_tpd_next_to_clean;
- u8 update = 0;
sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
struct tx_packet_desc *tpd;
- update = 1;
+
tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
if (buffer_info->dma) {
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
new file mode 100644
index 00000000000..d19874bf070
--- /dev/null
+++ b/drivers/net/ax88796.c
@@ -0,0 +1,952 @@
+/* drivers/net/ax88796.c
+ *
+ * Copyright 2005,2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Asix AX88796 10/100 Ethernet controller support
+ * Based on ne.c, by Donald Becker, et-al.
+ *
+ * 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.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+#include <net/ax88796.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+static int phy_debug = 0;
+
+/* Rename the lib8390.c functions to show that they are in this driver */
+#define __ei_open ax_ei_open
+#define __ei_close ax_ei_close
+#define __ei_poll ax_ei_poll
+#define __ei_tx_timeout ax_ei_tx_timeout
+#define __ei_interrupt ax_ei_interrupt
+#define ____alloc_ei_netdev ax__alloc_ei_netdev
+#define __NS8390_init ax_NS8390_init
+
+/* force unsigned long back to 'void __iomem *' */
+#define ax_convert_addr(_a) ((void __force __iomem *)(_a))
+
+#define ei_inb(_a) readb(ax_convert_addr(_a))
+#define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
+
+#define ei_inb_p(_a) ei_inb(_a)
+#define ei_outb_p(_v, _a) ei_outb(_v, _a)
+
+/* define EI_SHIFT() to take into account our register offsets */
+#define EI_SHIFT(x) (ei_local->reg_offset[(x)])
+
+/* Ensure we have our RCR base value */
+#define AX88796_PLATFORM
+
+static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
+
+#include "lib8390.c"
+
+#define DRV_NAME "ax88796"
+#define DRV_VERSION "1.00"
+
+/* from ne.c */
+#define NE_CMD EI_SHIFT(0x00)
+#define NE_RESET EI_SHIFT(0x1f)
+#define NE_DATAPORT EI_SHIFT(0x10)
+
+#define NE1SM_START_PG 0x20 /* First page of TX buffer */
+#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
+#define NESM_START_PG 0x40 /* First page of TX buffer */
+#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
+
+/* device private data */
+
+struct ax_device {
+ struct timer_list mii_timer;
+ spinlock_t mii_lock;
+ struct mii_if_info mii;
+
+ u32 msg_enable;
+ void __iomem *map2;
+ struct platform_device *dev;
+ struct resource *mem;
+ struct resource *mem2;
+ struct ax_plat_data *plat;
+
+ unsigned char running;
+ unsigned char resume_open;
+
+ u32 reg_offsets[0x20];
+};
+
+static inline struct ax_device *to_ax_dev(struct net_device *dev)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ return (struct ax_device *)(ei_local+1);
+}
+
+/* ax_initial_check
+ *
+ * do an initial probe for the card to check wether it exists
+ * and is functional
+ */
+
+static int ax_initial_check(struct net_device *dev)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ void __iomem *ioaddr = ei_local->mem;
+ int reg0;
+ int regd;
+
+ reg0 = ei_inb(ioaddr);
+ if (reg0 == 0xFF)
+ return -ENODEV;
+
+ ei_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+ regd = ei_inb(ioaddr + 0x0d);
+ ei_outb(0xff, ioaddr + 0x0d);
+ ei_outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+ ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+ if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
+ ei_outb(reg0, ioaddr);
+ ei_outb(regd, ioaddr + 0x0d); /* Restore the old values. */
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/* Hard reset the card. This used to pause for the same period that a
+ 8390 reset command required, but that shouldn't be necessary. */
+
+static void ax_reset_8390(struct net_device *dev)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ unsigned long reset_start_time = jiffies;
+ void __iomem *addr = (void __iomem *)dev->base_addr;
+
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+ ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
+
+ ei_status.txing = 0;
+ ei_status.dmaing = 0;
+
+ /* This check _should_not_ be necessary, omit eventually. */
+ while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
+ if (jiffies - reset_start_time > 2*HZ/100) {
+ printk(KERN_WARNING "%s: %s did not complete.\n",
+ __FUNCTION__, dev->name);
+ break;
+ }
+ }
+
+ ei_outb(ENISR_RESET, addr + EN0_ISR); /* Ack intr. */
+}
+
+
+static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+ int ring_page)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ void __iomem *nic_base = ei_local->mem;
+
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ if (ei_status.dmaing) {
+ printk(KERN_EMERG "%s: DMAing conflict in %s [DMAstat:%d][irqlock:%d].\n",
+ dev->name, __FUNCTION__,
+ ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+ ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+ ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+ ei_outb(0, nic_base + EN0_RCNTHI);
+ ei_outb(0, nic_base + EN0_RSARLO); /* On page boundary */
+ ei_outb(ring_page, nic_base + EN0_RSARHI);
+ ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+ if (ei_status.word16)
+ readsw(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+ else
+ readsb(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+ ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
+
+ le16_to_cpus(&hdr->count);
+}
+
+
+/* Block input and output, similar to the Crynwr packet driver. If you
+ are porting to a new ethercard, look at the packet driver source for hints.
+ The NEx000 doesn't share the on-board packet memory -- you have to put
+ the packet out through the "remote DMA" dataport using ei_outb. */
+
+static void ax_block_input(struct net_device *dev, int count,
+ struct sk_buff *skb, int ring_offset)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ void __iomem *nic_base = ei_local->mem;
+ char *buf = skb->data;
+
+ if (ei_status.dmaing) {
+ printk(KERN_EMERG "%s: DMAing conflict in ax_block_input "
+ "[DMAstat:%d][irqlock:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+
+ ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+ ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+ ei_outb(count >> 8, nic_base + EN0_RCNTHI);
+ ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
+ ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
+ ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+ if (ei_status.word16) {
+ readsw(nic_base + NE_DATAPORT, buf, count >> 1);
+ if (count & 0x01)
+ buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
+
+ } else {
+ readsb(nic_base + NE_DATAPORT, buf, count);
+ }
+
+ ei_status.dmaing &= ~1;
+}
+
+static void ax_block_output(struct net_device *dev, int count,
+ const unsigned char *buf, const int start_page)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ void __iomem *nic_base = ei_local->mem;
+ unsigned long dma_start;
+
+ /* Round the count up for word writes. Do we need to do this?
+ What effect will an odd byte count have on the 8390?
+ I should check someday. */
+
+ if (ei_status.word16 && (count & 0x01))
+ count++;
+
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ if (ei_status.dmaing) {
+ printk(KERN_EMERG "%s: DMAing conflict in %s."
+ "[DMAstat:%d][irqlock:%d]\n",
+ dev->name, __FUNCTION__,
+ ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+ /* We should already be in page 0, but to be safe... */
+ ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+ ei_outb(ENISR_RDC, nic_base + EN0_ISR);
+
+ /* Now the normal output. */
+ ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+ ei_outb(count >> 8, nic_base + EN0_RCNTHI);
+ ei_outb(0x00, nic_base + EN0_RSARLO);
+ ei_outb(start_page, nic_base + EN0_RSARHI);
+
+ ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+ if (ei_status.word16) {
+ writesw(nic_base + NE_DATAPORT, buf, count>>1);
+ } else {
+ writesb(nic_base + NE_DATAPORT, buf, count);
+ }
+
+ dma_start = jiffies;
+
+ while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
+ if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
+ printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+ ax_reset_8390(dev);
+ ax_NS8390_init(dev,1);
+ break;
+ }
+ }
+
+ ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
+ return;
+}
+
+/* definitions for accessing MII/EEPROM interface */
+
+#define AX_MEMR EI_SHIFT(0x14)
+#define AX_MEMR_MDC (1<<0)
+#define AX_MEMR_MDIR (1<<1)
+#define AX_MEMR_MDI (1<<2)
+#define AX_MEMR_MDO (1<<3)
+#define AX_MEMR_EECS (1<<4)
+#define AX_MEMR_EEI (1<<5)
+#define AX_MEMR_EEO (1<<6)
+#define AX_MEMR_EECLK (1<<7)
+
+/* ax_mii_ei_outbits
+ *
+ * write the specified set of bits to the phy
+*/
+
+static void
+ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len)
+{
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
+ unsigned int memr;
+
+ /* clock low, data to output mode */
+ memr = ei_inb(memr_addr);
+ memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR);
+ ei_outb(memr, memr_addr);
+
+ for (len--; len >= 0; len--) {
+ if (bits & (1 << len))
+ memr |= AX_MEMR_MDO;
+ else
+ memr &= ~AX_MEMR_MDO;
+
+ ei_outb(memr, memr_addr);
+
+ /* clock high */
+
+ ei_outb(memr | AX_MEMR_MDC, memr_addr);
+ udelay(1);
+
+ /* clock low */
+ ei_outb(memr, memr_addr);
+ }
+
+ /* leaves the clock line low, mdir input */
+ memr |= AX_MEMR_MDIR;
+ ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR);
+}
+
+/* ax_phy_ei_inbits
+ *
+ * read a specified number of bits from the phy
+*/
+
+static unsigned int
+ax_phy_ei_inbits(struct net_device *dev, int no)
+{
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
+ unsigned int memr;
+ unsigned int result = 0;
+
+ /* clock low, data to input mode */
+ memr = ei_inb(memr_addr);
+ memr &= ~AX_MEMR_MDC;
+ memr |= AX_MEMR_MDIR;
+ ei_outb(memr, memr_addr);
+
+ for (no--; no >= 0; no--) {
+ ei_outb(memr | AX_MEMR_MDC, memr_addr);
+
+ udelay(1);
+
+ if (ei_inb(memr_addr) & AX_MEMR_MDI)
+ result |= (1<<no);
+
+ ei_outb(memr, memr_addr);
+ }
+
+ return result;
+}
+
+/* ax_phy_issueaddr
+ *
+ * use the low level bit shifting routines to send the address
+ * and command to the specified phy
+*/
+
+static void
+ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc)
+{
+ if (phy_debug)
+ pr_debug("%s: dev %p, %04x, %04x, %d\n",
+ __FUNCTION__, dev, phy_addr, reg, opc);
+
+ ax_mii_ei_outbits(dev, 0x3f, 6); /* pre-amble */
+ ax_mii_ei_outbits(dev, 1, 2); /* frame-start */
+ ax_mii_ei_outbits(dev, opc, 2); /* op code */
+ ax_mii_ei_outbits(dev, phy_addr, 5); /* phy address */
+ ax_mii_ei_outbits(dev, reg, 5); /* reg address */
+}
+
+static int
+ax_phy_read(struct net_device *dev, int phy_addr, int reg)
+{
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ unsigned long flags;
+ unsigned int result;
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+
+ ax_phy_issueaddr(dev, phy_addr, reg, 2);
+
+ result = ax_phy_ei_inbits(dev, 17);
+ result &= ~(3<<16);
+
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+ if (phy_debug)
+ pr_debug("%s: %04x.%04x => read %04x\n", __FUNCTION__,
+ phy_addr, reg, result);
+
+ return result;
+}
+
+static void
+ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
+{
+ struct ei_device *ei = (struct ei_device *) netdev_priv(dev);
+ unsigned long flags;
+
+ printk(KERN_DEBUG "%s: %p, %04x, %04x %04x\n",
+ __FUNCTION__, dev, phy_addr, reg, value);
+
+ spin_lock_irqsave(&ei->page_lock, flags);
+
+ ax_phy_issueaddr(dev, phy_addr, reg, 1);
+ ax_mii_ei_outbits(dev, 2, 2); /* send TA */
+ ax_mii_ei_outbits(dev, value, 16);
+
+ spin_unlock_irqrestore(&ei->page_lock, flags);
+}
+
+static void ax_mii_expiry(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct ax_device *ax = to_ax_dev(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ax->mii_lock, flags);
+ mii_check_media(&ax->mii, netif_msg_link(ax), 0);
+ spin_unlock_irqrestore(&ax->mii_lock, flags);
+
+ if (ax->running) {
+ ax->mii_timer.expires = jiffies + HZ*2;
+ add_timer(&ax->mii_timer);
+ }
+}
+
+static int ax_open(struct net_device *dev)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ struct ei_device *ei_local = netdev_priv(dev);
+ int ret;
+
+ dev_dbg(ax->dev, "%s: open\n", dev->name);
+
+ ret = request_irq(dev->irq, ax_ei_interrupt, 0, dev->name, dev);
+ if (ret)
+ return ret;
+
+ ret = ax_ei_open(dev);
+ if (ret)
+ return ret;
+
+ /* turn the phy on (if turned off) */
+
+ ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17));
+ ax->running = 1;
+
+ /* start the MII timer */
+
+ init_timer(&ax->mii_timer);
+
+ ax->mii_timer.expires = jiffies+1;
+ ax->mii_timer.data = (unsigned long) dev;
+ ax->mii_timer.function = ax_mii_expiry;
+
+ add_timer(&ax->mii_timer);
+
+ return 0;
+}
+
+static int ax_close(struct net_device *dev)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ struct ei_device *ei_local = netdev_priv(dev);
+
+ dev_dbg(ax->dev, "%s: close\n", dev->name);
+
+ /* turn the phy off */
+
+ ei_outb(ax->plat->gpoc_val | (1<<6),
+ ei_local->mem + EI_SHIFT(0x17));
+
+ ax->running = 0;
+ wmb();
+
+ del_timer_sync(&ax->mii_timer);
+ ax_ei_close(dev);
+
+ free_irq(dev->irq, dev);
+ return 0;
+}
+
+static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ unsigned long flags;
+ int rc;
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&ax->mii_lock, flags);
+ rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL);
+ spin_unlock_irqrestore(&ax->mii_lock, flags);
+
+ return rc;
+}
+
+/* ethtool ops */
+
+static void ax_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, ax->dev->name);
+}
+
+static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ax->mii_lock, flags);
+ mii_ethtool_gset(&ax->mii, cmd);
+ spin_lock_irqsave(&ax->mii_lock, flags);
+
+ return 0;
+}
+
+static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&ax->mii_lock, flags);
+ rc = mii_ethtool_sset(&ax->mii, cmd);
+ spin_lock_irqsave(&ax->mii_lock, flags);
+
+ return rc;
+}
+
+static int ax_nway_reset(struct net_device *dev)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ return mii_nway_restart(&ax->mii);
+}
+
+static u32 ax_get_link(struct net_device *dev)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ return mii_link_ok(&ax->mii);
+}
+
+static const struct ethtool_ops ax_ethtool_ops = {
+ .get_drvinfo = ax_get_drvinfo,
+ .get_settings = ax_get_settings,
+ .set_settings = ax_set_settings,
+ .nway_reset = ax_nway_reset,
+ .get_link = ax_get_link,
+ .get_perm_addr = ethtool_op_get_perm_addr,
+};
+
+/* setup code */
+
+static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
+{
+ void __iomem *ioaddr = ei_local->mem;
+ struct ax_device *ax = to_ax_dev(dev);
+
+ /* Select page 0*/
+ ei_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr + E8390_CMD);
+
+ /* set to byte access */
+ ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
+ ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
+}
+
+/* ax_init_dev
+ *
+ * initialise the specified device, taking care to note the MAC
+ * address it may already have (if configured), ensure
+ * the device is ready to be used by lib8390.c and registerd with
+ * the network layer.
+ */
+
+static int ax_init_dev(struct net_device *dev, int first_init)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ struct ax_device *ax = to_ax_dev(dev);
+ void __iomem *ioaddr = ei_local->mem;
+ unsigned int start_page;
+ unsigned int stop_page;
+ int ret;
+ int i;
+
+ ret = ax_initial_check(dev);
+ if (ret)
+ goto err_out;
+
+ /* setup goes here */
+
+ ax_initial_setup(dev, ei_local);
+
+ /* read the mac from the card prom if we need it */
+
+ if (first_init && ax->plat->flags & AXFLG_HAS_EEPROM) {
+ unsigned char SA_prom[32];
+
+ for(i = 0; i < sizeof(SA_prom); i+=2) {
+ SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
+ SA_prom[i+1] = ei_inb(ioaddr + NE_DATAPORT);
+ }
+
+ if (ax->plat->wordlength == 2)
+ for (i = 0; i < 16; i++)
+ SA_prom[i] = SA_prom[i+i];
+
+ memcpy(dev->dev_addr, SA_prom, 6);
+ }
+
+ if (ax->plat->wordlength == 2) {
+ /* We must set the 8390 for word mode. */
+ ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
+ start_page = NESM_START_PG;
+ stop_page = NESM_STOP_PG;
+ } else {
+ start_page = NE1SM_START_PG;
+ stop_page = NE1SM_STOP_PG;
+ }
+
+ /* load the mac-address from the device if this is the
+ * first time we've initialised */
+
+ if (first_init && ax->plat->flags & AXFLG_MAC_FROMDEV) {
+ ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+ ei_local->mem + E8390_CMD); /* 0x61 */
+
+ for (i = 0 ; i < ETHER_ADDR_LEN ; i++)
+ dev->dev_addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
+ }
+
+ ax_reset_8390(dev);
+
+ ei_status.name = "AX88796";
+ ei_status.tx_start_page = start_page;
+ ei_status.stop_page = stop_page;
+ ei_status.word16 = (ax->plat->wordlength == 2);
+ ei_status.rx_start_page = start_page + TX_PAGES;
+
+#ifdef PACKETBUF_MEMSIZE
+ /* Allow the packet buffer size to be overridden by know-it-alls. */
+ ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+ ei_status.reset_8390 = &ax_reset_8390;
+ ei_status.block_input = &ax_block_input;
+ ei_status.block_output = &ax_block_output;
+ ei_status.get_8390_hdr = &ax_get_8390_hdr;
+ ei_status.priv = 0;
+
+ dev->open = ax_open;
+ dev->stop = ax_close;
+ dev->do_ioctl = ax_ioctl;
+ dev->ethtool_ops = &ax_ethtool_ops;
+
+ ax->msg_enable = NETIF_MSG_LINK;
+ ax->mii.phy_id_mask = 0x1f;
+ ax->mii.reg_num_mask = 0x1f;
+ ax->mii.phy_id = 0x10; /* onboard phy */
+ ax->mii.force_media = 0;
+ ax->mii.full_duplex = 0;
+ ax->mii.mdio_read = ax_phy_read;
+ ax->mii.mdio_write = ax_phy_write;
+ ax->mii.dev = dev;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = ax_ei_poll;
+#endif
+ ax_NS8390_init(dev, 0);
+
+ if (first_init) {
+ printk("AX88796: %dbit, irq %d, %lx, MAC: ",
+ ei_status.word16 ? 16:8, dev->irq, dev->base_addr);
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ printk("%2.2x%c", dev->dev_addr[i],
+ (i < (ETHER_ADDR_LEN-1) ? ':' : ' '));
+
+ printk("\n");
+ }
+
+ ret = register_netdev(dev);
+ if (ret)
+ goto out_irq;
+
+ return 0;
+
+ out_irq:
+ /* cleanup irq */
+ free_irq(dev->irq, dev);
+ err_out:
+ return ret;
+}
+
+static int ax_remove(struct platform_device *_dev)
+{
+ struct net_device *dev = platform_get_drvdata(_dev);
+ struct ax_device *ax;
+
+ ax = to_ax_dev(dev);
+
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+
+ iounmap(ei_status.mem);
+ release_resource(ax->mem);
+ kfree(ax->mem);
+
+ if (ax->map2) {
+ iounmap(ax->map2);
+ release_resource(ax->mem2);
+ kfree(ax->mem2);
+ }
+
+ free_netdev(dev);
+
+ return 0;
+}
+
+/* ax_probe
+ *
+ * This is the entry point when the platform device system uses to
+ * notify us of a new device to attach to. Allocate memory, find
+ * the resources and information passed, and map the necessary registers.
+*/
+
+static int ax_probe(struct platform_device *pdev)
+{
+ struct net_device *dev;
+ struct ax_device *ax;
+ struct resource *res;
+ size_t size;
+ int ret;
+
+ dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
+ if (dev == NULL)
+ return -ENOMEM;
+
+ /* ok, let's setup our device */
+ ax = to_ax_dev(dev);
+
+ memset(ax, 0, sizeof(struct ax_device));
+
+ spin_lock_init(&ax->mii_lock);
+
+ ax->dev = pdev;
+ ax->plat = pdev->dev.platform_data;
+ platform_set_drvdata(pdev, dev);
+
+ ei_status.rxcr_base = ax->plat->rcr_val;
+
+ /* find the platform resources */
+
+ dev->irq = platform_get_irq(pdev, 0);
+ if (dev->irq < 0) {
+ dev_err(&pdev->dev, "no IRQ specified\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no MEM specified\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ size = (res->end - res->start) + 1;
+
+ /* setup the register offsets from either the platform data
+ * or by using the size of the resource provided */
+
+ if (ax->plat->reg_offsets)
+ ei_status.reg_offset = ax->plat->reg_offsets;
+ else {
+ ei_status.reg_offset = ax->reg_offsets;
+ for (ret = 0; ret < 0x18; ret++)
+ ax->reg_offsets[ret] = (size / 0x18) * ret;
+ }
+
+ ax->mem = request_mem_region(res->start, size, pdev->name);
+ if (ax->mem == NULL) {
+ dev_err(&pdev->dev, "cannot reserve registers\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ ei_status.mem = ioremap(res->start, size);
+ dev->base_addr = (long)ei_status.mem;
+
+ if (ei_status.mem == NULL) {
+ dev_err(&pdev->dev, "Cannot ioremap area (%08zx,%08zx)\n",
+ res->start, res->end);
+
+ ret = -ENXIO;
+ goto exit_req;
+ }
+
+ /* look for reset area */
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res == NULL) {
+ if (!ax->plat->reg_offsets) {
+ for (ret = 0; ret < 0x20; ret++)
+ ax->reg_offsets[ret] = (size / 0x20) * ret;
+ }
+
+ ax->map2 = NULL;
+ } else {
+ size = (res->end - res->start) + 1;
+
+ ax->mem2 = request_mem_region(res->start, size, pdev->name);
+ if (ax->mem == NULL) {
+ dev_err(&pdev->dev, "cannot reserve registers\n");
+ ret = -ENXIO;
+ goto exit_mem1;
+ }
+
+ ax->map2 = ioremap(res->start, size);
+ if (ax->map2 == NULL) {
+ dev_err(&pdev->dev, "cannot map reset register");
+ ret = -ENXIO;
+ goto exit_mem2;
+ }
+
+ ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;
+ }
+
+ /* got resources, now initialise and register device */
+
+ ret = ax_init_dev(dev, 1);
+ if (!ret)
+ return 0;
+
+ if (ax->map2 == NULL)
+ goto exit_mem1;
+
+ iounmap(ax->map2);
+
+ exit_mem2:
+ release_resource(ax->mem2);
+ kfree(ax->mem2);
+
+ exit_mem1:
+ iounmap(ei_status.mem);
+
+ exit_req:
+ release_resource(ax->mem);
+ kfree(ax->mem);
+
+ exit_mem:
+ free_netdev(dev);
+
+ return ret;
+}
+
+/* suspend and resume */
+
+#ifdef CONFIG_PM
+static int ax_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct net_device *ndev = platform_get_drvdata(dev);
+ struct ax_device *ax = to_ax_dev(ndev);
+
+ ax->resume_open = ax->running;
+
+ netif_device_detach(ndev);
+ ax_close(ndev);
+
+ return 0;
+}
+
+static int ax_resume(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ax_device *ax = to_ax_dev(ndev);
+
+ ax_initial_setup(ndev, netdev_priv(ndev));
+ ax_NS8390_init(ndev, ax->resume_open);
+ netif_device_attach(ndev);
+
+ if (ax->resume_open)
+ ax_open(ndev);
+
+ return 0;
+}
+
+#else
+#define ax_suspend NULL
+#define ax_resume NULL
+#endif
+
+static struct platform_driver axdrv = {
+ .driver = {
+ .name = "ax88796",
+ .owner = THIS_MODULE,
+ },
+ .probe = ax_probe,
+ .remove = ax_remove,
+ .suspend = ax_suspend,
+ .resume = ax_resume,
+};
+
+static int __init axdrv_init(void)
+{
+ return platform_driver_register(&axdrv);
+}
+
+static void __exit axdrv_exit(void)
+{
+ platform_driver_unregister(&axdrv);
+}
+
+module_init(axdrv_init);
+module_exit(axdrv_exit);
+
+MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 879a2fff474..96fb0ec905a 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -15,6 +15,7 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/delay.h>
@@ -68,8 +69,8 @@
(BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
#define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1))
-#define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64)
-#define TX_PKT_BUF_SZ (B44_MAX_MTU + ETH_HLEN + 8)
+#define RX_PKT_OFFSET 30
+#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64)
/* minimum number of free TX descriptors required to wake up TX process */
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
@@ -599,8 +600,7 @@ static void b44_timer(unsigned long __opaque)
spin_unlock_irq(&bp->lock);
- bp->timer.expires = jiffies + HZ;
- add_timer(&bp->timer);
+ mod_timer(&bp->timer, round_jiffies(jiffies + HZ));
}
static void b44_tx(struct b44 *bp)
@@ -653,7 +653,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
src_map = &bp->rx_buffers[src_idx];
dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
map = &bp->rx_buffers[dest_idx];
- skb = dev_alloc_skb(RX_PKT_BUF_SZ);
+ skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ);
if (skb == NULL)
return -ENOMEM;
@@ -669,7 +669,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
- skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
+ skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
if (skb == NULL)
return -ENOMEM;
mapping = pci_map_single(bp->pdev, skb->data,
@@ -684,11 +684,9 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
}
}
- skb->dev = bp->dev;
- skb_reserve(skb, bp->rx_offset);
+ rh = (struct rx_header *) skb->data;
+ skb_reserve(skb, RX_PKT_OFFSET);
- rh = (struct rx_header *)
- (skb->data - bp->rx_offset);
rh->len = 0;
rh->flags = 0;
@@ -698,13 +696,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (src_map != NULL)
src_map->skb = NULL;
- ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - bp->rx_offset));
+ ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= DESC_CTRL_EOT;
dp = &bp->rx_ring[dest_idx];
dp->ctrl = cpu_to_le32(ctrl);
- dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
+ dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
if (bp->flags & B44_FLAG_RX_RING_HACK)
b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
@@ -783,7 +781,7 @@ static int b44_rx(struct b44 *bp, int budget)
PCI_DMA_FROMDEVICE);
rh = (struct rx_header *) skb->data;
len = le16_to_cpu(rh->len);
- if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
+ if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
(rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
drop_it:
b44_recycle_rx(bp, cons, bp->rx_prod);
@@ -815,8 +813,8 @@ static int b44_rx(struct b44 *bp, int budget)
pci_unmap_single(bp->pdev, map,
skb_size, PCI_DMA_FROMDEVICE);
/* Leave out rx_header */
- skb_put(skb, len+bp->rx_offset);
- skb_pull(skb,bp->rx_offset);
+ skb_put(skb, len + RX_PKT_OFFSET);
+ skb_pull(skb, RX_PKT_OFFSET);
} else {
struct sk_buff *copy_skb;
@@ -828,7 +826,7 @@ static int b44_rx(struct b44 *bp, int budget)
skb_reserve(copy_skb, 2);
skb_put(copy_skb, len);
/* DMA sync done above, copy just the actual packet */
- skb_copy_from_linear_data_offset(skb, bp->rx_offset,
+ skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET,
copy_skb->data, len);
skb = copy_skb;
}
@@ -969,7 +967,6 @@ static void b44_tx_timeout(struct net_device *dev)
static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct b44 *bp = netdev_priv(dev);
- struct sk_buff *bounce_skb;
int rc = NETDEV_TX_OK;
dma_addr_t mapping;
u32 len, entry, ctrl;
@@ -987,12 +984,13 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
+ struct sk_buff *bounce_skb;
+
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
- bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
- GFP_ATOMIC|GFP_DMA);
+ bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
if (!bounce_skb)
goto err_out;
@@ -1001,13 +999,12 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping,
- len, PCI_DMA_TODEVICE);
+ len, PCI_DMA_TODEVICE);
dev_kfree_skb_any(bounce_skb);
goto err_out;
}
- skb_copy_from_linear_data(skb, skb_put(bounce_skb, len),
- skb->len);
+ skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
dev_kfree_skb_any(skb);
skb = bounce_skb;
}
@@ -1396,12 +1393,12 @@ static void b44_init_hw(struct b44 *bp, int reset_kind)
bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
if (reset_kind == B44_PARTIAL_RESET) {
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
- (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
} else {
bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
- (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
@@ -2093,11 +2090,6 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->phy_addr = eeprom[90] & 0x1f;
- /* With this, plus the rx_header prepended to the data by the
- * hardware, we'll land the ethernet header on a 2-byte boundary.
- */
- bp->rx_offset = 30;
-
bp->imask = IMASK_DEF;
bp->core_unit = ssb_core_unit(bp);
@@ -2348,11 +2340,11 @@ static int b44_resume(struct pci_dev *pdev)
netif_device_attach(bp->dev);
spin_unlock_irq(&bp->lock);
- bp->timer.expires = jiffies + HZ;
- add_timer(&bp->timer);
-
b44_enable_ints(bp);
netif_wake_queue(dev);
+
+ mod_timer(&bp->timer, jiffies + 1);
+
return 0;
}
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 18fc1333662..e537e63f292 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -443,8 +443,6 @@ struct b44 {
#define B44_FLAG_TX_RING_HACK 0x40000000
#define B44_FLAG_WOL_ENABLE 0x80000000
- u32 rx_offset;
-
u32 msg_enable;
struct timer_list timer;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6287ffbda7f..cb9cb3013f4 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -187,7 +187,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond);
/*---------------------------- General routines -----------------------------*/
-const char *bond_mode_name(int mode)
+static const char *bond_mode_name(int mode)
{
switch (mode) {
case BOND_MODE_ROUNDROBIN :
@@ -1224,7 +1224,8 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave)
/*---------------------------------- IOCTL ----------------------------------*/
-int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+static int bond_sethwaddr(struct net_device *bond_dev,
+ struct net_device *slave_dev)
{
dprintk("bond_dev=%p\n", bond_dev);
dprintk("slave_dev=%p\n", slave_dev);
@@ -1390,6 +1391,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_free;
}
+ res = netdev_set_master(slave_dev, bond_dev);
+ if (res) {
+ dprintk("Error %d calling netdev_set_master\n", res);
+ goto err_close;
+ }
/* open the slave since the application closed it */
res = dev_open(slave_dev);
if (res) {
@@ -1397,12 +1403,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_restore_mac;
}
- res = netdev_set_master(slave_dev, bond_dev);
- if (res) {
- dprintk("Error %d calling netdev_set_master\n", res);
- goto err_close;
- }
-
new_slave->dev = slave_dev;
slave_dev->priv_flags |= IFF_BONDING;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index a89102116cc..6dcbd25e3ef 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -301,13 +301,11 @@ int bond_create_slave_symlinks(struct net_device *master, struct net_device *sla
void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
-int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
void bond_mii_monitor(struct net_device *bond_dev);
void bond_loadbalance_arp_mon(struct net_device *bond_dev);
void bond_activebackup_arp_mon(struct net_device *bond_dev);
void bond_set_mode_ops(struct bonding *bond, int mode);
int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
-const char *bond_mode_name(int mode);
void bond_select_active_slave(struct bonding *bond);
void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
void bond_register_arp(struct bonding *);
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 80c3d8f268a..ab72563b81e 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -71,27 +71,29 @@ enum { /* adapter flags */
QUEUES_BOUND = (1 << 3),
};
+struct fl_pg_chunk {
+ struct page *page;
+ void *va;
+ unsigned int offset;
+};
+
struct rx_desc;
struct rx_sw_desc;
-struct sge_fl_page {
- struct skb_frag_struct frag;
- unsigned char *va;
-};
-
-struct sge_fl { /* SGE per free-buffer list state */
- unsigned int buf_size; /* size of each Rx buffer */
- unsigned int credits; /* # of available Rx buffers */
- unsigned int size; /* capacity of free list */
- unsigned int cidx; /* consumer index */
- unsigned int pidx; /* producer index */
- unsigned int gen; /* free list generation */
- unsigned int cntxt_id; /* SGE context id for the free list */
- struct sge_fl_page page;
- struct rx_desc *desc; /* address of HW Rx descriptor ring */
- struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */
- dma_addr_t phys_addr; /* physical address of HW ring start */
- unsigned long empty; /* # of times queue ran out of buffers */
+struct sge_fl { /* SGE per free-buffer list state */
+ unsigned int buf_size; /* size of each Rx buffer */
+ unsigned int credits; /* # of available Rx buffers */
+ unsigned int size; /* capacity of free list */
+ unsigned int cidx; /* consumer index */
+ unsigned int pidx; /* producer index */
+ unsigned int gen; /* free list generation */
+ struct fl_pg_chunk pg_chunk;/* page chunk cache */
+ unsigned int use_pages; /* whether FL uses pages or sk_buffs */
+ struct rx_desc *desc; /* address of HW Rx descriptor ring */
+ struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */
+ dma_addr_t phys_addr; /* physical address of HW ring start */
+ unsigned int cntxt_id; /* SGE context id for the free list */
+ unsigned long empty; /* # of times queue ran out of buffers */
unsigned long alloc_failed; /* # of times buffer allocation failed */
};
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 8d137963369..16378004507 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -101,6 +101,7 @@ enum {
TCB_SIZE = 128, /* TCB size */
NMTUS = 16, /* size of MTU table */
NCCTRL_WIN = 32, /* # of congestion control windows */
+ PROTO_SRAM_LINES = 128, /* size of TP sram */
};
#define MAX_RX_COALESCING_LEN 16224U
@@ -124,6 +125,30 @@ enum { /* adapter interrupt-maintained statistics */
};
enum {
+ TP_VERSION_MAJOR = 1,
+ TP_VERSION_MINOR = 0,
+ TP_VERSION_MICRO = 44
+};
+
+#define S_TP_VERSION_MAJOR 16
+#define M_TP_VERSION_MAJOR 0xFF
+#define V_TP_VERSION_MAJOR(x) ((x) << S_TP_VERSION_MAJOR)
+#define G_TP_VERSION_MAJOR(x) \
+ (((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR)
+
+#define S_TP_VERSION_MINOR 8
+#define M_TP_VERSION_MINOR 0xFF
+#define V_TP_VERSION_MINOR(x) ((x) << S_TP_VERSION_MINOR)
+#define G_TP_VERSION_MINOR(x) \
+ (((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR)
+
+#define S_TP_VERSION_MICRO 0
+#define M_TP_VERSION_MICRO 0xFF
+#define V_TP_VERSION_MICRO(x) ((x) << S_TP_VERSION_MICRO)
+#define G_TP_VERSION_MICRO(x) \
+ (((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO)
+
+enum {
SGE_QSETS = 8, /* # of SGE Tx/Rx/RspQ sets */
SGE_RXQ_PER_SET = 2, /* # of Rx queues per set */
SGE_TXQ_PER_SET = 3 /* # of Tx queues per set */
@@ -654,6 +679,9 @@ const struct adapter_info *t3_get_adapter_info(unsigned int board_id);
int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data);
int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data);
int t3_seeprom_wp(struct adapter *adapter, int enable);
+int t3_check_tpsram_version(struct adapter *adapter);
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size);
+int t3_set_proto_sram(struct adapter *adap, u8 *data);
int t3_read_flash(struct adapter *adapter, unsigned int addr,
unsigned int nwords, u32 *data, int byte_oriented);
int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index d8a1f5452c5..6fd1e524183 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -43,6 +43,7 @@
#include <linux/proc_fs.h>
#include <linux/rtnetlink.h>
#include <linux/firmware.h>
+#include <linux/log2.h>
#include <asm/uaccess.h>
#include "common.h"
@@ -1818,8 +1819,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
return -EBUSY;
if (copy_from_user(&m, useraddr, sizeof(m)))
return -EFAULT;
- if (!m.rx_pg_sz || (m.rx_pg_sz & (m.rx_pg_sz - 1)) ||
- !m.tx_pg_sz || (m.tx_pg_sz & (m.tx_pg_sz - 1)))
+ if (!is_power_of_2(m.rx_pg_sz) ||
+ !is_power_of_2(m.tx_pg_sz))
return -EINVAL; /* not power of 2 */
if (!(m.rx_pg_sz & 0x14000))
return -EINVAL; /* not 16KB or 64KB */
@@ -2088,6 +2089,42 @@ static void cxgb_netpoll(struct net_device *dev)
}
#endif
+#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin"
+int update_tpsram(struct adapter *adap)
+{
+ const struct firmware *tpsram;
+ char buf[64];
+ struct device *dev = &adap->pdev->dev;
+ int ret;
+ char rev;
+
+ rev = adap->params.rev == T3_REV_B2 ? 'b' : 'a';
+
+ snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
+ TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+
+ ret = request_firmware(&tpsram, buf, dev);
+ if (ret < 0) {
+ dev_err(dev, "could not load TP SRAM: unable to load %s\n",
+ buf);
+ return ret;
+ }
+
+ ret = t3_check_tpsram(adap, tpsram->data, tpsram->size);
+ if (ret)
+ goto release_tpsram;
+
+ ret = t3_set_proto_sram(adap, tpsram->data);
+ if (ret)
+ dev_err(dev, "loading protocol SRAM failed\n");
+
+release_tpsram:
+ release_firmware(tpsram);
+
+ return ret;
+}
+
+
/*
* Periodic accumulation of MAC statistics.
*/
@@ -2437,6 +2474,13 @@ static int __devinit init_one(struct pci_dev *pdev,
goto out_free_dev;
}
+ err = t3_check_tpsram_version(adapter);
+ if (err == -EINVAL)
+ err = update_tpsram(adapter);
+
+ if (err)
+ goto out_free_dev;
+
/*
* The card is now ready to go. If any errors occur during device
* registration we do not fail the whole card but rather proceed only
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index 020859c855d..aa80313c922 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -1160,6 +1160,8 @@
#define A_TP_MOD_CHANNEL_WEIGHT 0x434
+#define A_TP_MOD_RATE_LIMIT 0x438
+
#define A_TP_PIO_ADDR 0x440
#define A_TP_PIO_DATA 0x444
@@ -1214,6 +1216,15 @@
#define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \
M_TXDROPCNTCH0RCVD)
+#define A_TP_PROXY_FLOW_CNTL 0x4b0
+
+#define A_TP_EMBED_OP_FIELD0 0x4e8
+#define A_TP_EMBED_OP_FIELD1 0x4ec
+#define A_TP_EMBED_OP_FIELD2 0x4f0
+#define A_TP_EMBED_OP_FIELD3 0x4f4
+#define A_TP_EMBED_OP_FIELD4 0x4f8
+#define A_TP_EMBED_OP_FIELD5 0x4fc
+
#define A_ULPRX_CTL 0x500
#define S_ROUND_ROBIN 4
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index a60ec4d4707..a2cfd68ac75 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -46,23 +46,16 @@
#define SGE_RX_SM_BUF_SIZE 1536
-/*
- * If USE_RX_PAGE is defined, the small freelist populated with (partial)
- * pages instead of skbs. Pages are carved up into RX_PAGE_SIZE chunks (must
- * be a multiple of the host page size).
- */
-#define USE_RX_PAGE
-#define RX_PAGE_SIZE 2048
-
-/*
- * skb freelist packets are copied into a new skb (and the freelist one is
- * reused) if their len is <=
- */
#define SGE_RX_COPY_THRES 256
+#define SGE_RX_PULL_LEN 128
/*
- * Minimum number of freelist entries before we start dropping TUNNEL frames.
+ * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks.
+ * It must be a divisor of PAGE_SIZE. If set to 0 FL0 will use sk_buffs
+ * directly.
*/
+#define FL0_PG_CHUNK_SIZE 2048
+
#define SGE_RX_DROP_THRES 16
/*
@@ -100,12 +93,12 @@ struct tx_sw_desc { /* SW state per Tx descriptor */
struct sk_buff *skb;
};
-struct rx_sw_desc { /* SW state per Rx descriptor */
+struct rx_sw_desc { /* SW state per Rx descriptor */
union {
struct sk_buff *skb;
- struct sge_fl_page page;
- } t;
- DECLARE_PCI_UNMAP_ADDR(dma_addr);
+ struct fl_pg_chunk pg_chunk;
+ };
+ DECLARE_PCI_UNMAP_ADDR(dma_addr);
};
struct rsp_desc { /* response queue descriptor */
@@ -351,27 +344,26 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr),
q->buf_size, PCI_DMA_FROMDEVICE);
-
- if (q->buf_size != RX_PAGE_SIZE) {
- kfree_skb(d->t.skb);
- d->t.skb = NULL;
+ if (q->use_pages) {
+ put_page(d->pg_chunk.page);
+ d->pg_chunk.page = NULL;
} else {
- if (d->t.page.frag.page)
- put_page(d->t.page.frag.page);
- d->t.page.frag.page = NULL;
+ kfree_skb(d->skb);
+ d->skb = NULL;
}
if (++cidx == q->size)
cidx = 0;
}
- if (q->page.frag.page)
- put_page(q->page.frag.page);
- q->page.frag.page = NULL;
+ if (q->pg_chunk.page) {
+ __free_page(q->pg_chunk.page);
+ q->pg_chunk.page = NULL;
+ }
}
/**
* add_one_rx_buf - add a packet buffer to a free-buffer list
- * @va: va of the buffer to add
+ * @va: buffer start VA
* @len: the buffer length
* @d: the HW Rx descriptor to write
* @sd: the SW Rx descriptor to write
@@ -381,7 +373,7 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
* Add a buffer of the given length to the supplied HW and SW Rx
* descriptors.
*/
-static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
+static inline void add_one_rx_buf(void *va, unsigned int len,
struct rx_desc *d, struct rx_sw_desc *sd,
unsigned int gen, struct pci_dev *pdev)
{
@@ -397,6 +389,27 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
}
+static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp)
+{
+ if (!q->pg_chunk.page) {
+ q->pg_chunk.page = alloc_page(gfp);
+ if (unlikely(!q->pg_chunk.page))
+ return -ENOMEM;
+ q->pg_chunk.va = page_address(q->pg_chunk.page);
+ q->pg_chunk.offset = 0;
+ }
+ sd->pg_chunk = q->pg_chunk;
+
+ q->pg_chunk.offset += q->buf_size;
+ if (q->pg_chunk.offset == PAGE_SIZE)
+ q->pg_chunk.page = NULL;
+ else {
+ q->pg_chunk.va += q->buf_size;
+ get_page(q->pg_chunk.page);
+ }
+ return 0;
+}
+
/**
* refill_fl - refill an SGE free-buffer list
* @adapter: the adapter
@@ -410,49 +423,29 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
*/
static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
{
+ void *buf_start;
struct rx_sw_desc *sd = &q->sdesc[q->pidx];
struct rx_desc *d = &q->desc[q->pidx];
- struct sge_fl_page *p = &q->page;
while (n--) {
- unsigned char *va;
-
- if (unlikely(q->buf_size != RX_PAGE_SIZE)) {
- struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
-
- if (!skb) {
- q->alloc_failed++;
+ if (q->use_pages) {
+ if (unlikely(alloc_pg_chunk(q, sd, gfp))) {
+nomem: q->alloc_failed++;
break;
}
- va = skb->data;
- sd->t.skb = skb;
+ buf_start = sd->pg_chunk.va;
} else {
- if (!p->frag.page) {
- p->frag.page = alloc_pages(gfp, 0);
- if (unlikely(!p->frag.page)) {
- q->alloc_failed++;
- break;
- } else {
- p->frag.size = RX_PAGE_SIZE;
- p->frag.page_offset = 0;
- p->va = page_address(p->frag.page);
- }
- }
+ struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
- memcpy(&sd->t, p, sizeof(*p));
- va = p->va;
+ if (!skb)
+ goto nomem;
- p->frag.page_offset += RX_PAGE_SIZE;
- BUG_ON(p->frag.page_offset > PAGE_SIZE);
- p->va += RX_PAGE_SIZE;
- if (p->frag.page_offset == PAGE_SIZE)
- p->frag.page = NULL;
- else
- get_page(p->frag.page);
+ sd->skb = skb;
+ buf_start = skb->data;
}
- add_one_rx_buf(va, q->buf_size, d, sd, q->gen, adap->pdev);
-
+ add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen,
+ adap->pdev);
d++;
sd++;
if (++q->pidx == q->size) {
@@ -487,7 +480,7 @@ static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q,
struct rx_desc *from = &q->desc[idx];
struct rx_desc *to = &q->desc[q->pidx];
- memcpy(&q->sdesc[q->pidx], &q->sdesc[idx], sizeof(struct rx_sw_desc));
+ q->sdesc[q->pidx] = q->sdesc[idx];
to->addr_lo = from->addr_lo; /* already big endian */
to->addr_hi = from->addr_hi; /* likewise */
wmb();
@@ -650,6 +643,132 @@ static inline unsigned int flits_to_desc(unsigned int n)
}
/**
+ * get_packet - return the next ingress packet buffer from a free list
+ * @adap: the adapter that received the packet
+ * @fl: the SGE free list holding the packet
+ * @len: the packet length including any SGE padding
+ * @drop_thres: # of remaining buffers before we start dropping packets
+ *
+ * Get the next packet from a free list and complete setup of the
+ * sk_buff. If the packet is small we make a copy and recycle the
+ * original buffer, otherwise we use the original buffer itself. If a
+ * positive drop threshold is supplied packets are dropped and their
+ * buffers recycled if (a) the number of remaining buffers is under the
+ * threshold and the packet is too big to copy, or (b) the packet should
+ * be copied but there is no memory for the copy.
+ */
+static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
+ unsigned int len, unsigned int drop_thres)
+{
+ struct sk_buff *skb = NULL;
+ struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+ prefetch(sd->skb->data);
+ fl->credits--;
+
+ if (len <= SGE_RX_COPY_THRES) {
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (likely(skb != NULL)) {
+ __skb_put(skb, len);
+ pci_dma_sync_single_for_cpu(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ memcpy(skb->data, sd->skb->data, len);
+ pci_dma_sync_single_for_device(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ } else if (!drop_thres)
+ goto use_orig_buf;
+recycle:
+ recycle_rx_buf(adap, fl, fl->cidx);
+ return skb;
+ }
+
+ if (unlikely(fl->credits < drop_thres))
+ goto recycle;
+
+use_orig_buf:
+ pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+ fl->buf_size, PCI_DMA_FROMDEVICE);
+ skb = sd->skb;
+ skb_put(skb, len);
+ __refill_fl(adap, fl);
+ return skb;
+}
+
+/**
+ * get_packet_pg - return the next ingress packet buffer from a free list
+ * @adap: the adapter that received the packet
+ * @fl: the SGE free list holding the packet
+ * @len: the packet length including any SGE padding
+ * @drop_thres: # of remaining buffers before we start dropping packets
+ *
+ * Get the next packet from a free list populated with page chunks.
+ * If the packet is small we make a copy and recycle the original buffer,
+ * otherwise we attach the original buffer as a page fragment to a fresh
+ * sk_buff. If a positive drop threshold is supplied packets are dropped
+ * and their buffers recycled if (a) the number of remaining buffers is
+ * under the threshold and the packet is too big to copy, or (b) there's
+ * no system memory.
+ *
+ * Note: this function is similar to @get_packet but deals with Rx buffers
+ * that are page chunks rather than sk_buffs.
+ */
+static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl,
+ unsigned int len, unsigned int drop_thres)
+{
+ struct sk_buff *skb = NULL;
+ struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+ if (len <= SGE_RX_COPY_THRES) {
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (likely(skb != NULL)) {
+ __skb_put(skb, len);
+ pci_dma_sync_single_for_cpu(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ memcpy(skb->data, sd->pg_chunk.va, len);
+ pci_dma_sync_single_for_device(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ } else if (!drop_thres)
+ return NULL;
+recycle:
+ fl->credits--;
+ recycle_rx_buf(adap, fl, fl->cidx);
+ return skb;
+ }
+
+ if (unlikely(fl->credits <= drop_thres))
+ goto recycle;
+
+ skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC);
+ if (unlikely(!skb)) {
+ if (!drop_thres)
+ return NULL;
+ goto recycle;
+ }
+
+ pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+ fl->buf_size, PCI_DMA_FROMDEVICE);
+ __skb_put(skb, SGE_RX_PULL_LEN);
+ memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN);
+ skb_fill_page_desc(skb, 0, sd->pg_chunk.page,
+ sd->pg_chunk.offset + SGE_RX_PULL_LEN,
+ len - SGE_RX_PULL_LEN);
+ skb->len = len;
+ skb->data_len = len - SGE_RX_PULL_LEN;
+ skb->truesize += skb->data_len;
+
+ fl->credits--;
+ /*
+ * We do not refill FLs here, we let the caller do it to overlap a
+ * prefetch.
+ */
+ return skb;
+}
+
+/**
* get_imm_packet - return the next ingress packet buffer from a response
* @resp: the response descriptor containing the packet data
*
@@ -1715,85 +1834,6 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
netif_rx(skb);
}
-#define SKB_DATA_SIZE 128
-
-static void skb_data_init(struct sk_buff *skb, struct sge_fl_page *p,
- unsigned int len)
-{
- skb->len = len;
- if (len <= SKB_DATA_SIZE) {
- skb_copy_to_linear_data(skb, p->va, len);
- skb->tail += len;
- put_page(p->frag.page);
- } else {
- skb_copy_to_linear_data(skb, p->va, SKB_DATA_SIZE);
- skb_shinfo(skb)->frags[0].page = p->frag.page;
- skb_shinfo(skb)->frags[0].page_offset =
- p->frag.page_offset + SKB_DATA_SIZE;
- skb_shinfo(skb)->frags[0].size = len - SKB_DATA_SIZE;
- skb_shinfo(skb)->nr_frags = 1;
- skb->data_len = len - SKB_DATA_SIZE;
- skb->tail += SKB_DATA_SIZE;
- skb->truesize += skb->data_len;
- }
-}
-
-/**
-* get_packet - return the next ingress packet buffer from a free list
-* @adap: the adapter that received the packet
-* @fl: the SGE free list holding the packet
-* @len: the packet length including any SGE padding
-* @drop_thres: # of remaining buffers before we start dropping packets
-*
-* Get the next packet from a free list and complete setup of the
-* sk_buff. If the packet is small we make a copy and recycle the
-* original buffer, otherwise we use the original buffer itself. If a
-* positive drop threshold is supplied packets are dropped and their
-* buffers recycled if (a) the number of remaining buffers is under the
-* threshold and the packet is too big to copy, or (b) the packet should
-* be copied but there is no memory for the copy.
-*/
-static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
- unsigned int len, unsigned int drop_thres)
-{
- struct sk_buff *skb = NULL;
- struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-
- prefetch(sd->t.skb->data);
-
- if (len <= SGE_RX_COPY_THRES) {
- skb = alloc_skb(len, GFP_ATOMIC);
- if (likely(skb != NULL)) {
- struct rx_desc *d = &fl->desc[fl->cidx];
- dma_addr_t mapping =
- (dma_addr_t)((u64) be32_to_cpu(d->addr_hi) << 32 |
- be32_to_cpu(d->addr_lo));
-
- __skb_put(skb, len);
- pci_dma_sync_single_for_cpu(adap->pdev, mapping, len,
- PCI_DMA_FROMDEVICE);
- skb_copy_from_linear_data(sd->t.skb, skb->data, len);
- pci_dma_sync_single_for_device(adap->pdev, mapping, len,
- PCI_DMA_FROMDEVICE);
- } else if (!drop_thres)
- goto use_orig_buf;
-recycle:
- recycle_rx_buf(adap, fl, fl->cidx);
- return skb;
- }
-
- if (unlikely(fl->credits < drop_thres))
- goto recycle;
-
-use_orig_buf:
- pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
- fl->buf_size, PCI_DMA_FROMDEVICE);
- skb = sd->t.skb;
- skb_put(skb, len);
- __refill_fl(adap, fl);
- return skb;
-}
-
/**
* handle_rsp_cntrl_info - handles control information in a response
* @qs: the queue set corresponding to the response
@@ -1935,7 +1975,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
} else if (flags & F_RSPD_IMM_DATA_VALID) {
skb = get_imm_packet(r);
if (unlikely(!skb)) {
- no_mem:
+no_mem:
q->next_holdoff = NOMEM_INTR_DELAY;
q->nomem++;
/* consume one credit since we tried */
@@ -1945,53 +1985,29 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
q->imm_data++;
ethpad = 0;
} else if ((len = ntohl(r->len_cq)) != 0) {
- struct sge_fl *fl =
- (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+ struct sge_fl *fl;
- if (fl->buf_size == RX_PAGE_SIZE) {
- struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
- struct sge_fl_page *p = &sd->t.page;
-
- prefetch(p->va);
- prefetch(p->va + L1_CACHE_BYTES);
+ fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+ if (fl->use_pages) {
+ void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
+ prefetch(addr);
+#if L1_CACHE_BYTES < 128
+ prefetch(addr + L1_CACHE_BYTES);
+#endif
__refill_fl(adap, fl);
- pci_unmap_single(adap->pdev,
- pci_unmap_addr(sd, dma_addr),
- fl->buf_size,
- PCI_DMA_FROMDEVICE);
-
- if (eth) {
- if (unlikely(fl->credits <
- SGE_RX_DROP_THRES))
- goto eth_recycle;
-
- skb = alloc_skb(SKB_DATA_SIZE,
- GFP_ATOMIC);
- if (unlikely(!skb)) {
-eth_recycle:
- q->rx_drops++;
- recycle_rx_buf(adap, fl,
- fl->cidx);
- goto eth_done;
- }
- } else {
- skb = alloc_skb(SKB_DATA_SIZE,
- GFP_ATOMIC);
- if (unlikely(!skb))
- goto no_mem;
- }
-
- skb_data_init(skb, p, G_RSPD_LEN(len));
-eth_done:
- fl->credits--;
- q->eth_pkts++;
- } else {
- fl->credits--;
+ skb = get_packet_pg(adap, fl, G_RSPD_LEN(len),
+ eth ? SGE_RX_DROP_THRES : 0);
+ } else
skb = get_packet(adap, fl, G_RSPD_LEN(len),
eth ? SGE_RX_DROP_THRES : 0);
- }
+ if (unlikely(!skb)) {
+ if (!eth)
+ goto no_mem;
+ q->rx_drops++;
+ } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT))
+ __skb_pull(skb, 2);
if (++fl->cidx == fl->size)
fl->cidx = 0;
@@ -2016,20 +2032,15 @@ eth_done:
q->credits = 0;
}
- if (skb) {
- /* Preserve the RSS info in csum & priority */
- skb->csum = rss_hi;
- skb->priority = rss_lo;
-
+ if (likely(skb != NULL)) {
if (eth)
rx_eth(adap, q, skb, ethpad);
else {
- if (unlikely(r->rss_hdr.opcode ==
- CPL_TRACE_PKT))
- __skb_pull(skb, ethpad);
-
- ngathered = rx_offload(&adap->tdev, q,
- skb, offload_skbs,
+ /* Preserve the RSS info in csum & priority */
+ skb->csum = rss_hi;
+ skb->priority = rss_lo;
+ ngathered = rx_offload(&adap->tdev, q, skb,
+ offload_skbs,
ngathered);
}
}
@@ -2635,25 +2646,15 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
q->txq[TXQ_ETH].stop_thres = nports *
flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
- if (!is_offload(adapter)) {
-#ifdef USE_RX_PAGE
- q->fl[0].buf_size = RX_PAGE_SIZE;
+#if FL0_PG_CHUNK_SIZE > 0
+ q->fl[0].buf_size = FL0_PG_CHUNK_SIZE;
#else
- q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 +
- sizeof(struct cpl_rx_pkt);
+ q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data);
#endif
- q->fl[1].buf_size = MAX_FRAME_SIZE + 2 +
- sizeof(struct cpl_rx_pkt);
- } else {
-#ifdef USE_RX_PAGE
- q->fl[0].buf_size = RX_PAGE_SIZE;
-#else
- q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE +
- sizeof(struct cpl_rx_data);
-#endif
- q->fl[1].buf_size = (16 * 1024) -
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- }
+ q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0;
+ q->fl[1].buf_size = is_offload(adapter) ?
+ (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
+ MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt);
spin_lock(&adapter->sge.reg_lock);
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index fb485d0a43d..dd3149d94ba 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -847,6 +847,64 @@ static int t3_write_flash(struct adapter *adapter, unsigned int addr,
return 0;
}
+/**
+ * t3_check_tpsram_version - read the tp sram version
+ * @adapter: the adapter
+ *
+ * Reads the protocol sram version from serial eeprom.
+ */
+int t3_check_tpsram_version(struct adapter *adapter)
+{
+ int ret;
+ u32 vers;
+ unsigned int major, minor;
+
+ /* Get version loaded in SRAM */
+ t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
+ ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
+ 1, 1, 5, 1);
+ if (ret)
+ return ret;
+
+ vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
+
+ major = G_TP_VERSION_MAJOR(vers);
+ minor = G_TP_VERSION_MINOR(vers);
+
+ if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
+ return 0;
+
+ return -EINVAL;
+}
+
+/**
+ * t3_check_tpsram - check if provided protocol SRAM
+ * is compatible with this driver
+ * @adapter: the adapter
+ * @tp_sram: the firmware image to write
+ * @size: image size
+ *
+ * Checks if an adapter's tp sram is compatible with the driver.
+ * Returns 0 if the versions are compatible, a negative error otherwise.
+ */
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size)
+{
+ u32 csum;
+ unsigned int i;
+ const u32 *p = (const u32 *)tp_sram;
+
+ /* Verify checksum */
+ for (csum = 0, i = 0; i < size / sizeof(csum); i++)
+ csum += ntohl(p[i]);
+ if (csum != 0xffffffff) {
+ CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
+ csum);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
enum fw_version_type {
FW_VERSION_N3,
FW_VERSION_T3
@@ -921,7 +979,7 @@ static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end)
/*
* t3_load_fw - download firmware
* @adapter: the adapter
- * @fw_data: the firrware image to write
+ * @fw_data: the firmware image to write
* @size: image size
*
* Write the supplied firmware image to the card's serial flash.
@@ -2362,7 +2420,7 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
F_MTUENABLE | V_WINDOWSCALEMODE(1) |
- V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
+ V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1));
t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) |
@@ -2371,16 +2429,18 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
F_IPV6ENABLE | F_NICMODE);
t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
- t3_set_reg_field(adap, A_TP_PARA_REG6,
- adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND,
- 0);
+ t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
+ adap->params.rev > 0 ? F_ENABLEESND :
+ F_T3A_ENABLEESND);
t3_set_reg_field(adap, A_TP_PC_CONFIG,
- F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL,
- F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE |
- F_RXCONGESTIONMODE);
+ F_ENABLEEPCMDAFULL,
+ F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
+ F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
-
+ t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
+ t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
+
if (adap->params.rev > 0) {
tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
@@ -2390,9 +2450,10 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
} else
t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
- t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212);
- t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212);
- t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212);
+ t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
+ t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
+ t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
+ t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
}
/* Desired TP timer resolution in usec */
@@ -2468,6 +2529,7 @@ int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh)
val |= F_RXCOALESCEENABLE;
if (psh)
val |= F_RXCOALESCEPSHEN;
+ size = min(MAX_RX_COALESCING_LEN, size);
t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
V_MAXRXDATA(MAX_RX_COALESCING_LEN));
}
@@ -2496,11 +2558,11 @@ static void __devinit init_mtus(unsigned short mtus[])
* it can accomodate max size TCP/IP headers when SACK and timestamps
* are enabled and still have at least 8 bytes of payload.
*/
- mtus[0] = 88;
- mtus[1] = 256;
- mtus[2] = 512;
- mtus[3] = 576;
- mtus[4] = 808;
+ mtus[1] = 88;
+ mtus[1] = 88;
+ mtus[2] = 256;
+ mtus[3] = 512;
+ mtus[4] = 576;
mtus[5] = 1024;
mtus[6] = 1280;
mtus[7] = 1492;
@@ -2682,6 +2744,34 @@ static void ulp_config(struct adapter *adap, const struct tp_params *p)
t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
}
+/**
+ * t3_set_proto_sram - set the contents of the protocol sram
+ * @adapter: the adapter
+ * @data: the protocol image
+ *
+ * Write the contents of the protocol SRAM.
+ */
+int t3_set_proto_sram(struct adapter *adap, u8 *data)
+{
+ int i;
+ u32 *buf = (u32 *)data;
+
+ for (i = 0; i < PROTO_SRAM_LINES; i++) {
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++));
+
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
+ if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
+ return -EIO;
+ }
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0);
+
+ return 0;
+}
+
void t3_config_trace_filter(struct adapter *adapter,
const struct trace_params *tp, int filter_index,
int invert, int enable)
@@ -2802,7 +2892,7 @@ static void init_hw_for_avail_ports(struct adapter *adap, int nports)
t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN |
F_PORT0ACTIVE | F_ENFORCEPKT);
- t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000);
+ t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff);
} else {
t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
@@ -3097,7 +3187,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
else
t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN);
- t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000);
+ t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
init_hw_for_avail_ports(adapter, adapter->params.nports);
t3_sge_init(adapter, &adapter->params.sge);
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h
index b112317f033..8eddd23a3a5 100644
--- a/drivers/net/cxgb3/version.h
+++ b/drivers/net/cxgb3/version.h
@@ -39,6 +39,6 @@
/* Firmware version */
#define FW_VERSION_MAJOR 4
-#define FW_VERSION_MINOR 0
+#define FW_VERSION_MINOR 1
#define FW_VERSION_MICRO 0
#endif /* __CHELSIO_VERSION_H */
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 763810c7f33..74ea6373c7c 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -159,7 +159,7 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.5.17-k4"DRV_EXT
+#define DRV_VERSION "3.5.23-k4"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation"
#define PFX DRV_NAME ": "
@@ -1024,10 +1024,16 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
config->mwi_enable = 0x1; /* 1=enable, 0=disable */
config->standard_tcb = 0x0; /* 1=standard, 0=extended */
config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */
- if(nic->mac >= mac_82559_D101M)
+ if (nic->mac >= mac_82559_D101M) {
config->tno_intr = 0x1; /* TCO stats enable */
- else
+ /* Enable TCO in extended config */
+ if (nic->mac >= mac_82551_10) {
+ config->byte_count = 0x20; /* extended bytes */
+ config->rx_d102_mode = 0x1; /* GMRC for TCO */
+ }
+ } else {
config->standard_stat_counter = 0x0;
+ }
}
DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index c0f81b5a30f..f03f070451d 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,13 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0064"
+#define DRV_VERSION "EHEA_0067"
+
+/* EHEA capability flags */
+#define DLPAR_PORT_ADD_REM 1
+#define DLPAR_MEM_ADD 2
+#define DLPAR_MEM_REM 4
+#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -136,10 +142,10 @@ void ehea_dump(void *adr, int len, char *msg);
(0xffffffffffffffffULL >> ((64 - (mask)) & 0xffff))
#define EHEA_BMASK_SET(mask, value) \
- ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
+ ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
#define EHEA_BMASK_GET(mask, value) \
- (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
+ (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
/*
* Generic ehea page
@@ -190,7 +196,7 @@ struct ehea_av;
* Queue attributes passed to ehea_create_qp()
*/
struct ehea_qp_init_attr {
- /* input parameter */
+ /* input parameter */
u32 qp_token; /* queue token */
u8 low_lat_rq1;
u8 signalingtype; /* cqe generation flag */
@@ -212,7 +218,7 @@ struct ehea_qp_init_attr {
u64 recv_cq_handle;
u64 aff_eq_handle;
- /* output parameter */
+ /* output parameter */
u32 qp_nr;
u16 act_nr_send_wqes;
u16 act_nr_rwqes_rq1;
@@ -279,12 +285,12 @@ struct ehea_qp {
* Completion Queue attributes
*/
struct ehea_cq_attr {
- /* input parameter */
+ /* input parameter */
u32 max_nr_of_cqes;
u32 cq_token;
u64 eq_handle;
- /* output parameter */
+ /* output parameter */
u32 act_nr_of_cqes;
u32 nr_pages;
};
diff --git a/drivers/net/ehea/ehea_hw.h b/drivers/net/ehea/ehea_hw.h
index 1246757f2c2..1af7ca499ec 100644
--- a/drivers/net/ehea/ehea_hw.h
+++ b/drivers/net/ehea/ehea_hw.h
@@ -211,34 +211,34 @@ static inline void epa_store_acc(struct h_epa epa, u32 offset, u64 value)
}
#define epa_store_eq(epa, offset, value)\
- epa_store(epa, EQTEMM_OFFSET(offset), value)
+ epa_store(epa, EQTEMM_OFFSET(offset), value)
#define epa_load_eq(epa, offset)\
- epa_load(epa, EQTEMM_OFFSET(offset))
+ epa_load(epa, EQTEMM_OFFSET(offset))
#define epa_store_cq(epa, offset, value)\
- epa_store(epa, CQTEMM_OFFSET(offset), value)
+ epa_store(epa, CQTEMM_OFFSET(offset), value)
#define epa_load_cq(epa, offset)\
- epa_load(epa, CQTEMM_OFFSET(offset))
+ epa_load(epa, CQTEMM_OFFSET(offset))
#define epa_store_qp(epa, offset, value)\
- epa_store(epa, QPTEMM_OFFSET(offset), value)
+ epa_store(epa, QPTEMM_OFFSET(offset), value)
#define epa_load_qp(epa, offset)\
- epa_load(epa, QPTEMM_OFFSET(offset))
+ epa_load(epa, QPTEMM_OFFSET(offset))
#define epa_store_qped(epa, offset, value)\
- epa_store(epa, QPEDMM_OFFSET(offset), value)
+ epa_store(epa, QPEDMM_OFFSET(offset), value)
#define epa_load_qped(epa, offset)\
- epa_load(epa, QPEDMM_OFFSET(offset))
+ epa_load(epa, QPEDMM_OFFSET(offset))
#define epa_store_mrmw(epa, offset, value)\
- epa_store(epa, MRMWMM_OFFSET(offset), value)
+ epa_store(epa, MRMWMM_OFFSET(offset), value)
#define epa_load_mrmw(epa, offset)\
- epa_load(epa, MRMWMM_OFFSET(offset))
+ epa_load(epa, MRMWMM_OFFSET(offset))
#define epa_store_base(epa, offset, value)\
- epa_store(epa, HCAGR_OFFSET(offset), value)
+ epa_store(epa, HCAGR_OFFSET(offset), value)
#define epa_load_base(epa, offset)\
- epa_load(epa, HCAGR_OFFSET(offset))
+ epa_load(epa, HCAGR_OFFSET(offset))
static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes)
{
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 9e13433a268..383144db4d1 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -81,7 +81,7 @@ MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
static int port_name_cnt = 0;
static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
- const struct of_device_id *id);
+ const struct of_device_id *id);
static int __devexit ehea_remove(struct ibmebus_dev *dev);
@@ -236,7 +236,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
rwqe = ehea_get_next_rwqe(qp, rq_nr);
rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
- | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
+ | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
rwqe->sg_list[0].vaddr = (u64)skb->data;
rwqe->sg_list[0].len = packet_size;
@@ -427,7 +427,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
break;
}
skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
- cqe->num_bytes_transfered - 4);
+ cqe->num_bytes_transfered - 4);
ehea_fill_skb(port->netdev, skb, cqe);
} else if (rq == 2) { /* RQ2 */
skb = get_skb_by_index(skb_arr_rq2,
@@ -618,7 +618,7 @@ static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter,
for (i = 0; i < EHEA_MAX_PORTS; i++)
if (adapter->port[i])
- if (adapter->port[i]->logical_port_id == logical_port)
+ if (adapter->port[i]->logical_port_id == logical_port)
return adapter->port[i];
return NULL;
}
@@ -1695,6 +1695,7 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
{
if (skb->protocol == htons(ETH_P_IP)) {
const struct iphdr *iph = ip_hdr(skb);
+
/* IPv4 */
swqe->tx_control |= EHEA_SWQE_CRC
| EHEA_SWQE_IP_CHECKSUM
@@ -1705,13 +1706,12 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
write_ip_start_end(swqe, skb);
if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
+ if ((iph->frag_off & IP_MF)
+ || (iph->frag_off & IP_OFFSET))
/* IP fragment, so don't change cs */
swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
else
write_udp_offset_end(swqe, skb);
-
} else if (iph->protocol == IPPROTO_TCP) {
write_tcp_offset_end(swqe, skb);
}
@@ -1739,6 +1739,7 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
if (skb->protocol == htons(ETH_P_IP)) {
const struct iphdr *iph = ip_hdr(skb);
+
/* IPv4 */
write_ip_start_end(swqe, skb);
@@ -1751,8 +1752,8 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
write_tcp_offset_end(swqe, skb);
} else if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
+ if ((iph->frag_off & IP_MF)
+ || (iph->frag_off & IP_OFFSET))
/* IP fragment, so don't change cs */
swqe->tx_control |= EHEA_SWQE_CRC
| EHEA_SWQE_IMM_DATA_PRESENT;
@@ -2407,7 +2408,7 @@ static void __devinit logical_port_release(struct device *dev)
}
static int ehea_driver_sysfs_add(struct device *dev,
- struct device_driver *driver)
+ struct device_driver *driver)
{
int ret;
@@ -2424,7 +2425,7 @@ static int ehea_driver_sysfs_add(struct device *dev,
}
static void ehea_driver_sysfs_remove(struct device *dev,
- struct device_driver *driver)
+ struct device_driver *driver)
{
struct device_driver *drv = driver;
@@ -2453,7 +2454,7 @@ static struct device *ehea_register_port(struct ehea_port *port,
}
ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
- if (ret) {
+ if (ret) {
ehea_error("failed to register attributes, ret=%d", ret);
goto out_unreg_of_dev;
}
@@ -2601,6 +2602,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
{
struct device_node *lhea_dn;
struct device_node *eth_dn = NULL;
+
const u32 *dn_log_port_id;
int i = 0;
@@ -2608,7 +2610,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
- NULL);
+ NULL);
if (!dn_log_port_id) {
ehea_error("bad device node: eth_dn name=%s",
eth_dn->full_name);
@@ -2648,7 +2650,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
- NULL);
+ NULL);
if (dn_log_port_id)
if (*dn_log_port_id == logical_port_id)
return eth_dn;
@@ -2789,7 +2791,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
adapter->ebus_dev = dev;
adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
- NULL);
+ NULL);
if (adapter_handle)
adapter->handle = *adapter_handle;
@@ -2921,6 +2923,15 @@ static int check_module_parm(void)
return ret;
}
+static ssize_t ehea_show_capabilities(struct device_driver *drv,
+ char *buf)
+{
+ return sprintf(buf, "%d", EHEA_CAPABILITIES);
+}
+
+static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
+ ehea_show_capabilities, NULL);
+
int __init ehea_module_init(void)
{
int ret;
@@ -2932,8 +2943,19 @@ int __init ehea_module_init(void)
if (ret)
goto out;
ret = ibmebus_register_driver(&ehea_driver);
- if (ret)
+ if (ret) {
ehea_error("failed registering eHEA device driver on ebus");
+ goto out;
+ }
+
+ ret = driver_create_file(&ehea_driver.driver,
+ &driver_attr_capabilities);
+ if (ret) {
+ ehea_error("failed to register capabilities attribute, ret=%d",
+ ret);
+ ibmebus_unregister_driver(&ehea_driver);
+ goto out;
+ }
out:
return ret;
@@ -2941,6 +2963,7 @@ out:
static void __exit ehea_module_exit(void)
{
+ driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
ibmebus_unregister_driver(&ehea_driver);
}
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index f24a8862977..29eaa46948b 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -211,7 +211,7 @@ u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
u64 hret;
u64 adapter_handle = cq->adapter->handle;
- /* deregister all previous registered pages */
+ /* deregister all previous registered pages */
hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force);
if (hret != H_SUCCESS)
return hret;
@@ -362,7 +362,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)
if (hret != H_SUCCESS) {
ehea_error("destroy EQ failed");
return -EIO;
- }
+ }
return 0;
}
@@ -507,44 +507,44 @@ out_freemem:
u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
{
- u64 hret;
- struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
+ u64 hret;
+ struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
- ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
- hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
- if (hret != H_SUCCESS)
- return hret;
+ ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
+ hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
+ if (hret != H_SUCCESS)
+ return hret;
- hw_queue_dtor(&qp->hw_squeue);
- hw_queue_dtor(&qp->hw_rqueue1);
+ hw_queue_dtor(&qp->hw_squeue);
+ hw_queue_dtor(&qp->hw_rqueue1);
- if (qp_attr->rq_count > 1)
- hw_queue_dtor(&qp->hw_rqueue2);
- if (qp_attr->rq_count > 2)
- hw_queue_dtor(&qp->hw_rqueue3);
- kfree(qp);
+ if (qp_attr->rq_count > 1)
+ hw_queue_dtor(&qp->hw_rqueue2);
+ if (qp_attr->rq_count > 2)
+ hw_queue_dtor(&qp->hw_rqueue3);
+ kfree(qp);
- return hret;
+ return hret;
}
int ehea_destroy_qp(struct ehea_qp *qp)
{
- u64 hret;
- if (!qp)
- return 0;
+ u64 hret;
+ if (!qp)
+ return 0;
- if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
- ehea_error_data(qp->adapter, qp->fw_handle);
- hret = ehea_destroy_qp_res(qp, FORCE_FREE);
- }
+ if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
+ ehea_error_data(qp->adapter, qp->fw_handle);
+ hret = ehea_destroy_qp_res(qp, FORCE_FREE);
+ }
- if (hret != H_SUCCESS) {
- ehea_error("destroy QP failed");
- return -EIO;
- }
+ if (hret != H_SUCCESS) {
+ ehea_error("destroy QP failed");
+ return -EIO;
+ }
- return 0;
+ return 0;
}
int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig
index a84c232395e..afb34ded26e 100644
--- a/drivers/net/fec_8xx/Kconfig
+++ b/drivers/net/fec_8xx/Kconfig
@@ -1,6 +1,6 @@
config FEC_8XX
tristate "Motorola 8xx FEC driver"
- depends on NET_ETHERNET && 8xx
+ depends on 8XX
select MII
config FEC_8XX_GENERIC_PHY
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 6aaee67dd4b..e27ee210b60 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -1,6 +1,6 @@
config FS_ENET
tristate "Freescale Ethernet Driver"
- depends on NET_ETHERNET && (CPM1 || CPM2)
+ depends on CPM1 || CPM2
select MII
config FS_ENET_HAS_SCC
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 1b854bf07b0..d7a1a58de76 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -130,6 +130,9 @@ static int gfar_remove(struct platform_device *pdev);
static void free_skb_resources(struct gfar_private *priv);
static void gfar_set_multi(struct net_device *dev);
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
+static void gfar_configure_serdes(struct net_device *dev);
+extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value);
+extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum);
#ifdef CONFIG_GFAR_NAPI
static int gfar_poll(struct net_device *dev, int *budget);
#endif
@@ -451,6 +454,9 @@ static int init_phy(struct net_device *dev)
phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface);
+ if (interface == PHY_INTERFACE_MODE_SGMII)
+ gfar_configure_serdes(dev);
+
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
return PTR_ERR(phydev);
@@ -465,6 +471,27 @@ static int init_phy(struct net_device *dev)
return 0;
}
+static void gfar_configure_serdes(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_mii __iomem *regs =
+ (void __iomem *)&priv->regs->gfar_mii_regs;
+
+ /* Initialise TBI i/f to communicate with serdes (lynx phy) */
+
+ /* Single clk mode, mii mode off(for aerdes communication) */
+ gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT);
+
+ /* Supported pause and full-duplex, no half-duplex */
+ gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE,
+ ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
+ ADVERTISE_1000XPSE_ASYM);
+
+ /* ANEG enable, restart ANEG, full duplex mode, speed[1] set */
+ gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE |
+ BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
+}
+
static void init_registers(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 39e9e321fcb..d8e779c102f 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -136,6 +136,12 @@ extern const char gfar_driver_version[];
#define MIIMCFG_RESET 0x80000000
#define MIIMIND_BUSY 0x00000001
+/* TBI register addresses */
+#define MII_TBICON 0x11
+
+/* TBICON register bit fields */
+#define TBICON_CLK_SELECT 0x0020
+
/* MAC register bits */
#define MACCFG1_SOFT_RESET 0x80000000
#define MACCFG1_RESET_RX_MC 0x00080000
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index bcc6b82f4a3..5dd34a1a7b8 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -43,13 +43,18 @@
#include "gianfar.h"
#include "gianfar_mii.h"
-/* Write value to the PHY at mii_id at register regnum,
- * on the bus, waiting until the write is done before returning.
- * All PHY configuration is done through the TSEC1 MIIM regs */
-int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+/*
+ * Write value to the PHY at mii_id at register regnum,
+ * on the bus attached to the local interface, which may be different from the
+ * generic mdio bus (tied to a single interface), waiting until the write is
+ * done before returning. This is helpful in programming interfaces like
+ * the TBI which control interfaces like onchip SERDES and are always tied to
+ * the local mdio pins, which may not be the same as system mdio bus, used for
+ * controlling the external PHYs, for example.
+ */
+int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id,
+ int regnum, u16 value)
{
- struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
-
/* Set the PHY address and the register address we want to write */
gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
@@ -63,12 +68,19 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
return 0;
}
-/* Read the bus for PHY at addr mii_id, register regnum, and
- * return the value. Clears miimcom first. All PHY
- * configuration has to be done through the TSEC1 MIIM regs */
-int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+/*
+ * Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value. Clears miimcom first. All PHY operation
+ * done on the bus attached to the local interface,
+ * which may be different from the generic mdio bus
+ * This is helpful in programming interfaces like
+ * the TBI which, inturn, control interfaces like onchip SERDES
+ * and are always tied to the local mdio pins, which may not be the
+ * same as system mdio bus, used for controlling the external PHYs, for eg.
+ */
+int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum)
+
{
- struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
u16 value;
/* Set the PHY address and the register address we want to read */
@@ -88,6 +100,27 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
return value;
}
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+ /* Write to the local MII regs */
+ return(gfar_local_mdio_write(regs, mii_id, regnum, value));
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value. Clears miimcom first. All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+ /* Read the local MII regs */
+ return(gfar_local_mdio_read(regs, mii_id, regnum));
+}
/* Reset the MIIM registers, and wait for the bus to free */
int gfar_mdio_reset(struct mii_bus *bus)
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index f749e07c642..3ca1e8ece54 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -352,13 +352,12 @@ static u64 nic_find(struct ioc3 *ioc3, int *last)
static int nic_init(struct ioc3 *ioc3)
{
- const char *type;
+ const char *unknown = "unknown";
+ const char *type = unknown;
u8 crc;
u8 serial[6];
int save = 0, i;
- type = "unknown";
-
while (1) {
u64 reg;
reg = nic_find(ioc3, &save);
@@ -392,7 +391,7 @@ static int nic_init(struct ioc3 *ioc3)
}
printk("Found %s NIC", type);
- if (type != "unknown") {
+ if (type != unknown) {
printk (" registration number %02x:%02x:%02x:%02x:%02x:%02x,"
" CRC %02x", serial[0], serial[1], serial[2],
serial[3], serial[4], serial[5], crc);
@@ -1103,20 +1102,28 @@ static int ioc3_close(struct net_device *dev)
* MiniDINs; all other subdevices are left swinging in the wind, leave
* them disabled.
*/
-static inline int ioc3_is_menet(struct pci_dev *pdev)
+
+static int ioc3_adjacent_is_ioc3(struct pci_dev *pdev, int slot)
+{
+ struct pci_dev *dev = pci_get_slot(pdev->bus, PCI_DEVFN(slot, 0));
+ int ret = 0;
+
+ if (dev) {
+ if (dev->vendor == PCI_VENDOR_ID_SGI &&
+ dev->device == PCI_DEVICE_ID_SGI_IOC3)
+ ret = 1;
+ pci_dev_put(dev);
+ }
+
+ return ret;
+}
+
+static int ioc3_is_menet(struct pci_dev *pdev)
{
- struct pci_dev *dev;
-
- return pdev->bus->parent == NULL
- && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(0, 0)))
- && dev->vendor == PCI_VENDOR_ID_SGI
- && dev->device == PCI_DEVICE_ID_SGI_IOC3
- && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(1, 0)))
- && dev->vendor == PCI_VENDOR_ID_SGI
- && dev->device == PCI_DEVICE_ID_SGI_IOC3
- && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(2, 0)))
- && dev->vendor == PCI_VENDOR_ID_SGI
- && dev->device == PCI_DEVICE_ID_SGI_IOC3;
+ return pdev->bus->parent == NULL &&
+ ioc3_adjacent_is_ioc3(pdev, 0) &&
+ ioc3_adjacent_is_ioc3(pdev, 1) &&
+ ioc3_adjacent_is_ioc3(pdev, 2);
}
#ifdef CONFIG_SERIAL_8250
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 6683afc02aa..d5f694fc4a2 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -222,7 +222,7 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id)
static void ixpdev_poll_controller(struct net_device *dev)
{
disable_irq(IRQ_IXP2000_THDA0);
- ixpdev_interrupt(IRQ_IXP2000_THDA0, dev, NULL);
+ ixpdev_interrupt(IRQ_IXP2000_THDA0, dev);
enable_irq(IRQ_IXP2000_THDA0);
}
#endif
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 741780e14b2..efbae4b8398 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -86,93 +86,36 @@
#include <linux/dma-mapping.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/pdc.h>
-#include <asm/cache.h>
#include <asm/parisc-device.h>
#define LASI_82596_DRIVER_VERSION "LASI 82596 driver - Revision: 1.30"
-/* DEBUG flags
- */
-
-#define DEB_INIT 0x0001
-#define DEB_PROBE 0x0002
-#define DEB_SERIOUS 0x0004
-#define DEB_ERRORS 0x0008
-#define DEB_MULTI 0x0010
-#define DEB_TDR 0x0020
-#define DEB_OPEN 0x0040
-#define DEB_RESET 0x0080
-#define DEB_ADDCMD 0x0100
-#define DEB_STATUS 0x0200
-#define DEB_STARTTX 0x0400
-#define DEB_RXADDR 0x0800
-#define DEB_TXADDR 0x1000
-#define DEB_RXFRAME 0x2000
-#define DEB_INTS 0x4000
-#define DEB_STRUCT 0x8000
-#define DEB_ANY 0xffff
-
-
-#define DEB(x,y) if (i596_debug & (x)) { y; }
-
-
-#define CHECK_WBACK(priv, addr,len) \
- do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0)
-
-#define CHECK_INV(priv, addr,len) \
- do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0)
-
-#define CHECK_WBACK_INV(priv, addr,len) \
- do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
-
-
#define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/
#define PA_CPU_PORT_L_ACCESS 4
#define PA_CHANNEL_ATTENTION 8
+#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */
-/*
- * Define various macros for Channel Attention, word swapping etc., dependent
- * on architecture. MVME and BVME are 680x0 based, otherwise it is Intel.
- */
+#define DMA_ALLOC dma_alloc_noncoherent
+#define DMA_FREE dma_free_noncoherent
+#define DMA_WBACK(ndev, addr, len) \
+ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0)
-#ifdef __BIG_ENDIAN
-#define WSWAPrfd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPrbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPiscp(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPscb(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPcmd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPtbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPchar(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define ISCP_BUSY 0x00010000
-#define MACH_IS_APRICOT 0
-#else
-#define WSWAPrfd(x) ((struct i596_rfd *)(x))
-#define WSWAPrbd(x) ((struct i596_rbd *)(x))
-#define WSWAPiscp(x) ((struct i596_iscp *)(x))
-#define WSWAPscb(x) ((struct i596_scb *)(x))
-#define WSWAPcmd(x) ((struct i596_cmd *)(x))
-#define WSWAPtbd(x) ((struct i596_tbd *)(x))
-#define WSWAPchar(x) ((char *)(x))
-#define ISCP_BUSY 0x0001
-#define MACH_IS_APRICOT 1
-#endif
+#define DMA_INV(ndev, addr, len) \
+ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_FROM_DEVICE); } while (0)
-/*
- * The MPU_PORT command allows direct access to the 82596. With PORT access
- * the following commands are available (p5-18). The 32-bit port command
- * must be word-swapped with the most significant word written first.
- * This only applies to VME boards.
- */
-#define PORT_RESET 0x00 /* reset 82596 */
-#define PORT_SELFTEST 0x01 /* selftest */
-#define PORT_ALTSCP 0x02 /* alternate SCB address */
-#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */
+#define DMA_WBACK_INV(ndev, addr, len) \
+ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
+
+#define SYSBUS 0x0000006c;
+
+/* big endian CPU, 82596 "big" endian mode */
+#define SWAP32(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
+#define SWAP16(x) (x)
-static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+#include "lib82596.c"
MODULE_AUTHOR("Richard Hirst");
MODULE_DESCRIPTION("i82596 driver");
@@ -180,255 +123,15 @@ MODULE_LICENSE("GPL");
module_param(i596_debug, int, 0);
MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask");
-/* Copy frames shorter than rx_copybreak, otherwise pass on up in
- * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha).
- */
-static int rx_copybreak = 100;
-
-#define MAX_DRIVERS 4 /* max count of drivers */
-
-#define PKT_BUF_SZ 1536
-#define MAX_MC_CNT 64
-
-#define I596_NULL ((u32)0xffffffff)
-
-#define CMD_EOL 0x8000 /* The last command of the list, stop. */
-#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */
-#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */
-
-#define CMD_FLEX 0x0008 /* Enable flexible memory model */
-
-enum commands {
- CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
- CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
-};
-
-#define STAT_C 0x8000 /* Set to 0 after execution */
-#define STAT_B 0x4000 /* Command being executed */
-#define STAT_OK 0x2000 /* Command executed ok */
-#define STAT_A 0x1000 /* Command aborted */
-
-#define CUC_START 0x0100
-#define CUC_RESUME 0x0200
-#define CUC_SUSPEND 0x0300
-#define CUC_ABORT 0x0400
-#define RX_START 0x0010
-#define RX_RESUME 0x0020
-#define RX_SUSPEND 0x0030
-#define RX_ABORT 0x0040
-
-#define TX_TIMEOUT 5
-
-#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */
-
-
-struct i596_reg {
- unsigned short porthi;
- unsigned short portlo;
- u32 ca;
-};
-
-#define EOF 0x8000
-#define SIZE_MASK 0x3fff
-
-struct i596_tbd {
- unsigned short size;
- unsigned short pad;
- dma_addr_t next;
- dma_addr_t data;
- u32 cache_pad[5]; /* Total 32 bytes... */
-};
-
-/* The command structure has two 'next' pointers; v_next is the address of
- * the next command as seen by the CPU, b_next is the address of the next
- * command as seen by the 82596. The b_next pointer, as used by the 82596
- * always references the status field of the next command, rather than the
- * v_next field, because the 82596 is unaware of v_next. It may seem more
- * logical to put v_next at the end of the structure, but we cannot do that
- * because the 82596 expects other fields to be there, depending on command
- * type.
- */
-
-struct i596_cmd {
- struct i596_cmd *v_next; /* Address from CPUs viewpoint */
- unsigned short status;
- unsigned short command;
- dma_addr_t b_next; /* Address from i596 viewpoint */
-};
-
-struct tx_cmd {
- struct i596_cmd cmd;
- dma_addr_t tbd;
- unsigned short size;
- unsigned short pad;
- struct sk_buff *skb; /* So we can free it after tx */
- dma_addr_t dma_addr;
-#ifdef __LP64__
- u32 cache_pad[6]; /* Total 64 bytes... */
-#else
- u32 cache_pad[1]; /* Total 32 bytes... */
-#endif
-};
-
-struct tdr_cmd {
- struct i596_cmd cmd;
- unsigned short status;
- unsigned short pad;
-};
-
-struct mc_cmd {
- struct i596_cmd cmd;
- short mc_cnt;
- char mc_addrs[MAX_MC_CNT*6];
-};
-
-struct sa_cmd {
- struct i596_cmd cmd;
- char eth_addr[8];
-};
-
-struct cf_cmd {
- struct i596_cmd cmd;
- char i596_config[16];
-};
-
-struct i596_rfd {
- unsigned short stat;
- unsigned short cmd;
- dma_addr_t b_next; /* Address from i596 viewpoint */
- dma_addr_t rbd;
- unsigned short count;
- unsigned short size;
- struct i596_rfd *v_next; /* Address from CPUs viewpoint */
- struct i596_rfd *v_prev;
-#ifndef __LP64__
- u32 cache_pad[2]; /* Total 32 bytes... */
-#endif
-};
-
-struct i596_rbd {
- /* hardware data */
- unsigned short count;
- unsigned short zero1;
- dma_addr_t b_next;
- dma_addr_t b_data; /* Address from i596 viewpoint */
- unsigned short size;
- unsigned short zero2;
- /* driver data */
- struct sk_buff *skb;
- struct i596_rbd *v_next;
- dma_addr_t b_addr; /* This rbd addr from i596 view */
- unsigned char *v_data; /* Address from CPUs viewpoint */
- /* Total 32 bytes... */
-#ifdef __LP64__
- u32 cache_pad[4];
-#endif
-};
-
-/* These values as chosen so struct i596_private fits in one page... */
-
-#define TX_RING_SIZE 32
-#define RX_RING_SIZE 16
-
-struct i596_scb {
- unsigned short status;
- unsigned short command;
- dma_addr_t cmd;
- dma_addr_t rfd;
- u32 crc_err;
- u32 align_err;
- u32 resource_err;
- u32 over_err;
- u32 rcvdt_err;
- u32 short_err;
- unsigned short t_on;
- unsigned short t_off;
-};
-
-struct i596_iscp {
- u32 stat;
- dma_addr_t scb;
-};
-
-struct i596_scp {
- u32 sysbus;
- u32 pad;
- dma_addr_t iscp;
-};
-
-struct i596_private {
- volatile struct i596_scp scp __attribute__((aligned(32)));
- volatile struct i596_iscp iscp __attribute__((aligned(32)));
- volatile struct i596_scb scb __attribute__((aligned(32)));
- struct sa_cmd sa_cmd __attribute__((aligned(32)));
- struct cf_cmd cf_cmd __attribute__((aligned(32)));
- struct tdr_cmd tdr_cmd __attribute__((aligned(32)));
- struct mc_cmd mc_cmd __attribute__((aligned(32)));
- struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32)));
- struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32)));
- struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32)));
- struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32)));
- u32 stat;
- int last_restart;
- struct i596_rfd *rfd_head;
- struct i596_rbd *rbd_head;
- struct i596_cmd *cmd_tail;
- struct i596_cmd *cmd_head;
- int cmd_backlog;
- u32 last_cmd;
- struct net_device_stats stats;
- int next_tx_cmd;
- int options;
- spinlock_t lock;
- dma_addr_t dma_addr;
- struct device *dev;
-};
-
-static const char init_setup[] =
-{
- 0x8E, /* length, prefetch on */
- 0xC8, /* fifo to 8, monitor off */
- 0x80, /* don't save bad frames */
- 0x2E, /* No source address insertion, 8 byte preamble */
- 0x00, /* priority and backoff defaults */
- 0x60, /* interframe spacing */
- 0x00, /* slot time LSB */
- 0xf2, /* slot time and retries */
- 0x00, /* promiscuous mode */
- 0x00, /* collision detect */
- 0x40, /* minimum frame length */
- 0xff,
- 0x00,
- 0x7f /* *multi IA */ };
-
-static int i596_open(struct net_device *dev);
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id);
-static int i596_close(struct net_device *dev);
-static struct net_device_stats *i596_get_stats(struct net_device *dev);
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
-static void i596_tx_timeout (struct net_device *dev);
-static void print_eth(unsigned char *buf, char *str);
-static void set_multicast_list(struct net_device *dev);
-
-static int rx_ring_size = RX_RING_SIZE;
-static int ticks_limit = 100;
-static int max_cmd_backlog = TX_RING_SIZE-1;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev);
-#endif
-
-
-static inline void CA(struct net_device *dev)
+static inline void ca(struct net_device *dev)
{
gsc_writel(0, dev->base_addr + PA_CHANNEL_ATTENTION);
}
-static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x)
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
u32 v = (u32) (c) | (u32) (x);
u16 a, b;
@@ -446,1078 +149,15 @@ static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x)
gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS);
}
-
-static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
- CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
- while (--delcnt && lp->iscp.stat) {
- udelay(10);
- CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
- }
- if (!delcnt) {
- printk("%s: %s, iscp.stat %04x, didn't clear\n",
- dev->name, str, lp->iscp.stat);
- return -1;
- }
- else
- return 0;
-}
-
-
-static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
- CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
- while (--delcnt && lp->scb.command) {
- udelay(10);
- CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
- }
- if (!delcnt) {
- printk("%s: %s, status %4.4x, cmd %4.4x.\n",
- dev->name, str, lp->scb.status, lp->scb.command);
- return -1;
- }
- else
- return 0;
-}
-
-
-static void i596_display_data(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct i596_cmd *cmd;
- struct i596_rfd *rfd;
- struct i596_rbd *rbd;
-
- printk("lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
- &lp->scp, lp->scp.sysbus, lp->scp.iscp);
- printk("iscp at %p, iscp.stat = %08x, .scb = %08x\n",
- &lp->iscp, lp->iscp.stat, lp->iscp.scb);
- printk("scb at %p, scb.status = %04x, .command = %04x,"
- " .cmd = %08x, .rfd = %08x\n",
- &lp->scb, lp->scb.status, lp->scb.command,
- lp->scb.cmd, lp->scb.rfd);
- printk(" errors: crc %x, align %x, resource %x,"
- " over %x, rcvdt %x, short %x\n",
- lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err,
- lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err);
- cmd = lp->cmd_head;
- while (cmd != NULL) {
- printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %08x\n",
- cmd, cmd->status, cmd->command, cmd->b_next);
- cmd = cmd->v_next;
- }
- rfd = lp->rfd_head;
- printk("rfd_head = %p\n", rfd);
- do {
- printk(" %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
- " count %04x\n",
- rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd,
- rfd->count);
- rfd = rfd->v_next;
- } while (rfd != lp->rfd_head);
- rbd = lp->rbd_head;
- printk("rbd_head = %p\n", rbd);
- do {
- printk(" %p .count %04x, b_next %08x, b_data %08x, size %04x\n",
- rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size);
- rbd = rbd->v_next;
- } while (rbd != lp->rbd_head);
- CHECK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-static void i596_error(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
- pcc2[0x28] = 1;
- pcc2[0x2b] = 0x1d;
- printk("%s: Error interrupt\n", dev->name);
- i596_display_data(dev);
-}
-#endif
-
-#define virt_to_dma(lp,v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)(lp)))
-
-static inline void init_rx_bufs(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- int i;
- struct i596_rfd *rfd;
- struct i596_rbd *rbd;
-
- /* First build the Receive Buffer Descriptor List */
-
- for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
- dma_addr_t dma_addr;
- struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4);
-
- if (skb == NULL)
- panic("%s: alloc_skb() failed", __FILE__);
- skb_reserve(skb, 2);
- dma_addr = dma_map_single(lp->dev, skb->data,PKT_BUF_SZ,
- DMA_FROM_DEVICE);
- skb->dev = dev;
- rbd->v_next = rbd+1;
- rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1));
- rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd));
- rbd->skb = skb;
- rbd->v_data = skb->data;
- rbd->b_data = WSWAPchar(dma_addr);
- rbd->size = PKT_BUF_SZ;
- }
- lp->rbd_head = lp->rbds;
- rbd = lp->rbds + rx_ring_size - 1;
- rbd->v_next = lp->rbds;
- rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
- /* Now build the Receive Frame Descriptor List */
-
- for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
- rfd->rbd = I596_NULL;
- rfd->v_next = rfd+1;
- rfd->v_prev = rfd-1;
- rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1));
- rfd->cmd = CMD_FLEX;
- }
- lp->rfd_head = lp->rfds;
- lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- rfd = lp->rfds;
- rfd->rbd = WSWAPrbd(virt_to_dma(lp,lp->rbd_head));
- rfd->v_prev = lp->rfds + rx_ring_size - 1;
- rfd = lp->rfds + rx_ring_size - 1;
- rfd->v_next = lp->rfds;
- rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- rfd->cmd = CMD_EOL|CMD_FLEX;
-
- CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-static inline void remove_rx_bufs(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct i596_rbd *rbd;
- int i;
-
- for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
- if (rbd->skb == NULL)
- break;
- dma_unmap_single(lp->dev,
- (dma_addr_t)WSWAPchar(rbd->b_data),
- PKT_BUF_SZ, DMA_FROM_DEVICE);
- dev_kfree_skb(rbd->skb);
- }
-}
-
-
-static void rebuild_rx_bufs(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- int i;
-
- /* Ensure rx frame/buffer descriptors are tidy */
-
- for (i = 0; i < rx_ring_size; i++) {
- lp->rfds[i].rbd = I596_NULL;
- lp->rfds[i].cmd = CMD_FLEX;
- }
- lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
- lp->rfd_head = lp->rfds;
- lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- lp->rbd_head = lp->rbds;
- lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
- CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-static int init_i596_mem(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- unsigned long flags;
-
- disable_irq(dev->irq); /* disable IRQs from LAN */
- DEB(DEB_INIT,
- printk("RESET 82596 port: %lx (with IRQ %d disabled)\n",
- (dev->base_addr + PA_I82596_RESET),
- dev->irq));
-
- gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
- udelay(100); /* Wait 100us - seems to help */
-
- /* change the scp address */
-
- lp->last_cmd = jiffies;
-
-
- lp->scp.sysbus = 0x0000006c;
- lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp)));
- lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb)));
- lp->iscp.stat = ISCP_BUSY;
- lp->cmd_backlog = 0;
-
- lp->cmd_head = NULL;
- lp->scb.cmd = I596_NULL;
-
- DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name));
-
- CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp));
- CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp));
-
- MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp));
-
- CA(dev);
-
- if (wait_istat(dev, lp, 1000, "initialization timed out"))
- goto failed;
- DEB(DEB_INIT, printk("%s: i82596 initialization successful\n", dev->name));
-
- /* Ensure rx frame/buffer descriptors are tidy */
- rebuild_rx_bufs(dev);
-
- lp->scb.command = 0;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
- enable_irq(dev->irq); /* enable IRQs from LAN */
-
- DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name));
- memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup));
- lp->cf_cmd.cmd.command = CmdConfigure;
- CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd));
- i596_add_cmd(dev, &lp->cf_cmd.cmd);
-
- DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name));
- memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);
- lp->sa_cmd.cmd.command = CmdSASetup;
- CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd));
- i596_add_cmd(dev, &lp->sa_cmd.cmd);
-
- DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name));
- lp->tdr_cmd.cmd.command = CmdTDR;
- CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd));
- i596_add_cmd(dev, &lp->tdr_cmd.cmd);
-
- spin_lock_irqsave (&lp->lock, flags);
-
- if (wait_cmd(dev, lp, 1000, "timed out waiting to issue RX_START")) {
- spin_unlock_irqrestore (&lp->lock, flags);
- goto failed;
- }
- DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name));
- lp->scb.command = RX_START;
- lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
- CA(dev);
-
- spin_unlock_irqrestore (&lp->lock, flags);
-
- if (wait_cmd(dev, lp, 1000, "RX_START not processed"))
- goto failed;
- DEB(DEB_INIT, printk("%s: Receive unit started OK\n", dev->name));
-
- return 0;
-
-failed:
- printk("%s: Failed to initialise 82596\n", dev->name);
- MPU_PORT(dev, PORT_RESET, 0);
- return -1;
-}
-
-
-static inline int i596_rx(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct i596_rfd *rfd;
- struct i596_rbd *rbd;
- int frames = 0;
-
- DEB(DEB_RXFRAME, printk("i596_rx(), rfd_head %p, rbd_head %p\n",
- lp->rfd_head, lp->rbd_head));
-
-
- rfd = lp->rfd_head; /* Ref next frame to check */
-
- CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
- while ((rfd->stat) & STAT_C) { /* Loop while complete frames */
- if (rfd->rbd == I596_NULL)
- rbd = NULL;
- else if (rfd->rbd == lp->rbd_head->b_addr) {
- rbd = lp->rbd_head;
- CHECK_INV(lp, rbd, sizeof(struct i596_rbd));
- }
- else {
- printk("%s: rbd chain broken!\n", dev->name);
- /* XXX Now what? */
- rbd = NULL;
- }
- DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
- rfd, rfd->rbd, rfd->stat));
-
- if (rbd != NULL && ((rfd->stat) & STAT_OK)) {
- /* a good frame */
- int pkt_len = rbd->count & 0x3fff;
- struct sk_buff *skb = rbd->skb;
- int rx_in_place = 0;
-
- DEB(DEB_RXADDR,print_eth(rbd->v_data, "received"));
- frames++;
-
- /* Check if the packet is long enough to just accept
- * without copying to a properly sized skbuff.
- */
-
- if (pkt_len > rx_copybreak) {
- struct sk_buff *newskb;
- dma_addr_t dma_addr;
-
- dma_unmap_single(lp->dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
- /* Get fresh skbuff to replace filled one. */
- newskb = dev_alloc_skb(PKT_BUF_SZ + 4);
- if (newskb == NULL) {
- skb = NULL; /* drop pkt */
- goto memory_squeeze;
- }
- skb_reserve(newskb, 2);
-
- /* Pass up the skb already on the Rx ring. */
- skb_put(skb, pkt_len);
- rx_in_place = 1;
- rbd->skb = newskb;
- newskb->dev = dev;
- dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE);
- rbd->v_data = newskb->data;
- rbd->b_data = WSWAPchar(dma_addr);
- CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
- }
- else
- skb = dev_alloc_skb(pkt_len + 2);
-memory_squeeze:
- if (skb == NULL) {
- /* XXX tulip.c can defer packets here!! */
- printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- }
- else {
- if (!rx_in_place) {
- /* 16 byte align the data fields */
- dma_sync_single_for_cpu(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
- skb_reserve(skb, 2);
- memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len);
- dma_sync_single_for_device(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
- }
- skb->len = pkt_len;
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
- lp->stats.rx_bytes+=pkt_len;
- }
- }
- else {
- DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n",
- dev->name, rfd->stat));
- lp->stats.rx_errors++;
- if ((rfd->stat) & 0x0001)
- lp->stats.collisions++;
- if ((rfd->stat) & 0x0080)
- lp->stats.rx_length_errors++;
- if ((rfd->stat) & 0x0100)
- lp->stats.rx_over_errors++;
- if ((rfd->stat) & 0x0200)
- lp->stats.rx_fifo_errors++;
- if ((rfd->stat) & 0x0400)
- lp->stats.rx_frame_errors++;
- if ((rfd->stat) & 0x0800)
- lp->stats.rx_crc_errors++;
- if ((rfd->stat) & 0x1000)
- lp->stats.rx_length_errors++;
- }
-
- /* Clear the buffer descriptor count and EOF + F flags */
-
- if (rbd != NULL && (rbd->count & 0x4000)) {
- rbd->count = 0;
- lp->rbd_head = rbd->v_next;
- CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
- }
-
- /* Tidy the frame descriptor, marking it as end of list */
-
- rfd->rbd = I596_NULL;
- rfd->stat = 0;
- rfd->cmd = CMD_EOL|CMD_FLEX;
- rfd->count = 0;
-
- /* Remove end-of-list from old end descriptor */
-
- rfd->v_prev->cmd = CMD_FLEX;
-
- /* Update record of next frame descriptor to process */
-
- lp->scb.rfd = rfd->b_next;
- lp->rfd_head = rfd->v_next;
- CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd));
- CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd));
- rfd = lp->rfd_head;
- CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
- }
-
- DEB(DEB_RXFRAME, printk("frames %d\n", frames));
-
- return 0;
-}
-
-
-static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
-{
- struct i596_cmd *ptr;
-
- while (lp->cmd_head != NULL) {
- ptr = lp->cmd_head;
- lp->cmd_head = ptr->v_next;
- lp->cmd_backlog--;
-
- switch ((ptr->command) & 0x7) {
- case CmdTx:
- {
- struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
- struct sk_buff *skb = tx_cmd->skb;
- dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
-
- dev_kfree_skb(skb);
-
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
-
- ptr->v_next = NULL;
- ptr->b_next = I596_NULL;
- tx_cmd->cmd.command = 0; /* Mark as free */
- break;
- }
- default:
- ptr->v_next = NULL;
- ptr->b_next = I596_NULL;
- }
- CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd));
- }
-
- wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out");
- lp->scb.cmd = I596_NULL;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-}
-
-
-static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
-{
- unsigned long flags;
-
- DEB(DEB_RESET, printk("i596_reset\n"));
-
- spin_lock_irqsave (&lp->lock, flags);
-
- wait_cmd(dev, lp, 100, "i596_reset timed out");
-
- netif_stop_queue(dev);
-
- /* FIXME: this command might cause an lpmc */
- lp->scb.command = CUC_ABORT | RX_ABORT;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
- CA(dev);
-
- /* wait for shutdown */
- wait_cmd(dev, lp, 1000, "i596_reset 2 timed out");
- spin_unlock_irqrestore (&lp->lock, flags);
-
- i596_cleanup_cmd(dev,lp);
- i596_rx(dev);
-
- netif_start_queue(dev);
- init_i596_mem(dev);
-}
-
-
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
-{
- struct i596_private *lp = dev->priv;
- unsigned long flags;
-
- DEB(DEB_ADDCMD, printk("i596_add_cmd cmd_head %p\n", lp->cmd_head));
-
- cmd->status = 0;
- cmd->command |= (CMD_EOL | CMD_INTR);
- cmd->v_next = NULL;
- cmd->b_next = I596_NULL;
- CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd));
-
- spin_lock_irqsave (&lp->lock, flags);
-
- if (lp->cmd_head != NULL) {
- lp->cmd_tail->v_next = cmd;
- lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status));
- CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd));
- } else {
- lp->cmd_head = cmd;
- wait_cmd(dev, lp, 100, "i596_add_cmd timed out");
- lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status));
- lp->scb.command = CUC_START;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
- CA(dev);
- }
- lp->cmd_tail = cmd;
- lp->cmd_backlog++;
-
- spin_unlock_irqrestore (&lp->lock, flags);
-
- if (lp->cmd_backlog > max_cmd_backlog) {
- unsigned long tickssofar = jiffies - lp->last_cmd;
-
- if (tickssofar < ticks_limit)
- return;
-
- printk("%s: command unit timed out, status resetting.\n", dev->name);
-#if 1
- i596_reset(dev, lp);
-#endif
- }
-}
-
-#if 0
-/* this function makes a perfectly adequate probe... but we have a
- device list */
-static int i596_test(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- volatile int *tint;
- u32 data;
-
- tint = (volatile int *)(&(lp->scp));
- data = virt_to_dma(lp,tint);
-
- tint[1] = -1;
- CHECK_WBACK(lp, tint, PAGE_SIZE);
-
- MPU_PORT(dev, 1, data);
-
- for(data = 1000000; data; data--) {
- CHECK_INV(lp, tint, PAGE_SIZE);
- if(tint[1] != -1)
- break;
-
- }
-
- printk("i596_test result %d\n", tint[1]);
-
-}
-#endif
-
-
-static int i596_open(struct net_device *dev)
-{
- DEB(DEB_OPEN, printk("%s: i596_open() irq %d.\n", dev->name, dev->irq));
-
- if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
- printk("%s: IRQ %d not free\n", dev->name, dev->irq);
- goto out;
- }
-
- init_rx_bufs(dev);
-
- if (init_i596_mem(dev)) {
- printk("%s: Failed to init memory\n", dev->name);
- goto out_remove_rx_bufs;
- }
-
- netif_start_queue(dev);
-
- return 0;
-
-out_remove_rx_bufs:
- remove_rx_bufs(dev);
- free_irq(dev->irq, dev);
-out:
- return -EAGAIN;
-}
-
-static void i596_tx_timeout (struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
-
- /* Transmitter timeout, serious problems. */
- DEB(DEB_ERRORS, printk("%s: transmit timed out, status resetting.\n",
- dev->name));
-
- lp->stats.tx_errors++;
-
- /* Try to restart the adaptor */
- if (lp->last_restart == lp->stats.tx_packets) {
- DEB(DEB_ERRORS, printk("Resetting board.\n"));
- /* Shutdown and restart */
- i596_reset (dev, lp);
- } else {
- /* Issue a channel attention signal */
- DEB(DEB_ERRORS, printk("Kicking board.\n"));
- lp->scb.command = CUC_START | RX_START;
- CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
- CA (dev);
- lp->last_restart = lp->stats.tx_packets;
- }
-
- dev->trans_start = jiffies;
- netif_wake_queue (dev);
-}
-
-
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct tx_cmd *tx_cmd;
- struct i596_tbd *tbd;
- short length = skb->len;
- dev->trans_start = jiffies;
-
- DEB(DEB_STARTTX, printk("%s: i596_start_xmit(%x,%p) called\n", dev->name,
- skb->len, skb->data));
-
- if (length < ETH_ZLEN) {
- if (skb_padto(skb, ETH_ZLEN))
- return 0;
- length = ETH_ZLEN;
- }
-
- netif_stop_queue(dev);
-
- tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
- tbd = lp->tbds + lp->next_tx_cmd;
-
- if (tx_cmd->cmd.command) {
- DEB(DEB_ERRORS, printk("%s: xmit ring full, dropping packet.\n",
- dev->name));
- lp->stats.tx_dropped++;
-
- dev_kfree_skb(skb);
- } else {
- if (++lp->next_tx_cmd == TX_RING_SIZE)
- lp->next_tx_cmd = 0;
- tx_cmd->tbd = WSWAPtbd(virt_to_dma(lp,tbd));
- tbd->next = I596_NULL;
-
- tx_cmd->cmd.command = CMD_FLEX | CmdTx;
- tx_cmd->skb = skb;
-
- tx_cmd->pad = 0;
- tx_cmd->size = 0;
- tbd->pad = 0;
- tbd->size = EOF | length;
-
- tx_cmd->dma_addr = dma_map_single(lp->dev, skb->data, skb->len,
- DMA_TO_DEVICE);
- tbd->data = WSWAPchar(tx_cmd->dma_addr);
-
- DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued"));
- CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd));
- CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd));
- i596_add_cmd(dev, &tx_cmd->cmd);
-
- lp->stats.tx_packets++;
- lp->stats.tx_bytes += length;
- }
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-static void print_eth(unsigned char *add, char *str)
-{
- int i;
-
- printk("i596 0x%p, ", add);
- for (i = 0; i < 6; i++)
- printk(" %02X", add[i + 6]);
- printk(" -->");
- for (i = 0; i < 6; i++)
- printk(" %02X", add[i]);
- printk(" %02X%02X, %s\n", add[12], add[13], str);
-}
-
-
#define LAN_PROM_ADDR 0xF0810000
-static int __devinit i82596_probe(struct net_device *dev,
- struct device *gen_dev)
-{
- int i;
- struct i596_private *lp;
- char eth_addr[6];
- dma_addr_t dma_addr;
-
- /* This lot is ensure things have been cache line aligned. */
- BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
- BUILD_BUG_ON(sizeof(struct i596_rbd) & 31);
- BUILD_BUG_ON(sizeof(struct tx_cmd) & 31);
- BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
-#ifndef __LP64__
- BUILD_BUG_ON(sizeof(struct i596_private) > 4096);
-#endif
-
- if (!dev->base_addr || !dev->irq)
- return -ENODEV;
-
- if (pdc_lan_station_id(eth_addr, dev->base_addr)) {
- for (i=0; i < 6; i++) {
- eth_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
- }
- printk(KERN_INFO "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
- }
-
- dev->mem_start = (unsigned long) dma_alloc_noncoherent(gen_dev,
- sizeof(struct i596_private), &dma_addr, GFP_KERNEL);
- if (!dev->mem_start) {
- printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
- return -ENOMEM;
- }
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = eth_addr[i];
-
- /* The 82596-specific entries in the device structure. */
- dev->open = i596_open;
- dev->stop = i596_close;
- dev->hard_start_xmit = i596_start_xmit;
- dev->get_stats = i596_get_stats;
- dev->set_multicast_list = set_multicast_list;
- dev->tx_timeout = i596_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = i596_poll_controller;
-#endif
-
- dev->priv = (void *)(dev->mem_start);
-
- lp = dev->priv;
- memset(lp, 0, sizeof(struct i596_private));
-
- lp->scb.command = 0;
- lp->scb.cmd = I596_NULL;
- lp->scb.rfd = I596_NULL;
- spin_lock_init(&lp->lock);
- lp->dma_addr = dma_addr;
- lp->dev = gen_dev;
-
- CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private));
-
- i = register_netdev(dev);
- if (i) {
- lp = dev->priv;
- dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
- (void *)dev->mem_start, lp->dma_addr);
- return i;
- };
-
- DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr));
- for (i = 0; i < 6; i++)
- DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
- DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
- DEB(DEB_INIT, printk(KERN_INFO "%s: lp at 0x%p (%d bytes), lp->scb at 0x%p\n",
- dev->name, lp, (int)sizeof(struct i596_private), &lp->scb));
-
- return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev)
-{
- disable_irq(dev->irq);
- i596_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
-static irqreturn_t i596_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct i596_private *lp;
- unsigned short status, ack_cmd = 0;
-
- if (dev == NULL) {
- printk("%s: irq %d for unknown device.\n", __FUNCTION__, irq);
- return IRQ_NONE;
- }
-
- lp = dev->priv;
-
- spin_lock (&lp->lock);
-
- wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
- status = lp->scb.status;
-
- DEB(DEB_INTS, printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n",
- dev->name, irq, status));
-
- ack_cmd = status & 0xf000;
-
- if (!ack_cmd) {
- DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name));
- spin_unlock (&lp->lock);
- return IRQ_NONE;
- }
-
- if ((status & 0x8000) || (status & 0x2000)) {
- struct i596_cmd *ptr;
-
- if ((status & 0x8000))
- DEB(DEB_INTS, printk("%s: i596 interrupt completed command.\n", dev->name));
- if ((status & 0x2000))
- DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700));
-
- while (lp->cmd_head != NULL) {
- CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd));
- if (!(lp->cmd_head->status & STAT_C))
- break;
-
- ptr = lp->cmd_head;
-
- DEB(DEB_STATUS, printk("cmd_head->status = %04x, ->command = %04x\n",
- lp->cmd_head->status, lp->cmd_head->command));
- lp->cmd_head = ptr->v_next;
- lp->cmd_backlog--;
-
- switch ((ptr->command) & 0x7) {
- case CmdTx:
- {
- struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
- struct sk_buff *skb = tx_cmd->skb;
-
- if ((ptr->status) & STAT_OK) {
- DEB(DEB_TXADDR, print_eth(skb->data, "tx-done"));
- } else {
- lp->stats.tx_errors++;
- if ((ptr->status) & 0x0020)
- lp->stats.collisions++;
- if (!((ptr->status) & 0x0040))
- lp->stats.tx_heartbeat_errors++;
- if ((ptr->status) & 0x0400)
- lp->stats.tx_carrier_errors++;
- if ((ptr->status) & 0x0800)
- lp->stats.collisions++;
- if ((ptr->status) & 0x1000)
- lp->stats.tx_aborted_errors++;
- }
- dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
- dev_kfree_skb_irq(skb);
-
- tx_cmd->cmd.command = 0; /* Mark free */
- break;
- }
- case CmdTDR:
- {
- unsigned short status = ((struct tdr_cmd *)ptr)->status;
-
- if (status & 0x8000) {
- DEB(DEB_ANY, printk("%s: link ok.\n", dev->name));
- } else {
- if (status & 0x4000)
- printk("%s: Transceiver problem.\n", dev->name);
- if (status & 0x2000)
- printk("%s: Termination problem.\n", dev->name);
- if (status & 0x1000)
- printk("%s: Short circuit.\n", dev->name);
-
- DEB(DEB_TDR, printk("%s: Time %d.\n", dev->name, status & 0x07ff));
- }
- break;
- }
- case CmdConfigure:
- /* Zap command so set_multicast_list() knows it is free */
- ptr->command = 0;
- break;
- }
- ptr->v_next = NULL;
- ptr->b_next = I596_NULL;
- CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd));
- lp->last_cmd = jiffies;
- }
-
- /* This mess is arranging that only the last of any outstanding
- * commands has the interrupt bit set. Should probably really
- * only add to the cmd queue when the CU is stopped.
- */
- ptr = lp->cmd_head;
- while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
- struct i596_cmd *prev = ptr;
-
- ptr->command &= 0x1fff;
- ptr = ptr->v_next;
- CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd));
- }
-
- if ((lp->cmd_head != NULL))
- ack_cmd |= CUC_START;
- lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status));
- CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb));
- }
- if ((status & 0x1000) || (status & 0x4000)) {
- if ((status & 0x4000))
- DEB(DEB_INTS, printk("%s: i596 interrupt received a frame.\n", dev->name));
- i596_rx(dev);
- /* Only RX_START if stopped - RGH 07-07-96 */
- if (status & 0x1000) {
- if (netif_running(dev)) {
- DEB(DEB_ERRORS, printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status));
- ack_cmd |= RX_START;
- lp->stats.rx_errors++;
- lp->stats.rx_fifo_errors++;
- rebuild_rx_bufs(dev);
- }
- }
- }
- wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
- lp->scb.command = ack_cmd;
- CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
- /* DANGER: I suspect that some kind of interrupt
- acknowledgement aside from acking the 82596 might be needed
- here... but it's running acceptably without */
-
- CA(dev);
-
- wait_cmd(dev, lp, 100, "i596 interrupt, exit timeout");
- DEB(DEB_INTS, printk("%s: exiting interrupt.\n", dev->name));
-
- spin_unlock (&lp->lock);
- return IRQ_HANDLED;
-}
-
-static int i596_close(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- unsigned long flags;
-
- netif_stop_queue(dev);
-
- DEB(DEB_INIT, printk("%s: Shutting down ethercard, status was %4.4x.\n",
- dev->name, lp->scb.status));
-
- spin_lock_irqsave(&lp->lock, flags);
-
- wait_cmd(dev, lp, 100, "close1 timed out");
- lp->scb.command = CUC_ABORT | RX_ABORT;
- CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
- CA(dev);
-
- wait_cmd(dev, lp, 100, "close2 timed out");
- spin_unlock_irqrestore(&lp->lock, flags);
- DEB(DEB_STRUCT,i596_display_data(dev));
- i596_cleanup_cmd(dev,lp);
-
- disable_irq(dev->irq);
-
- free_irq(dev->irq, dev);
- remove_rx_bufs(dev);
-
- return 0;
-}
-
-static struct net_device_stats *
- i596_get_stats(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
-
- return &lp->stats;
-}
-
-/*
- * Set or clear the multicast filter for this adaptor.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- int config = 0, cnt;
-
- DEB(DEB_MULTI, printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
- dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF",
- dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
-
- if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) {
- lp->cf_cmd.i596_config[8] |= 0x01;
- config = 1;
- }
- if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) {
- lp->cf_cmd.i596_config[8] &= ~0x01;
- config = 1;
- }
- if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) {
- lp->cf_cmd.i596_config[11] &= ~0x20;
- config = 1;
- }
- if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) {
- lp->cf_cmd.i596_config[11] |= 0x20;
- config = 1;
- }
- if (config) {
- if (lp->cf_cmd.cmd.command)
- printk("%s: config change request already queued\n",
- dev->name);
- else {
- lp->cf_cmd.cmd.command = CmdConfigure;
- CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd));
- i596_add_cmd(dev, &lp->cf_cmd.cmd);
- }
- }
-
- cnt = dev->mc_count;
- if (cnt > MAX_MC_CNT)
- {
- cnt = MAX_MC_CNT;
- printk("%s: Only %d multicast addresses supported",
- dev->name, cnt);
- }
-
- if (dev->mc_count > 0) {
- struct dev_mc_list *dmi;
- unsigned char *cp;
- struct mc_cmd *cmd;
-
- cmd = &lp->mc_cmd;
- cmd->cmd.command = CmdMulticastList;
- cmd->mc_cnt = dev->mc_count * 6;
- cp = cmd->mc_addrs;
- for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) {
- memcpy(cp, dmi->dmi_addr, 6);
- if (i596_debug > 1)
- DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
- dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5]));
- }
- CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd));
- i596_add_cmd(dev, &cmd->cmd);
- }
-}
-
-static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "lasi_82596 debug mask");
-
-static int num_drivers;
-static struct net_device *netdevs[MAX_DRIVERS];
-
static int __devinit
lan_init_chip(struct parisc_device *dev)
{
struct net_device *netdevice;
+ struct i596_private *lp;
int retval;
-
- if (num_drivers >= MAX_DRIVERS) {
- /* max count of possible i82596 drivers reached */
- return -ENOMEM;
- }
-
- if (num_drivers == 0)
- printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
+ int i;
if (!dev->irq) {
printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
@@ -1528,28 +168,45 @@ lan_init_chip(struct parisc_device *dev)
printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
dev->irq);
- netdevice = alloc_etherdev(0);
+ netdevice = alloc_etherdev(sizeof(struct i596_private));
if (!netdevice)
return -ENOMEM;
+ SET_NETDEV_DEV(netdevice, &dev->dev);
+ parisc_set_drvdata (dev, netdevice);
netdevice->base_addr = dev->hpa.start;
netdevice->irq = dev->irq;
- retval = i82596_probe(netdevice, &dev->dev);
+ if (pdc_lan_station_id(netdevice->dev_addr, netdevice->base_addr)) {
+ for (i = 0; i < 6; i++) {
+ netdevice->dev_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
+ }
+ printk(KERN_INFO
+ "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
+ }
+
+ lp = netdev_priv(netdevice);
+ lp->options = dev->id.sversion == 0x72 ? OPT_SWAP_PORT : 0;
+
+ retval = i82596_probe(netdevice);
if (retval) {
free_netdev(netdevice);
return -ENODEV;
}
-
- if (dev->id.sversion == 0x72) {
- ((struct i596_private *)netdevice->priv)->options = OPT_SWAP_PORT;
- }
-
- netdevs[num_drivers++] = netdevice;
-
return retval;
}
+static int __devexit lan_remove_chip (struct parisc_device *pdev)
+{
+ struct net_device *dev = parisc_get_drvdata(pdev);
+ struct i596_private *lp = netdev_priv(dev);
+
+ unregister_netdev (dev);
+ DMA_FREE(&pdev->dev, sizeof(struct i596_private),
+ (void *)lp->dma, lp->dma_addr);
+ free_netdev (dev);
+ return 0;
+}
static struct parisc_device_id lan_tbl[] = {
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008a },
@@ -1563,12 +220,12 @@ static struct parisc_driver lan_driver = {
.name = "lasi_82596",
.id_table = lan_tbl,
.probe = lan_init_chip,
+ .remove = __devexit_p(lan_remove_chip),
};
static int __devinit lasi_82596_init(void)
{
- if (debug >= 0)
- i596_debug = debug;
+ printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
return register_parisc_driver(&lan_driver);
}
@@ -1576,25 +233,6 @@ module_init(lasi_82596_init);
static void __exit lasi_82596_exit(void)
{
- int i;
-
- for (i=0; i<MAX_DRIVERS; i++) {
- struct i596_private *lp;
- struct net_device *netdevice;
-
- netdevice = netdevs[i];
- if (!netdevice)
- continue;
-
- unregister_netdev(netdevice);
-
- lp = netdevice->priv;
- dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
- (void *)netdevice->mem_start, lp->dma_addr);
- free_netdev(netdevice);
- }
- num_drivers = 0;
-
unregister_parisc_driver(&lan_driver);
}
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
new file mode 100644
index 00000000000..5884f5bd04a
--- /dev/null
+++ b/drivers/net/lib82596.c
@@ -0,0 +1,1434 @@
+/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
+ munged into HPPA boxen .
+
+ This driver is based upon 82596.c, original credits are below...
+ but there were too many hoops which HP wants jumped through to
+ keep this code in there in a sane manner.
+
+ 3 primary sources of the mess --
+ 1) hppa needs *lots* of cacheline flushing to keep this kind of
+ MMIO running.
+
+ 2) The 82596 needs to see all of its pointers as their physical
+ address. Thus virt_to_bus/bus_to_virt are *everywhere*.
+
+ 3) The implementation HP is using seems to be significantly pickier
+ about when and how the command and RX units are started. some
+ command ordering was changed.
+
+ Examination of the mach driver leads one to believe that there
+ might be a saner way to pull this off... anyone who feels like a
+ full rewrite can be my guest.
+
+ Split 02/13/2000 Sam Creasey (sammy@oh.verio.com)
+
+ 02/01/2000 Initial modifications for parisc by Helge Deller (deller@gmx.de)
+ 03/02/2000 changes for better/correct(?) cache-flushing (deller)
+*/
+
+/* 82596.c: A generic 82596 ethernet driver for linux. */
+/*
+ Based on Apricot.c
+ Written 1994 by Mark Evans.
+ This driver is for the Apricot 82596 bus-master interface
+
+ Modularised 12/94 Mark Evans
+
+
+ Modified to support the 82596 ethernet chips on 680x0 VME boards.
+ by Richard Hirst <richard@sleepie.demon.co.uk>
+ Renamed to be 82596.c
+
+ 980825: Changed to receive directly in to sk_buffs which are
+ allocated at open() time. Eliminates copy on incoming frames
+ (small ones are still copied). Shared data now held in a
+ non-cached page, so we can run on 68060 in copyback mode.
+
+ TBD:
+ * look at deferring rx frames rather than discarding (as per tulip)
+ * handle tx ring full as per tulip
+ * performace test to tune rx_copybreak
+
+ Most of my modifications relate to the braindead big-endian
+ implementation by Intel. When the i596 is operating in
+ 'big-endian' mode, it thinks a 32 bit value of 0x12345678
+ should be stored as 0x56781234. This is a real pain, when
+ you have linked lists which are shared by the 680x0 and the
+ i596.
+
+ Driver skeleton
+ Written 1993 by Donald Becker.
+ Copyright 1993 United States Government as represented by the Director,
+ National Security Agency. This software may only be used and distributed
+ according to the terms of the GNU General Public License as modified by SRC,
+ incorporated herein by reference.
+
+ The author may be reached as becker@scyld.com, or C/O
+ Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+/* DEBUG flags
+ */
+
+#define DEB_INIT 0x0001
+#define DEB_PROBE 0x0002
+#define DEB_SERIOUS 0x0004
+#define DEB_ERRORS 0x0008
+#define DEB_MULTI 0x0010
+#define DEB_TDR 0x0020
+#define DEB_OPEN 0x0040
+#define DEB_RESET 0x0080
+#define DEB_ADDCMD 0x0100
+#define DEB_STATUS 0x0200
+#define DEB_STARTTX 0x0400
+#define DEB_RXADDR 0x0800
+#define DEB_TXADDR 0x1000
+#define DEB_RXFRAME 0x2000
+#define DEB_INTS 0x4000
+#define DEB_STRUCT 0x8000
+#define DEB_ANY 0xffff
+
+
+#define DEB(x, y) if (i596_debug & (x)) { y; }
+
+
+/*
+ * The MPU_PORT command allows direct access to the 82596. With PORT access
+ * the following commands are available (p5-18). The 32-bit port command
+ * must be word-swapped with the most significant word written first.
+ * This only applies to VME boards.
+ */
+#define PORT_RESET 0x00 /* reset 82596 */
+#define PORT_SELFTEST 0x01 /* selftest */
+#define PORT_ALTSCP 0x02 /* alternate SCB address */
+#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */
+
+static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+
+/* Copy frames shorter than rx_copybreak, otherwise pass on up in
+ * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha).
+ */
+static int rx_copybreak = 100;
+
+#define PKT_BUF_SZ 1536
+#define MAX_MC_CNT 64
+
+#define ISCP_BUSY 0x0001
+
+#define I596_NULL ((u32)0xffffffff)
+
+#define CMD_EOL 0x8000 /* The last command of the list, stop. */
+#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */
+#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */
+
+#define CMD_FLEX 0x0008 /* Enable flexible memory model */
+
+enum commands {
+ CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
+ CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
+};
+
+#define STAT_C 0x8000 /* Set to 0 after execution */
+#define STAT_B 0x4000 /* Command being executed */
+#define STAT_OK 0x2000 /* Command executed ok */
+#define STAT_A 0x1000 /* Command aborted */
+
+#define CUC_START 0x0100
+#define CUC_RESUME 0x0200
+#define CUC_SUSPEND 0x0300
+#define CUC_ABORT 0x0400
+#define RX_START 0x0010
+#define RX_RESUME 0x0020
+#define RX_SUSPEND 0x0030
+#define RX_ABORT 0x0040
+
+#define TX_TIMEOUT 5
+
+
+struct i596_reg {
+ unsigned short porthi;
+ unsigned short portlo;
+ u32 ca;
+};
+
+#define EOF 0x8000
+#define SIZE_MASK 0x3fff
+
+struct i596_tbd {
+ unsigned short size;
+ unsigned short pad;
+ dma_addr_t next;
+ dma_addr_t data;
+ u32 cache_pad[5]; /* Total 32 bytes... */
+};
+
+/* The command structure has two 'next' pointers; v_next is the address of
+ * the next command as seen by the CPU, b_next is the address of the next
+ * command as seen by the 82596. The b_next pointer, as used by the 82596
+ * always references the status field of the next command, rather than the
+ * v_next field, because the 82596 is unaware of v_next. It may seem more
+ * logical to put v_next at the end of the structure, but we cannot do that
+ * because the 82596 expects other fields to be there, depending on command
+ * type.
+ */
+
+struct i596_cmd {
+ struct i596_cmd *v_next; /* Address from CPUs viewpoint */
+ unsigned short status;
+ unsigned short command;
+ dma_addr_t b_next; /* Address from i596 viewpoint */
+};
+
+struct tx_cmd {
+ struct i596_cmd cmd;
+ dma_addr_t tbd;
+ unsigned short size;
+ unsigned short pad;
+ struct sk_buff *skb; /* So we can free it after tx */
+ dma_addr_t dma_addr;
+#ifdef __LP64__
+ u32 cache_pad[6]; /* Total 64 bytes... */
+#else
+ u32 cache_pad[1]; /* Total 32 bytes... */
+#endif
+};
+
+struct tdr_cmd {
+ struct i596_cmd cmd;
+ unsigned short status;
+ unsigned short pad;
+};
+
+struct mc_cmd {
+ struct i596_cmd cmd;
+ short mc_cnt;
+ char mc_addrs[MAX_MC_CNT*6];
+};
+
+struct sa_cmd {
+ struct i596_cmd cmd;
+ char eth_addr[8];
+};
+
+struct cf_cmd {
+ struct i596_cmd cmd;
+ char i596_config[16];
+};
+
+struct i596_rfd {
+ unsigned short stat;
+ unsigned short cmd;
+ dma_addr_t b_next; /* Address from i596 viewpoint */
+ dma_addr_t rbd;
+ unsigned short count;
+ unsigned short size;
+ struct i596_rfd *v_next; /* Address from CPUs viewpoint */
+ struct i596_rfd *v_prev;
+#ifndef __LP64__
+ u32 cache_pad[2]; /* Total 32 bytes... */
+#endif
+};
+
+struct i596_rbd {
+ /* hardware data */
+ unsigned short count;
+ unsigned short zero1;
+ dma_addr_t b_next;
+ dma_addr_t b_data; /* Address from i596 viewpoint */
+ unsigned short size;
+ unsigned short zero2;
+ /* driver data */
+ struct sk_buff *skb;
+ struct i596_rbd *v_next;
+ dma_addr_t b_addr; /* This rbd addr from i596 view */
+ unsigned char *v_data; /* Address from CPUs viewpoint */
+ /* Total 32 bytes... */
+#ifdef __LP64__
+ u32 cache_pad[4];
+#endif
+};
+
+/* These values as chosen so struct i596_dma fits in one page... */
+
+#define TX_RING_SIZE 32
+#define RX_RING_SIZE 16
+
+struct i596_scb {
+ unsigned short status;
+ unsigned short command;
+ dma_addr_t cmd;
+ dma_addr_t rfd;
+ u32 crc_err;
+ u32 align_err;
+ u32 resource_err;
+ u32 over_err;
+ u32 rcvdt_err;
+ u32 short_err;
+ unsigned short t_on;
+ unsigned short t_off;
+};
+
+struct i596_iscp {
+ u32 stat;
+ dma_addr_t scb;
+};
+
+struct i596_scp {
+ u32 sysbus;
+ u32 pad;
+ dma_addr_t iscp;
+};
+
+struct i596_dma {
+ struct i596_scp scp __attribute__((aligned(32)));
+ volatile struct i596_iscp iscp __attribute__((aligned(32)));
+ volatile struct i596_scb scb __attribute__((aligned(32)));
+ struct sa_cmd sa_cmd __attribute__((aligned(32)));
+ struct cf_cmd cf_cmd __attribute__((aligned(32)));
+ struct tdr_cmd tdr_cmd __attribute__((aligned(32)));
+ struct mc_cmd mc_cmd __attribute__((aligned(32)));
+ struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32)));
+ struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32)));
+ struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32)));
+ struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32)));
+};
+
+struct i596_private {
+ struct i596_dma *dma;
+ u32 stat;
+ int last_restart;
+ struct i596_rfd *rfd_head;
+ struct i596_rbd *rbd_head;
+ struct i596_cmd *cmd_tail;
+ struct i596_cmd *cmd_head;
+ int cmd_backlog;
+ u32 last_cmd;
+ struct net_device_stats stats;
+ int next_tx_cmd;
+ int options;
+ spinlock_t lock; /* serialize access to chip */
+ dma_addr_t dma_addr;
+ void __iomem *mpu_port;
+ void __iomem *ca;
+};
+
+static const char init_setup[] =
+{
+ 0x8E, /* length, prefetch on */
+ 0xC8, /* fifo to 8, monitor off */
+ 0x80, /* don't save bad frames */
+ 0x2E, /* No source address insertion, 8 byte preamble */
+ 0x00, /* priority and backoff defaults */
+ 0x60, /* interframe spacing */
+ 0x00, /* slot time LSB */
+ 0xf2, /* slot time and retries */
+ 0x00, /* promiscuous mode */
+ 0x00, /* collision detect */
+ 0x40, /* minimum frame length */
+ 0xff,
+ 0x00,
+ 0x7f /* *multi IA */ };
+
+static int i596_open(struct net_device *dev);
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t i596_interrupt(int irq, void *dev_id);
+static int i596_close(struct net_device *dev);
+static struct net_device_stats *i596_get_stats(struct net_device *dev);
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
+static void i596_tx_timeout (struct net_device *dev);
+static void print_eth(unsigned char *buf, char *str);
+static void set_multicast_list(struct net_device *dev);
+static inline void ca(struct net_device *dev);
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x);
+
+static int rx_ring_size = RX_RING_SIZE;
+static int ticks_limit = 100;
+static int max_cmd_backlog = TX_RING_SIZE-1;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev);
+#endif
+
+
+static inline int wait_istat(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+ DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+ while (--delcnt && dma->iscp.stat) {
+ udelay(10);
+ DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+ }
+ if (!delcnt) {
+ printk(KERN_ERR "%s: %s, iscp.stat %04x, didn't clear\n",
+ dev->name, str, SWAP16(dma->iscp.stat));
+ return -1;
+ } else
+ return 0;
+}
+
+
+static inline int wait_cmd(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+ DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+ while (--delcnt && dma->scb.command) {
+ udelay(10);
+ DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+ }
+ if (!delcnt) {
+ printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n",
+ dev->name, str,
+ SWAP16(dma->scb.status),
+ SWAP16(dma->scb.command));
+ return -1;
+ } else
+ return 0;
+}
+
+
+static void i596_display_data(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ struct i596_cmd *cmd;
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+
+ printk(KERN_DEBUG "lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
+ &dma->scp, dma->scp.sysbus, SWAP32(dma->scp.iscp));
+ printk(KERN_DEBUG "iscp at %p, iscp.stat = %08x, .scb = %08x\n",
+ &dma->iscp, SWAP32(dma->iscp.stat), SWAP32(dma->iscp.scb));
+ printk(KERN_DEBUG "scb at %p, scb.status = %04x, .command = %04x,"
+ " .cmd = %08x, .rfd = %08x\n",
+ &dma->scb, SWAP16(dma->scb.status), SWAP16(dma->scb.command),
+ SWAP16(dma->scb.cmd), SWAP32(dma->scb.rfd));
+ printk(KERN_DEBUG " errors: crc %x, align %x, resource %x,"
+ " over %x, rcvdt %x, short %x\n",
+ SWAP32(dma->scb.crc_err), SWAP32(dma->scb.align_err),
+ SWAP32(dma->scb.resource_err), SWAP32(dma->scb.over_err),
+ SWAP32(dma->scb.rcvdt_err), SWAP32(dma->scb.short_err));
+ cmd = lp->cmd_head;
+ while (cmd != NULL) {
+ printk(KERN_DEBUG
+ "cmd at %p, .status = %04x, .command = %04x,"
+ " .b_next = %08x\n",
+ cmd, SWAP16(cmd->status), SWAP16(cmd->command),
+ SWAP32(cmd->b_next));
+ cmd = cmd->v_next;
+ }
+ rfd = lp->rfd_head;
+ printk(KERN_DEBUG "rfd_head = %p\n", rfd);
+ do {
+ printk(KERN_DEBUG
+ " %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
+ " count %04x\n",
+ rfd, SWAP16(rfd->stat), SWAP16(rfd->cmd),
+ SWAP32(rfd->b_next), SWAP32(rfd->rbd),
+ SWAP16(rfd->count));
+ rfd = rfd->v_next;
+ } while (rfd != lp->rfd_head);
+ rbd = lp->rbd_head;
+ printk(KERN_DEBUG "rbd_head = %p\n", rbd);
+ do {
+ printk(KERN_DEBUG
+ " %p .count %04x, b_next %08x, b_data %08x,"
+ " size %04x\n",
+ rbd, SWAP16(rbd->count), SWAP32(rbd->b_next),
+ SWAP32(rbd->b_data), SWAP16(rbd->size));
+ rbd = rbd->v_next;
+ } while (rbd != lp->rbd_head);
+ DMA_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+#define virt_to_dma(lp, v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)((lp)->dma)))
+
+static inline int init_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ int i;
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+
+ /* First build the Receive Buffer Descriptor List */
+
+ for (i = 0, rbd = dma->rbds; i < rx_ring_size; i++, rbd++) {
+ dma_addr_t dma_addr;
+ struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+
+ if (skb == NULL)
+ return -1;
+ skb_reserve(skb, 2);
+ dma_addr = dma_map_single(dev->dev.parent, skb->data,
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ rbd->v_next = rbd+1;
+ rbd->b_next = SWAP32(virt_to_dma(lp, rbd+1));
+ rbd->b_addr = SWAP32(virt_to_dma(lp, rbd));
+ rbd->skb = skb;
+ rbd->v_data = skb->data;
+ rbd->b_data = SWAP32(dma_addr);
+ rbd->size = SWAP16(PKT_BUF_SZ);
+ }
+ lp->rbd_head = dma->rbds;
+ rbd = dma->rbds + rx_ring_size - 1;
+ rbd->v_next = dma->rbds;
+ rbd->b_next = SWAP32(virt_to_dma(lp, dma->rbds));
+
+ /* Now build the Receive Frame Descriptor List */
+
+ for (i = 0, rfd = dma->rfds; i < rx_ring_size; i++, rfd++) {
+ rfd->rbd = I596_NULL;
+ rfd->v_next = rfd+1;
+ rfd->v_prev = rfd-1;
+ rfd->b_next = SWAP32(virt_to_dma(lp, rfd+1));
+ rfd->cmd = SWAP16(CMD_FLEX);
+ }
+ lp->rfd_head = dma->rfds;
+ dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+ rfd = dma->rfds;
+ rfd->rbd = SWAP32(virt_to_dma(lp, lp->rbd_head));
+ rfd->v_prev = dma->rfds + rx_ring_size - 1;
+ rfd = dma->rfds + rx_ring_size - 1;
+ rfd->v_next = dma->rfds;
+ rfd->b_next = SWAP32(virt_to_dma(lp, dma->rfds));
+ rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+
+ DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+ return 0;
+}
+
+static inline void remove_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_rbd *rbd;
+ int i;
+
+ for (i = 0, rbd = lp->dma->rbds; i < rx_ring_size; i++, rbd++) {
+ if (rbd->skb == NULL)
+ break;
+ dma_unmap_single(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ dev_kfree_skb(rbd->skb);
+ }
+}
+
+
+static void rebuild_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ int i;
+
+ /* Ensure rx frame/buffer descriptors are tidy */
+
+ for (i = 0; i < rx_ring_size; i++) {
+ dma->rfds[i].rbd = I596_NULL;
+ dma->rfds[i].cmd = SWAP16(CMD_FLEX);
+ }
+ dma->rfds[rx_ring_size-1].cmd = SWAP16(CMD_EOL|CMD_FLEX);
+ lp->rfd_head = dma->rfds;
+ dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+ lp->rbd_head = dma->rbds;
+ dma->rfds[0].rbd = SWAP32(virt_to_dma(lp, dma->rbds));
+
+ DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+static int init_i596_mem(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ unsigned long flags;
+
+ mpu_port(dev, PORT_RESET, 0);
+ udelay(100); /* Wait 100us - seems to help */
+
+ /* change the scp address */
+
+ lp->last_cmd = jiffies;
+
+ dma->scp.sysbus = SYSBUS;
+ dma->scp.iscp = SWAP32(virt_to_dma(lp, &(dma->iscp)));
+ dma->iscp.scb = SWAP32(virt_to_dma(lp, &(dma->scb)));
+ dma->iscp.stat = SWAP32(ISCP_BUSY);
+ lp->cmd_backlog = 0;
+
+ lp->cmd_head = NULL;
+ dma->scb.cmd = I596_NULL;
+
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: starting i82596.\n", dev->name));
+
+ DMA_WBACK(dev, &(dma->scp), sizeof(struct i596_scp));
+ DMA_WBACK(dev, &(dma->iscp), sizeof(struct i596_iscp));
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+ mpu_port(dev, PORT_ALTSCP, virt_to_dma(lp, &dma->scp));
+ ca(dev);
+ if (wait_istat(dev, dma, 1000, "initialization timed out"))
+ goto failed;
+ DEB(DEB_INIT, printk(KERN_DEBUG
+ "%s: i82596 initialization successful\n",
+ dev->name));
+
+ if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
+ printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq);
+ goto failed;
+ }
+
+ /* Ensure rx frame/buffer descriptors are tidy */
+ rebuild_rx_bufs(dev);
+
+ dma->scb.command = 0;
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+ DEB(DEB_INIT, printk(KERN_DEBUG
+ "%s: queuing CmdConfigure\n", dev->name));
+ memcpy(dma->cf_cmd.i596_config, init_setup, 14);
+ dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+ DMA_WBACK(dev, &(dma->cf_cmd), sizeof(struct cf_cmd));
+ i596_add_cmd(dev, &dma->cf_cmd.cmd);
+
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdSASetup\n", dev->name));
+ memcpy(dma->sa_cmd.eth_addr, dev->dev_addr, 6);
+ dma->sa_cmd.cmd.command = SWAP16(CmdSASetup);
+ DMA_WBACK(dev, &(dma->sa_cmd), sizeof(struct sa_cmd));
+ i596_add_cmd(dev, &dma->sa_cmd.cmd);
+
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdTDR\n", dev->name));
+ dma->tdr_cmd.cmd.command = SWAP16(CmdTDR);
+ DMA_WBACK(dev, &(dma->tdr_cmd), sizeof(struct tdr_cmd));
+ i596_add_cmd(dev, &dma->tdr_cmd.cmd);
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ if (wait_cmd(dev, dma, 1000, "timed out waiting to issue RX_START")) {
+ spin_unlock_irqrestore (&lp->lock, flags);
+ goto failed_free_irq;
+ }
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: Issuing RX_START\n", dev->name));
+ dma->scb.command = SWAP16(RX_START);
+ dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+ ca(dev);
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+ if (wait_cmd(dev, dma, 1000, "RX_START not processed"))
+ goto failed_free_irq;
+ DEB(DEB_INIT, printk(KERN_DEBUG
+ "%s: Receive unit started OK\n", dev->name));
+ return 0;
+
+failed_free_irq:
+ free_irq(dev->irq, dev);
+failed:
+ printk(KERN_ERR "%s: Failed to initialise 82596\n", dev->name);
+ mpu_port(dev, PORT_RESET, 0);
+ return -1;
+}
+
+
+static inline int i596_rx(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+ int frames = 0;
+
+ DEB(DEB_RXFRAME, printk(KERN_DEBUG
+ "i596_rx(), rfd_head %p, rbd_head %p\n",
+ lp->rfd_head, lp->rbd_head));
+
+
+ rfd = lp->rfd_head; /* Ref next frame to check */
+
+ DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+ while (rfd->stat & SWAP16(STAT_C)) { /* Loop while complete frames */
+ if (rfd->rbd == I596_NULL)
+ rbd = NULL;
+ else if (rfd->rbd == lp->rbd_head->b_addr) {
+ rbd = lp->rbd_head;
+ DMA_INV(dev, rbd, sizeof(struct i596_rbd));
+ } else {
+ printk(KERN_ERR "%s: rbd chain broken!\n", dev->name);
+ /* XXX Now what? */
+ rbd = NULL;
+ }
+ DEB(DEB_RXFRAME, printk(KERN_DEBUG
+ " rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
+ rfd, rfd->rbd, rfd->stat));
+
+ if (rbd != NULL && (rfd->stat & SWAP16(STAT_OK))) {
+ /* a good frame */
+ int pkt_len = SWAP16(rbd->count) & 0x3fff;
+ struct sk_buff *skb = rbd->skb;
+ int rx_in_place = 0;
+
+ DEB(DEB_RXADDR, print_eth(rbd->v_data, "received"));
+ frames++;
+
+ /* Check if the packet is long enough to just accept
+ * without copying to a properly sized skbuff.
+ */
+
+ if (pkt_len > rx_copybreak) {
+ struct sk_buff *newskb;
+ dma_addr_t dma_addr;
+
+ dma_unmap_single(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ /* Get fresh skbuff to replace filled one. */
+ newskb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+ if (newskb == NULL) {
+ skb = NULL; /* drop pkt */
+ goto memory_squeeze;
+ }
+ skb_reserve(newskb, 2);
+
+ /* Pass up the skb already on the Rx ring. */
+ skb_put(skb, pkt_len);
+ rx_in_place = 1;
+ rbd->skb = newskb;
+ dma_addr = dma_map_single(dev->dev.parent,
+ newskb->data,
+ PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
+ rbd->v_data = newskb->data;
+ rbd->b_data = SWAP32(dma_addr);
+ DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+ } else
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
+memory_squeeze:
+ if (skb == NULL) {
+ /* XXX tulip.c can defer packets here!! */
+ printk(KERN_ERR
+ "%s: i596_rx Memory squeeze, dropping packet.\n",
+ dev->name);
+ lp->stats.rx_dropped++;
+ } else {
+ if (!rx_in_place) {
+ /* 16 byte align the data fields */
+ dma_sync_single_for_cpu(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb, pkt_len), rbd->v_data, pkt_len);
+ dma_sync_single_for_device(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ }
+ skb->len = pkt_len;
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes += pkt_len;
+ }
+ } else {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: Error, rfd.stat = 0x%04x\n",
+ dev->name, rfd->stat));
+ lp->stats.rx_errors++;
+ if (rfd->stat & SWAP16(0x0100))
+ lp->stats.collisions++;
+ if (rfd->stat & SWAP16(0x8000))
+ lp->stats.rx_length_errors++;
+ if (rfd->stat & SWAP16(0x0001))
+ lp->stats.rx_over_errors++;
+ if (rfd->stat & SWAP16(0x0002))
+ lp->stats.rx_fifo_errors++;
+ if (rfd->stat & SWAP16(0x0004))
+ lp->stats.rx_frame_errors++;
+ if (rfd->stat & SWAP16(0x0008))
+ lp->stats.rx_crc_errors++;
+ if (rfd->stat & SWAP16(0x0010))
+ lp->stats.rx_length_errors++;
+ }
+
+ /* Clear the buffer descriptor count and EOF + F flags */
+
+ if (rbd != NULL && (rbd->count & SWAP16(0x4000))) {
+ rbd->count = 0;
+ lp->rbd_head = rbd->v_next;
+ DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+ }
+
+ /* Tidy the frame descriptor, marking it as end of list */
+
+ rfd->rbd = I596_NULL;
+ rfd->stat = 0;
+ rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+ rfd->count = 0;
+
+ /* Update record of next frame descriptor to process */
+
+ lp->dma->scb.rfd = rfd->b_next;
+ lp->rfd_head = rfd->v_next;
+ DMA_WBACK_INV(dev, rfd, sizeof(struct i596_rfd));
+
+ /* Remove end-of-list from old end descriptor */
+
+ rfd->v_prev->cmd = SWAP16(CMD_FLEX);
+ DMA_WBACK_INV(dev, rfd->v_prev, sizeof(struct i596_rfd));
+ rfd = lp->rfd_head;
+ DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+ }
+
+ DEB(DEB_RXFRAME, printk(KERN_DEBUG "frames %d\n", frames));
+
+ return 0;
+}
+
+
+static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
+{
+ struct i596_cmd *ptr;
+
+ while (lp->cmd_head != NULL) {
+ ptr = lp->cmd_head;
+ lp->cmd_head = ptr->v_next;
+ lp->cmd_backlog--;
+
+ switch (SWAP16(ptr->command) & 0x7) {
+ case CmdTx:
+ {
+ struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+ struct sk_buff *skb = tx_cmd->skb;
+ dma_unmap_single(dev->dev.parent,
+ tx_cmd->dma_addr,
+ skb->len, DMA_TO_DEVICE);
+
+ dev_kfree_skb(skb);
+
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+
+ ptr->v_next = NULL;
+ ptr->b_next = I596_NULL;
+ tx_cmd->cmd.command = 0; /* Mark as free */
+ break;
+ }
+ default:
+ ptr->v_next = NULL;
+ ptr->b_next = I596_NULL;
+ }
+ DMA_WBACK_INV(dev, ptr, sizeof(struct i596_cmd));
+ }
+
+ wait_cmd(dev, lp->dma, 100, "i596_cleanup_cmd timed out");
+ lp->dma->scb.cmd = I596_NULL;
+ DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+}
+
+
+static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
+{
+ unsigned long flags;
+
+ DEB(DEB_RESET, printk(KERN_DEBUG "i596_reset\n"));
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ wait_cmd(dev, lp->dma, 100, "i596_reset timed out");
+
+ netif_stop_queue(dev);
+
+ /* FIXME: this command might cause an lpmc */
+ lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+ DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+ ca(dev);
+
+ /* wait for shutdown */
+ wait_cmd(dev, lp->dma, 1000, "i596_reset 2 timed out");
+ spin_unlock_irqrestore (&lp->lock, flags);
+
+ i596_cleanup_cmd(dev, lp);
+ i596_rx(dev);
+
+ netif_start_queue(dev);
+ init_i596_mem(dev);
+}
+
+
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ unsigned long flags;
+
+ DEB(DEB_ADDCMD, printk(KERN_DEBUG "i596_add_cmd cmd_head %p\n",
+ lp->cmd_head));
+
+ cmd->status = 0;
+ cmd->command |= SWAP16(CMD_EOL | CMD_INTR);
+ cmd->v_next = NULL;
+ cmd->b_next = I596_NULL;
+ DMA_WBACK(dev, cmd, sizeof(struct i596_cmd));
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ if (lp->cmd_head != NULL) {
+ lp->cmd_tail->v_next = cmd;
+ lp->cmd_tail->b_next = SWAP32(virt_to_dma(lp, &cmd->status));
+ DMA_WBACK(dev, lp->cmd_tail, sizeof(struct i596_cmd));
+ } else {
+ lp->cmd_head = cmd;
+ wait_cmd(dev, dma, 100, "i596_add_cmd timed out");
+ dma->scb.cmd = SWAP32(virt_to_dma(lp, &cmd->status));
+ dma->scb.command = SWAP16(CUC_START);
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+ ca(dev);
+ }
+ lp->cmd_tail = cmd;
+ lp->cmd_backlog++;
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+
+ if (lp->cmd_backlog > max_cmd_backlog) {
+ unsigned long tickssofar = jiffies - lp->last_cmd;
+
+ if (tickssofar < ticks_limit)
+ return;
+
+ printk(KERN_ERR
+ "%s: command unit timed out, status resetting.\n",
+ dev->name);
+#if 1
+ i596_reset(dev, lp);
+#endif
+ }
+}
+
+static int i596_open(struct net_device *dev)
+{
+ DEB(DEB_OPEN, printk(KERN_DEBUG
+ "%s: i596_open() irq %d.\n", dev->name, dev->irq));
+
+ if (init_rx_bufs(dev)) {
+ printk(KERN_ERR "%s: Failed to init rx bufs\n", dev->name);
+ return -EAGAIN;
+ }
+ if (init_i596_mem(dev)) {
+ printk(KERN_ERR "%s: Failed to init memory\n", dev->name);
+ goto out_remove_rx_bufs;
+ }
+ netif_start_queue(dev);
+
+ return 0;
+
+out_remove_rx_bufs:
+ remove_rx_bufs(dev);
+ return -EAGAIN;
+}
+
+static void i596_tx_timeout (struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ /* Transmitter timeout, serious problems. */
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: transmit timed out, status resetting.\n",
+ dev->name));
+
+ lp->stats.tx_errors++;
+
+ /* Try to restart the adaptor */
+ if (lp->last_restart == lp->stats.tx_packets) {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG "Resetting board.\n"));
+ /* Shutdown and restart */
+ i596_reset (dev, lp);
+ } else {
+ /* Issue a channel attention signal */
+ DEB(DEB_ERRORS, printk(KERN_DEBUG "Kicking board.\n"));
+ lp->dma->scb.command = SWAP16(CUC_START | RX_START);
+ DMA_WBACK_INV(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+ ca (dev);
+ lp->last_restart = lp->stats.tx_packets;
+ }
+
+ dev->trans_start = jiffies;
+ netif_wake_queue (dev);
+}
+
+
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct tx_cmd *tx_cmd;
+ struct i596_tbd *tbd;
+ short length = skb->len;
+ dev->trans_start = jiffies;
+
+ DEB(DEB_STARTTX, printk(KERN_DEBUG
+ "%s: i596_start_xmit(%x,%p) called\n",
+ dev->name, skb->len, skb->data));
+
+ if (length < ETH_ZLEN) {
+ if (skb_padto(skb, ETH_ZLEN))
+ return 0;
+ length = ETH_ZLEN;
+ }
+
+ netif_stop_queue(dev);
+
+ tx_cmd = lp->dma->tx_cmds + lp->next_tx_cmd;
+ tbd = lp->dma->tbds + lp->next_tx_cmd;
+
+ if (tx_cmd->cmd.command) {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: xmit ring full, dropping packet.\n",
+ dev->name));
+ lp->stats.tx_dropped++;
+
+ dev_kfree_skb(skb);
+ } else {
+ if (++lp->next_tx_cmd == TX_RING_SIZE)
+ lp->next_tx_cmd = 0;
+ tx_cmd->tbd = SWAP32(virt_to_dma(lp, tbd));
+ tbd->next = I596_NULL;
+
+ tx_cmd->cmd.command = SWAP16(CMD_FLEX | CmdTx);
+ tx_cmd->skb = skb;
+
+ tx_cmd->pad = 0;
+ tx_cmd->size = 0;
+ tbd->pad = 0;
+ tbd->size = SWAP16(EOF | length);
+
+ tx_cmd->dma_addr = dma_map_single(dev->dev.parent, skb->data,
+ skb->len, DMA_TO_DEVICE);
+ tbd->data = SWAP32(tx_cmd->dma_addr);
+
+ DEB(DEB_TXADDR, print_eth(skb->data, "tx-queued"));
+ DMA_WBACK_INV(dev, tx_cmd, sizeof(struct tx_cmd));
+ DMA_WBACK_INV(dev, tbd, sizeof(struct i596_tbd));
+ i596_add_cmd(dev, &tx_cmd->cmd);
+
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += length;
+ }
+
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static void print_eth(unsigned char *add, char *str)
+{
+ int i;
+
+ printk(KERN_DEBUG "i596 0x%p, ", add);
+ for (i = 0; i < 6; i++)
+ printk(" %02X", add[i + 6]);
+ printk(" -->");
+ for (i = 0; i < 6; i++)
+ printk(" %02X", add[i]);
+ printk(" %02X%02X, %s\n", add[12], add[13], str);
+}
+
+static int __devinit i82596_probe(struct net_device *dev)
+{
+ int i;
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma;
+
+ /* This lot is ensure things have been cache line aligned. */
+ BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
+ BUILD_BUG_ON(sizeof(struct i596_rbd) & 31);
+ BUILD_BUG_ON(sizeof(struct tx_cmd) & 31);
+ BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
+#ifndef __LP64__
+ BUILD_BUG_ON(sizeof(struct i596_dma) > 4096);
+#endif
+
+ if (!dev->base_addr || !dev->irq)
+ return -ENODEV;
+
+ dma = (struct i596_dma *) DMA_ALLOC(dev->dev.parent,
+ sizeof(struct i596_dma), &lp->dma_addr, GFP_KERNEL);
+ if (!dma) {
+ printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
+ return -ENOMEM;
+ }
+
+ /* The 82596-specific entries in the device structure. */
+ dev->open = i596_open;
+ dev->stop = i596_close;
+ dev->hard_start_xmit = i596_start_xmit;
+ dev->get_stats = i596_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+ dev->tx_timeout = i596_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = i596_poll_controller;
+#endif
+
+ memset(dma, 0, sizeof(struct i596_dma));
+ lp->dma = dma;
+
+ dma->scb.command = 0;
+ dma->scb.cmd = I596_NULL;
+ dma->scb.rfd = I596_NULL;
+ spin_lock_init(&lp->lock);
+
+ DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+
+ i = register_netdev(dev);
+ if (i) {
+ DMA_FREE(dev->dev.parent, sizeof(struct i596_dma),
+ (void *)dma, lp->dma_addr);
+ return i;
+ };
+
+ DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,",
+ dev->name, dev->base_addr));
+ for (i = 0; i < 6; i++)
+ DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
+ DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
+ DEB(DEB_INIT, printk(KERN_INFO
+ "%s: dma at 0x%p (%d bytes), lp->scb at 0x%p\n",
+ dev->name, dma, (int)sizeof(struct i596_dma),
+ &dma->scb));
+
+ return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ i596_interrupt(dev->irq, dev);
+ enable_irq(dev->irq);
+}
+#endif
+
+static irqreturn_t i596_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct i596_private *lp;
+ struct i596_dma *dma;
+ unsigned short status, ack_cmd = 0;
+
+ if (dev == NULL) {
+ printk(KERN_WARNING "%s: irq %d for unknown device.\n",
+ __FUNCTION__, irq);
+ return IRQ_NONE;
+ }
+
+ lp = netdev_priv(dev);
+ dma = lp->dma;
+
+ spin_lock (&lp->lock);
+
+ wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+ status = SWAP16(dma->scb.status);
+
+ DEB(DEB_INTS, printk(KERN_DEBUG
+ "%s: i596 interrupt, IRQ %d, status %4.4x.\n",
+ dev->name, irq, status));
+
+ ack_cmd = status & 0xf000;
+
+ if (!ack_cmd) {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: interrupt with no events\n",
+ dev->name));
+ spin_unlock (&lp->lock);
+ return IRQ_NONE;
+ }
+
+ if ((status & 0x8000) || (status & 0x2000)) {
+ struct i596_cmd *ptr;
+
+ if ((status & 0x8000))
+ DEB(DEB_INTS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt completed command.\n",
+ dev->name));
+ if ((status & 0x2000))
+ DEB(DEB_INTS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt command unit inactive %x.\n",
+ dev->name, status & 0x0700));
+
+ while (lp->cmd_head != NULL) {
+ DMA_INV(dev, lp->cmd_head, sizeof(struct i596_cmd));
+ if (!(lp->cmd_head->status & SWAP16(STAT_C)))
+ break;
+
+ ptr = lp->cmd_head;
+
+ DEB(DEB_STATUS,
+ printk(KERN_DEBUG
+ "cmd_head->status = %04x, ->command = %04x\n",
+ SWAP16(lp->cmd_head->status),
+ SWAP16(lp->cmd_head->command)));
+ lp->cmd_head = ptr->v_next;
+ lp->cmd_backlog--;
+
+ switch (SWAP16(ptr->command) & 0x7) {
+ case CmdTx:
+ {
+ struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+ struct sk_buff *skb = tx_cmd->skb;
+
+ if (ptr->status & SWAP16(STAT_OK)) {
+ DEB(DEB_TXADDR,
+ print_eth(skb->data, "tx-done"));
+ } else {
+ lp->stats.tx_errors++;
+ if (ptr->status & SWAP16(0x0020))
+ lp->stats.collisions++;
+ if (!(ptr->status & SWAP16(0x0040)))
+ lp->stats.tx_heartbeat_errors++;
+ if (ptr->status & SWAP16(0x0400))
+ lp->stats.tx_carrier_errors++;
+ if (ptr->status & SWAP16(0x0800))
+ lp->stats.collisions++;
+ if (ptr->status & SWAP16(0x1000))
+ lp->stats.tx_aborted_errors++;
+ }
+ dma_unmap_single(dev->dev.parent,
+ tx_cmd->dma_addr,
+ skb->len, DMA_TO_DEVICE);
+ dev_kfree_skb_irq(skb);
+
+ tx_cmd->cmd.command = 0; /* Mark free */
+ break;
+ }
+ case CmdTDR:
+ {
+ unsigned short status = SWAP16(((struct tdr_cmd *)ptr)->status);
+
+ if (status & 0x8000) {
+ DEB(DEB_ANY,
+ printk(KERN_DEBUG "%s: link ok.\n",
+ dev->name));
+ } else {
+ if (status & 0x4000)
+ printk(KERN_ERR
+ "%s: Transceiver problem.\n",
+ dev->name);
+ if (status & 0x2000)
+ printk(KERN_ERR
+ "%s: Termination problem.\n",
+ dev->name);
+ if (status & 0x1000)
+ printk(KERN_ERR
+ "%s: Short circuit.\n",
+ dev->name);
+
+ DEB(DEB_TDR,
+ printk(KERN_DEBUG "%s: Time %d.\n",
+ dev->name, status & 0x07ff));
+ }
+ break;
+ }
+ case CmdConfigure:
+ /*
+ * Zap command so set_multicast_list() know
+ * it is free
+ */
+ ptr->command = 0;
+ break;
+ }
+ ptr->v_next = NULL;
+ ptr->b_next = I596_NULL;
+ DMA_WBACK(dev, ptr, sizeof(struct i596_cmd));
+ lp->last_cmd = jiffies;
+ }
+
+ /* This mess is arranging that only the last of any outstanding
+ * commands has the interrupt bit set. Should probably really
+ * only add to the cmd queue when the CU is stopped.
+ */
+ ptr = lp->cmd_head;
+ while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
+ struct i596_cmd *prev = ptr;
+
+ ptr->command &= SWAP16(0x1fff);
+ ptr = ptr->v_next;
+ DMA_WBACK_INV(dev, prev, sizeof(struct i596_cmd));
+ }
+
+ if (lp->cmd_head != NULL)
+ ack_cmd |= CUC_START;
+ dma->scb.cmd = SWAP32(virt_to_dma(lp, &lp->cmd_head->status));
+ DMA_WBACK_INV(dev, &dma->scb, sizeof(struct i596_scb));
+ }
+ if ((status & 0x1000) || (status & 0x4000)) {
+ if ((status & 0x4000))
+ DEB(DEB_INTS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt received a frame.\n",
+ dev->name));
+ i596_rx(dev);
+ /* Only RX_START if stopped - RGH 07-07-96 */
+ if (status & 0x1000) {
+ if (netif_running(dev)) {
+ DEB(DEB_ERRORS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt receive unit inactive, status 0x%x\n",
+ dev->name, status));
+ ack_cmd |= RX_START;
+ lp->stats.rx_errors++;
+ lp->stats.rx_fifo_errors++;
+ rebuild_rx_bufs(dev);
+ }
+ }
+ }
+ wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+ dma->scb.command = SWAP16(ack_cmd);
+ DMA_WBACK(dev, &dma->scb, sizeof(struct i596_scb));
+
+ /* DANGER: I suspect that some kind of interrupt
+ acknowledgement aside from acking the 82596 might be needed
+ here... but it's running acceptably without */
+
+ ca(dev);
+
+ wait_cmd(dev, dma, 100, "i596 interrupt, exit timeout");
+ DEB(DEB_INTS, printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name));
+
+ spin_unlock (&lp->lock);
+ return IRQ_HANDLED;
+}
+
+static int i596_close(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ unsigned long flags;
+
+ netif_stop_queue(dev);
+
+ DEB(DEB_INIT,
+ printk(KERN_DEBUG
+ "%s: Shutting down ethercard, status was %4.4x.\n",
+ dev->name, SWAP16(lp->dma->scb.status)));
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ wait_cmd(dev, lp->dma, 100, "close1 timed out");
+ lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+ DMA_WBACK(dev, &lp->dma->scb, sizeof(struct i596_scb));
+
+ ca(dev);
+
+ wait_cmd(dev, lp->dma, 100, "close2 timed out");
+ spin_unlock_irqrestore(&lp->lock, flags);
+ DEB(DEB_STRUCT, i596_display_data(dev));
+ i596_cleanup_cmd(dev, lp);
+
+ free_irq(dev->irq, dev);
+ remove_rx_bufs(dev);
+
+ return 0;
+}
+
+static struct net_device_stats *i596_get_stats(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ return &lp->stats;
+}
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ int config = 0, cnt;
+
+ DEB(DEB_MULTI,
+ printk(KERN_DEBUG
+ "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
+ dev->name, dev->mc_count,
+ dev->flags & IFF_PROMISC ? "ON" : "OFF",
+ dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
+
+ if ((dev->flags & IFF_PROMISC) &&
+ !(dma->cf_cmd.i596_config[8] & 0x01)) {
+ dma->cf_cmd.i596_config[8] |= 0x01;
+ config = 1;
+ }
+ if (!(dev->flags & IFF_PROMISC) &&
+ (dma->cf_cmd.i596_config[8] & 0x01)) {
+ dma->cf_cmd.i596_config[8] &= ~0x01;
+ config = 1;
+ }
+ if ((dev->flags & IFF_ALLMULTI) &&
+ (dma->cf_cmd.i596_config[11] & 0x20)) {
+ dma->cf_cmd.i596_config[11] &= ~0x20;
+ config = 1;
+ }
+ if (!(dev->flags & IFF_ALLMULTI) &&
+ !(dma->cf_cmd.i596_config[11] & 0x20)) {
+ dma->cf_cmd.i596_config[11] |= 0x20;
+ config = 1;
+ }
+ if (config) {
+ if (dma->cf_cmd.cmd.command)
+ printk(KERN_INFO
+ "%s: config change request already queued\n",
+ dev->name);
+ else {
+ dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+ DMA_WBACK_INV(dev, &dma->cf_cmd, sizeof(struct cf_cmd));
+ i596_add_cmd(dev, &dma->cf_cmd.cmd);
+ }
+ }
+
+ cnt = dev->mc_count;
+ if (cnt > MAX_MC_CNT) {
+ cnt = MAX_MC_CNT;
+ printk(KERN_NOTICE "%s: Only %d multicast addresses supported",
+ dev->name, cnt);
+ }
+
+ if (dev->mc_count > 0) {
+ struct dev_mc_list *dmi;
+ unsigned char *cp;
+ struct mc_cmd *cmd;
+
+ cmd = &dma->mc_cmd;
+ cmd->cmd.command = SWAP16(CmdMulticastList);
+ cmd->mc_cnt = SWAP16(dev->mc_count * 6);
+ cp = cmd->mc_addrs;
+ for (dmi = dev->mc_list;
+ cnt && dmi != NULL;
+ dmi = dmi->next, cnt--, cp += 6) {
+ memcpy(cp, dmi->dmi_addr, 6);
+ if (i596_debug > 1)
+ DEB(DEB_MULTI,
+ printk(KERN_DEBUG
+ "%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name, cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]));
+ }
+ DMA_WBACK_INV(dev, &dma->mc_cmd, sizeof(struct mc_cmd));
+ i596_add_cmd(dev, &cmd->cmd);
+ }
+}
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index fef3193121f..9a343b96597 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -577,7 +577,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
int intr, fs;
- unsigned int flags;
+ unsigned long flags;
/* don't want the dma interrupt handler to fire */
local_irq_save(flags);
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index 7f8b7d55b6e..492cfaaaa75 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -113,8 +113,7 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
struct mlx4_cmd_mailbox *mailbox;
int ret = 0;
- if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
- new_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
+ if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE ||
!op[cur_state][new_state])
return -EINVAL;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index d0cc122fa3f..e1732c164a4 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -60,6 +60,7 @@
#include <linux/crc32.h>
#include <linux/moduleparam.h>
#include <linux/io.h>
+#include <linux/log2.h>
#include <net/checksum.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -1804,7 +1805,7 @@ static int myri10ge_open(struct net_device *dev)
*/
big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) {
- while ((big_pow2 & (big_pow2 - 1)) != 0)
+ while (!is_power_of_2(big_pow2))
big_pow2++;
mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
} else {
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 619503742b7..325269d8ae3 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -1097,109 +1097,6 @@ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
int netxen_nic_set_mac(struct net_device *netdev, void *p);
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
-static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
-{
- uint32_t mask = 0x7ff;
- int retries = 32;
-
- DPRINTK(1, INFO, "Entered ISR Disable \n");
-
- switch (adapter->portnum) {
- case 0:
- writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
- break;
- case 1:
- writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
- break;
- case 2:
- writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
- break;
- case 3:
- writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
- break;
- }
-
- if (adapter->intr_scheme != -1 &&
- adapter->intr_scheme != INTR_SCHEME_PERPORT) {
- writel(mask,
- (void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)));
- }
-
- /* Window = 0 or 1 */
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
- do {
- writel(0xffffffff, (void *)
- (PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS)));
- mask = readl((void *)
- (pci_base_offset(adapter, ISR_INT_VECTOR)));
- if (!(mask & 0x80))
- break;
- udelay(10);
- } while (--retries);
-
- if (!retries) {
- printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n",
- netxen_nic_driver_name);
- }
- }
-
- DPRINTK(1, INFO, "Done with Disable Int\n");
-
- return;
-}
-
-static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
-{
- u32 mask;
-
- DPRINTK(1, INFO, "Entered ISR Enable \n");
-
- if (adapter->intr_scheme != -1 &&
- adapter->intr_scheme != INTR_SCHEME_PERPORT) {
- switch (adapter->ahw.board_type) {
- case NETXEN_NIC_GBE:
- mask = 0x77b;
- break;
- case NETXEN_NIC_XGBE:
- mask = 0x77f;
- break;
- default:
- mask = 0x7ff;
- break;
- }
-
- writel(mask,
- (void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)));
- }
- switch (adapter->portnum) {
- case 0:
- writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
- break;
- case 1:
- writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
- break;
- case 2:
- writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
- break;
- case 3:
- writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
- break;
- }
-
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
- mask = 0xbff;
- if (adapter->intr_scheme != -1 &&
- adapter->intr_scheme != INTR_SCHEME_PERPORT) {
- writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
- }
- writel(mask,
- (void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK)));
- }
-
- DPRINTK(1, INFO, "Done with enable Int\n");
-
- return;
-}
/*
* NetXen Board information
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index a66ff58366c..56f8197b953 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -156,6 +156,103 @@ static inline void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter
#define ADAPTER_LIST_SIZE 12
int netxen_cards_found;
+static void netxen_nic_disable_int(struct netxen_adapter *adapter)
+{
+ uint32_t mask = 0x7ff;
+ int retries = 32;
+
+ DPRINTK(1, INFO, "Entered ISR Disable \n");
+
+ switch (adapter->portnum) {
+ case 0:
+ writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+ break;
+ case 1:
+ writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+ break;
+ case 2:
+ writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+ break;
+ case 3:
+ writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+ break;
+ }
+
+ if (adapter->intr_scheme != -1 &&
+ adapter->intr_scheme != INTR_SCHEME_PERPORT)
+ writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+
+ /* Window = 0 or 1 */
+ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ do {
+ writel(0xffffffff,
+ PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS));
+ mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+ if (!(mask & 0x80))
+ break;
+ udelay(10);
+ } while (--retries);
+
+ if (!retries) {
+ printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n",
+ netxen_nic_driver_name);
+ }
+ }
+
+ DPRINTK(1, INFO, "Done with Disable Int\n");
+}
+
+static void netxen_nic_enable_int(struct netxen_adapter *adapter)
+{
+ u32 mask;
+
+ DPRINTK(1, INFO, "Entered ISR Enable \n");
+
+ if (adapter->intr_scheme != -1 &&
+ adapter->intr_scheme != INTR_SCHEME_PERPORT) {
+ switch (adapter->ahw.board_type) {
+ case NETXEN_NIC_GBE:
+ mask = 0x77b;
+ break;
+ case NETXEN_NIC_XGBE:
+ mask = 0x77f;
+ break;
+ default:
+ mask = 0x7ff;
+ break;
+ }
+
+ writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ }
+
+ switch (adapter->portnum) {
+ case 0:
+ writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+ break;
+ case 1:
+ writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+ break;
+ case 2:
+ writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+ break;
+ case 3:
+ writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+ break;
+ }
+
+ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ mask = 0xbff;
+ if (adapter->intr_scheme != -1 &&
+ adapter->intr_scheme != INTR_SCHEME_PERPORT) {
+ writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ }
+ writel(mask,
+ PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK));
+ }
+
+ DPRINTK(1, INFO, "Done with enable Int\n");
+}
+
/*
* netxen_nic_probe()
*
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 75102d30730..05e0577a0e1 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -724,7 +724,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
__u32 mac_cfg0;
u32 port = physical_port[adapter->portnum];
- if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ if (port > NETXEN_NIU_MAX_GBE_PORTS)
return -EINVAL;
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
@@ -757,7 +757,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
__u32 reg;
u32 port = physical_port[adapter->portnum];
- if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ if (port > NETXEN_NIU_MAX_GBE_PORTS)
return -EINVAL;
/* save previous contents */
@@ -894,7 +894,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
__u32 reg;
u32 port = physical_port[adapter->portnum];
- if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
+ if (port > NETXEN_NIU_MAX_XG_PORTS)
return -EINVAL;
if (netxen_nic_hw_read_wx(adapter,
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 8d38425e46c..0b3066a6fe4 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -755,7 +755,7 @@ static int pasemi_mac_open(struct net_device *dev)
flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
- PAS_IOB_DMA_RXCH_CFG_CNTTH(1));
+ PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 808fae1577e..50dff1b81d3 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -521,6 +521,7 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
static int axnet_open(struct net_device *dev)
{
+ int ret;
axnet_dev_t *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
@@ -529,9 +530,11 @@ static int axnet_open(struct net_device *dev)
if (!pcmcia_dev_present(link))
return -ENODEV;
- link->open++;
+ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+ if (ret)
+ return ret;
- request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+ link->open++;
info->link_status = 0x00;
init_timer(&info->watchdog);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 3f93d493323..85d5f2ca4bb 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -109,7 +109,7 @@ static const struct ethtool_ops netdev_ethtool_ops;
card type
*/
typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
- XXX10304
+ XXX10304, NEC, KME
} cardtype_t;
/*
@@ -374,6 +374,18 @@ static int fmvj18x_config(struct pcmcia_device *link)
link->io.NumPorts2 = 8;
}
break;
+ case MANFID_NEC:
+ cardtype = NEC; /* MultiFunction Card */
+ link->conf.ConfigBase = 0x800;
+ link->conf.ConfigIndex = 0x47;
+ link->io.NumPorts2 = 8;
+ break;
+ case MANFID_KME:
+ cardtype = KME; /* MultiFunction Card */
+ link->conf.ConfigBase = 0x800;
+ link->conf.ConfigIndex = 0x47;
+ link->io.NumPorts2 = 8;
+ break;
case MANFID_CONTEC:
cardtype = CONTEC;
break;
@@ -450,6 +462,8 @@ static int fmvj18x_config(struct pcmcia_device *link)
case TDK:
case LA501:
case CONTEC:
+ case NEC:
+ case KME:
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
@@ -469,6 +483,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
card_name = "TDK LAK-CD021";
} else if( cardtype == LA501 ) {
card_name = "LA501";
+ } else if( cardtype == NEC ) {
+ card_name = "PK-UG-J001";
+ } else if( cardtype == KME ) {
+ card_name = "Panasonic";
} else {
card_name = "C-NET(PC)C";
}
@@ -678,8 +696,11 @@ static struct pcmcia_device_id fmvj18x_ids[] = {
PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
+ PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
+ PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index d88e9b2e93c..63de89e93b7 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -960,6 +960,7 @@ static void mii_phy_probe(struct net_device *dev)
static int pcnet_open(struct net_device *dev)
{
+ int ret;
pcnet_dev_t *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
@@ -968,10 +969,12 @@ static int pcnet_open(struct net_device *dev)
if (!pcmcia_dev_present(link))
return -ENODEV;
- link->open++;
-
set_misc_reg(dev);
- request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+ if (ret)
+ return ret;
+
+ link->open++;
info->phy_id = info->eth_phy;
info->link_status = 0x00;
@@ -1552,6 +1555,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
+ PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
@@ -1577,6 +1581,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
+ PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 09b6f259eb9..dd09011c7ee 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -55,6 +55,11 @@ config BROADCOM_PHY
---help---
Currently supports the BCM5411, BCM5421 and BCM5461 PHYs.
+config ICPLUS_PHY
+ tristate "Drivers for ICPlus PHYs"
+ ---help---
+ Currently supports the IP175C PHY.
+
config FIXED_PHY
tristate "Drivers for PHY emulation on fixed speed/link"
---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index bcd1efbd2a1..8885650647f 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -11,4 +11,5 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
+obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_FIXED_PHY) += fixed.o
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
new file mode 100644
index 00000000000..af3f1f2a9f8
--- /dev/null
+++ b/drivers/net/phy/icplus.c
@@ -0,0 +1,134 @@
+/*
+ * Driver for ICPlus PHYs
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
+MODULE_AUTHOR("Michael Barkowski");
+MODULE_LICENSE("GPL");
+
+static int ip175c_config_init(struct phy_device *phydev)
+{
+ int err, i;
+ static int full_reset_performed = 0;
+
+ if (full_reset_performed == 0) {
+
+ /* master reset */
+ err = phydev->bus->write(phydev->bus, 30, 0, 0x175c);
+ if (err < 0)
+ return err;
+
+ /* ensure no bus delays overlap reset period */
+ err = phydev->bus->read(phydev->bus, 30, 0);
+
+ /* data sheet specifies reset period is 2 msec */
+ mdelay(2);
+
+ /* enable IP175C mode */
+ err = phydev->bus->write(phydev->bus, 29, 31, 0x175c);
+ if (err < 0)
+ return err;
+
+ /* Set MII0 speed and duplex (in PHY mode) */
+ err = phydev->bus->write(phydev->bus, 29, 22, 0x420);
+ if (err < 0)
+ return err;
+
+ /* reset switch ports */
+ for (i = 0; i < 5; i++) {
+ err = phydev->bus->write(phydev->bus, i,
+ MII_BMCR, BMCR_RESET);
+ if (err < 0)
+ return err;
+ }
+
+ for (i = 0; i < 5; i++)
+ err = phydev->bus->read(phydev->bus, i, MII_BMCR);
+
+ mdelay(2);
+
+ full_reset_performed = 1;
+ }
+
+ if (phydev->addr != 4) {
+ phydev->state = PHY_RUNNING;
+ phydev->speed = SPEED_100;
+ phydev->duplex = DUPLEX_FULL;
+ phydev->link = 1;
+ netif_carrier_on(phydev->attached_dev);
+ }
+
+ return 0;
+}
+
+static int ip175c_read_status(struct phy_device *phydev)
+{
+ if (phydev->addr == 4) /* WAN port */
+ genphy_read_status(phydev);
+ else
+ /* Don't need to read status for switch ports */
+ phydev->irq = PHY_IGNORE_INTERRUPT;
+
+ return 0;
+}
+
+static int ip175c_config_aneg(struct phy_device *phydev)
+{
+ if (phydev->addr == 4) /* WAN port */
+ genphy_config_aneg(phydev);
+
+ return 0;
+}
+
+static struct phy_driver ip175c_driver = {
+ .phy_id = 0x02430d80,
+ .name = "ICPlus IP175C",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .config_init = &ip175c_config_init,
+ .config_aneg = &ip175c_config_aneg,
+ .read_status = &ip175c_read_status,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init ip175c_init(void)
+{
+ return phy_driver_register(&ip175c_driver);
+}
+
+static void __exit ip175c_exit(void)
+{
+ phy_driver_unregister(&ip175c_driver);
+}
+
+module_init(ip175c_init);
+module_exit(ip175c_exit);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index b87f8d2a888..d2ede5ff9ff 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -60,6 +60,7 @@
#define MII_M1111_PHY_EXT_SR 0x1b
#define MII_M1111_HWCFG_MODE_MASK 0xf
#define MII_M1111_HWCFG_MODE_RGMII 0xb
+#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4
MODULE_DESCRIPTION("Marvell PHY driver");
MODULE_AUTHOR("Andy Fleming");
@@ -169,6 +170,21 @@ static int m88e1111_config_init(struct phy_device *phydev)
return err;
}
+ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+ int temp;
+
+ temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
+ if (temp < 0)
+ return temp;
+
+ temp &= ~(MII_M1111_HWCFG_MODE_MASK);
+ temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
+
+ err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+ if (err < 0)
+ return err;
+ }
+
err = phy_write(phydev, MII_BMCR, BMCR_RESET);
if (err < 0)
return err;
@@ -238,77 +254,84 @@ static int m88e1145_config_init(struct phy_device *phydev)
return 0;
}
-static struct phy_driver m88e1101_driver = {
- .phy_id = 0x01410c60,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1101",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1111_driver = {
- .phy_id = 0x01410cc0,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1111",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .config_init = &m88e1111_config_init,
- .driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1145_driver = {
- .phy_id = 0x01410cd0,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1145",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_init = &m88e1145_config_init,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
+static struct phy_driver marvell_drivers[] = {
+ {
+ .phy_id = 0x01410c60,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1101",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
+ .phy_id = 0x01410c90,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1112",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1111_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
+ .phy_id = 0x01410cc0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1111",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1111_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
+ .phy_id = 0x01410cd0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1145",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1145_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ }
};
static int __init marvell_init(void)
{
int ret;
+ int i;
- ret = phy_driver_register(&m88e1101_driver);
- if (ret)
- return ret;
+ for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) {
+ ret = phy_driver_register(&marvell_drivers[i]);
- ret = phy_driver_register(&m88e1111_driver);
- if (ret)
- goto err1111;
-
- ret = phy_driver_register(&m88e1145_driver);
- if (ret)
- goto err1145;
+ if (ret) {
+ while (i-- > 0)
+ phy_driver_unregister(&marvell_drivers[i]);
+ return ret;
+ }
+ }
return 0;
-
-err1145:
- phy_driver_unregister(&m88e1111_driver);
-err1111:
- phy_driver_unregister(&m88e1101_driver);
- return ret;
}
static void __exit marvell_exit(void)
{
- phy_driver_unregister(&m88e1101_driver);
- phy_driver_unregister(&m88e1111_driver);
- phy_driver_unregister(&m88e1145_driver);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++)
+ phy_driver_unregister(&marvell_drivers[i]);
}
module_init(marvell_init);
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
new file mode 100644
index 00000000000..08d25066f05
--- /dev/null
+++ b/drivers/net/ps3_gelic_net.c
@@ -0,0 +1,1576 @@
+/*
+ * PS3 gelic network driver.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * This file is based on: spider_net.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.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, 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.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+#include <linux/dma-mapping.h>
+#include <net/checksum.h>
+#include <asm/firmware.h>
+#include <asm/ps3.h>
+#include <asm/lv1call.h>
+
+#include "ps3_gelic_net.h"
+
+#define DRV_NAME "Gelic Network Driver"
+#define DRV_VERSION "1.0"
+
+MODULE_AUTHOR("SCE Inc.");
+MODULE_DESCRIPTION("Gelic Network driver");
+MODULE_LICENSE("GPL");
+
+static inline struct device *ctodev(struct gelic_net_card *card)
+{
+ return &card->dev->core;
+}
+static inline unsigned int bus_id(struct gelic_net_card *card)
+{
+ return card->dev->bus_id;
+}
+static inline unsigned int dev_id(struct gelic_net_card *card)
+{
+ return card->dev->dev_id;
+}
+
+/* set irq_mask */
+static int gelic_net_set_irq_mask(struct gelic_net_card *card, u64 mask)
+{
+ int status;
+
+ status = lv1_net_set_interrupt_mask(bus_id(card), dev_id(card),
+ mask, 0);
+ if (status)
+ dev_info(ctodev(card),
+ "lv1_net_set_interrupt_mask failed %d\n", status);
+ return status;
+}
+static inline void gelic_net_rx_irq_on(struct gelic_net_card *card)
+{
+ gelic_net_set_irq_mask(card, card->ghiintmask | GELIC_NET_RXINT);
+}
+static inline void gelic_net_rx_irq_off(struct gelic_net_card *card)
+{
+ gelic_net_set_irq_mask(card, card->ghiintmask & ~GELIC_NET_RXINT);
+}
+/**
+ * gelic_net_get_descr_status -- returns the status of a descriptor
+ * @descr: descriptor to look at
+ *
+ * returns the status as in the dmac_cmd_status field of the descriptor
+ */
+static enum gelic_net_descr_status
+gelic_net_get_descr_status(struct gelic_net_descr *descr)
+{
+ u32 cmd_status;
+
+ cmd_status = descr->dmac_cmd_status;
+ cmd_status >>= GELIC_NET_DESCR_IND_PROC_SHIFT;
+ return cmd_status;
+}
+
+/**
+ * gelic_net_set_descr_status -- sets the status of a descriptor
+ * @descr: descriptor to change
+ * @status: status to set in the descriptor
+ *
+ * changes the status to the specified value. Doesn't change other bits
+ * in the status
+ */
+static void gelic_net_set_descr_status(struct gelic_net_descr *descr,
+ enum gelic_net_descr_status status)
+{
+ u32 cmd_status;
+
+ /* read the status */
+ cmd_status = descr->dmac_cmd_status;
+ /* clean the upper 4 bits */
+ cmd_status &= GELIC_NET_DESCR_IND_PROC_MASKO;
+ /* add the status to it */
+ cmd_status |= ((u32)status) << GELIC_NET_DESCR_IND_PROC_SHIFT;
+ /* and write it back */
+ descr->dmac_cmd_status = cmd_status;
+ /*
+ * dma_cmd_status field is used to indicate whether the descriptor
+ * is valid or not.
+ * Usually caller of this function wants to inform that to the
+ * hardware, so we assure here the hardware sees the change.
+ */
+ wmb();
+}
+
+/**
+ * gelic_net_free_chain - free descriptor chain
+ * @card: card structure
+ * @descr_in: address of desc
+ */
+static void gelic_net_free_chain(struct gelic_net_card *card,
+ struct gelic_net_descr *descr_in)
+{
+ struct gelic_net_descr *descr;
+
+ for (descr = descr_in; descr && descr->bus_addr; descr = descr->next) {
+ dma_unmap_single(ctodev(card), descr->bus_addr,
+ GELIC_NET_DESCR_SIZE, DMA_BIDIRECTIONAL);
+ descr->bus_addr = 0;
+ }
+}
+
+/**
+ * gelic_net_init_chain - links descriptor chain
+ * @card: card structure
+ * @chain: address of chain
+ * @start_descr: address of descriptor array
+ * @no: number of descriptors
+ *
+ * we manage a circular list that mirrors the hardware structure,
+ * except that the hardware uses bus addresses.
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_init_chain(struct gelic_net_card *card,
+ struct gelic_net_descr_chain *chain,
+ struct gelic_net_descr *start_descr, int no)
+{
+ int i;
+ struct gelic_net_descr *descr;
+
+ descr = start_descr;
+ memset(descr, 0, sizeof(*descr) * no);
+
+ /* set up the hardware pointers in each descriptor */
+ for (i = 0; i < no; i++, descr++) {
+ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+ descr->bus_addr =
+ dma_map_single(ctodev(card), descr,
+ GELIC_NET_DESCR_SIZE,
+ DMA_BIDIRECTIONAL);
+
+ if (!descr->bus_addr)
+ goto iommu_error;
+
+ descr->next = descr + 1;
+ descr->prev = descr - 1;
+ }
+ /* make them as ring */
+ (descr - 1)->next = start_descr;
+ start_descr->prev = (descr - 1);
+
+ /* chain bus addr of hw descriptor */
+ descr = start_descr;
+ for (i = 0; i < no; i++, descr++) {
+ descr->next_descr_addr = descr->next->bus_addr;
+ }
+
+ chain->head = start_descr;
+ chain->tail = start_descr;
+
+ /* do not chain last hw descriptor */
+ (descr - 1)->next_descr_addr = 0;
+
+ return 0;
+
+iommu_error:
+ for (i--, descr--; 0 <= i; i--, descr--)
+ if (descr->bus_addr)
+ dma_unmap_single(ctodev(card), descr->bus_addr,
+ GELIC_NET_DESCR_SIZE,
+ DMA_BIDIRECTIONAL);
+ return -ENOMEM;
+}
+
+/**
+ * gelic_net_prepare_rx_descr - reinitializes a rx descriptor
+ * @card: card structure
+ * @descr: descriptor to re-init
+ *
+ * return 0 on succes, <0 on failure
+ *
+ * allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
+ * Activate the descriptor state-wise
+ */
+static int gelic_net_prepare_rx_descr(struct gelic_net_card *card,
+ struct gelic_net_descr *descr)
+{
+ int offset;
+ unsigned int bufsize;
+
+ if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE) {
+ dev_info(ctodev(card), "%s: ERROR status \n", __func__);
+ }
+ /* we need to round up the buffer size to a multiple of 128 */
+ bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN);
+
+ /* and we need to have it 128 byte aligned, therefore we allocate a
+ * bit more */
+ descr->skb = netdev_alloc_skb(card->netdev,
+ bufsize + GELIC_NET_RXBUF_ALIGN - 1);
+ if (!descr->skb) {
+ descr->buf_addr = 0; /* tell DMAC don't touch memory */
+ dev_info(ctodev(card),
+ "%s:allocate skb failed !!\n", __func__);
+ return -ENOMEM;
+ }
+ descr->buf_size = bufsize;
+ descr->dmac_cmd_status = 0;
+ descr->result_size = 0;
+ descr->valid_size = 0;
+ descr->data_error = 0;
+
+ offset = ((unsigned long)descr->skb->data) &
+ (GELIC_NET_RXBUF_ALIGN - 1);
+ if (offset)
+ skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset);
+ /* io-mmu-map the skb */
+ descr->buf_addr = dma_map_single(ctodev(card), descr->skb->data,
+ GELIC_NET_MAX_MTU,
+ DMA_FROM_DEVICE);
+ if (!descr->buf_addr) {
+ dev_kfree_skb_any(descr->skb);
+ descr->skb = NULL;
+ dev_info(ctodev(card),
+ "%s:Could not iommu-map rx buffer\n", __func__);
+ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+ return -ENOMEM;
+ } else {
+ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_CARDOWNED);
+ return 0;
+ }
+}
+
+/**
+ * gelic_net_release_rx_chain - free all skb of rx descr
+ * @card: card structure
+ *
+ */
+static void gelic_net_release_rx_chain(struct gelic_net_card *card)
+{
+ struct gelic_net_descr *descr = card->rx_chain.head;
+
+ do {
+ if (descr->skb) {
+ dma_unmap_single(ctodev(card),
+ descr->buf_addr,
+ descr->skb->len,
+ DMA_FROM_DEVICE);
+ descr->buf_addr = 0;
+ dev_kfree_skb_any(descr->skb);
+ descr->skb = NULL;
+ descr->dmac_cmd_status = GELIC_NET_DESCR_NOT_IN_USE;
+ }
+ descr = descr->next;
+ } while (descr != card->rx_chain.head);
+}
+
+/**
+ * gelic_net_fill_rx_chain - fills descriptors/skbs in the rx chains
+ * @card: card structure
+ *
+ * fills all descriptors in the rx chain: allocates skbs
+ * and iommu-maps them.
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_fill_rx_chain(struct gelic_net_card *card)
+{
+ struct gelic_net_descr *descr = card->rx_chain.head;
+ int ret;
+
+ do {
+ if (!descr->skb) {
+ ret = gelic_net_prepare_rx_descr(card, descr);
+ if (ret)
+ goto rewind;
+ }
+ descr = descr->next;
+ } while (descr != card->rx_chain.head);
+
+ return 0;
+rewind:
+ gelic_net_release_rx_chain(card);
+ return ret;
+}
+
+/**
+ * gelic_net_alloc_rx_skbs - allocates rx skbs in rx descriptor chains
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_alloc_rx_skbs(struct gelic_net_card *card)
+{
+ struct gelic_net_descr_chain *chain;
+ int ret;
+ chain = &card->rx_chain;
+ ret = gelic_net_fill_rx_chain(card);
+ chain->head = card->rx_top->prev; /* point to the last */
+ return ret;
+}
+
+/**
+ * gelic_net_release_tx_descr - processes a used tx descriptor
+ * @card: card structure
+ * @descr: descriptor to release
+ *
+ * releases a used tx descriptor (unmapping, freeing of skb)
+ */
+static void gelic_net_release_tx_descr(struct gelic_net_card *card,
+ struct gelic_net_descr *descr)
+{
+ struct sk_buff *skb;
+
+
+ if (descr->data_status & (1 << GELIC_NET_TXDESC_TAIL)) {
+ /* 2nd descriptor */
+ skb = descr->skb;
+ dma_unmap_single(ctodev(card), descr->buf_addr, skb->len,
+ DMA_TO_DEVICE);
+ dev_kfree_skb_any(skb);
+ } else {
+ dma_unmap_single(ctodev(card), descr->buf_addr,
+ descr->buf_size, DMA_TO_DEVICE);
+ }
+
+ descr->buf_addr = 0;
+ descr->buf_size = 0;
+ descr->next_descr_addr = 0;
+ descr->result_size = 0;
+ descr->valid_size = 0;
+ descr->data_status = 0;
+ descr->data_error = 0;
+ descr->skb = NULL;
+
+ /* set descr status */
+ descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE;
+}
+
+/**
+ * gelic_net_release_tx_chain - processes sent tx descriptors
+ * @card: adapter structure
+ * @stop: net_stop sequence
+ *
+ * releases the tx descriptors that gelic has finished with
+ */
+static void gelic_net_release_tx_chain(struct gelic_net_card *card, int stop)
+{
+ struct gelic_net_descr_chain *tx_chain;
+ enum gelic_net_descr_status status;
+ int release = 0;
+
+ for (tx_chain = &card->tx_chain;
+ tx_chain->head != tx_chain->tail && tx_chain->tail;
+ tx_chain->tail = tx_chain->tail->next) {
+ status = gelic_net_get_descr_status(tx_chain->tail);
+ switch (status) {
+ case GELIC_NET_DESCR_RESPONSE_ERROR:
+ case GELIC_NET_DESCR_PROTECTION_ERROR:
+ case GELIC_NET_DESCR_FORCE_END:
+ if (printk_ratelimit())
+ dev_info(ctodev(card),
+ "%s: forcing end of tx descriptor " \
+ "with status %x\n",
+ __func__, status);
+ card->netdev_stats.tx_dropped++;
+ break;
+
+ case GELIC_NET_DESCR_COMPLETE:
+ card->netdev_stats.tx_packets++;
+ card->netdev_stats.tx_bytes +=
+ tx_chain->tail->skb->len;
+ break;
+
+ case GELIC_NET_DESCR_CARDOWNED:
+ /* pending tx request */
+ default:
+ /* any other value (== GELIC_NET_DESCR_NOT_IN_USE) */
+ goto out;
+ }
+ gelic_net_release_tx_descr(card, tx_chain->tail);
+ release = 1;
+ }
+out:
+ if (!stop && release)
+ netif_wake_queue(card->netdev);
+}
+
+/**
+ * gelic_net_set_multi - sets multicast addresses and promisc flags
+ * @netdev: interface device structure
+ *
+ * gelic_net_set_multi configures multicast addresses as needed for the
+ * netdev interface. It also sets up multicast, allmulti and promisc
+ * flags appropriately
+ */
+static void gelic_net_set_multi(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ struct dev_mc_list *mc;
+ unsigned int i;
+ uint8_t *p;
+ u64 addr;
+ int status;
+
+ /* clear all multicast address */
+ status = lv1_net_remove_multicast_address(bus_id(card), dev_id(card),
+ 0, 1);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_remove_multicast_address failed %d\n",
+ status);
+ /* set broadcast address */
+ status = lv1_net_add_multicast_address(bus_id(card), dev_id(card),
+ GELIC_NET_BROADCAST_ADDR, 0);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_add_multicast_address failed, %d\n",
+ status);
+
+ if (netdev->flags & IFF_ALLMULTI
+ || netdev->mc_count > GELIC_NET_MC_COUNT_MAX) { /* list max */
+ status = lv1_net_add_multicast_address(bus_id(card),
+ dev_id(card),
+ 0, 1);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_add_multicast_address failed, %d\n",
+ status);
+ return;
+ }
+
+ /* set multicast address */
+ for (mc = netdev->mc_list; mc; mc = mc->next) {
+ addr = 0;
+ p = mc->dmi_addr;
+ for (i = 0; i < ETH_ALEN; i++) {
+ addr <<= 8;
+ addr |= *p++;
+ }
+ status = lv1_net_add_multicast_address(bus_id(card),
+ dev_id(card),
+ addr, 0);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_add_multicast_address failed, %d\n",
+ status);
+ }
+}
+
+/**
+ * gelic_net_enable_rxdmac - enables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
+ * in the GDADMACCNTR register
+ */
+static inline void gelic_net_enable_rxdmac(struct gelic_net_card *card)
+{
+ int status;
+
+ status = lv1_net_start_rx_dma(bus_id(card), dev_id(card),
+ card->rx_chain.tail->bus_addr, 0);
+ if (status)
+ dev_info(ctodev(card),
+ "lv1_net_start_rx_dma failed, status=%d\n", status);
+}
+
+/**
+ * gelic_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_net_disable_rxdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static inline void gelic_net_disable_rxdmac(struct gelic_net_card *card)
+{
+ int status;
+
+ /* this hvc blocks until the DMA in progress really stopped */
+ status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card), 0);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_stop_rx_dma faild, %d\n", status);
+}
+
+/**
+ * gelic_net_disable_txdmac - disables the transmit DMA controller
+ * @card: card structure
+ *
+ * gelic_net_disable_txdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static inline void gelic_net_disable_txdmac(struct gelic_net_card *card)
+{
+ int status;
+
+ /* this hvc blocks until the DMA in progress really stopped */
+ status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_stop_tx_dma faild, status=%d\n", status);
+}
+
+/**
+ * gelic_net_stop - called upon ifconfig down
+ * @netdev: interface device structure
+ *
+ * always returns 0
+ */
+static int gelic_net_stop(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ netif_poll_disable(netdev);
+ netif_stop_queue(netdev);
+
+ /* turn off DMA, force end */
+ gelic_net_disable_rxdmac(card);
+ gelic_net_disable_txdmac(card);
+
+ gelic_net_set_irq_mask(card, 0);
+
+ /* disconnect event port */
+ free_irq(card->netdev->irq, card->netdev);
+ ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq);
+ card->netdev->irq = NO_IRQ;
+
+ netif_carrier_off(netdev);
+
+ /* release chains */
+ gelic_net_release_tx_chain(card, 1);
+ gelic_net_release_rx_chain(card);
+
+ gelic_net_free_chain(card, card->tx_top);
+ gelic_net_free_chain(card, card->rx_top);
+
+ return 0;
+}
+
+/**
+ * gelic_net_get_next_tx_descr - returns the next available tx descriptor
+ * @card: device structure to get descriptor from
+ *
+ * returns the address of the next descriptor, or NULL if not available.
+ */
+static struct gelic_net_descr *
+gelic_net_get_next_tx_descr(struct gelic_net_card *card)
+{
+ if (!card->tx_chain.head)
+ return NULL;
+ /* see if we can two consecutive free descrs */
+ if (card->tx_chain.tail != card->tx_chain.head->next &&
+ gelic_net_get_descr_status(card->tx_chain.head) ==
+ GELIC_NET_DESCR_NOT_IN_USE &&
+ card->tx_chain.tail != card->tx_chain.head->next->next &&
+ gelic_net_get_descr_status(card->tx_chain.head->next) ==
+ GELIC_NET_DESCR_NOT_IN_USE )
+ return card->tx_chain.head;
+ else
+ return NULL;
+
+}
+
+/**
+ * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field
+ * @descr: descriptor structure to fill out
+ * @skb: packet to consider
+ * @middle: middle of frame
+ *
+ * fills out the command and status field of the descriptor structure,
+ * depending on hardware checksum settings. This function assumes a wmb()
+ * has executed before.
+ */
+static void gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr,
+ struct sk_buff *skb, int middle)
+{
+ u32 eofr;
+
+ if (middle)
+ eofr = 0;
+ else
+ eofr = GELIC_NET_DMAC_CMDSTAT_END_FRAME;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOCS | eofr;
+ else {
+ /* is packet ip?
+ * if yes: tcp? udp? */
+ if (skb->protocol == htons(ETH_P_IP)) {
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ descr->dmac_cmd_status =
+ GELIC_NET_DMAC_CMDSTAT_TCPCS | eofr;
+ else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ descr->dmac_cmd_status =
+ GELIC_NET_DMAC_CMDSTAT_UDPCS | eofr;
+ else /*
+ * the stack should checksum non-tcp and non-udp
+ * packets on his own: NETIF_F_IP_CSUM
+ */
+ descr->dmac_cmd_status =
+ GELIC_NET_DMAC_CMDSTAT_NOCS | eofr;
+ }
+ }
+}
+
+/**
+ * gelic_net_prepare_tx_descr_v - get dma address of skb_data
+ * @card: card structure
+ * @descr: descriptor structure
+ * @skb: packet to use
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ */
+static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card,
+ struct gelic_net_descr *descr,
+ struct sk_buff *skb)
+{
+ dma_addr_t buf[2];
+ unsigned int vlan_len;
+
+ if (skb->len < GELIC_NET_VLAN_POS)
+ return -EINVAL;
+
+ memcpy(&descr->vlan, skb->data, GELIC_NET_VLAN_POS);
+ if (card->vlan_index != -1) {
+ descr->vlan.h_vlan_proto = htons(ETH_P_8021Q); /* vlan 0x8100*/
+ descr->vlan.h_vlan_TCI = htons(card->vlan_id[card->vlan_index]);
+ vlan_len = GELIC_NET_VLAN_POS + VLAN_HLEN; /* VLAN_HLEN=4 */
+ } else
+ vlan_len = GELIC_NET_VLAN_POS; /* no vlan tag */
+
+ /* first descr */
+ buf[0] = dma_map_single(ctodev(card), &descr->vlan,
+ vlan_len, DMA_TO_DEVICE);
+
+ if (!buf[0]) {
+ dev_err(ctodev(card),
+ "dma map 1 failed (%p, %i). Dropping packet\n",
+ skb->data, vlan_len);
+ return -ENOMEM;
+ }
+
+ descr->buf_addr = buf[0];
+ descr->buf_size = vlan_len;
+ descr->skb = skb; /* not used */
+ descr->data_status = 0;
+ gelic_net_set_txdescr_cmdstat(descr, skb, 1); /* not the frame end */
+
+ /* second descr */
+ card->tx_chain.head = card->tx_chain.head->next;
+ descr->next_descr_addr = descr->next->bus_addr;
+ descr = descr->next;
+ if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE)
+ /* XXX will be removed */
+ dev_err(ctodev(card), "descr is not free!\n");
+
+ buf[1] = dma_map_single(ctodev(card), skb->data + GELIC_NET_VLAN_POS,
+ skb->len - GELIC_NET_VLAN_POS,
+ DMA_TO_DEVICE);
+
+ if (!buf[1]) {
+ dev_err(ctodev(card),
+ "dma map 2 failed (%p, %i). Dropping packet\n",
+ skb->data + GELIC_NET_VLAN_POS,
+ skb->len - GELIC_NET_VLAN_POS);
+ dma_unmap_single(ctodev(card), buf[0], vlan_len,
+ DMA_TO_DEVICE);
+ return -ENOMEM;
+ }
+
+ descr->buf_addr = buf[1];
+ descr->buf_size = skb->len - GELIC_NET_VLAN_POS;
+ descr->skb = skb;
+ descr->data_status = 0;
+ descr->next_descr_addr = 0; /* terminate hw descr */
+ gelic_net_set_txdescr_cmdstat(descr, skb, 0);
+
+ return 0;
+}
+
+/**
+ * gelic_net_kick_txdma - enables TX DMA processing
+ * @card: card structure
+ * @descr: descriptor address to enable TX processing at
+ *
+ */
+static int gelic_net_kick_txdma(struct gelic_net_card *card,
+ struct gelic_net_descr *descr)
+{
+ int status = -ENXIO;
+ int count = 10;
+
+ if (card->tx_dma_progress)
+ return 0;
+
+ if (gelic_net_get_descr_status(descr) == GELIC_NET_DESCR_CARDOWNED) {
+ card->tx_dma_progress = 1;
+ /* sometimes we need retry here */
+ while (count--) {
+ status = lv1_net_start_tx_dma(bus_id(card),
+ dev_id(card),
+ descr->bus_addr, 0);
+ if (!status)
+ break;
+ }
+ if (!count)
+ dev_info(ctodev(card), "lv1_net_start_txdma failed," \
+ "status=%d %#lx\n",
+ status, card->irq_status);
+ }
+ return status;
+}
+
+/**
+ * gelic_net_xmit - transmits a frame over the device
+ * @skb: packet to send out
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ struct gelic_net_descr *descr = NULL;
+ int result;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->tx_dma_lock, flags);
+
+ gelic_net_release_tx_chain(card, 0);
+ if (!skb)
+ goto kick;
+ descr = gelic_net_get_next_tx_descr(card);
+ if (!descr) {
+ netif_stop_queue(netdev);
+ spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+ result = gelic_net_prepare_tx_descr_v(card, descr, skb);
+
+ if (result)
+ goto error;
+
+ card->tx_chain.head = card->tx_chain.head->next;
+
+ if (descr->prev)
+ descr->prev->next_descr_addr = descr->bus_addr;
+kick:
+ /*
+ * as hardware descriptor is modified in the above lines,
+ * ensure that the hardware sees it
+ */
+ wmb();
+ if (gelic_net_kick_txdma(card, card->tx_chain.tail))
+ goto error;
+
+ netdev->trans_start = jiffies;
+ spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+ return NETDEV_TX_OK;
+
+error:
+ card->netdev_stats.tx_dropped++;
+ spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+ return NETDEV_TX_LOCKED;
+}
+
+/**
+ * gelic_net_pass_skb_up - takes an skb from a descriptor and passes it on
+ * @descr: descriptor to process
+ * @card: card structure
+ *
+ * iommu-unmaps the skb, fills out skb structure and passes the data to the
+ * stack. The descriptor state is not changed.
+ */
+static void gelic_net_pass_skb_up(struct gelic_net_descr *descr,
+ struct gelic_net_card *card)
+{
+ struct sk_buff *skb;
+ struct net_device *netdev;
+ u32 data_status, data_error;
+
+ data_status = descr->data_status;
+ data_error = descr->data_error;
+ netdev = card->netdev;
+ /* unmap skb buffer */
+ skb = descr->skb;
+ dma_unmap_single(ctodev(card), descr->buf_addr, GELIC_NET_MAX_MTU,
+ DMA_FROM_DEVICE);
+
+ skb_put(skb, descr->valid_size? descr->valid_size : descr->result_size);
+ if (!descr->valid_size)
+ dev_info(ctodev(card), "buffer full %x %x %x\n",
+ descr->result_size, descr->buf_size,
+ descr->dmac_cmd_status);
+
+ descr->skb = NULL;
+ /*
+ * the card put 2 bytes vlan tag in front
+ * of the ethernet frame
+ */
+ skb_pull(skb, 2);
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ /* checksum offload */
+ if (card->rx_csum) {
+ if ((data_status & GELIC_NET_DATA_STATUS_CHK_MASK) &&
+ (!(data_error & GELIC_NET_DATA_ERROR_CHK_MASK)))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+ } else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* update netdevice statistics */
+ card->netdev_stats.rx_packets++;
+ card->netdev_stats.rx_bytes += skb->len;
+
+ /* pass skb up to stack */
+ netif_receive_skb(skb);
+}
+
+/**
+ * gelic_net_decode_one_descr - processes an rx descriptor
+ * @card: card structure
+ *
+ * returns 1 if a packet has been sent to the stack, otherwise 0
+ *
+ * processes an rx descriptor by iommu-unmapping the data buffer and passing
+ * the packet up to the stack
+ */
+static int gelic_net_decode_one_descr(struct gelic_net_card *card)
+{
+ enum gelic_net_descr_status status;
+ struct gelic_net_descr_chain *chain = &card->rx_chain;
+ struct gelic_net_descr *descr = chain->tail;
+ int dmac_chain_ended;
+
+ status = gelic_net_get_descr_status(descr);
+ /* is this descriptor terminated with next_descr == NULL? */
+ dmac_chain_ended =
+ descr->dmac_cmd_status & GELIC_NET_DMAC_CMDSTAT_RXDCEIS;
+
+ if (status == GELIC_NET_DESCR_CARDOWNED)
+ return 0;
+
+ if (status == GELIC_NET_DESCR_NOT_IN_USE) {
+ dev_dbg(ctodev(card), "dormant descr? %p\n", descr);
+ return 0;
+ }
+
+ if ((status == GELIC_NET_DESCR_RESPONSE_ERROR) ||
+ (status == GELIC_NET_DESCR_PROTECTION_ERROR) ||
+ (status == GELIC_NET_DESCR_FORCE_END)) {
+ dev_info(ctodev(card), "dropping RX descriptor with state %x\n",
+ status);
+ card->netdev_stats.rx_dropped++;
+ goto refill;
+ }
+
+ if ((status != GELIC_NET_DESCR_COMPLETE) &&
+ (status != GELIC_NET_DESCR_FRAME_END)) {
+ dev_dbg(ctodev(card), "RX descriptor with state %x\n",
+ status);
+ goto refill;
+ }
+
+ /* ok, we've got a packet in descr */
+ gelic_net_pass_skb_up(descr, card); /* 1: skb_up sccess */
+
+refill:
+ descr->next_descr_addr = 0; /* unlink the descr */
+
+ /* change the descriptor state: */
+ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+
+ /* refill one desc
+ * FIXME: this can fail, but for now, just leave this
+ * descriptor without skb
+ */
+ gelic_net_prepare_rx_descr(card, descr);
+ chain->head = descr;
+ chain->tail = descr->next;
+ descr->prev->next_descr_addr = descr->bus_addr;
+
+ if (dmac_chain_ended) {
+ gelic_net_enable_rxdmac(card);
+ dev_dbg(ctodev(card), "reenable rx dma\n");
+ }
+
+ return 1;
+}
+
+/**
+ * gelic_net_poll - NAPI poll function called by the stack to return packets
+ * @netdev: interface device structure
+ * @budget: number of packets we can pass to the stack at most
+ *
+ * returns 0 if no more packets available to the driver/stack. Returns 1,
+ * if the quota is exceeded, but the driver has still packets.
+ *
+ */
+static int gelic_net_poll(struct net_device *netdev, int *budget)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ int packets_to_do, packets_done = 0;
+ int no_more_packets = 0;
+
+ packets_to_do = min(*budget, netdev->quota);
+
+ while (packets_to_do) {
+ if (gelic_net_decode_one_descr(card)) {
+ packets_done++;
+ packets_to_do--;
+ } else {
+ /* no more packets for the stack */
+ no_more_packets = 1;
+ break;
+ }
+ }
+ netdev->quota -= packets_done;
+ *budget -= packets_done;
+ if (no_more_packets) {
+ netif_rx_complete(netdev);
+ gelic_net_rx_irq_on(card);
+ return 0;
+ } else
+ return 1;
+}
+
+/**
+ * gelic_net_get_stats - get interface statistics
+ * @netdev: interface device structure
+ *
+ * returns the interface statistics residing in the gelic_net_card struct
+ */
+static struct net_device_stats *gelic_net_get_stats(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ return &card->netdev_stats;
+}
+
+/**
+ * gelic_net_change_mtu - changes the MTU of an interface
+ * @netdev: interface device structure
+ * @new_mtu: new MTU value
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ /* no need to re-alloc skbs or so -- the max mtu is about 2.3k
+ * and mtu is outbound only anyway */
+ if ((new_mtu < GELIC_NET_MIN_MTU) ||
+ (new_mtu > GELIC_NET_MAX_MTU)) {
+ return -EINVAL;
+ }
+ netdev->mtu = new_mtu;
+ return 0;
+}
+
+/**
+ * gelic_net_interrupt - event handler for gelic_net
+ */
+static irqreturn_t gelic_net_interrupt(int irq, void *ptr)
+{
+ unsigned long flags;
+ struct net_device *netdev = ptr;
+ struct gelic_net_card *card = netdev_priv(netdev);
+ u64 status;
+
+ status = card->irq_status;
+
+ if (!status)
+ return IRQ_NONE;
+
+ if (status & GELIC_NET_RXINT) {
+ gelic_net_rx_irq_off(card);
+ netif_rx_schedule(netdev);
+ }
+
+ if (status & GELIC_NET_TXINT) {
+ spin_lock_irqsave(&card->tx_dma_lock, flags);
+ card->tx_dma_progress = 0;
+ spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+ /* start pending DMA */
+ gelic_net_xmit(NULL, netdev);
+ }
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * gelic_net_poll_controller - artificial interrupt for netconsole etc.
+ * @netdev: interface device structure
+ *
+ * see Documentation/networking/netconsole.txt
+ */
+static void gelic_net_poll_controller(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ gelic_net_set_irq_mask(card, 0);
+ gelic_net_interrupt(netdev->irq, netdev);
+ gelic_net_set_irq_mask(card, card->ghiintmask);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+/**
+ * gelic_net_open_device - open device and map dma region
+ * @card: card structure
+ */
+static int gelic_net_open_device(struct gelic_net_card *card)
+{
+ int result;
+
+ result = ps3_sb_event_receive_port_setup(card->dev, PS3_BINDING_CPU_ANY,
+ &card->netdev->irq);
+
+ if (result) {
+ dev_info(ctodev(card),
+ "%s:%d: gelic_net_open_device failed (%d)\n",
+ __func__, __LINE__, result);
+ result = -EPERM;
+ goto fail_alloc_irq;
+ }
+
+ result = request_irq(card->netdev->irq, gelic_net_interrupt,
+ IRQF_DISABLED, "gelic network", card->netdev);
+
+ if (result) {
+ dev_info(ctodev(card), "%s:%d: request_irq failed (%d)\n",
+ __func__, __LINE__, result);
+ goto fail_request_irq;
+ }
+
+ return 0;
+
+fail_request_irq:
+ ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq);
+ card->netdev->irq = NO_IRQ;
+fail_alloc_irq:
+ return result;
+}
+
+
+/**
+ * gelic_net_open - called upon ifonfig up
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * gelic_net_open allocates all the descriptors and memory needed for
+ * operation, sets up multicast list and enables interrupts
+ */
+static int gelic_net_open(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ dev_dbg(ctodev(card), " -> %s:%d\n", __func__, __LINE__);
+
+ gelic_net_open_device(card);
+
+ if (gelic_net_init_chain(card, &card->tx_chain,
+ card->descr, GELIC_NET_TX_DESCRIPTORS))
+ goto alloc_tx_failed;
+ if (gelic_net_init_chain(card, &card->rx_chain,
+ card->descr + GELIC_NET_RX_DESCRIPTORS,
+ GELIC_NET_RX_DESCRIPTORS))
+ goto alloc_rx_failed;
+
+ /* head of chain */
+ card->tx_top = card->tx_chain.head;
+ card->rx_top = card->rx_chain.head;
+ dev_dbg(ctodev(card), "descr rx %p, tx %p, size %#lx, num %#x\n",
+ card->rx_top, card->tx_top, sizeof(struct gelic_net_descr),
+ GELIC_NET_RX_DESCRIPTORS);
+ /* allocate rx skbs */
+ if (gelic_net_alloc_rx_skbs(card))
+ goto alloc_skbs_failed;
+
+ card->tx_dma_progress = 0;
+ card->ghiintmask = GELIC_NET_RXINT | GELIC_NET_TXINT;
+
+ gelic_net_set_irq_mask(card, card->ghiintmask);
+ gelic_net_enable_rxdmac(card);
+
+ netif_start_queue(netdev);
+ netif_carrier_on(netdev);
+ netif_poll_enable(netdev);
+
+ return 0;
+
+alloc_skbs_failed:
+ gelic_net_free_chain(card, card->rx_top);
+alloc_rx_failed:
+ gelic_net_free_chain(card, card->tx_top);
+alloc_tx_failed:
+ return -ENOMEM;
+}
+
+#ifdef GELIC_NET_ETHTOOL
+static void gelic_net_get_drvinfo (struct net_device *netdev,
+ struct ethtool_drvinfo *info)
+{
+ strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1);
+ strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1);
+}
+
+static int gelic_net_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *cmd)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ int status;
+ u64 v1, v2;
+ int speed, duplex;
+
+ speed = duplex = -1;
+ status = lv1_net_control(bus_id(card), dev_id(card),
+ GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
+ &v1, &v2);
+ if (status) {
+ /* link down */
+ } else {
+ if (v1 & GELIC_NET_FULL_DUPLEX) {
+ duplex = DUPLEX_FULL;
+ } else {
+ duplex = DUPLEX_HALF;
+ }
+
+ if (v1 & GELIC_NET_SPEED_10 ) {
+ speed = SPEED_10;
+ } else if (v1 & GELIC_NET_SPEED_100) {
+ speed = SPEED_100;
+ } else if (v1 & GELIC_NET_SPEED_1000) {
+ speed = SPEED_1000;
+ }
+ }
+ cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg |
+ SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
+ cmd->advertising = cmd->supported;
+ cmd->speed = speed;
+ cmd->duplex = duplex;
+ cmd->autoneg = AUTONEG_ENABLE; /* always enabled */
+ cmd->port = PORT_TP;
+
+ return 0;
+}
+
+static u32 gelic_net_get_link(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ int status;
+ u64 v1, v2;
+ int link;
+
+ status = lv1_net_control(bus_id(card), dev_id(card),
+ GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
+ &v1, &v2);
+ if (status)
+ return 0; /* link down */
+
+ if (v1 & GELIC_NET_LINK_UP)
+ link = 1;
+ else
+ link = 0;
+
+ return link;
+}
+
+static int gelic_net_nway_reset(struct net_device *netdev)
+{
+ if (netif_running(netdev)) {
+ gelic_net_stop(netdev);
+ gelic_net_open(netdev);
+ }
+ return 0;
+}
+
+static u32 gelic_net_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_IP_CSUM) != 0;
+}
+
+static int gelic_net_set_tx_csum(struct net_device *netdev, u32 data)
+{
+ if (data)
+ netdev->features |= NETIF_F_IP_CSUM;
+ else
+ netdev->features &= ~NETIF_F_IP_CSUM;
+
+ return 0;
+}
+
+static u32 gelic_net_get_rx_csum(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ return card->rx_csum;
+}
+
+static int gelic_net_set_rx_csum(struct net_device *netdev, u32 data)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ card->rx_csum = data;
+ return 0;
+}
+
+static struct ethtool_ops gelic_net_ethtool_ops = {
+ .get_drvinfo = gelic_net_get_drvinfo,
+ .get_settings = gelic_net_get_settings,
+ .get_link = gelic_net_get_link,
+ .nway_reset = gelic_net_nway_reset,
+ .get_tx_csum = gelic_net_get_tx_csum,
+ .set_tx_csum = gelic_net_set_tx_csum,
+ .get_rx_csum = gelic_net_get_rx_csum,
+ .set_rx_csum = gelic_net_set_rx_csum,
+};
+#endif
+
+/**
+ * gelic_net_tx_timeout_task - task scheduled by the watchdog timeout
+ * function (to be called not under interrupt status)
+ * @work: work is context of tx timout task
+ *
+ * called as task when tx hangs, resets interface (if interface is up)
+ */
+static void gelic_net_tx_timeout_task(struct work_struct *work)
+{
+ struct gelic_net_card *card =
+ container_of(work, struct gelic_net_card, tx_timeout_task);
+ struct net_device *netdev = card->netdev;
+
+ dev_info(ctodev(card), "%s:Timed out. Restarting... \n", __func__);
+
+ if (!(netdev->flags & IFF_UP))
+ goto out;
+
+ netif_device_detach(netdev);
+ gelic_net_stop(netdev);
+
+ gelic_net_open(netdev);
+ netif_device_attach(netdev);
+
+out:
+ atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * gelic_net_tx_timeout - called when the tx timeout watchdog kicks in.
+ * @netdev: interface device structure
+ *
+ * called, if tx hangs. Schedules a task that resets the interface
+ */
+static void gelic_net_tx_timeout(struct net_device *netdev)
+{
+ struct gelic_net_card *card;
+
+ card = netdev_priv(netdev);
+ atomic_inc(&card->tx_timeout_task_counter);
+ if (netdev->flags & IFF_UP)
+ schedule_work(&card->tx_timeout_task);
+ else
+ atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * gelic_net_setup_netdev_ops - initialization of net_device operations
+ * @netdev: net_device structure
+ *
+ * fills out function pointers in the net_device structure
+ */
+static void gelic_net_setup_netdev_ops(struct net_device *netdev)
+{
+ netdev->open = &gelic_net_open;
+ netdev->stop = &gelic_net_stop;
+ netdev->hard_start_xmit = &gelic_net_xmit;
+ netdev->get_stats = &gelic_net_get_stats;
+ netdev->set_multicast_list = &gelic_net_set_multi;
+ netdev->change_mtu = &gelic_net_change_mtu;
+ /* tx watchdog */
+ netdev->tx_timeout = &gelic_net_tx_timeout;
+ netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
+ /* NAPI */
+ netdev->poll = &gelic_net_poll;
+ netdev->weight = GELIC_NET_NAPI_WEIGHT;
+#ifdef GELIC_NET_ETHTOOL
+ netdev->ethtool_ops = &gelic_net_ethtool_ops;
+#endif
+}
+
+/**
+ * gelic_net_setup_netdev - initialization of net_device
+ * @card: card structure
+ *
+ * Returns 0 on success or <0 on failure
+ *
+ * gelic_net_setup_netdev initializes the net_device structure
+ **/
+static int gelic_net_setup_netdev(struct gelic_net_card *card)
+{
+ struct net_device *netdev = card->netdev;
+ struct sockaddr addr;
+ unsigned int i;
+ int status;
+ u64 v1, v2;
+
+ SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &card->dev->core);
+ spin_lock_init(&card->tx_dma_lock);
+
+ card->rx_csum = GELIC_NET_RX_CSUM_DEFAULT;
+
+ gelic_net_setup_netdev_ops(netdev);
+
+ netdev->features = NETIF_F_IP_CSUM;
+
+ status = lv1_net_control(bus_id(card), dev_id(card),
+ GELIC_NET_GET_MAC_ADDRESS,
+ 0, 0, 0, &v1, &v2);
+ if (status || !is_valid_ether_addr((u8 *)&v1)) {
+ dev_info(ctodev(card),
+ "%s:lv1_net_control GET_MAC_ADDR failed %d\n",
+ __func__, status);
+ return -EINVAL;
+ }
+ v1 <<= 16;
+ memcpy(addr.sa_data, &v1, ETH_ALEN);
+ memcpy(netdev->dev_addr, addr.sa_data, ETH_ALEN);
+ dev_info(ctodev(card), "MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+ netdev->dev_addr[0], netdev->dev_addr[1],
+ netdev->dev_addr[2], netdev->dev_addr[3],
+ netdev->dev_addr[4], netdev->dev_addr[5]);
+
+ card->vlan_index = -1; /* no vlan */
+ for (i = 0; i < GELIC_NET_VLAN_MAX; i++) {
+ status = lv1_net_control(bus_id(card), dev_id(card),
+ GELIC_NET_GET_VLAN_ID,
+ i + 1, /* index; one based */
+ 0, 0, &v1, &v2);
+ if (status == GELIC_NET_VLAN_NO_ENTRY) {
+ dev_dbg(ctodev(card),
+ "GELIC_VLAN_ID no entry:%d, VLAN disabled\n",
+ status);
+ card->vlan_id[i] = 0;
+ } else if (status) {
+ dev_dbg(ctodev(card),
+ "%s:GELIC_NET_VLAN_ID faild, status=%d\n",
+ __func__, status);
+ card->vlan_id[i] = 0;
+ } else {
+ card->vlan_id[i] = (u32)v1;
+ dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1);
+ }
+ }
+ if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1])
+ card->vlan_index = GELIC_NET_VLAN_WIRED - 1;
+
+ status = register_netdev(netdev);
+ if (status) {
+ dev_err(ctodev(card), "%s:Couldn't register net_device: %d\n",
+ __func__, status);
+ return status;
+ }
+
+ return 0;
+}
+
+/**
+ * gelic_net_alloc_card - allocates net_device and card structure
+ *
+ * returns the card structure or NULL in case of errors
+ *
+ * the card and net_device structures are linked to each other
+ */
+static struct gelic_net_card *gelic_net_alloc_card(void)
+{
+ struct net_device *netdev;
+ struct gelic_net_card *card;
+ size_t alloc_size;
+
+ alloc_size = sizeof (*card) +
+ sizeof (struct gelic_net_descr) * GELIC_NET_RX_DESCRIPTORS +
+ sizeof (struct gelic_net_descr) * GELIC_NET_TX_DESCRIPTORS;
+ /*
+ * we assume private data is allocated 32 bytes (or more) aligned
+ * so that gelic_net_descr should be 32 bytes aligned.
+ * Current alloc_etherdev() does do it because NETDEV_ALIGN
+ * is 32.
+ * check this assumption here.
+ */
+ BUILD_BUG_ON(NETDEV_ALIGN < 32);
+ BUILD_BUG_ON(offsetof(struct gelic_net_card, irq_status) % 8);
+ BUILD_BUG_ON(offsetof(struct gelic_net_card, descr) % 32);
+
+ netdev = alloc_etherdev(alloc_size);
+ if (!netdev)
+ return NULL;
+
+ card = netdev_priv(netdev);
+ card->netdev = netdev;
+ INIT_WORK(&card->tx_timeout_task, gelic_net_tx_timeout_task);
+ init_waitqueue_head(&card->waitq);
+ atomic_set(&card->tx_timeout_task_counter, 0);
+
+ return card;
+}
+
+/**
+ * ps3_gelic_driver_probe - add a device to the control of this driver
+ */
+static int ps3_gelic_driver_probe (struct ps3_system_bus_device *dev)
+{
+ struct gelic_net_card *card = gelic_net_alloc_card();
+ int result;
+
+ if (!card) {
+ dev_info(&dev->core, "gelic_net_alloc_card failed\n");
+ result = -ENOMEM;
+ goto fail_alloc_card;
+ }
+
+ ps3_system_bus_set_driver_data(dev, card);
+ card->dev = dev;
+
+ result = ps3_open_hv_device(dev);
+
+ if (result) {
+ dev_dbg(&dev->core, "ps3_open_hv_device failed\n");
+ goto fail_open;
+ }
+
+ result = ps3_dma_region_create(dev->d_region);
+
+ if (result) {
+ dev_dbg(&dev->core, "ps3_dma_region_create failed(%d)\n",
+ result);
+ BUG_ON("check region type");
+ goto fail_dma_region;
+ }
+
+ result = lv1_net_set_interrupt_status_indicator(bus_id(card),
+ dev_id(card),
+ ps3_mm_phys_to_lpar(__pa(&card->irq_status)),
+ 0);
+
+ if (result) {
+ dev_dbg(&dev->core,
+ "lv1_net_set_interrupt_status_indicator failed: %s\n",
+ ps3_result(result));
+ result = -EIO;
+ goto fail_status_indicator;
+ }
+
+ result = gelic_net_setup_netdev(card);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+ "(%d)\n", __func__, __LINE__, result);
+ goto fail_setup_netdev;
+ }
+
+ return 0;
+
+fail_setup_netdev:
+ lv1_net_set_interrupt_status_indicator(bus_id(card),
+ bus_id(card),
+ 0 , 0);
+fail_status_indicator:
+ ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+ ps3_close_hv_device(dev);
+fail_open:
+ ps3_system_bus_set_driver_data(dev, NULL);
+ free_netdev(card->netdev);
+fail_alloc_card:
+ return result;
+}
+
+/**
+ * ps3_gelic_driver_remove - remove a device from the control of this driver
+ */
+
+static int ps3_gelic_driver_remove (struct ps3_system_bus_device *dev)
+{
+ struct gelic_net_card *card = ps3_system_bus_get_driver_data(dev);
+
+ wait_event(card->waitq,
+ atomic_read(&card->tx_timeout_task_counter) == 0);
+
+ lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card),
+ 0 , 0);
+
+ unregister_netdev(card->netdev);
+ free_netdev(card->netdev);
+
+ ps3_system_bus_set_driver_data(dev, NULL);
+
+ ps3_dma_region_free(dev->d_region);
+
+ ps3_close_hv_device(dev);
+
+ return 0;
+}
+
+static struct ps3_system_bus_driver ps3_gelic_driver = {
+ .match_id = PS3_MATCH_ID_GELIC,
+ .probe = ps3_gelic_driver_probe,
+ .remove = ps3_gelic_driver_remove,
+ .shutdown = ps3_gelic_driver_remove,
+ .core.name = "ps3_gelic_driver",
+ .core.owner = THIS_MODULE,
+};
+
+static int __init ps3_gelic_driver_init (void)
+{
+ return firmware_has_feature(FW_FEATURE_PS3_LV1)
+ ? ps3_system_bus_driver_register(&ps3_gelic_driver)
+ : -ENODEV;
+}
+
+static void __exit ps3_gelic_driver_exit (void)
+{
+ ps3_system_bus_driver_unregister(&ps3_gelic_driver);
+}
+
+module_init (ps3_gelic_driver_init);
+module_exit (ps3_gelic_driver_exit);
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_GELIC);
+
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h
new file mode 100644
index 00000000000..5e1c28654e1
--- /dev/null
+++ b/drivers/net/ps3_gelic_net.h
@@ -0,0 +1,239 @@
+/*
+ * PS3 Platfom gelic network driver.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation.
+ *
+ * This file is based on: spider_net.h
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.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, 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.
+ */
+#ifndef _GELIC_NET_H
+#define _GELIC_NET_H
+
+#define GELIC_NET_DRV_NAME "Gelic Network Driver"
+#define GELIC_NET_DRV_VERSION "1.0"
+
+#define GELIC_NET_ETHTOOL /* use ethtool */
+
+/* ioctl */
+#define GELIC_NET_GET_MODE (SIOCDEVPRIVATE + 0)
+#define GELIC_NET_SET_MODE (SIOCDEVPRIVATE + 1)
+
+/* descriptors */
+#define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */
+#define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */
+
+#define GELIC_NET_MAX_MTU 2308
+#define GELIC_NET_MIN_MTU 64
+#define GELIC_NET_RXBUF_ALIGN 128
+#define GELIC_NET_RX_CSUM_DEFAULT 1 /* hw chksum */
+#define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ
+#define GELIC_NET_NAPI_WEIGHT (GELIC_NET_RX_DESCRIPTORS)
+#define GELIC_NET_BROADCAST_ADDR 0xffffffffffffL
+#define GELIC_NET_VLAN_POS (VLAN_ETH_ALEN * 2)
+#define GELIC_NET_VLAN_MAX 4
+#define GELIC_NET_MC_COUNT_MAX 32 /* multicast address list */
+
+enum gelic_net_int0_status {
+ GELIC_NET_GDTDCEINT = 24,
+ GELIC_NET_GRFANMINT = 28,
+};
+
+/* GHIINT1STS bits */
+enum gelic_net_int1_status {
+ GELIC_NET_GDADCEINT = 14,
+};
+
+/* interrupt mask */
+#define GELIC_NET_TXINT (1L << (GELIC_NET_GDTDCEINT + 32))
+
+#define GELIC_NET_RXINT0 (1L << (GELIC_NET_GRFANMINT + 32))
+#define GELIC_NET_RXINT1 (1L << GELIC_NET_GDADCEINT)
+#define GELIC_NET_RXINT (GELIC_NET_RXINT0 | GELIC_NET_RXINT1)
+
+ /* RX descriptor data_status bits */
+#define GELIC_NET_RXDMADU 0x80000000 /* destination MAC addr unknown */
+#define GELIC_NET_RXLSTFBF 0x40000000 /* last frame buffer */
+#define GELIC_NET_RXIPCHK 0x20000000 /* IP checksum performed */
+#define GELIC_NET_RXTCPCHK 0x10000000 /* TCP/UDP checksup performed */
+#define GELIC_NET_RXIPSPKT 0x08000000 /* IPsec packet */
+#define GELIC_NET_RXIPSAHPRT 0x04000000 /* IPsec AH protocol performed */
+#define GELIC_NET_RXIPSESPPRT 0x02000000 /* IPsec ESP protocol performed */
+#define GELIC_NET_RXSESPAH 0x01000000 /*
+ * IPsec ESP protocol auth
+ * performed
+ */
+
+#define GELIC_NET_RXWTPKT 0x00C00000 /*
+ * wakeup trigger packet
+ * 01: Magic Packet (TM)
+ * 10: ARP packet
+ * 11: Multicast MAC addr
+ */
+#define GELIC_NET_RXVLNPKT 0x00200000 /* VLAN packet */
+/* bit 20..16 reserved */
+#define GELIC_NET_RXRECNUM 0x0000ff00 /* reception receipt number */
+/* bit 7..0 reserved */
+
+#define GELIC_NET_TXDESC_TAIL 0
+#define GELIC_NET_DATA_STATUS_CHK_MASK (GELIC_NET_RXIPCHK | GELIC_NET_RXTCPCHK)
+
+/* RX descriptor data_error bits */
+/* bit 31 reserved */
+#define GELIC_NET_RXALNERR 0x40000000 /* alignement error 10/100M */
+#define GELIC_NET_RXOVERERR 0x20000000 /* oversize error */
+#define GELIC_NET_RXRNTERR 0x10000000 /* Runt error */
+#define GELIC_NET_RXIPCHKERR 0x08000000 /* IP checksum error */
+#define GELIC_NET_RXTCPCHKERR 0x04000000 /* TCP/UDP checksum error */
+#define GELIC_NET_RXUMCHSP 0x02000000 /* unmatched sp on sp */
+#define GELIC_NET_RXUMCHSPI 0x01000000 /* unmatched SPI on SAD */
+#define GELIC_NET_RXUMCHSAD 0x00800000 /* unmatched SAD */
+#define GELIC_NET_RXIPSAHERR 0x00400000 /* auth error on AH protocol
+ * processing */
+#define GELIC_NET_RXIPSESPAHERR 0x00200000 /* auth error on ESP protocol
+ * processing */
+#define GELIC_NET_RXDRPPKT 0x00100000 /* drop packet */
+#define GELIC_NET_RXIPFMTERR 0x00080000 /* IP packet format error */
+/* bit 18 reserved */
+#define GELIC_NET_RXDATAERR 0x00020000 /* IP packet format error */
+#define GELIC_NET_RXCALERR 0x00010000 /* cariier extension length
+ * error */
+#define GELIC_NET_RXCREXERR 0x00008000 /* carrier extention error */
+#define GELIC_NET_RXMLTCST 0x00004000 /* multicast address frame */
+/* bit 13..0 reserved */
+#define GELIC_NET_DATA_ERROR_CHK_MASK \
+ (GELIC_NET_RXIPCHKERR | GELIC_NET_RXTCPCHKERR)
+
+
+/* tx descriptor command and status */
+#define GELIC_NET_DMAC_CMDSTAT_NOCS 0xa0080000 /* middle of frame */
+#define GELIC_NET_DMAC_CMDSTAT_TCPCS 0xa00a0000
+#define GELIC_NET_DMAC_CMDSTAT_UDPCS 0xa00b0000
+#define GELIC_NET_DMAC_CMDSTAT_END_FRAME 0x00040000 /* end of frame */
+
+#define GELIC_NET_DMAC_CMDSTAT_RXDCEIS 0x00000002 /* descriptor chain end
+ * interrupt status */
+
+#define GELIC_NET_DMAC_CMDSTAT_CHAIN_END 0x00000002 /* RXDCEIS:DMA stopped */
+#define GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE 0xb0000000
+#define GELIC_NET_DESCR_IND_PROC_SHIFT 28
+#define GELIC_NET_DESCR_IND_PROC_MASKO 0x0fffffff
+
+
+enum gelic_net_descr_status {
+ GELIC_NET_DESCR_COMPLETE = 0x00, /* used in rx and tx */
+ GELIC_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */
+ GELIC_NET_DESCR_PROTECTION_ERROR = 0x02, /* used in rx and tx */
+ GELIC_NET_DESCR_FRAME_END = 0x04, /* used in rx */
+ GELIC_NET_DESCR_FORCE_END = 0x05, /* used in rx and tx */
+ GELIC_NET_DESCR_CARDOWNED = 0x0a, /* used in rx and tx */
+ GELIC_NET_DESCR_NOT_IN_USE /* any other value */
+};
+/* for lv1_net_control */
+#define GELIC_NET_GET_MAC_ADDRESS 0x0000000000000001
+#define GELIC_NET_GET_ETH_PORT_STATUS 0x0000000000000002
+#define GELIC_NET_SET_NEGOTIATION_MODE 0x0000000000000003
+#define GELIC_NET_GET_VLAN_ID 0x0000000000000004
+
+#define GELIC_NET_LINK_UP 0x0000000000000001
+#define GELIC_NET_FULL_DUPLEX 0x0000000000000002
+#define GELIC_NET_AUTO_NEG 0x0000000000000004
+#define GELIC_NET_SPEED_10 0x0000000000000010
+#define GELIC_NET_SPEED_100 0x0000000000000020
+#define GELIC_NET_SPEED_1000 0x0000000000000040
+
+#define GELIC_NET_VLAN_ALL 0x0000000000000001
+#define GELIC_NET_VLAN_WIRED 0x0000000000000002
+#define GELIC_NET_VLAN_WIRELESS 0x0000000000000003
+#define GELIC_NET_VLAN_PSP 0x0000000000000004
+#define GELIC_NET_VLAN_PORT0 0x0000000000000010
+#define GELIC_NET_VLAN_PORT1 0x0000000000000011
+#define GELIC_NET_VLAN_PORT2 0x0000000000000012
+#define GELIC_NET_VLAN_DAEMON_CLIENT_BSS 0x0000000000000013
+#define GELIC_NET_VLAN_LIBERO_CLIENT_BSS 0x0000000000000014
+#define GELIC_NET_VLAN_NO_ENTRY -6
+
+#define GELIC_NET_PORT 2 /* for port status */
+
+/* size of hardware part of gelic descriptor */
+#define GELIC_NET_DESCR_SIZE (32)
+struct gelic_net_descr {
+ /* as defined by the hardware */
+ u32 buf_addr;
+ u32 buf_size;
+ u32 next_descr_addr;
+ u32 dmac_cmd_status;
+ u32 result_size;
+ u32 valid_size; /* all zeroes for tx */
+ u32 data_status;
+ u32 data_error; /* all zeroes for tx */
+
+ /* used in the driver */
+ struct sk_buff *skb;
+ dma_addr_t bus_addr;
+ struct gelic_net_descr *next;
+ struct gelic_net_descr *prev;
+ struct vlan_ethhdr vlan;
+} __attribute__((aligned(32)));
+
+struct gelic_net_descr_chain {
+ /* we walk from tail to head */
+ struct gelic_net_descr *head;
+ struct gelic_net_descr *tail;
+};
+
+struct gelic_net_card {
+ struct net_device *netdev;
+ /*
+ * hypervisor requires irq_status should be
+ * 8 bytes aligned, but u64 member is
+ * always disposed in that manner
+ */
+ u64 irq_status;
+ u64 ghiintmask;
+
+ struct ps3_system_bus_device *dev;
+ u32 vlan_id[GELIC_NET_VLAN_MAX];
+ int vlan_index;
+
+ struct gelic_net_descr_chain tx_chain;
+ struct gelic_net_descr_chain rx_chain;
+ /* gurad dmac descriptor chain*/
+ spinlock_t chain_lock;
+
+ struct net_device_stats netdev_stats;
+ int rx_csum;
+ /* guard tx_dma_progress */
+ spinlock_t tx_dma_lock;
+ int tx_dma_progress;
+
+ struct work_struct tx_timeout_task;
+ atomic_t tx_timeout_task_counter;
+ wait_queue_head_t waitq;
+
+ struct gelic_net_descr *tx_top, *rx_top;
+ struct gelic_net_descr descr[0];
+};
+
+
+extern unsigned long p_to_lp(long pa);
+
+#endif /* _GELIC_NET_H */
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 585be044ebb..8be8be451ad 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2433,37 +2433,22 @@ static int ql_get_seg_count(struct ql3_adapter *qdev,
return -1;
}
-static void ql_hw_csum_setup(struct sk_buff *skb,
+static void ql_hw_csum_setup(const struct sk_buff *skb,
struct ob_mac_iocb_req *mac_iocb_ptr)
{
- struct ethhdr *eth;
- struct iphdr *ip = NULL;
- u8 offset = ETH_HLEN;
+ const struct iphdr *ip = ip_hdr(skb);
- eth = (struct ethhdr *)(skb->data);
+ mac_iocb_ptr->ip_hdr_off = skb_network_offset(skb);
+ mac_iocb_ptr->ip_hdr_len = ip->ihl;
- if (eth->h_proto == __constant_htons(ETH_P_IP)) {
- ip = (struct iphdr *)&skb->data[ETH_HLEN];
- } else if (eth->h_proto == htons(ETH_P_8021Q) &&
- ((struct vlan_ethhdr *)skb->data)->
- h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) {
- ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN];
- offset = VLAN_ETH_HLEN;
- }
-
- if (ip) {
- if (ip->protocol == IPPROTO_TCP) {
- mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
+ if (ip->protocol == IPPROTO_TCP) {
+ mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
OB_3032MAC_IOCB_REQ_IC;
- mac_iocb_ptr->ip_hdr_off = offset;
- mac_iocb_ptr->ip_hdr_len = ip->ihl;
- } else if (ip->protocol == IPPROTO_UDP) {
- mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
+ } else {
+ mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
OB_3032MAC_IOCB_REQ_IC;
- mac_iocb_ptr->ip_hdr_off = offset;
- mac_iocb_ptr->ip_hdr_len = ip->ihl;
- }
}
+
}
/*
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 5ec7752caa4..982a9010c7a 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1,53 +1,11 @@
/*
-=========================================================================
- r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x.
- --------------------------------------------------------------------
-
- History:
- Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>.
- May 20 2002 - Add link status force-mode and TBI mode support.
- 2004 - Massive updates. See kernel SCM system for details.
-=========================================================================
- 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
- Command: 'insmod r8169 media = SET_MEDIA'
- Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
-
- SET_MEDIA can be:
- _10_Half = 0x01
- _10_Full = 0x02
- _100_Half = 0x04
- _100_Full = 0x08
- _1000_Full = 0x10
-
- 2. Support TBI mode.
-=========================================================================
-VERSION 1.1 <2002/10/4>
-
- The bit4:0 of MII register 4 is called "selector field", and have to be
- 00001b to indicate support of IEEE std 802.3 during NWay process of
- exchanging Link Code Word (FLP).
-
-VERSION 1.2 <2002/11/30>
-
- - Large style cleanup
- - Use ether_crc in stock kernel (linux/crc32.h)
- - Copy mc_filter setup code from 8139cp
- (includes an optimization, and avoids set_bit use)
-
-VERSION 1.6LK <2004/04/14>
-
- - Merge of Realtek's version 1.6
- - Conversion to DMA API
- - Suspend/resume
- - Endianness
- - Misc Rx/Tx bugs
-
-VERSION 2.2LK <2005/01/25>
-
- - RX csum, TX csum/SG, TSO
- - VLAN
- - baby (< 7200) Jumbo frames support
- - Merge of Realtek's version 2.2 (new phy)
+ * r8169.c: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
*/
#include <linux/module.h>
@@ -108,11 +66,6 @@ VERSION 2.2LK <2005/01/25>
#define rtl8169_rx_quota(count, quota) count
#endif
-/* media options */
-#define MAX_UNITS 8
-static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-static int num_media = 0;
-
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static const int max_interrupt_work = 20;
@@ -126,7 +79,7 @@ static const int multicast_filter_limit = 32;
#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
-#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
+#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */
#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
@@ -151,16 +104,17 @@ static const int multicast_filter_limit = 32;
#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
enum mac_version {
- RTL_GIGA_MAC_VER_01 = 0x00,
- RTL_GIGA_MAC_VER_02 = 0x01,
- RTL_GIGA_MAC_VER_03 = 0x02,
- RTL_GIGA_MAC_VER_04 = 0x03,
- RTL_GIGA_MAC_VER_05 = 0x04,
- RTL_GIGA_MAC_VER_11 = 0x0b,
- RTL_GIGA_MAC_VER_12 = 0x0c,
- RTL_GIGA_MAC_VER_13 = 0x0d,
- RTL_GIGA_MAC_VER_14 = 0x0e,
- RTL_GIGA_MAC_VER_15 = 0x0f
+ RTL_GIGA_MAC_VER_01 = 0x01, // 8169
+ RTL_GIGA_MAC_VER_02 = 0x02, // 8169S
+ RTL_GIGA_MAC_VER_03 = 0x03, // 8110S
+ RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB
+ RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
+ RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
+ RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
+ RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be 8168Bf
+ RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb 8101Ec
+ RTL_GIGA_MAC_VER_14 = 0x0e, // 8101
+ RTL_GIGA_MAC_VER_15 = 0x0f // 8101
};
enum phy_version {
@@ -180,11 +134,12 @@ static const struct {
u8 mac_version;
u32 RxConfigMask; /* Clears the bits supported by this chip */
} rtl_chip_info[] = {
- _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880),
- _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_02, 0xff7e1880),
- _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880),
- _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880),
- _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880),
+ _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169
+ _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S
+ _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S
+ _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB
+ _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd
+ _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
_R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
@@ -199,20 +154,15 @@ enum cfg_version {
RTL_CFG_2
};
-static const struct {
- unsigned int region;
- unsigned int align;
-} rtl_cfg_info[] = {
- [RTL_CFG_0] = { 1, NET_IP_ALIGN },
- [RTL_CFG_1] = { 2, NET_IP_ALIGN },
- [RTL_CFG_2] = { 2, 8 }
-};
+static void rtl_hw_start_8169(struct net_device *);
+static void rtl_hw_start_8168(struct net_device *);
+static void rtl_hw_start_8101(struct net_device *);
static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_2 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(0x1259, 0xc107), 0, 0, RTL_CFG_0 },
@@ -230,62 +180,63 @@ static struct {
u32 msg_enable;
} debug = { -1 };
-enum RTL8169_registers {
- MAC0 = 0, /* Ethernet hardware address. */
- MAR0 = 8, /* Multicast filter. */
- CounterAddrLow = 0x10,
- CounterAddrHigh = 0x14,
- TxDescStartAddrLow = 0x20,
- TxDescStartAddrHigh = 0x24,
- TxHDescStartAddrLow = 0x28,
- TxHDescStartAddrHigh = 0x2c,
- FLASH = 0x30,
- ERSR = 0x36,
- ChipCmd = 0x37,
- TxPoll = 0x38,
- IntrMask = 0x3C,
- IntrStatus = 0x3E,
- TxConfig = 0x40,
- RxConfig = 0x44,
- RxMissed = 0x4C,
- Cfg9346 = 0x50,
- Config0 = 0x51,
- Config1 = 0x52,
- Config2 = 0x53,
- Config3 = 0x54,
- Config4 = 0x55,
- Config5 = 0x56,
- MultiIntr = 0x5C,
- PHYAR = 0x60,
- TBICSR = 0x64,
- TBI_ANAR = 0x68,
- TBI_LPAR = 0x6A,
- PHYstatus = 0x6C,
- RxMaxSize = 0xDA,
- CPlusCmd = 0xE0,
- IntrMitigate = 0xE2,
- RxDescAddrLow = 0xE4,
- RxDescAddrHigh = 0xE8,
- EarlyTxThres = 0xEC,
- FuncEvent = 0xF0,
- FuncEventMask = 0xF4,
- FuncPresetState = 0xF8,
- FuncForceEvent = 0xFC,
+enum rtl_registers {
+ MAC0 = 0, /* Ethernet hardware address. */
+ MAC4 = 4,
+ MAR0 = 8, /* Multicast filter. */
+ CounterAddrLow = 0x10,
+ CounterAddrHigh = 0x14,
+ TxDescStartAddrLow = 0x20,
+ TxDescStartAddrHigh = 0x24,
+ TxHDescStartAddrLow = 0x28,
+ TxHDescStartAddrHigh = 0x2c,
+ FLASH = 0x30,
+ ERSR = 0x36,
+ ChipCmd = 0x37,
+ TxPoll = 0x38,
+ IntrMask = 0x3c,
+ IntrStatus = 0x3e,
+ TxConfig = 0x40,
+ RxConfig = 0x44,
+ RxMissed = 0x4c,
+ Cfg9346 = 0x50,
+ Config0 = 0x51,
+ Config1 = 0x52,
+ Config2 = 0x53,
+ Config3 = 0x54,
+ Config4 = 0x55,
+ Config5 = 0x56,
+ MultiIntr = 0x5c,
+ PHYAR = 0x60,
+ TBICSR = 0x64,
+ TBI_ANAR = 0x68,
+ TBI_LPAR = 0x6a,
+ PHYstatus = 0x6c,
+ RxMaxSize = 0xda,
+ CPlusCmd = 0xe0,
+ IntrMitigate = 0xe2,
+ RxDescAddrLow = 0xe4,
+ RxDescAddrHigh = 0xe8,
+ EarlyTxThres = 0xec,
+ FuncEvent = 0xf0,
+ FuncEventMask = 0xf4,
+ FuncPresetState = 0xf8,
+ FuncForceEvent = 0xfc,
};
-enum RTL8169_register_content {
+enum rtl_register_content {
/* InterruptStatusBits */
- SYSErr = 0x8000,
- PCSTimeout = 0x4000,
- SWInt = 0x0100,
- TxDescUnavail = 0x80,
- RxFIFOOver = 0x40,
- LinkChg = 0x20,
- RxOverflow = 0x10,
- TxErr = 0x08,
- TxOK = 0x04,
- RxErr = 0x02,
- RxOK = 0x01,
+ SYSErr = 0x8000,
+ PCSTimeout = 0x4000,
+ SWInt = 0x0100,
+ TxDescUnavail = 0x0080,
+ RxFIFOOver = 0x0040,
+ LinkChg = 0x0020,
+ RxOverflow = 0x0010,
+ TxErr = 0x0008,
+ TxOK = 0x0004,
+ RxErr = 0x0002,
+ RxOK = 0x0001,
/* RxStatusDesc */
RxFOVF = (1 << 23),
@@ -295,26 +246,31 @@ enum RTL8169_register_content {
RxCRC = (1 << 19),
/* ChipCmdBits */
- CmdReset = 0x10,
- CmdRxEnb = 0x08,
- CmdTxEnb = 0x04,
- RxBufEmpty = 0x01,
+ CmdReset = 0x10,
+ CmdRxEnb = 0x08,
+ CmdTxEnb = 0x04,
+ RxBufEmpty = 0x01,
+
+ /* TXPoll register p.5 */
+ HPQ = 0x80, /* Poll cmd on the high prio queue */
+ NPQ = 0x40, /* Poll cmd on the low prio queue */
+ FSWInt = 0x01, /* Forced software interrupt */
/* Cfg9346Bits */
- Cfg9346_Lock = 0x00,
- Cfg9346_Unlock = 0xC0,
+ Cfg9346_Lock = 0x00,
+ Cfg9346_Unlock = 0xc0,
/* rx_mode_bits */
- AcceptErr = 0x20,
- AcceptRunt = 0x10,
- AcceptBroadcast = 0x08,
- AcceptMulticast = 0x04,
- AcceptMyPhys = 0x02,
- AcceptAllPhys = 0x01,
+ AcceptErr = 0x20,
+ AcceptRunt = 0x10,
+ AcceptBroadcast = 0x08,
+ AcceptMulticast = 0x04,
+ AcceptMyPhys = 0x02,
+ AcceptAllPhys = 0x01,
/* RxConfigBits */
- RxCfgFIFOShift = 13,
- RxCfgDMAShift = 8,
+ RxCfgFIFOShift = 13,
+ RxCfgDMAShift = 8,
/* TxConfigBits */
TxInterFrameGapShift = 24,
@@ -323,6 +279,10 @@ enum RTL8169_register_content {
/* Config1 register p.24 */
PMEnable = (1 << 0), /* Power Management Enable */
+ /* Config2 register p. 25 */
+ PCI_Clock_66MHz = 0x01,
+ PCI_Clock_33MHz = 0x00,
+
/* Config3 register p.25 */
MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
@@ -343,36 +303,34 @@ enum RTL8169_register_content {
TBINwComplete = 0x01000000,
/* CPlusCmd p.31 */
+ PktCntrDisable = (1 << 7), // 8168
RxVlan = (1 << 6),
RxChkSum = (1 << 5),
PCIDAC = (1 << 4),
PCIMulRW = (1 << 3),
+ INTT_0 = 0x0000, // 8168
+ INTT_1 = 0x0001, // 8168
+ INTT_2 = 0x0002, // 8168
+ INTT_3 = 0x0003, // 8168
/* rtl8169_PHYstatus */
- TBI_Enable = 0x80,
- TxFlowCtrl = 0x40,
- RxFlowCtrl = 0x20,
- _1000bpsF = 0x10,
- _100bps = 0x08,
- _10bps = 0x04,
- LinkStatus = 0x02,
- FullDup = 0x01,
-
- /* _MediaType */
- _10_Half = 0x01,
- _10_Full = 0x02,
- _100_Half = 0x04,
- _100_Full = 0x08,
- _1000_Full = 0x10,
+ TBI_Enable = 0x80,
+ TxFlowCtrl = 0x40,
+ RxFlowCtrl = 0x20,
+ _1000bpsF = 0x10,
+ _100bps = 0x08,
+ _10bps = 0x04,
+ LinkStatus = 0x02,
+ FullDup = 0x01,
/* _TBICSRBit */
- TBILinkOK = 0x02000000,
+ TBILinkOK = 0x02000000,
/* DumpCounterCommand */
- CounterDump = 0x8,
+ CounterDump = 0x8,
};
-enum _DescStatusBit {
+enum desc_status_bit {
DescOwn = (1 << 31), /* Descriptor is owned by NIC */
RingEnd = (1 << 30), /* End of descriptor ring */
FirstFrag = (1 << 29), /* First segment of a packet */
@@ -405,15 +363,15 @@ enum _DescStatusBit {
#define RsvdMask 0x3fffc000
struct TxDesc {
- u32 opts1;
- u32 opts2;
- u64 addr;
+ __le32 opts1;
+ __le32 opts2;
+ __le64 addr;
};
struct RxDesc {
- u32 opts1;
- u32 opts2;
- u64 addr;
+ __le32 opts1;
+ __le32 opts2;
+ __le64 addr;
};
struct ring_info {
@@ -446,6 +404,8 @@ struct rtl8169_private {
unsigned rx_buf_sz;
struct timer_list timer;
u16 cp_cmd;
+ u16 intr_event;
+ u16 napi_event;
u16 intr_mask;
int phy_auto_nego_reg;
int phy_1000_ctrl_reg;
@@ -455,6 +415,7 @@ struct rtl8169_private {
int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
void (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(void __iomem *);
+ void (*hw_start)(struct net_device *);
unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *);
struct delayed_work task;
@@ -463,8 +424,6 @@ struct rtl8169_private {
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
-module_param_array(media, int, &num_media, 0);
-MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8).");
module_param(rx_copybreak, int, 0);
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
module_param(use_dac, int, 0);
@@ -478,9 +437,9 @@ static int rtl8169_open(struct net_device *dev);
static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance);
static int rtl8169_init_ring(struct net_device *dev);
-static void rtl8169_hw_start(struct net_device *dev);
+static void rtl_hw_start(struct net_device *dev);
static int rtl8169_close(struct net_device *dev);
-static void rtl8169_set_rx_mode(struct net_device *dev);
+static void rtl_set_rx_mode(struct net_device *dev);
static void rtl8169_tx_timeout(struct net_device *dev);
static struct net_device_stats *rtl8169_get_stats(struct net_device *dev);
static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
@@ -493,35 +452,37 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp);
static int rtl8169_poll(struct net_device *dev, int *budget);
#endif
-static const u16 rtl8169_intr_mask =
- SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
-static const u16 rtl8169_napi_event =
- RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
static const unsigned int rtl8169_rx_config =
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
-static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
+static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
{
int i;
- RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
+ RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value);
for (i = 20; i > 0; i--) {
- /* Check if the RTL8169 has completed writing to the specified MII register */
+ /*
+ * Check if the RTL8169 has completed writing to the specified
+ * MII register.
+ */
if (!(RTL_R32(PHYAR) & 0x80000000))
break;
udelay(25);
}
}
-static int mdio_read(void __iomem *ioaddr, int RegAddr)
+static int mdio_read(void __iomem *ioaddr, int reg_addr)
{
int i, value = -1;
- RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
+ RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16);
for (i = 20; i > 0; i--) {
- /* Check if the RTL8169 has completed retrieving data from the specified MII register */
+ /*
+ * Check if the RTL8169 has completed retrieving data from
+ * the specified MII register.
+ */
if (RTL_R32(PHYAR) & 0x80000000) {
value = (int) (RTL_R32(PHYAR) & 0xFFFF);
break;
@@ -579,7 +540,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
}
static void rtl8169_check_link_status(struct net_device *dev,
- struct rtl8169_private *tp, void __iomem *ioaddr)
+ struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
unsigned long flags;
@@ -596,38 +558,6 @@ static void rtl8169_check_link_status(struct net_device *dev,
spin_unlock_irqrestore(&tp->lock, flags);
}
-static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
-{
- struct {
- u16 speed;
- u8 duplex;
- u8 autoneg;
- u8 media;
- } link_settings[] = {
- { SPEED_10, DUPLEX_HALF, AUTONEG_DISABLE, _10_Half },
- { SPEED_10, DUPLEX_FULL, AUTONEG_DISABLE, _10_Full },
- { SPEED_100, DUPLEX_HALF, AUTONEG_DISABLE, _100_Half },
- { SPEED_100, DUPLEX_FULL, AUTONEG_DISABLE, _100_Full },
- { SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE, _1000_Full },
- /* Make TBI happy */
- { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff }
- }, *p;
- unsigned char option;
-
- option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
-
- if ((option != 0xff) && !idx && netif_msg_drv(&debug))
- printk(KERN_WARNING PFX "media option is deprecated.\n");
-
- for (p = link_settings; p->media != 0xff; p++) {
- if (p->media == option)
- break;
- }
- *autoneg = p->autoneg;
- *speed = p->speed;
- *duplex = p->duplex;
-}
-
static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -667,7 +597,7 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- int i;
+ unsigned int i;
static struct {
u32 opt;
u16 reg;
@@ -893,8 +823,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
int ret;
if (tp->vlgrp && (opts2 & RxVlanTag)) {
- rtl8169_rx_hwaccel_skb(skb, tp->vlgrp,
- swab16(opts2 & 0xffff));
+ rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff));
ret = 0;
} else
ret = -1;
@@ -1115,7 +1044,6 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
}
}
-
static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_drvinfo = rtl8169_get_drvinfo,
.get_regs_len = rtl8169_get_regs_len,
@@ -1141,8 +1069,8 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_perm_addr = ethtool_op_get_perm_addr,
};
-static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
- int bitval)
+static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg,
+ int bitnum, int bitval)
{
int val;
@@ -1152,8 +1080,20 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum
mdio_write(ioaddr, reg, val & 0xffff);
}
-static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_mac_version(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
+ /*
+ * The driver currently handles the 8168Bf and the 8168Be identically
+ * but they can be identified more specifically through the test below
+ * if needed:
+ *
+ * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
+ *
+ * Same thing for the 8101Eb and the 8101Ec:
+ *
+ * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
+ */
const struct {
u32 mask;
int mac_version;
@@ -1163,6 +1103,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
{ 0x34000000, RTL_GIGA_MAC_VER_13 },
{ 0x30800000, RTL_GIGA_MAC_VER_14 },
{ 0x30000000, RTL_GIGA_MAC_VER_11 },
+ { 0x98000000, RTL_GIGA_MAC_VER_06 },
{ 0x18000000, RTL_GIGA_MAC_VER_05 },
{ 0x10000000, RTL_GIGA_MAC_VER_04 },
{ 0x04000000, RTL_GIGA_MAC_VER_03 },
@@ -1171,7 +1112,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
}, *p = mac_info;
u32 reg;
- reg = RTL_R32(TxConfig) & 0x7c800000;
+ reg = RTL_R32(TxConfig) & 0xfc800000;
while ((reg & p->mask) != p->mask)
p++;
tp->mac_version = p->mac_version;
@@ -1182,7 +1123,8 @@ static void rtl8169_print_mac_version(struct rtl8169_private *tp)
dprintk("mac_version = 0x%02x\n", tp->mac_version);
}
-static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_phy_version(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
const struct {
u16 mask;
@@ -1259,7 +1201,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
0xbf00 } //w 0 15 0 bf00
}
}, *p = phy_magic;
- int i;
+ unsigned int i;
rtl8169_print_mac_version(tp);
rtl8169_print_phy_version(tp);
@@ -1393,7 +1335,7 @@ static void rtl8169_phy_reset(struct net_device *dev,
struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- int i;
+ unsigned int i;
tp->phy_reset_enable(ioaddr);
for (i = 0; i < 100; i++) {
@@ -1408,21 +1350,16 @@ static void rtl8169_phy_reset(struct net_device *dev,
static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- static int board_idx = -1;
- u8 autoneg, duplex;
- u16 speed;
-
- board_idx++;
rtl8169_hw_phy_config(dev);
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8(0x82, 0x01);
- if (tp->mac_version < RTL_GIGA_MAC_VER_03) {
- dprintk("Set PCI Latency=0x40\n");
- pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
- }
+ pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
+
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+ pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
@@ -1431,16 +1368,52 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
}
- rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
-
rtl8169_phy_reset(dev, tp);
- rtl8169_set_speed(dev, autoneg, speed, duplex);
+ /*
+ * rtl8169_set_speed_xmii takes good care of the Fast Ethernet
+ * only 8101. Don't panic.
+ */
+ rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
}
+static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ u32 high;
+ u32 low;
+
+ low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
+ high = addr[4] | (addr[5] << 8);
+
+ spin_lock_irq(&tp->lock);
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+ RTL_W32(MAC0, low);
+ RTL_W32(MAC4, high);
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ spin_unlock_irq(&tp->lock);
+}
+
+static int rtl_set_mac_address(struct net_device *dev, void *p)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ rtl_rar_set(tp, dev->dev_addr);
+
+ return 0;
+}
+
static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -1467,15 +1440,49 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EOPNOTSUPP;
}
+static const struct rtl_cfg_info {
+ void (*hw_start)(struct net_device *);
+ unsigned int region;
+ unsigned int align;
+ u16 intr_event;
+ u16 napi_event;
+} rtl_cfg_infos [] = {
+ [RTL_CFG_0] = {
+ .hw_start = rtl_hw_start_8169,
+ .region = 1,
+ .align = 0,
+ .intr_event = SYSErr | LinkChg | RxOverflow |
+ RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ },
+ [RTL_CFG_1] = {
+ .hw_start = rtl_hw_start_8168,
+ .region = 2,
+ .align = 8,
+ .intr_event = SYSErr | LinkChg | RxOverflow |
+ TxErr | TxOK | RxOK | RxErr,
+ .napi_event = TxErr | TxOK | RxOK | RxOverflow
+ },
+ [RTL_CFG_2] = {
+ .hw_start = rtl_hw_start_8101,
+ .region = 2,
+ .align = 8,
+ .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
+ RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ }
+};
+
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- const unsigned int region = rtl_cfg_info[ent->driver_data].region;
+ const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
+ const unsigned int region = cfg->region;
struct rtl8169_private *tp;
struct net_device *dev;
void __iomem *ioaddr;
- unsigned int pm_cap;
- int i, rc;
+ unsigned int i;
+ int rc;
if (netif_msg_drv(&debug)) {
printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
@@ -1508,20 +1515,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc < 0)
goto err_out_disable_2;
- /* save power state before pci_enable_device overwrites it */
- pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
- if (pm_cap) {
- u16 pwr_command, acpi_idle_state;
-
- pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
- acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
- } else {
- if (netif_msg_probe(tp)) {
- dev_err(&pdev->dev,
- "PowerManagement capability not found.\n");
- }
- }
-
/* make sure PCI base addr 1 is MMIO */
if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
if (netif_msg_probe(tp)) {
@@ -1585,7 +1578,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
RTL_W8(ChipCmd, CmdReset);
/* Check that the chip has finished the reset. */
- for (i = 100; i > 0; i--) {
+ for (i = 0; i < 100; i++) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break;
msleep_interruptible(1);
@@ -1647,11 +1640,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
dev->stop = rtl8169_close;
dev->tx_timeout = rtl8169_tx_timeout;
- dev->set_multicast_list = rtl8169_set_rx_mode;
+ dev->set_multicast_list = rtl_set_rx_mode;
dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr;
dev->change_mtu = rtl8169_change_mtu;
+ dev->set_mac_address = rtl_set_mac_address;
#ifdef CONFIG_R8169_NAPI
dev->poll = rtl8169_poll;
@@ -1670,7 +1664,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->intr_mask = 0xffff;
tp->pci_dev = pdev;
tp->mmio_addr = ioaddr;
- tp->align = rtl_cfg_info[ent->driver_data].align;
+ tp->align = cfg->align;
+ tp->hw_start = cfg->hw_start;
+ tp->intr_event = cfg->intr_event;
+ tp->napi_event = cfg->napi_event;
init_timer(&tp->timer);
tp->timer.data = (unsigned long) dev;
@@ -1685,15 +1682,17 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
if (netif_msg_probe(tp)) {
+ u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff;
+
printk(KERN_INFO "%s: %s at 0x%lx, "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
- "IRQ %d\n",
+ "XID %08x IRQ %d\n",
dev->name,
rtl_chip_info[tp->chipset].name,
dev->base_addr,
dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3],
- dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+ dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq);
}
rtl8169_init_phy(dev, tp);
@@ -1714,15 +1713,11 @@ err_out_free_dev_1:
goto out;
}
-static void __devexit
-rtl8169_remove_one(struct pci_dev *pdev)
+static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);
- assert(dev != NULL);
- assert(tp != NULL);
-
flush_scheduled_work();
unregister_netdev(dev);
@@ -1774,7 +1769,7 @@ static int rtl8169_open(struct net_device *dev)
if (retval < 0)
goto err_release_ring_2;
- rtl8169_hw_start(dev);
+ rtl_hw_start(dev);
rtl8169_request_timer(dev);
@@ -1805,7 +1800,7 @@ static void rtl8169_hw_reset(void __iomem *ioaddr)
RTL_R8(ChipCmd);
}
-static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp)
+static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
u32 cfg = rtl8169_rx_config;
@@ -1818,45 +1813,90 @@ static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp)
(InterFrameGap << TxInterFrameGapShift));
}
-static void rtl8169_hw_start(struct net_device *dev)
+static void rtl_hw_start(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- struct pci_dev *pdev = tp->pci_dev;
- u16 cmd;
- u32 i;
+ unsigned int i;
/* Soft reset the chip. */
RTL_W8(ChipCmd, CmdReset);
/* Check that the chip has finished the reset. */
- for (i = 100; i > 0; i--) {
+ for (i = 0; i < 100; i++) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break;
msleep_interruptible(1);
}
- if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
- RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
- pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
- }
+ tp->hw_start(dev);
- if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
- pci_write_config_word(pdev, 0x68, 0x00);
- pci_write_config_word(pdev, 0x69, 0x08);
- }
+ netif_start_queue(dev);
+}
- /* Undocumented stuff. */
- if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
- /* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */
- if ((RTL_R8(Config2) & 0x07) & 0x01)
- RTL_W32(0x7c, 0x0007ffff);
- RTL_W32(0x7c, 0x0007ff00);
+static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
+{
+ /*
+ * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
+ * register to be written before TxDescAddrLow to work.
+ * Switching from MMIO to I/O access fixes the issue as well.
+ */
+ RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
+ RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK);
+ RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
+ RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK);
+}
+
+static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
+{
+ u16 cmd;
+
+ cmd = RTL_R16(CPlusCmd);
+ RTL_W16(CPlusCmd, cmd);
+ return cmd;
+}
+
+static void rtl_set_rx_max_size(void __iomem *ioaddr)
+{
+ /* Low hurts. Let's disable the filtering. */
+ RTL_W16(RxMaxSize, 16383);
+}
+
+static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
+{
+ struct {
+ u32 mac_version;
+ u32 clk;
+ u32 val;
+ } cfg2_info [] = {
+ { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
+ { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
+ { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
+ { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
+ }, *p = cfg2_info;
+ unsigned int i;
+ u32 clk;
- pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- cmd = cmd & 0xef;
- pci_write_config_word(pdev, PCI_COMMAND, cmd);
+ clk = RTL_R8(Config2) & PCI_Clock_66MHz;
+ for (i = 0; i < ARRAY_SIZE(cfg2_info); i++) {
+ if ((p->mac_version == mac_version) && (p->clk == clk)) {
+ RTL_W32(0x7c, p->val);
+ break;
+ }
+ }
+}
+
+static void rtl_hw_start_8169(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
}
RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -1868,19 +1908,11 @@ static void rtl8169_hw_start(struct net_device *dev)
RTL_W8(EarlyTxThres, EarlyTxThld);
- /* Low hurts. Let's disable the filtering. */
- RTL_W16(RxMaxSize, 16383);
-
- if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_04))
- rtl8169_set_rx_tx_config_registers(tp);
+ rtl_set_rx_max_size(ioaddr);
- cmd = RTL_R16(CPlusCmd);
- RTL_W16(CPlusCmd, cmd);
+ rtl_set_rx_tx_config_registers(tp);
- tp->cp_cmd |= cmd | PCIMulRW;
+ tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
(tp->mac_version == RTL_GIGA_MAC_VER_03)) {
@@ -1891,29 +1923,15 @@ static void rtl8169_hw_start(struct net_device *dev)
RTL_W16(CPlusCmd, tp->cp_cmd);
+ rtl8169_set_magic_reg(ioaddr, tp->mac_version);
+
/*
* Undocumented corner. Supposedly:
* (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
*/
RTL_W16(IntrMitigate, 0x0000);
- /*
- * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
- * register to be written before TxDescAddrLow to work.
- * Switching from MMIO to I/O access fixes the issue as well.
- */
- RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
- RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
- RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
- RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
-
- if ((tp->mac_version != RTL_GIGA_MAC_VER_01) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_02) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_03) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_04)) {
- RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
- rtl8169_set_rx_tx_config_registers(tp);
- }
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
RTL_W8(Cfg9346, Cfg9346_Lock);
@@ -1922,15 +1940,107 @@ static void rtl8169_hw_start(struct net_device *dev)
RTL_W32(RxMissed, 0);
- rtl8169_set_rx_mode(dev);
+ rtl_set_rx_mode(dev);
/* no early-rx interrupts */
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
/* Enable all known interrupts by setting the interrupt mask. */
- RTL_W16(IntrMask, rtl8169_intr_mask);
+ RTL_W16(IntrMask, tp->intr_event);
- netif_start_queue(dev);
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+}
+
+static void rtl_hw_start_8168(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+ u8 ctl;
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_set_rx_max_size(ioaddr);
+
+ rtl_set_rx_tx_config_registers(tp);
+
+ tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
+
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+
+ /* Tx performance tweak. */
+ pci_read_config_byte(pdev, 0x69, &ctl);
+ ctl = (ctl & ~0x70) | 0x50;
+ pci_write_config_byte(pdev, 0x69, ctl);
+
+ RTL_W16(IntrMitigate, 0x5151);
+
+ /* Work around for RxFIFO overflow. */
+ if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
+ tp->intr_event |= RxFIFOOver | PCSTimeout;
+ tp->intr_event &= ~RxOverflow;
+ }
+
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ RTL_R8(IntrMask);
+
+ RTL_W32(RxMissed, 0);
+
+ rtl_set_rx_mode(dev);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
+
+ RTL_W16(IntrMask, tp->intr_event);
+}
+
+static void rtl_hw_start_8101(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
+ pci_write_config_word(pdev, 0x68, 0x00);
+ pci_write_config_word(pdev, 0x69, 0x08);
+ }
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_set_rx_max_size(ioaddr);
+
+ tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
+
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+
+ RTL_W16(IntrMitigate, 0x0000);
+
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+ rtl_set_rx_tx_config_registers(tp);
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ RTL_R8(IntrMask);
+
+ RTL_W32(RxMissed, 0);
+
+ rtl_set_rx_mode(dev);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
+
+ RTL_W16(IntrMask, tp->intr_event);
}
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
@@ -1956,7 +2066,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
netif_poll_enable(dev);
- rtl8169_hw_start(dev);
+ rtl_hw_start(dev);
rtl8169_request_timer(dev);
@@ -1997,38 +2107,38 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
rtl8169_mark_to_asic(desc, rx_buf_sz);
}
-static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
- struct RxDesc *desc, int rx_buf_sz,
- unsigned int align)
+static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
+ struct net_device *dev,
+ struct RxDesc *desc, int rx_buf_sz,
+ unsigned int align)
{
struct sk_buff *skb;
dma_addr_t mapping;
- int ret = 0;
+ unsigned int pad;
- skb = dev_alloc_skb(rx_buf_sz + align);
+ pad = align ? align : NET_IP_ALIGN;
+
+ skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
if (!skb)
goto err_out;
- skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
- *sk_buff = skb;
+ skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
PCI_DMA_FROMDEVICE);
rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
-
out:
- return ret;
+ return skb;
err_out:
- ret = -ENOMEM;
rtl8169_make_unusable_by_asic(desc);
goto out;
}
static void rtl8169_rx_clear(struct rtl8169_private *tp)
{
- int i;
+ unsigned int i;
for (i = 0; i < NUM_RX_DESC; i++) {
if (tp->Rx_skbuff[i]) {
@@ -2043,16 +2153,22 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
{
u32 cur;
- for (cur = start; end - cur > 0; cur++) {
- int ret, i = cur % NUM_RX_DESC;
+ for (cur = start; end - cur != 0; cur++) {
+ struct sk_buff *skb;
+ unsigned int i = cur % NUM_RX_DESC;
+
+ WARN_ON((s32)(end - cur) < 0);
if (tp->Rx_skbuff[i])
continue;
- ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
- tp->RxDescArray + i, tp->rx_buf_sz, tp->align);
- if (ret < 0)
+ skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev,
+ tp->RxDescArray + i,
+ tp->rx_buf_sz, tp->align);
+ if (!skb)
break;
+
+ tp->Rx_skbuff[i] = skb;
}
return cur - start;
}
@@ -2164,14 +2280,9 @@ static void rtl8169_reinit_task(struct work_struct *work)
ret = rtl8169_open(dev);
if (unlikely(ret < 0)) {
- if (net_ratelimit()) {
- struct rtl8169_private *tp = netdev_priv(dev);
-
- if (netif_msg_drv(tp)) {
- printk(PFX KERN_ERR
- "%s: reinit failure (status = %d)."
- " Rescheduling.\n", dev->name, ret);
- }
+ if (net_ratelimit() && netif_msg_drv(tp)) {
+ printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
+ " Rescheduling.\n", dev->name, ret);
}
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
@@ -2198,16 +2309,12 @@ static void rtl8169_reset_task(struct work_struct *work)
if (tp->dirty_rx == tp->cur_rx) {
rtl8169_init_ring_indexes(tp);
- rtl8169_hw_start(dev);
+ rtl_hw_start(dev);
netif_wake_queue(dev);
} else {
- if (net_ratelimit()) {
- struct rtl8169_private *tp = netdev_priv(dev);
-
- if (netif_msg_intr(tp)) {
- printk(PFX KERN_EMERG
- "%s: Rx buffers shortage\n", dev->name);
- }
+ if (net_ratelimit() && netif_msg_intr(tp)) {
+ printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
+ dev->name);
}
rtl8169_schedule_work(dev, rtl8169_reset_task);
}
@@ -2344,7 +2451,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
smp_wmb();
- RTL_W8(TxPoll, 0x40); /* set polling bit */
+ RTL_W8(TxPoll, NPQ); /* set polling bit */
if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
netif_stop_queue(dev);
@@ -2414,16 +2521,12 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
-static void
-rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
- void __iomem *ioaddr)
+static void rtl8169_tx_interrupt(struct net_device *dev,
+ struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
unsigned int dirty_tx, tx_left;
- assert(dev != NULL);
- assert(tp != NULL);
- assert(ioaddr != NULL);
-
dirty_tx = tp->dirty_tx;
smp_rmb();
tx_left = tp->cur_tx - dirty_tx;
@@ -2480,38 +2583,37 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
skb->ip_summed = CHECKSUM_NONE;
}
-static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
- struct RxDesc *desc, int rx_buf_sz,
- unsigned int align)
+static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
+ struct rtl8169_private *tp, int pkt_size,
+ dma_addr_t addr)
{
- int ret = -1;
+ struct sk_buff *skb;
+ bool done = false;
- if (pkt_size < rx_copybreak) {
- struct sk_buff *skb;
+ if (pkt_size >= rx_copybreak)
+ goto out;
- skb = dev_alloc_skb(pkt_size + align);
- if (skb) {
- skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
- eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
- *sk_buff = skb;
- rtl8169_mark_to_asic(desc, rx_buf_sz);
- ret = 0;
- }
- }
- return ret;
+ skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN);
+ if (!skb)
+ goto out;
+
+ pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
+ PCI_DMA_FROMDEVICE);
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
+ *sk_buff = skb;
+ done = true;
+out:
+ return done;
}
-static int
-rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
- void __iomem *ioaddr)
+static int rtl8169_rx_interrupt(struct net_device *dev,
+ struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
unsigned int cur_rx, rx_left;
unsigned int delta, count;
- assert(dev != NULL);
- assert(tp != NULL);
- assert(ioaddr != NULL);
-
cur_rx = tp->cur_rx;
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
@@ -2544,9 +2646,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
} else {
struct sk_buff *skb = tp->Rx_skbuff[entry];
+ dma_addr_t addr = le64_to_cpu(desc->addr);
int pkt_size = (status & 0x00001FFF) - 4;
- void (*pci_action)(struct pci_dev *, dma_addr_t,
- size_t, int) = pci_dma_sync_single_for_device;
+ struct pci_dev *pdev = tp->pci_dev;
/*
* The driver does not support incoming fragmented
@@ -2562,19 +2664,16 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
rtl8169_rx_csum(skb, desc);
- pci_dma_sync_single_for_cpu(tp->pci_dev,
- le64_to_cpu(desc->addr), tp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
-
- if (rtl8169_try_rx_copy(&skb, pkt_size, desc,
- tp->rx_buf_sz, tp->align)) {
- pci_action = pci_unmap_single;
+ if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
+ pci_dma_sync_single_for_device(pdev, addr,
+ pkt_size, PCI_DMA_FROMDEVICE);
+ rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+ } else {
+ pci_unmap_single(pdev, addr, pkt_size,
+ PCI_DMA_FROMDEVICE);
tp->Rx_skbuff[entry] = NULL;
}
- pci_action(tp->pci_dev, le64_to_cpu(desc->addr),
- tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
skb_put(skb, pkt_size);
skb->protocol = eth_type_trans(skb, dev);
@@ -2585,6 +2684,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
}
+
+ /* Work around for AMD plateform. */
+ if ((desc->opts2 & 0xfffe000) &&
+ (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
+ desc->opts2 = 0;
+ cur_rx++;
+ }
}
count = cur_rx - tp->cur_rx;
@@ -2608,11 +2714,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
return count;
}
-/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
-static irqreturn_t
-rtl8169_interrupt(int irq, void *dev_instance)
+static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
{
- struct net_device *dev = (struct net_device *) dev_instance;
+ struct net_device *dev = dev_instance;
struct rtl8169_private *tp = netdev_priv(dev);
int boguscnt = max_interrupt_work;
void __iomem *ioaddr = tp->mmio_addr;
@@ -2637,9 +2741,17 @@ rtl8169_interrupt(int irq, void *dev_instance)
RTL_W16(IntrStatus,
(status & RxFIFOOver) ? (status | RxOverflow) : status);
- if (!(status & rtl8169_intr_mask))
+ if (!(status & tp->intr_event))
break;
+ /* Work around for rx fifo overflow */
+ if (unlikely(status & RxFIFOOver) &&
+ (tp->mac_version == RTL_GIGA_MAC_VER_11)) {
+ netif_stop_queue(dev);
+ rtl8169_tx_timeout(dev);
+ break;
+ }
+
if (unlikely(status & SYSErr)) {
rtl8169_pcierr_interrupt(dev);
break;
@@ -2649,8 +2761,8 @@ rtl8169_interrupt(int irq, void *dev_instance)
rtl8169_check_link_status(dev, tp, ioaddr);
#ifdef CONFIG_R8169_NAPI
- RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
- tp->intr_mask = ~rtl8169_napi_event;
+ RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event);
+ tp->intr_mask = ~tp->napi_event;
if (likely(netif_rx_schedule_prep(dev)))
__netif_rx_schedule(dev);
@@ -2661,9 +2773,9 @@ rtl8169_interrupt(int irq, void *dev_instance)
break;
#else
/* Rx interrupt */
- if (status & (RxOK | RxOverflow | RxFIFOOver)) {
+ if (status & (RxOK | RxOverflow | RxFIFOOver))
rtl8169_rx_interrupt(dev, tp, ioaddr);
- }
+
/* Tx interrupt */
if (status & (TxOK | TxErr))
rtl8169_tx_interrupt(dev, tp, ioaddr);
@@ -2707,7 +2819,7 @@ static int rtl8169_poll(struct net_device *dev, int *budget)
* write is safe - FR
*/
smp_wmb();
- RTL_W16(IntrMask, rtl8169_intr_mask);
+ RTL_W16(IntrMask, tp->intr_event);
}
return (work_done >= work_to_do);
@@ -2789,14 +2901,13 @@ static int rtl8169_close(struct net_device *dev)
return 0;
}
-static void
-rtl8169_set_rx_mode(struct net_device *dev)
+static void rtl_set_rx_mode(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
u32 mc_filter[2]; /* Multicast hash filter */
- int i, rx_mode;
+ int rx_mode;
u32 tmp = 0;
if (dev->flags & IFF_PROMISC) {
@@ -2816,6 +2927,8 @@ rtl8169_set_rx_mode(struct net_device *dev)
mc_filter[1] = mc_filter[0] = 0xffffffff;
} else {
struct dev_mc_list *mclist;
+ unsigned int i;
+
rx_mode = AcceptBroadcast | AcceptMyPhys;
mc_filter[1] = mc_filter[0] = 0;
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
@@ -2840,10 +2953,11 @@ rtl8169_set_rx_mode(struct net_device *dev)
mc_filter[1] = 0xffffffff;
}
- RTL_W32(RxConfig, tmp);
RTL_W32(MAR0 + 0, mc_filter[0]);
RTL_W32(MAR0 + 4, mc_filter[1]);
+ RTL_W32(RxConfig, tmp);
+
spin_unlock_irqrestore(&tp->lock, flags);
}
@@ -2931,14 +3045,12 @@ static struct pci_driver rtl8169_pci_driver = {
#endif
};
-static int __init
-rtl8169_init_module(void)
+static int __init rtl8169_init_module(void)
{
return pci_register_driver(&rtl8169_pci_driver);
}
-static void __exit
-rtl8169_cleanup_module(void)
+static void __exit rtl8169_cleanup_module(void)
{
pci_unregister_driver(&rtl8169_pci_driver);
}
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 25c73d47daa..5c2e41fac6d 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -516,7 +516,7 @@ static unsigned int write_eeprom(struct rr_private *rrpriv,
}
-static int __init rr_init(struct net_device *dev)
+static int __devinit rr_init(struct net_device *dev)
{
struct rr_private *rrpriv;
struct rr_regs __iomem *regs;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 09078ff84cd..fa29a403a24 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -469,11 +469,18 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, s2io_tbl);
+static struct pci_error_handlers s2io_err_handler = {
+ .error_detected = s2io_io_error_detected,
+ .slot_reset = s2io_io_slot_reset,
+ .resume = s2io_io_resume,
+};
+
static struct pci_driver s2io_driver = {
.name = "S2IO",
.id_table = s2io_tbl,
.probe = s2io_init_nic,
.remove = __devexit_p(s2io_rem_nic),
+ .err_handler = &s2io_err_handler,
};
/* A simplifier macro used both by init and free shared_mem Fns(). */
@@ -2689,6 +2696,9 @@ static void s2io_netpoll(struct net_device *dev)
u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
int i;
+ if (pci_channel_offline(nic->pdev))
+ return;
+
disable_irq(dev->irq);
atomic_inc(&nic->isr_cnt);
@@ -3215,6 +3225,8 @@ static void alarm_intr_handler(struct s2io_nic *nic)
int i;
if (atomic_read(&nic->card_state) == CARD_DOWN)
return;
+ if (pci_channel_offline(nic->pdev))
+ return;
nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
/* Handling the XPAK counters update */
if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
@@ -3958,7 +3970,6 @@ static int s2io_close(struct net_device *dev)
/* Reset card, kill tasklet and free Tx and Rx buffers. */
s2io_card_down(sp);
- sp->device_close_flag = TRUE; /* Device is shut down. */
return 0;
}
@@ -4314,6 +4325,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
struct mac_info *mac_control;
struct config_param *config;
+ /* Pretend we handled any irq's from a disconnected card */
+ if (pci_channel_offline(sp->pdev))
+ return IRQ_NONE;
+
atomic_inc(&sp->isr_cnt);
mac_control = &sp->mac_control;
config = &sp->config;
@@ -6569,7 +6584,7 @@ static void s2io_rem_isr(struct s2io_nic * sp)
} while(cnt < 5);
}
-static void s2io_card_down(struct s2io_nic * sp)
+static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
{
int cnt = 0;
struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -6584,7 +6599,8 @@ static void s2io_card_down(struct s2io_nic * sp)
atomic_set(&sp->card_state, CARD_DOWN);
/* disable Tx and Rx traffic on the NIC */
- stop_nic(sp);
+ if (do_io)
+ stop_nic(sp);
s2io_rem_isr(sp);
@@ -6592,7 +6608,7 @@ static void s2io_card_down(struct s2io_nic * sp)
tasklet_kill(&sp->task);
/* Check if the device is Quiescent and then Reset the NIC */
- do {
+ while(do_io) {
/* As per the HW requirement we need to replenish the
* receive buffer to avoid the ring bump. Since there is
* no intention of processing the Rx frame at this pointwe are
@@ -6617,8 +6633,9 @@ static void s2io_card_down(struct s2io_nic * sp)
(unsigned long long) val64);
break;
}
- } while (1);
- s2io_reset(sp);
+ }
+ if (do_io)
+ s2io_reset(sp);
spin_lock_irqsave(&sp->tx_lock, flags);
/* Free all Tx buffers */
@@ -6633,6 +6650,11 @@ static void s2io_card_down(struct s2io_nic * sp)
clear_bit(0, &(sp->link_state));
}
+static void s2io_card_down(struct s2io_nic * sp)
+{
+ do_s2io_card_down(sp, 1);
+}
+
static int s2io_card_up(struct s2io_nic * sp)
{
int i, ret = 0;
@@ -8010,3 +8032,85 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
return;
}
+
+/**
+ * s2io_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct s2io_nic *sp = netdev->priv;
+
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev)) {
+ /* Bring down the card, while avoiding PCI I/O */
+ do_s2io_card_down(sp, 0);
+ }
+ pci_disable_device(pdev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * s2io_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ * At this point, the card has exprienced a hard reset,
+ * followed by fixups by BIOS, and has its config space
+ * set up identically to what it was at cold boot.
+ */
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct s2io_nic *sp = netdev->priv;
+
+ if (pci_enable_device(pdev)) {
+ printk(KERN_ERR "s2io: "
+ "Cannot re-enable PCI device after reset.\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ pci_set_master(pdev);
+ s2io_reset(sp);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * s2io_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells
+ * us that its OK to resume normal operation.
+ */
+static void s2io_io_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct s2io_nic *sp = netdev->priv;
+
+ if (netif_running(netdev)) {
+ if (s2io_card_up(sp)) {
+ printk(KERN_ERR "s2io: "
+ "Can't bring device back up after reset.\n");
+ return;
+ }
+
+ if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
+ s2io_card_down(sp);
+ printk(KERN_ERR "s2io: "
+ "Can't resetore mac addr after reset.\n");
+ return;
+ }
+ }
+
+ netif_device_attach(netdev);
+ netif_wake_queue(netdev);
+}
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 54baa0b8ec7..58592780f51 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -794,7 +794,6 @@ struct s2io_nic {
struct net_device_stats stats;
int high_dma_flag;
- int device_close_flag;
int device_enabled_once;
char name[60];
@@ -1052,6 +1051,11 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
struct sk_buff *skb, u32 tcp_len);
static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring);
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state);
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev);
+static void s2io_io_resume(struct pci_dev *pdev);
+
#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size
#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size
#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 132e2148b21..e7fdcf15b5a 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -1159,7 +1159,7 @@ static void sbmac_netpoll(struct net_device *netdev)
__raw_writeq(0, sc->sbm_imr);
- sbmac_intr(irq, netdev, NULL);
+ sbmac_intr(irq, netdev);
#ifdef CONFIG_SBMAC_COALESCE
__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 2cb2e156c75..7c6e4808399 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -573,7 +573,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
* return error if it failed to found.
*/
-static int __init sis900_mii_probe(struct net_device * net_dev)
+static int __devinit sis900_mii_probe(struct net_device * net_dev)
{
struct sis900_private * sis_priv = net_dev->priv;
const char *dev_name = pci_name(sis_priv->pci_dev);
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
deleted file mode 100644
index afd900d5d73..00000000000
--- a/drivers/net/sk98lin/Makefile
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# Makefile for the SysKonnect SK-98xx device driver.
-#
-
-
-#
-# Standalone driver params
-# SKPARAM += -DSK_KERNEL_24
-# SKPARAM += -DSK_KERNEL_24_26
-# SKPARAM += -DSK_KERNEL_26
-# SKPARAM += -DSK_KERNEL_22_24
-
-obj-$(CONFIG_SK98LIN) += sk98lin.o
-sk98lin-objs := \
- skge.o \
- skethtool.o \
- skdim.o \
- skaddr.o \
- skgehwt.o \
- skgeinit.o \
- skgepnmi.o \
- skgesirq.o \
- ski2c.o \
- sklm80.o \
- skqueue.o \
- skrlmt.o \
- sktimer.o \
- skvpd.o \
- skxmac2.o
-
-# DBGDEF = \
-# -DDEBUG
-
-ifdef DEBUG
-DBGDEF += \
--DSK_DEBUG_CHKMOD=0x00000000L \
--DSK_DEBUG_CHKCAT=0x00000000L
-endif
-
-
-# **** possible debug modules for SK_DEBUG_CHKMOD *****************
-# SK_DBGMOD_MERR 0x00000001L /* general module error indication */
-# SK_DBGMOD_HWM 0x00000002L /* Hardware init module */
-# SK_DBGMOD_RLMT 0x00000004L /* RLMT module */
-# SK_DBGMOD_VPD 0x00000008L /* VPD module */
-# SK_DBGMOD_I2C 0x00000010L /* I2C module */
-# SK_DBGMOD_PNMI 0x00000020L /* PNMI module */
-# SK_DBGMOD_CSUM 0x00000040L /* CSUM module */
-# SK_DBGMOD_ADDR 0x00000080L /* ADDR module */
-# SK_DBGMOD_DRV 0x00010000L /* DRV module */
-
-# **** possible debug categories for SK_DEBUG_CHKCAT **************
-# *** common modules ***
-# SK_DBGCAT_INIT 0x00000001L module/driver initialization
-# SK_DBGCAT_CTRL 0x00000002L controlling: add/rmv MCA/MAC and other controls (IOCTL)
-# SK_DBGCAT_ERR 0x00000004L error handling paths
-# SK_DBGCAT_TX 0x00000008L transmit path
-# SK_DBGCAT_RX 0x00000010L receive path
-# SK_DBGCAT_IRQ 0x00000020L general IRQ handling
-# SK_DBGCAT_QUEUE 0x00000040L any queue management
-# SK_DBGCAT_DUMP 0x00000080L large data output e.g. hex dump
-# SK_DBGCAT_FATAL 0x00000100L large data output e.g. hex dump
-
-# *** driver (file skge.c) ***
-# SK_DBGCAT_DRV_ENTRY 0x00010000 entry points
-# SK_DBGCAT_DRV_??? 0x00020000 not used
-# SK_DBGCAT_DRV_MCA 0x00040000 multicast
-# SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 tx path
-# SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 rx path
-# SK_DBGCAT_DRV_PROGRESS 0x00200000 general runtime
-# SK_DBGCAT_DRV_??? 0x00400000 not used
-# SK_DBGCAT_DRV_PROM 0x00800000 promiscuous mode
-# SK_DBGCAT_DRV_TX_FRAME 0x01000000 display tx frames
-# SK_DBGCAT_DRV_ERROR 0x02000000 error conditions
-# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources
-# SK_DBGCAT_DRV_EVENT 0x08000000 driver events
-
-EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
-
-clean:
- rm -f core *.o *.a *.s
-
-
-
-
-
-
diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h
deleted file mode 100644
index 4e2dbbf7800..00000000000
--- a/drivers/net/sk98lin/h/lm80.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name: lm80.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.6 $
- * Date: $Date: 2003/05/13 17:26:52 $
- * Purpose: Contains all defines for the LM80 Chip
- * (National Semiconductor).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_LM80_H
-#define __INC_LM80_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * LM80 register definition
- *
- * All registers are 8 bit wide
- */
-#define LM80_CFG 0x00 /* Configuration Register */
-#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */
-#define LM80_ISRC_2 0x02 /* Interrupt Status Register 2 */
-#define LM80_IMSK_1 0x03 /* Interrupt Mask Register 1 */
-#define LM80_IMSK_2 0x04 /* Interrupt Mask Register 2 */
-#define LM80_FAN_CTRL 0x05 /* Fan Devisor/RST#/OS# Register */
-#define LM80_TEMP_CTRL 0x06 /* OS# Config, Temp Res. Reg */
- /* 0x07 - 0x1f reserved */
- /* current values */
-#define LM80_VT0_IN 0x20 /* current Voltage 0 value */
-#define LM80_VT1_IN 0x21 /* current Voltage 1 value */
-#define LM80_VT2_IN 0x22 /* current Voltage 2 value */
-#define LM80_VT3_IN 0x23 /* current Voltage 3 value */
-#define LM80_VT4_IN 0x24 /* current Voltage 4 value */
-#define LM80_VT5_IN 0x25 /* current Voltage 5 value */
-#define LM80_VT6_IN 0x26 /* current Voltage 6 value */
-#define LM80_TEMP_IN 0x27 /* current Temperature value */
-#define LM80_FAN1_IN 0x28 /* current Fan 1 count */
-#define LM80_FAN2_IN 0x29 /* current Fan 2 count */
- /* limit values */
-#define LM80_VT0_HIGH_LIM 0x2a /* high limit val for Voltage 0 */
-#define LM80_VT0_LOW_LIM 0x2b /* low limit val for Voltage 0 */
-#define LM80_VT1_HIGH_LIM 0x2c /* high limit val for Voltage 1 */
-#define LM80_VT1_LOW_LIM 0x2d /* low limit val for Voltage 1 */
-#define LM80_VT2_HIGH_LIM 0x2e /* high limit val for Voltage 2 */
-#define LM80_VT2_LOW_LIM 0x2f /* low limit val for Voltage 2 */
-#define LM80_VT3_HIGH_LIM 0x30 /* high limit val for Voltage 3 */
-#define LM80_VT3_LOW_LIM 0x31 /* low limit val for Voltage 3 */
-#define LM80_VT4_HIGH_LIM 0x32 /* high limit val for Voltage 4 */
-#define LM80_VT4_LOW_LIM 0x33 /* low limit val for Voltage 4 */
-#define LM80_VT5_HIGH_LIM 0x34 /* high limit val for Voltage 5 */
-#define LM80_VT5_LOW_LIM 0x35 /* low limit val for Voltage 5 */
-#define LM80_VT6_HIGH_LIM 0x36 /* high limit val for Voltage 6 */
-#define LM80_VT6_LOW_LIM 0x37 /* low limit val for Voltage 6 */
-#define LM80_THOT_LIM_UP 0x38 /* hot temperature limit (high) */
-#define LM80_THOT_LIM_LO 0x39 /* hot temperature limit (low) */
-#define LM80_TOS_LIM_UP 0x3a /* OS temperature limit (high) */
-#define LM80_TOS_LIM_LO 0x3b /* OS temperature limit (low) */
-#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */
-#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */
- /* 0x3e - 0x3f reserved */
-
-/*
- * LM80 bit definitions
- */
-
-/* LM80_CFG Configuration Register */
-#define LM80_CFG_START (1<<0) /* start monitoring operation */
-#define LM80_CFG_INT_ENA (1<<1) /* enables the INT# Interrupt output */
-#define LM80_CFG_INT_POL (1<<2) /* INT# pol: 0 act low, 1 act high */
-#define LM80_CFG_INT_CLR (1<<3) /* disables INT#/RST_OUT#/OS# outputs */
-#define LM80_CFG_RESET (1<<4) /* signals a reset */
-#define LM80_CFG_CHASS_CLR (1<<5) /* clears Chassis Intrusion (CI) pin */
-#define LM80_CFG_GPO (1<<6) /* drives the GPO# pin */
-#define LM80_CFG_INIT (1<<7) /* restore power on defaults */
-
-/* LM80_ISRC_1 Interrupt Status Register 1 */
-/* LM80_IMSK_1 Interrupt Mask Register 1 */
-#define LM80_IS_VT0 (1<<0) /* limit exceeded for Voltage 0 */
-#define LM80_IS_VT1 (1<<1) /* limit exceeded for Voltage 1 */
-#define LM80_IS_VT2 (1<<2) /* limit exceeded for Voltage 2 */
-#define LM80_IS_VT3 (1<<3) /* limit exceeded for Voltage 3 */
-#define LM80_IS_VT4 (1<<4) /* limit exceeded for Voltage 4 */
-#define LM80_IS_VT5 (1<<5) /* limit exceeded for Voltage 5 */
-#define LM80_IS_VT6 (1<<6) /* limit exceeded for Voltage 6 */
-#define LM80_IS_INT_IN (1<<7) /* state of INT_IN# */
-
-/* LM80_ISRC_2 Interrupt Status Register 2 */
-/* LM80_IMSK_2 Interrupt Mask Register 2 */
-#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */
-#define LM80_IS_BTI (1<<1) /* state of BTI# pin */
-#define LM80_IS_FAN1 (1<<2) /* count limit exceeded for Fan 1 */
-#define LM80_IS_FAN2 (1<<3) /* count limit exceeded for Fan 2 */
-#define LM80_IS_CI (1<<4) /* Chassis Intrusion occured */
-#define LM80_IS_OS (1<<5) /* OS temperature limit exceeded */
- /* bit 6 and 7 are reserved in LM80_ISRC_2 */
-#define LM80_IS_HT_IRQ_MD (1<<6) /* Hot temperature interrupt mode */
-#define LM80_IS_OT_IRQ_MD (1<<7) /* OS temperature interrupt mode */
-
-/* LM80_FAN_CTRL Fan Devisor/RST#/OS# Register */
-#define LM80_FAN1_MD_SEL (1<<0) /* Fan 1 mode select */
-#define LM80_FAN2_MD_SEL (1<<1) /* Fan 2 mode select */
-#define LM80_FAN1_PRM_CTL (3<<2) /* Fan 1 speed control */
-#define LM80_FAN2_PRM_CTL (3<<4) /* Fan 2 speed control */
-#define LM80_FAN_OS_ENA (1<<6) /* enable OS mode on RST_OUT#/OS# pins*/
-#define LM80_FAN_RST_ENA (1<<7) /* sets RST_OUT#/OS# pins in RST mode */
-
-/* LM80_TEMP_CTRL OS# Config, Temp Res. Reg */
-#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */
-#define LM80_TEMP_OS_POL (1<<1) /* select OS# polarity */
-#define LM80_TEMP_OS_MODE (1<<2) /* selects Interrupt mode */
-#define LM80_TEMP_RES (1<<3) /* selects 9 or 11 bit temp resulution*/
-#define LM80_TEMP_LSB (0xf<<4)/* 4 LSBs of 11 bit temp data */
-#define LM80_TEMP_LSB_9 (1<<7) /* LSB of 9 bit temperature data */
-
- /* 0x07 - 0x1f reserved */
-/* LM80_VT0_IN current Voltage 0 value */
-/* LM80_VT1_IN current Voltage 1 value */
-/* LM80_VT2_IN current Voltage 2 value */
-/* LM80_VT3_IN current Voltage 3 value */
-/* LM80_VT4_IN current Voltage 4 value */
-/* LM80_VT5_IN current Voltage 5 value */
-/* LM80_VT6_IN current Voltage 6 value */
-/* LM80_TEMP_IN current temperature value */
-/* LM80_FAN1_IN current Fan 1 count */
-/* LM80_FAN2_IN current Fan 2 count */
-/* LM80_VT0_HIGH_LIM high limit val for Voltage 0 */
-/* LM80_VT0_LOW_LIM low limit val for Voltage 0 */
-/* LM80_VT1_HIGH_LIM high limit val for Voltage 1 */
-/* LM80_VT1_LOW_LIM low limit val for Voltage 1 */
-/* LM80_VT2_HIGH_LIM high limit val for Voltage 2 */
-/* LM80_VT2_LOW_LIM low limit val for Voltage 2 */
-/* LM80_VT3_HIGH_LIM high limit val for Voltage 3 */
-/* LM80_VT3_LOW_LIM low limit val for Voltage 3 */
-/* LM80_VT4_HIGH_LIM high limit val for Voltage 4 */
-/* LM80_VT4_LOW_LIM low limit val for Voltage 4 */
-/* LM80_VT5_HIGH_LIM high limit val for Voltage 5 */
-/* LM80_VT5_LOW_LIM low limit val for Voltage 5 */
-/* LM80_VT6_HIGH_LIM high limit val for Voltage 6 */
-/* LM80_VT6_LOW_LIM low limit val for Voltage 6 */
-/* LM80_THOT_LIM_UP hot temperature limit (high) */
-/* LM80_THOT_LIM_LO hot temperature limit (low) */
-/* LM80_TOS_LIM_UP OS temperature limit (high) */
-/* LM80_TOS_LIM_LO OS temperature limit (low) */
-/* LM80_FAN1_COUNT_LIM Fan 1 count limit (high) */
-/* LM80_FAN2_COUNT_LIM Fan 2 count limit (low) */
- /* 0x3e - 0x3f reserved */
-
-#define LM80_ADDR 0x28 /* LM80 default addr */
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_LM80_H */
diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h
deleted file mode 100644
index 423ad063d09..00000000000
--- a/drivers/net/sk98lin/h/skaddr.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/******************************************************************************
- *
- * Name: skaddr.h
- * Project: Gigabit Ethernet Adapters, ADDR-Modul
- * Version: $Revision: 1.29 $
- * Date: $Date: 2003/05/13 16:57:24 $
- * Purpose: Header file for Address Management (MC, UC, Prom).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses and promiscuous mode
- * on GEnesis adapters.
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * ...
- * "sktypes.h"
- * "skqueue.h"
- * "skaddr.h"
- * ...
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKADDR_H
-#define __INC_SKADDR_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_MAC_ADDR_LEN 6 /* Length of MAC address. */
-#define SK_MAX_ADDRS 14 /* #Addrs for exact match. */
-
-/* ----- Common return values ----- */
-
-#define SK_ADDR_SUCCESS 0 /* Function returned successfully. */
-#define SK_ADDR_ILLEGAL_PORT 100 /* Port number too high. */
-#define SK_ADDR_TOO_EARLY 101 /* Function called too early. */
-
-/* ----- Clear/Add flag bits ----- */
-
-#define SK_ADDR_PERMANENT 1 /* RLMT Address */
-
-/* ----- Additional Clear flag bits ----- */
-
-#define SK_MC_SW_ONLY 2 /* Do not update HW when clearing. */
-
-/* ----- Override flag bits ----- */
-
-#define SK_ADDR_LOGICAL_ADDRESS 0
-#define SK_ADDR_VIRTUAL_ADDRESS (SK_ADDR_LOGICAL_ADDRESS) /* old */
-#define SK_ADDR_PHYSICAL_ADDRESS 1
-#define SK_ADDR_CLEAR_LOGICAL 2
-#define SK_ADDR_SET_LOGICAL 4
-
-/* ----- Override return values ----- */
-
-#define SK_ADDR_OVERRIDE_SUCCESS (SK_ADDR_SUCCESS)
-#define SK_ADDR_DUPLICATE_ADDRESS 1
-#define SK_ADDR_MULTICAST_ADDRESS 2
-
-/* ----- Partitioning of excact match table ----- */
-
-#define SK_ADDR_EXACT_MATCHES 16 /* #Exact match entries. */
-
-#define SK_ADDR_FIRST_MATCH_RLMT 1
-#define SK_ADDR_LAST_MATCH_RLMT 2
-#define SK_ADDR_FIRST_MATCH_DRV 3
-#define SK_ADDR_LAST_MATCH_DRV (SK_ADDR_EXACT_MATCHES - 1)
-
-/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */
-
-#define SK_MC_FILTERING_EXACT 0 /* Exact filtering. */
-#define SK_MC_FILTERING_INEXACT 1 /* Inexact filtering. */
-
-/* ----- Additional SkAddrMcAdd return values ----- */
-
-#define SK_MC_ILLEGAL_ADDRESS 2 /* Illegal address. */
-#define SK_MC_ILLEGAL_PORT 3 /* Illegal port (not the active one). */
-#define SK_MC_RLMT_OVERFLOW 4 /* Too many RLMT mc addresses. */
-
-/* Promiscuous mode bits ----- */
-
-#define SK_PROM_MODE_NONE 0 /* Normal receive. */
-#define SK_PROM_MODE_LLC 1 /* Receive all LLC frames. */
-#define SK_PROM_MODE_ALL_MC 2 /* Receive all multicast frames. */
-/* #define SK_PROM_MODE_NON_LLC 4 */ /* Receive all non-LLC frames. */
-
-/* Macros */
-
-#ifdef OLD_STUFF
-#ifndef SK_ADDR_EQUAL
-/*
- * "&" instead of "&&" allows better optimization on IA-64.
- * The replacement is safe here, as all bytes exist.
- */
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2) ( \
- (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \
- (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \
- (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \
- (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \
- (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \
- (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0]))
-#else /* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2) ( \
- (*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \
- (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0])))
-#endif /* SK_ADDR_DWORD_COMPARE */
-#endif /* SK_ADDR_EQUAL */
-#endif /* 0 */
-
-#ifndef SK_ADDR_EQUAL
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2) ( \
- (((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \
- (((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \
- (((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \
- (((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \
- (((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \
- (((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0]))
-#else /* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2) ( \
- (*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \
- *(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \
- (*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \
- *(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0])))
-#endif /* SK_ADDR_DWORD_COMPARE */
-#endif /* SK_ADDR_EQUAL */
-
-/* typedefs *******************************************************************/
-
-typedef struct s_MacAddr {
- SK_U8 a[SK_MAC_ADDR_LEN];
-} SK_MAC_ADDR;
-
-
-/* SK_FILTER is used to ensure alignment of the filter. */
-typedef union s_InexactFilter {
- SK_U8 Bytes[8];
- SK_U64 Val; /* Dummy entry for alignment only. */
-} SK_FILTER64;
-
-
-typedef struct s_AddrNet SK_ADDR_NET;
-
-
-typedef struct s_AddrPort {
-
-/* ----- Public part (read-only) ----- */
-
- SK_MAC_ADDR CurrentMacAddress; /* Current physical MAC Address. */
- SK_MAC_ADDR PermanentMacAddress; /* Permanent physical MAC Address. */
- int PromMode; /* Promiscuous Mode. */
-
-/* ----- Private part ----- */
-
- SK_MAC_ADDR PreviousMacAddress; /* Prev. phys. MAC Address. */
- SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */
- SK_U8 Align01;
-
- SK_U32 FirstExactMatchRlmt;
- SK_U32 NextExactMatchRlmt;
- SK_U32 FirstExactMatchDrv;
- SK_U32 NextExactMatchDrv;
- SK_MAC_ADDR Exact[SK_ADDR_EXACT_MATCHES];
- SK_FILTER64 InexactFilter; /* For 64-bit hash register. */
- SK_FILTER64 InexactRlmtFilter; /* For 64-bit hash register. */
- SK_FILTER64 InexactDrvFilter; /* For 64-bit hash register. */
-} SK_ADDR_PORT;
-
-
-struct s_AddrNet {
-/* ----- Public part (read-only) ----- */
-
- SK_MAC_ADDR CurrentMacAddress; /* Logical MAC Address. */
- SK_MAC_ADDR PermanentMacAddress; /* Logical MAC Address. */
-
-/* ----- Private part ----- */
-
- SK_U32 ActivePort; /* View of module ADDR. */
- SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */
- SK_U8 Align01;
- SK_U16 Align02;
-};
-
-
-typedef struct s_Addr {
-
-/* ----- Public part (read-only) ----- */
-
- SK_ADDR_NET Net[SK_MAX_NETS];
- SK_ADDR_PORT Port[SK_MAX_MACS];
-
-/* ----- Private part ----- */
-} SK_ADDR;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkAddr */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern int SkAddrInit(
- SK_AC *pAC,
- SK_IOC IoC,
- int Level);
-
-extern int SkAddrMcClear(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber,
- int Flags);
-
-extern int SkAddrMcAdd(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber,
- SK_MAC_ADDR *pMc,
- int Flags);
-
-extern int SkAddrMcUpdate(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber);
-
-extern int SkAddrOverride(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber,
- SK_MAC_ADDR SK_FAR *pNewAddr,
- int Flags);
-
-extern int SkAddrPromiscuousChange(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber,
- int NewPromMode);
-
-#ifndef SK_SLIM
-extern int SkAddrSwap(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 FromPortNumber,
- SK_U32 ToPortNumber);
-#endif
-
-#else /* defined(SK_KR_PROTO)) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style prototypes are not yet provided.
-
-#endif /* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_SKADDR_H */
diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h
deleted file mode 100644
index 6e256bd9a28..00000000000
--- a/drivers/net/sk98lin/h/skcsum.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/******************************************************************************
- *
- * Name: skcsum.h
- * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
- * Version: $Revision: 1.10 $
- * Date: $Date: 2003/08/20 13:59:57 $
- * Purpose: Store/verify Internet checksum in send/receive packets.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2001 SysKonnect GmbH.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * Public header file for the "GEnesis" common module "CSUM".
- *
- * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
- * and is the code name of this SysKonnect project.
- *
- * Compilation Options:
- *
- * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
- * empty module.
- *
- * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
- * definitions. In this case, all SKCS_PROTO_xxx definitions must be made
- * external.
- *
- * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
- * definitions. In this case, all SKCS_STATUS_xxx definitions must be made
- * external.
- *
- * Include File Hierarchy:
- *
- * "h/skcsum.h"
- * "h/sktypes.h"
- * "h/skqueue.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKCSUM_H
-#define __INC_SKCSUM_H
-
-#include "h/sktypes.h"
-#include "h/skqueue.h"
-
-/* defines ********************************************************************/
-
-/*
- * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags' if no user
- * overwrite.
- */
-#ifndef SKCS_OVERWRITE_PROTO /* User overwrite? */
-#define SKCS_PROTO_IP 0x1 /* IP (Internet Protocol version 4) */
-#define SKCS_PROTO_TCP 0x2 /* TCP (Transmission Control Protocol) */
-#define SKCS_PROTO_UDP 0x4 /* UDP (User Datagram Protocol) */
-
-/* Indices for protocol statistics. */
-#define SKCS_PROTO_STATS_IP 0
-#define SKCS_PROTO_STATS_UDP 1
-#define SKCS_PROTO_STATS_TCP 2
-#define SKCS_NUM_PROTOCOLS 3 /* Number of supported protocols. */
-#endif /* !SKCS_OVERWRITE_PROTO */
-
-/*
- * Define the default SKCS_STATUS type and values if no user overwrite.
- *
- * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
- * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
- * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
- * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
- * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
- * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
- * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
- * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
- * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
- * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
- * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum.
- */
-#ifndef SKCS_OVERWRITE_STATUS /* User overwrite? */
-#define SKCS_STATUS int /* Define status type. */
-
-#define SKCS_STATUS_UNKNOWN_IP_VERSION 1
-#define SKCS_STATUS_IP_CSUM_ERROR 2
-#define SKCS_STATUS_IP_FRAGMENT 3
-#define SKCS_STATUS_IP_CSUM_OK 4
-#define SKCS_STATUS_TCP_CSUM_ERROR 5
-#define SKCS_STATUS_UDP_CSUM_ERROR 6
-#define SKCS_STATUS_TCP_CSUM_OK 7
-#define SKCS_STATUS_UDP_CSUM_OK 8
-/* needed for Microsoft */
-#define SKCS_STATUS_IP_CSUM_ERROR_UDP 9
-#define SKCS_STATUS_IP_CSUM_ERROR_TCP 10
-/* UDP checksum may be omitted */
-#define SKCS_STATUS_IP_CSUM_OK_NO_UDP 11
-#endif /* !SKCS_OVERWRITE_STATUS */
-
-/* Clear protocol statistics event. */
-#define SK_CSUM_EVENT_CLEAR_PROTO_STATS 1
-
-/*
- * Add two values in one's complement.
- *
- * Note: One of the two input values may be "longer" than 16-bit, but then the
- * resulting sum may be 17 bits long. In this case, add zero to the result using
- * SKCS_OC_ADD() again.
- *
- * Result = Value1 + Value2
- */
-#define SKCS_OC_ADD(Result, Value1, Value2) { \
- unsigned long Sum; \
- \
- Sum = (unsigned long) (Value1) + (unsigned long) (Value2); \
- /* Add-in any carry. */ \
- (Result) = (Sum & 0xffff) + (Sum >> 16); \
-}
-
-/*
- * Subtract two values in one's complement.
- *
- * Result = Value1 - Value2
- */
-#define SKCS_OC_SUB(Result, Value1, Value2) \
- SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff)
-
-/* typedefs *******************************************************************/
-
-/*
- * SKCS_PROTO_STATS - The CSUM protocol statistics structure.
- *
- * There is one instance of this structure for each protocol supported.
- */
-typedef struct s_CsProtocolStatistics {
- SK_U64 RxOkCts; /* Receive checksum ok. */
- SK_U64 RxUnableCts; /* Unable to verify receive checksum. */
- SK_U64 RxErrCts; /* Receive checksum error. */
- SK_U64 TxOkCts; /* Transmit checksum ok. */
- SK_U64 TxUnableCts; /* Unable to calculate checksum in hw. */
-} SKCS_PROTO_STATS;
-
-/*
- * s_Csum - The CSUM module context structure.
- */
-typedef struct s_Csum {
- /* Enabled receive SK_PROTO_XXX bit flags. */
- unsigned ReceiveFlags[SK_MAX_NETS];
-#ifdef TX_CSUM
- unsigned TransmitFlags[SK_MAX_NETS];
-#endif /* TX_CSUM */
-
- /* The protocol statistics structure; one per supported protocol. */
- SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS];
-} SK_CSUM;
-
-/*
- * SKCS_PACKET_INFO - The packet information structure.
- */
-typedef struct s_CsPacketInfo {
- /* Bit field specifiying the desired/found protocols. */
- unsigned ProtocolFlags;
-
- /* Length of complete IP header, including any option fields. */
- unsigned IpHeaderLength;
-
- /* IP header checksum. */
- unsigned IpHeaderChecksum;
-
- /* TCP/UDP pseudo header checksum. */
- unsigned PseudoHeaderChecksum;
-} SKCS_PACKET_INFO;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_CS_CALCULATE_CHECKSUM
-extern unsigned SkCsCalculateChecksum(
- void *pData,
- unsigned Length);
-#endif /* SK_CS_CALCULATE_CHECKSUM */
-
-extern int SkCsEvent(
- SK_AC *pAc,
- SK_IOC Ioc,
- SK_U32 Event,
- SK_EVPARA Param);
-
-extern SKCS_STATUS SkCsGetReceiveInfo(
- SK_AC *pAc,
- void *pIpHeader,
- unsigned Checksum1,
- unsigned Checksum2,
- int NetNumber);
-
-extern void SkCsSetReceiveFlags(
- SK_AC *pAc,
- unsigned ReceiveFlags,
- unsigned *pChecksum1Offset,
- unsigned *pChecksum2Offset,
- int NetNumber);
-
-#endif /* __INC_SKCSUM_H */
diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h
deleted file mode 100644
index 3cba171d74b..00000000000
--- a/drivers/net/sk98lin/h/skdebug.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/******************************************************************************
- *
- * Name: skdebug.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.14 $
- * Date: $Date: 2003/05/13 17:26:00 $
- * Purpose: SK specific DEBUG support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDEBUG_H
-#define __INC_SKDEBUG_H
-
-#ifdef DEBUG
-#ifndef SK_DBG_MSG
-#define SK_DBG_MSG(pAC,comp,cat,arg) \
- if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \
- ((cat) & SK_DBG_CHKCAT(pAC)) ) { \
- SK_DBG_PRINTF arg ; \
- }
-#endif
-#else
-#define SK_DBG_MSG(pAC,comp,lev,arg)
-#endif
-
-/* PLS NOTE:
- * =========
- * Due to any restrictions of kernel printf routines do not use other
- * format identifiers as: %x %d %c %s .
- * Never use any combined format identifiers such as: %lx %ld in your
- * printf - argument (arg) because some OS specific kernel printfs may
- * only support some basic identifiers.
- */
-
-/* Debug modules */
-
-#define SK_DBGMOD_MERR 0x00000001L /* general module error indication */
-#define SK_DBGMOD_HWM 0x00000002L /* Hardware init module */
-#define SK_DBGMOD_RLMT 0x00000004L /* RLMT module */
-#define SK_DBGMOD_VPD 0x00000008L /* VPD module */
-#define SK_DBGMOD_I2C 0x00000010L /* I2C module */
-#define SK_DBGMOD_PNMI 0x00000020L /* PNMI module */
-#define SK_DBGMOD_CSUM 0x00000040L /* CSUM module */
-#define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */
-#define SK_DBGMOD_PECP 0x00000100L /* PECP module */
-#define SK_DBGMOD_POWM 0x00000200L /* Power Management module */
-
-/* Debug events */
-
-#define SK_DBGCAT_INIT 0x00000001L /* module/driver initialization */
-#define SK_DBGCAT_CTRL 0x00000002L /* controlling devices */
-#define SK_DBGCAT_ERR 0x00000004L /* error handling paths */
-#define SK_DBGCAT_TX 0x00000008L /* transmit path */
-#define SK_DBGCAT_RX 0x00000010L /* receive path */
-#define SK_DBGCAT_IRQ 0x00000020L /* general IRQ handling */
-#define SK_DBGCAT_QUEUE 0x00000040L /* any queue management */
-#define SK_DBGCAT_DUMP 0x00000080L /* large data output e.g. hex dump */
-#define SK_DBGCAT_FATAL 0x00000100L /* fatal error */
-
-#endif /* __INC_SKDEBUG_H */
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
deleted file mode 100644
index 91b8d4f4590..00000000000
--- a/drivers/net/sk98lin/h/skdrv1st.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/******************************************************************************
- *
- * Name: skdrv1st.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.4 $
- * Date: $Date: 2003/11/12 14:28:14 $
- * Purpose: First header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the first include file of the driver, which includes all
- * neccessary system header files and some of the GEnesis header files.
- * It also defines some basic items.
- *
- * Include File Hierarchy:
- *
- * see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#define __INC_SKDRV1ST_H
-
-typedef struct s_AC SK_AC;
-
-/* Set card versions */
-#define SK_FAR
-
-/* override some default functions with optimized linux functions */
-
-#define SK_PNMI_STORE_U16(p,v) memcpy((char*)(p),(char*)&(v),2)
-#define SK_PNMI_STORE_U32(p,v) memcpy((char*)(p),(char*)&(v),4)
-#define SK_PNMI_STORE_U64(p,v) memcpy((char*)(p),(char*)&(v),8)
-#define SK_PNMI_READ_U16(p,v) memcpy((char*)&(v),(char*)(p),2)
-#define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),4)
-#define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),8)
-
-#define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6))
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <net/checksum.h>
-
-#define SK_CS_CALCULATE_CHECKSUM
-#ifndef CONFIG_X86_64
-#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff)
-#else
-#define SkCsCalculateChecksum(p,l) ((~ip_fast_csum(p, l)) & 0xffff)
-#endif
-
-#include "h/sktypes.h"
-#include "h/skerror.h"
-#include "h/skdebug.h"
-#include "h/lm80.h"
-#include "h/xmac_ii.h"
-
-#ifdef __LITTLE_ENDIAN
-#define SK_LITTLE_ENDIAN
-#else
-#define SK_BIG_ENDIAN
-#endif
-
-#define SK_NET_DEVICE net_device
-
-
-/* we use gethrtime(), return unit: nanoseconds */
-#define SK_TICKS_PER_SEC 100
-
-#define SK_MEM_MAPPED_IO
-
-// #define SK_RLMT_SLOW_LOOKAHEAD
-
-#define SK_MAX_MACS 2
-#define SK_MAX_NETS 2
-
-#define SK_IOC char __iomem *
-
-typedef struct s_DrvRlmtMbuf SK_MBUF;
-
-#define SK_CONST64 INT64_C
-#define SK_CONSTU64 UINT64_C
-
-#define SK_MEMCPY(dest,src,size) memcpy(dest,src,size)
-#define SK_MEMCMP(s1,s2,size) memcmp(s1,s2,size)
-#define SK_MEMSET(dest,val,size) memset(dest,val,size)
-#define SK_STRLEN(pStr) strlen((char*)(pStr))
-#define SK_STRNCPY(pDest,pSrc,size) strncpy((char*)(pDest),(char*)(pSrc),size)
-#define SK_STRCMP(pStr1,pStr2) strcmp((char*)(pStr1),(char*)(pStr2))
-
-/* macros to access the adapter */
-#define SK_OUT8(b,a,v) writeb((v), ((b)+(a)))
-#define SK_OUT16(b,a,v) writew((v), ((b)+(a)))
-#define SK_OUT32(b,a,v) writel((v), ((b)+(a)))
-#define SK_IN8(b,a,pv) (*(pv) = readb((b)+(a)))
-#define SK_IN16(b,a,pv) (*(pv) = readw((b)+(a)))
-#define SK_IN32(b,a,pv) (*(pv) = readl((b)+(a)))
-
-#define int8_t char
-#define int16_t short
-#define int32_t long
-#define int64_t long long
-#define uint8_t u_char
-#define uint16_t u_short
-#define uint32_t u_long
-#define uint64_t unsigned long long
-#define t_scalar_t int
-#define t_uscalar_t unsigned int
-#define uintptr_t unsigned long
-
-#define __CONCAT__(A,B) A##B
-
-#define INT32_C(a) __CONCAT__(a,L)
-#define INT64_C(a) __CONCAT__(a,LL)
-#define UINT32_C(a) __CONCAT__(a,UL)
-#define UINT64_C(a) __CONCAT__(a,ULL)
-
-#ifdef DEBUG
-#define SK_DBG_PRINTF printk
-#ifndef SK_DEBUG_CHKMOD
-#define SK_DEBUG_CHKMOD 0
-#endif
-#ifndef SK_DEBUG_CHKCAT
-#define SK_DEBUG_CHKCAT 0
-#endif
-/* those come from the makefile */
-#define SK_DBG_CHKMOD(pAC) (SK_DEBUG_CHKMOD)
-#define SK_DBG_CHKCAT(pAC) (SK_DEBUG_CHKCAT)
-
-extern void SkDbgPrintf(const char *format,...);
-
-#define SK_DBGMOD_DRV 0x00010000
-
-/**** possible driver debug categories ********************************/
-#define SK_DBGCAT_DRV_ENTRY 0x00010000
-#define SK_DBGCAT_DRV_SAP 0x00020000
-#define SK_DBGCAT_DRV_MCA 0x00040000
-#define SK_DBGCAT_DRV_TX_PROGRESS 0x00080000
-#define SK_DBGCAT_DRV_RX_PROGRESS 0x00100000
-#define SK_DBGCAT_DRV_PROGRESS 0x00200000
-#define SK_DBGCAT_DRV_MSG 0x00400000
-#define SK_DBGCAT_DRV_PROM 0x00800000
-#define SK_DBGCAT_DRV_TX_FRAME 0x01000000
-#define SK_DBGCAT_DRV_ERROR 0x02000000
-#define SK_DBGCAT_DRV_INT_SRC 0x04000000
-#define SK_DBGCAT_DRV_EVENT 0x08000000
-
-#endif
-
-#define SK_ERR_LOG SkErrorLog
-
-extern void SkErrorLog(SK_AC*, int, int, char*);
-
-#endif
-
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
deleted file mode 100644
index 3fa67171e83..00000000000
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ /dev/null
@@ -1,447 +0,0 @@
-/******************************************************************************
- *
- * Name: skdrv2nd.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.10 $
- * Date: $Date: 2003/12/11 16:04:45 $
- * Purpose: Second header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the second include file of the driver, which includes all other
- * neccessary files and defines all structures and constants used by the
- * driver and the common modules.
- *
- * Include File Hierarchy:
- *
- * see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV2ND_H
-#define __INC_SKDRV2ND_H
-
-#include "h/skqueue.h"
-#include "h/skgehwt.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skgepnmi.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skaddr.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skrlmt.h"
-#include "h/skgedrv.h"
-
-
-extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
-extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
-extern SK_U64 SkOsGetTime(SK_AC*);
-extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
-extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*);
-extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*);
-extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16);
-extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8);
-extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
-
-#ifdef SK_DIAG_SUPPORT
-extern int SkDrvEnterDiagMode(SK_AC *pAc);
-extern int SkDrvLeaveDiagMode(SK_AC *pAc);
-#endif
-
-struct s_DrvRlmtMbuf {
- SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */
- SK_U8 *pData; /* Data buffer (virtually contig.). */
- unsigned Size; /* Data buffer size. */
- unsigned Length; /* Length of packet (<= Size). */
- SK_U32 PortIdx; /* Receiving/transmitting port. */
-#ifdef SK_RLMT_MBUF_PRIVATE
- SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */
-#endif /* SK_RLMT_MBUF_PRIVATE */
- struct sk_buff *pOs; /* Pointer to message block */
-};
-
-
-/*
- * Time macros
- */
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t) (t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t) ((((unsigned long)t) * 100) / \
- (SK_TICKS_PER_SEC))
-#endif
-
-/*
- * New SkOsGetTime
- */
-#define SkOsGetTimeCurrent(pAC, pUsec) {\
- struct timeval t;\
- do_gettimeofday(&t);\
- *pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\
-}
-
-
-/*
- * ioctl definitions
- */
-#define SK_IOCTL_BASE (SIOCDEVPRIVATE)
-#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0)
-#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1)
-#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2)
-#define SK_IOCTL_GEN (SK_IOCTL_BASE + 3)
-#define SK_IOCTL_DIAG (SK_IOCTL_BASE + 4)
-
-typedef struct s_IOCTL SK_GE_IOCTL;
-
-struct s_IOCTL {
- char __user * pData;
- unsigned int Len;
-};
-
-
-/*
- * define sizes of descriptor rings in bytes
- */
-
-#define TX_RING_SIZE (8*1024)
-#define RX_RING_SIZE (24*1024)
-
-/*
- * Buffer size for ethernet packets
- */
-#define ETH_BUF_SIZE 1540
-#define ETH_MAX_MTU 1514
-#define ETH_MIN_MTU 60
-#define ETH_MULTICAST_BIT 0x01
-#define SK_JUMBO_MTU 9000
-
-/*
- * transmit priority selects the queue: LOW=asynchron, HIGH=synchron
- */
-#define TX_PRIO_LOW 0
-#define TX_PRIO_HIGH 1
-
-/*
- * alignment of rx/tx descriptors
- */
-#define DESCR_ALIGN 64
-
-/*
- * definitions for pnmi. TODO
- */
-#define SK_DRIVER_RESET(pAC, IoC) 0
-#define SK_DRIVER_SENDEVENT(pAC, IoC) 0
-#define SK_DRIVER_SELFTEST(pAC, IoC) 0
-/* For get mtu you must add an own function */
-#define SK_DRIVER_GET_MTU(pAc,IoC,i) 0
-#define SK_DRIVER_SET_MTU(pAc,IoC,i,v) 0
-#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v) 0
-
-/*
-** Interim definition of SK_DRV_TIMER placed in this file until
-** common modules have been finalized
-*/
-#define SK_DRV_TIMER 11
-#define SK_DRV_MODERATION_TIMER 1
-#define SK_DRV_MODERATION_TIMER_LENGTH 1000000 /* 1 second */
-#define SK_DRV_RX_CLEANUP_TIMER 2
-#define SK_DRV_RX_CLEANUP_TIMER_LENGTH 1000000 /* 100 millisecs */
-
-/*
-** Definitions regarding transmitting frames
-** any calculating any checksum.
-*/
-#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6
-#define C_LEN_ETHERMAC_HEADER_SRC_ADDR 6
-#define C_LEN_ETHERMAC_HEADER_LENTYPE 2
-#define C_LEN_ETHERMAC_HEADER ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \
- (C_LEN_ETHERMAC_HEADER_SRC_ADDR) + \
- (C_LEN_ETHERMAC_HEADER_LENTYPE) )
-
-#define C_LEN_ETHERMTU_MINSIZE 46
-#define C_LEN_ETHERMTU_MAXSIZE_STD 1500
-#define C_LEN_ETHERMTU_MAXSIZE_JUMBO 9000
-
-#define C_LEN_ETHERNET_MINSIZE ( (C_LEN_ETHERMAC_HEADER) + \
- (C_LEN_ETHERMTU_MINSIZE) )
-
-#define C_OFFSET_IPHEADER C_LEN_ETHERMAC_HEADER
-#define C_OFFSET_IPHEADER_IPPROTO 9
-#define C_OFFSET_TCPHEADER_TCPCS 16
-#define C_OFFSET_UDPHEADER_UDPCS 6
-
-#define C_OFFSET_IPPROTO ( (C_LEN_ETHERMAC_HEADER) + \
- (C_OFFSET_IPHEADER_IPPROTO) )
-
-#define C_PROTO_ID_UDP 17 /* refer to RFC 790 or Stevens' */
-#define C_PROTO_ID_TCP 6 /* TCP/IP illustrated for details */
-
-/* TX and RX descriptors *****************************************************/
-
-typedef struct s_RxD RXD; /* the receive descriptor */
-
-struct s_RxD {
- volatile SK_U32 RBControl; /* Receive Buffer Control */
- SK_U32 VNextRxd; /* Next receive descriptor,low dword */
- SK_U32 VDataLow; /* Receive buffer Addr, low dword */
- SK_U32 VDataHigh; /* Receive buffer Addr, high dword */
- SK_U32 FrameStat; /* Receive Frame Status word */
- SK_U32 TimeStamp; /* Time stamp from XMAC */
- SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */
- SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */
- RXD *pNextRxd; /* Pointer to next Rxd */
- struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
-};
-
-typedef struct s_TxD TXD; /* the transmit descriptor */
-
-struct s_TxD {
- volatile SK_U32 TBControl; /* Transmit Buffer Control */
- SK_U32 VNextTxd; /* Next transmit descriptor,low dword */
- SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */
- SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */
- SK_U32 FrameStat; /* Transmit Frame Status Word */
- SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */
- SK_U16 TcpSumSt; /* TCP Sum Start */
- SK_U16 TcpSumWr; /* TCP Sum Write */
- SK_U32 TcpReserved; /* not used */
- TXD *pNextTxd; /* Pointer to next Txd */
- struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
-};
-
-/* Used interrupt bits in the interrupts source register *********************/
-
-#define DRIVER_IRQS ((IS_IRQ_SW) | \
- (IS_R1_F) |(IS_R2_F) | \
- (IS_XS1_F) |(IS_XA1_F) | \
- (IS_XS2_F) |(IS_XA2_F))
-
-#define SPECIAL_IRQS ((IS_HW_ERR) |(IS_I2C_READY) | \
- (IS_EXT_REG) |(IS_TIMINT) | \
- (IS_PA_TO_RX1) |(IS_PA_TO_RX2) | \
- (IS_PA_TO_TX1) |(IS_PA_TO_TX2) | \
- (IS_MAC1) |(IS_LNK_SYNC_M1)| \
- (IS_MAC2) |(IS_LNK_SYNC_M2)| \
- (IS_R1_C) |(IS_R2_C) | \
- (IS_XS1_C) |(IS_XA1_C) | \
- (IS_XS2_C) |(IS_XA2_C))
-
-#define IRQ_MASK ((IS_IRQ_SW) | \
- (IS_R1_B) |(IS_R1_F) |(IS_R2_B) |(IS_R2_F) | \
- (IS_XS1_B) |(IS_XS1_F) |(IS_XA1_B)|(IS_XA1_F)| \
- (IS_XS2_B) |(IS_XS2_F) |(IS_XA2_B)|(IS_XA2_F)| \
- (IS_HW_ERR) |(IS_I2C_READY)| \
- (IS_EXT_REG) |(IS_TIMINT) | \
- (IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
- (IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
- (IS_MAC1) |(IS_MAC2) | \
- (IS_R1_C) |(IS_R2_C) | \
- (IS_XS1_C) |(IS_XA1_C) | \
- (IS_XS2_C) |(IS_XA2_C))
-
-#define IRQ_HWE_MASK (IS_ERR_MSK) /* enable all HW irqs */
-
-typedef struct s_DevNet DEV_NET;
-
-struct s_DevNet {
- int PortNr;
- int NetNr;
- SK_AC *pAC;
-};
-
-typedef struct s_TxPort TX_PORT;
-
-struct s_TxPort {
- /* the transmit descriptor rings */
- caddr_t pTxDescrRing; /* descriptor area memory */
- SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */
- TXD *pTxdRingHead; /* Head of Tx rings */
- TXD *pTxdRingTail; /* Tail of Tx rings */
- TXD *pTxdRingPrev; /* descriptor sent previously */
- int TxdRingFree; /* # of free entrys */
- spinlock_t TxDesRingLock; /* serialize descriptor accesses */
- SK_IOC HwAddr; /* bmu registers address */
- int PortIndex; /* index number of port (0 or 1) */
-};
-
-typedef struct s_RxPort RX_PORT;
-
-struct s_RxPort {
- /* the receive descriptor rings */
- caddr_t pRxDescrRing; /* descriptor area memory */
- SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */
- RXD *pRxdRingHead; /* Head of Rx rings */
- RXD *pRxdRingTail; /* Tail of Rx rings */
- RXD *pRxdRingPrev; /* descriptor given to BMU previously */
- int RxdRingFree; /* # of free entrys */
- int RxCsum; /* use receive checksum hardware */
- spinlock_t RxDesRingLock; /* serialize descriptor accesses */
- int RxFillLimit; /* limit for buffers in ring */
- SK_IOC HwAddr; /* bmu registers address */
- int PortIndex; /* index number of port (0 or 1) */
-};
-
-/* Definitions needed for interrupt moderation *******************************/
-
-#define IRQ_EOF_AS_TX ((IS_XA1_F) | (IS_XA2_F))
-#define IRQ_EOF_SY_TX ((IS_XS1_F) | (IS_XS2_F))
-#define IRQ_MASK_TX_ONLY ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX))
-#define IRQ_MASK_RX_ONLY ((IS_R1_F) | (IS_R2_F))
-#define IRQ_MASK_SP_ONLY (SPECIAL_IRQS)
-#define IRQ_MASK_TX_RX ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_RX ((SPECIAL_IRQS) | (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_TX ((SPECIAL_IRQS) | (IRQ_MASK_TX_ONLY))
-#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS) | (IRQ_MASK_TX_RX))
-
-#define C_INT_MOD_NONE 1
-#define C_INT_MOD_STATIC 2
-#define C_INT_MOD_DYNAMIC 4
-
-#define C_CLK_FREQ_GENESIS 53215000 /* shorter: 53.125 MHz */
-#define C_CLK_FREQ_YUKON 78215000 /* shorter: 78.125 MHz */
-
-#define C_INTS_PER_SEC_DEFAULT 2000
-#define C_INT_MOD_ENABLE_PERCENTAGE 50 /* if higher 50% enable */
-#define C_INT_MOD_DISABLE_PERCENTAGE 50 /* if lower 50% disable */
-#define C_INT_MOD_IPS_LOWER_RANGE 30
-#define C_INT_MOD_IPS_UPPER_RANGE 40000
-
-
-typedef struct s_DynIrqModInfo DIM_INFO;
-struct s_DynIrqModInfo {
- unsigned long PrevTimeVal;
- unsigned int PrevSysLoad;
- unsigned int PrevUsedTime;
- unsigned int PrevTotalTime;
- int PrevUsedDescrRatio;
- int NbrProcessedDescr;
- SK_U64 PrevPort0RxIntrCts;
- SK_U64 PrevPort1RxIntrCts;
- SK_U64 PrevPort0TxIntrCts;
- SK_U64 PrevPort1TxIntrCts;
- SK_BOOL ModJustEnabled; /* Moderation just enabled yes/no */
-
- int MaxModIntsPerSec; /* Moderation Threshold */
- int MaxModIntsPerSecUpperLimit; /* Upper limit for DIM */
- int MaxModIntsPerSecLowerLimit; /* Lower limit for DIM */
-
- long MaskIrqModeration; /* ModIrqType (eg. 'TxRx') */
- SK_BOOL DisplayStats; /* Stats yes/no */
- SK_BOOL AutoSizing; /* Resize DIM-timer on/off */
- int IntModTypeSelect; /* EnableIntMod (eg. 'dynamic') */
-
- SK_TIMER ModTimer; /* just some timer */
-};
-
-typedef struct s_PerStrm PER_STRM;
-
-#define SK_ALLOC_IRQ 0x00000001
-
-#ifdef SK_DIAG_SUPPORT
-#define DIAG_ACTIVE 1
-#define DIAG_NOTACTIVE 0
-#endif
-
-/****************************************************************************
- * Per board structure / Adapter Context structure:
- * Allocated within attach(9e) and freed within detach(9e).
- * Contains all 'per device' necessary handles, flags, locks etc.:
- */
-struct s_AC {
- SK_GEINIT GIni; /* GE init struct */
- SK_PNMI Pnmi; /* PNMI data struct */
- SK_VPD vpd; /* vpd data struct */
- SK_QUEUE Event; /* Event queue */
- SK_HWT Hwt; /* Hardware Timer control struct */
- SK_TIMCTRL Tim; /* Software Timer control struct */
- SK_I2C I2c; /* I2C relevant data structure */
- SK_ADDR Addr; /* for Address module */
- SK_CSUM Csum; /* for checksum module */
- SK_RLMT Rlmt; /* for rlmt module */
- spinlock_t SlowPathLock; /* Normal IRQ lock */
- struct timer_list BlinkTimer; /* for LED blinking */
- int LedsOn;
- SK_PNMI_STRUCT_DATA PnmiStruct; /* structure to get all Pnmi-Data */
- int RlmtMode; /* link check mode to set */
- int RlmtNets; /* Number of nets */
-
- SK_IOC IoBase; /* register set of adapter */
- int BoardLevel; /* level of active hw init (0-2) */
-
- SK_U32 AllocFlag; /* flag allocation of resources */
- struct pci_dev *PciDev; /* for access to pci config space */
- struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */
-
- int RxBufSize; /* length of receive buffers */
- struct net_device_stats stats; /* linux 'netstat -i' statistics */
- int Index; /* internal board index number */
-
- /* adapter RAM sizes for queues of active port */
- int RxQueueSize; /* memory used for receive queue */
- int TxSQueueSize; /* memory used for sync. tx queue */
- int TxAQueueSize; /* memory used for async. tx queue */
-
- int PromiscCount; /* promiscuous mode counter */
- int AllMultiCount; /* allmulticast mode counter */
- int MulticCount; /* number of different MC */
- /* addresses for this board */
- /* (may be more than HW can)*/
-
- int HWRevision; /* Hardware revision */
- int ActivePort; /* the active XMAC port */
- int MaxPorts; /* number of activated ports */
- int TxDescrPerRing; /* # of descriptors per tx ring */
- int RxDescrPerRing; /* # of descriptors per rx ring */
-
- caddr_t pDescrMem; /* Pointer to the descriptor area */
- dma_addr_t pDescrMemDMA; /* PCI DMA address of area */
-
- /* the port structures with descriptor rings */
- TX_PORT TxPort[SK_MAX_MACS][2];
- RX_PORT RxPort[SK_MAX_MACS];
-
- SK_BOOL CheckQueue; /* check event queue soon */
- SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */
- DIM_INFO DynIrqModInfo; /* all data related to DIM */
-
- /* Only for tests */
- int PortDown;
- int ChipsetType; /* Chipset family type
- * 0 == Genesis family support
- * 1 == Yukon family support
- */
-#ifdef SK_DIAG_SUPPORT
- SK_U32 DiagModeActive; /* is diag active? */
- SK_BOOL DiagFlowCtrl; /* for control purposes */
- SK_PNMI_STRUCT_DATA PnmiBackup; /* backup structure for all Pnmi-Data */
- SK_BOOL WasIfUp[SK_MAX_MACS]; /* for OpenClose while
- * DIAG is busy with NIC
- */
-#endif
-
-};
-
-
-#endif /* __INC_SKDRV2ND_H */
-
diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h
deleted file mode 100644
index da062f76623..00000000000
--- a/drivers/net/sk98lin/h/skerror.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/******************************************************************************
- *
- * Name: skerror.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.7 $
- * Date: $Date: 2003/05/13 17:25:13 $
- * Purpose: SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKERROR_H_
-#define _INC_SKERROR_H_
-
-/*
- * Define Error Classes
- */
-#define SK_ERRCL_OTHER (0) /* Other error */
-#define SK_ERRCL_CONFIG (1L<<0) /* Configuration error */
-#define SK_ERRCL_INIT (1L<<1) /* Initialization error */
-#define SK_ERRCL_NORES (1L<<2) /* Out of Resources error */
-#define SK_ERRCL_SW (1L<<3) /* Internal Software error */
-#define SK_ERRCL_HW (1L<<4) /* Hardware Failure */
-#define SK_ERRCL_COMM (1L<<5) /* Communication error */
-
-
-/*
- * Define Error Code Bases
- */
-#define SK_ERRBASE_RLMT 100 /* Base Error number for RLMT */
-#define SK_ERRBASE_HWINIT 200 /* Base Error number for HWInit */
-#define SK_ERRBASE_VPD 300 /* Base Error number for VPD */
-#define SK_ERRBASE_PNMI 400 /* Base Error number for PNMI */
-#define SK_ERRBASE_CSUM 500 /* Base Error number for Checksum */
-#define SK_ERRBASE_SIRQ 600 /* Base Error number for Special IRQ */
-#define SK_ERRBASE_I2C 700 /* Base Error number for I2C module */
-#define SK_ERRBASE_QUEUE 800 /* Base Error number for Scheduler */
-#define SK_ERRBASE_ADDR 900 /* Base Error number for Address module */
-#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */
-#define SK_ERRBASE_DRV 1100 /* Base Error number for Driver */
-
-#endif /* _INC_SKERROR_H_ */
diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h
deleted file mode 100644
index 44fd4c3de81..00000000000
--- a/drivers/net/sk98lin/h/skgedrv.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/******************************************************************************
- *
- * Name: skgedrv.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.10 $
- * Date: $Date: 2003/07/04 12:25:01 $
- * Purpose: Interface with the driver
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEDRV_H_
-#define __INC_SKGEDRV_H_
-
-/* defines ********************************************************************/
-
-/*
- * Define the driver events.
- * Usually the events are defined by the destination module.
- * In case of the driver we put the definition of the events here.
- */
-#define SK_DRV_PORT_RESET 1 /* The port needs to be reset */
-#define SK_DRV_NET_UP 2 /* The net is operational */
-#define SK_DRV_NET_DOWN 3 /* The net is down */
-#define SK_DRV_SWITCH_SOFT 4 /* Ports switch with both links connected */
-#define SK_DRV_SWITCH_HARD 5 /* Port switch due to link failure */
-#define SK_DRV_RLMT_SEND 6 /* Send a RLMT packet */
-#define SK_DRV_ADAP_FAIL 7 /* The whole adapter fails */
-#define SK_DRV_PORT_FAIL 8 /* One port fails */
-#define SK_DRV_SWITCH_INTERN 9 /* Port switch by the driver itself */
-#define SK_DRV_POWER_DOWN 10 /* Power down mode */
-#define SK_DRV_TIMER 11 /* Timer for free use */
-#ifdef SK_NO_RLMT
-#define SK_DRV_LINK_UP 12 /* Link Up event for driver */
-#define SK_DRV_LINK_DOWN 13 /* Link Down event for driver */
-#endif
-#define SK_DRV_DOWNSHIFT_DET 14 /* Downshift 4-Pair / 2-Pair (YUKON only) */
-#endif /* __INC_SKGEDRV_H_ */
diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
deleted file mode 100644
index f6282b7956d..00000000000
--- a/drivers/net/sk98lin/h/skgehw.h
+++ /dev/null
@@ -1,2126 +0,0 @@
-/******************************************************************************
- *
- * Name: skgehw.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.56 $
- * Date: $Date: 2003/09/23 09:01:00 $
- * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEHW_H
-#define __INC_SKGEHW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define BIT_31 (1UL << 31)
-#define BIT_30 (1L << 30)
-#define BIT_29 (1L << 29)
-#define BIT_28 (1L << 28)
-#define BIT_27 (1L << 27)
-#define BIT_26 (1L << 26)
-#define BIT_25 (1L << 25)
-#define BIT_24 (1L << 24)
-#define BIT_23 (1L << 23)
-#define BIT_22 (1L << 22)
-#define BIT_21 (1L << 21)
-#define BIT_20 (1L << 20)
-#define BIT_19 (1L << 19)
-#define BIT_18 (1L << 18)
-#define BIT_17 (1L << 17)
-#define BIT_16 (1L << 16)
-#define BIT_15 (1L << 15)
-#define BIT_14 (1L << 14)
-#define BIT_13 (1L << 13)
-#define BIT_12 (1L << 12)
-#define BIT_11 (1L << 11)
-#define BIT_10 (1L << 10)
-#define BIT_9 (1L << 9)
-#define BIT_8 (1L << 8)
-#define BIT_7 (1L << 7)
-#define BIT_6 (1L << 6)
-#define BIT_5 (1L << 5)
-#define BIT_4 (1L << 4)
-#define BIT_3 (1L << 3)
-#define BIT_2 (1L << 2)
-#define BIT_1 (1L << 1)
-#define BIT_0 1L
-
-#define BIT_15S (1U << 15)
-#define BIT_14S (1 << 14)
-#define BIT_13S (1 << 13)
-#define BIT_12S (1 << 12)
-#define BIT_11S (1 << 11)
-#define BIT_10S (1 << 10)
-#define BIT_9S (1 << 9)
-#define BIT_8S (1 << 8)
-#define BIT_7S (1 << 7)
-#define BIT_6S (1 << 6)
-#define BIT_5S (1 << 5)
-#define BIT_4S (1 << 4)
-#define BIT_3S (1 << 3)
-#define BIT_2S (1 << 2)
-#define BIT_1S (1 << 1)
-#define BIT_0S 1
-
-#define SHIFT31(x) ((x) << 31)
-#define SHIFT30(x) ((x) << 30)
-#define SHIFT29(x) ((x) << 29)
-#define SHIFT28(x) ((x) << 28)
-#define SHIFT27(x) ((x) << 27)
-#define SHIFT26(x) ((x) << 26)
-#define SHIFT25(x) ((x) << 25)
-#define SHIFT24(x) ((x) << 24)
-#define SHIFT23(x) ((x) << 23)
-#define SHIFT22(x) ((x) << 22)
-#define SHIFT21(x) ((x) << 21)
-#define SHIFT20(x) ((x) << 20)
-#define SHIFT19(x) ((x) << 19)
-#define SHIFT18(x) ((x) << 18)
-#define SHIFT17(x) ((x) << 17)
-#define SHIFT16(x) ((x) << 16)
-#define SHIFT15(x) ((x) << 15)
-#define SHIFT14(x) ((x) << 14)
-#define SHIFT13(x) ((x) << 13)
-#define SHIFT12(x) ((x) << 12)
-#define SHIFT11(x) ((x) << 11)
-#define SHIFT10(x) ((x) << 10)
-#define SHIFT9(x) ((x) << 9)
-#define SHIFT8(x) ((x) << 8)
-#define SHIFT7(x) ((x) << 7)
-#define SHIFT6(x) ((x) << 6)
-#define SHIFT5(x) ((x) << 5)
-#define SHIFT4(x) ((x) << 4)
-#define SHIFT3(x) ((x) << 3)
-#define SHIFT2(x) ((x) << 2)
-#define SHIFT1(x) ((x) << 1)
-#define SHIFT0(x) ((x) << 0)
-
-/*
- * Configuration Space header
- * Since this module is used for different OS', those may be
- * duplicate on some of them (e.g. Linux). But to keep the
- * common source, we have to live with this...
- */
-#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */
-#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */
-#define PCI_COMMAND 0x04 /* 16 bit Command */
-#define PCI_STATUS 0x06 /* 16 bit Status */
-#define PCI_REV_ID 0x08 /* 8 bit Revision ID */
-#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */
-#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */
-#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */
-#define PCI_HEADER_T 0x0e /* 8 bit Header Type */
-#define PCI_BIST 0x0f /* 8 bit Built-in selftest */
-#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */
-#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */
- /* Byte 0x18..0x2b: reserved */
-#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */
-#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */
-#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */
-#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Ptr */
- /* Byte 0x35..0x3b: reserved */
-#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */
-#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */
-#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */
-#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */
- /* Device Dependent Region */
-#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */
-#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */
- /* Power Management Region */
-#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */
-#define PCI_PM_NITEM 0x49 /* 8 bit Next Item Ptr */
-#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */
-#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */
- /* Byte 0x4e: reserved */
-#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */
- /* VPD Region */
-#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */
-#define PCI_VPD_NITEM 0x51 /* 8 bit Next Item Ptr */
-#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */
-#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */
- /* Byte 0x58..0x59: reserved */
-#define PCI_SER_LD_CTRL 0x5a /* 16 bit SEEPROM Loader Ctrl (YUKON only) */
- /* Byte 0x5c..0xff: reserved */
-
-/*
- * I2C Address (PCI Config)
- *
- * Note: The temperature and voltage sensors are relocated on a different
- * I2C bus.
- */
-#define I2C_ADDR_VPD 0xa0 /* I2C address for the VPD EEPROM */
-
-/*
- * Define Bits and Values of the registers
- */
-/* PCI_COMMAND 16 bit Command */
- /* Bit 15..11: reserved */
-#define PCI_INT_DIS BIT_10S /* Interrupt INTx# disable (PCI 2.3) */
-#define PCI_FBTEN BIT_9S /* Fast Back-To-Back enable */
-#define PCI_SERREN BIT_8S /* SERR enable */
-#define PCI_ADSTEP BIT_7S /* Address Stepping */
-#define PCI_PERREN BIT_6S /* Parity Report Response enable */
-#define PCI_VGA_SNOOP BIT_5S /* VGA palette snoop */
-#define PCI_MWIEN BIT_4S /* Memory write an inv cycl ena */
-#define PCI_SCYCEN BIT_3S /* Special Cycle enable */
-#define PCI_BMEN BIT_2S /* Bus Master enable */
-#define PCI_MEMEN BIT_1S /* Memory Space Access enable */
-#define PCI_IOEN BIT_0S /* I/O Space Access enable */
-
-#define PCI_COMMAND_VAL (PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\
- PCI_BMEN | PCI_MEMEN | PCI_IOEN)
-
-/* PCI_STATUS 16 bit Status */
-#define PCI_PERR BIT_15S /* Parity Error */
-#define PCI_SERR BIT_14S /* Signaled SERR */
-#define PCI_RMABORT BIT_13S /* Received Master Abort */
-#define PCI_RTABORT BIT_12S /* Received Target Abort */
- /* Bit 11: reserved */
-#define PCI_DEVSEL (3<<9) /* Bit 10.. 9: DEVSEL Timing */
-#define PCI_DEV_FAST (0<<9) /* fast */
-#define PCI_DEV_MEDIUM (1<<9) /* medium */
-#define PCI_DEV_SLOW (2<<9) /* slow */
-#define PCI_DATAPERR BIT_8S /* DATA Parity error detected */
-#define PCI_FB2BCAP BIT_7S /* Fast Back-to-Back Capability */
-#define PCI_UDF BIT_6S /* User Defined Features */
-#define PCI_66MHZCAP BIT_5S /* 66 MHz PCI bus clock capable */
-#define PCI_NEWCAP BIT_4S /* New cap. list implemented */
-#define PCI_INT_STAT BIT_3S /* Interrupt INTx# Status (PCI 2.3) */
- /* Bit 2.. 0: reserved */
-
-#define PCI_ERRBITS (PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\
- PCI_DATAPERR)
-
-/* PCI_CLASS_CODE 24 bit Class Code */
-/* Byte 2: Base Class (02) */
-/* Byte 1: SubClass (00) */
-/* Byte 0: Programming Interface (00) */
-
-/* PCI_CACHE_LSZ 8 bit Cache Line Size */
-/* Possible values: 0,2,4,8,16,32,64,128 */
-
-/* PCI_HEADER_T 8 bit Header Type */
-#define PCI_HD_MF_DEV BIT_7S /* 0= single, 1= multi-func dev */
-#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */
-
-/* PCI_BIST 8 bit Built-in selftest */
-/* Built-in Self test not supported (optional) */
-
-/* PCI_BASE_1ST 32 bit 1st Base address */
-#define PCI_MEMSIZE 0x4000L /* use 16 kB Memory Base */
-#define PCI_MEMBASE_MSK 0xffffc000L /* Bit 31..14: Memory Base Address */
-#define PCI_MEMSIZE_MSK 0x00003ff0L /* Bit 13.. 4: Memory Size Req. */
-#define PCI_PREFEN BIT_3 /* Prefetchable */
-#define PCI_MEM_TYP (3L<<2) /* Bit 2.. 1: Memory Type */
-#define PCI_MEM32BIT (0L<<1) /* Base addr anywhere in 32 Bit range */
-#define PCI_MEM1M (1L<<1) /* Base addr below 1 MegaByte */
-#define PCI_MEM64BIT (2L<<1) /* Base addr anywhere in 64 Bit range */
-#define PCI_MEMSPACE BIT_0 /* Memory Space Indicator */
-
-/* PCI_BASE_2ND 32 bit 2nd Base address */
-#define PCI_IOBASE 0xffffff00L /* Bit 31.. 8: I/O Base address */
-#define PCI_IOSIZE 0x000000fcL /* Bit 7.. 2: I/O Size Requirements */
- /* Bit 1: reserved */
-#define PCI_IOSPACE BIT_0 /* I/O Space Indicator */
-
-/* PCI_BASE_ROM 32 bit Expansion ROM Base Address */
-#define PCI_ROMBASE_MSK 0xfffe0000L /* Bit 31..17: ROM Base address */
-#define PCI_ROMBASE_SIZ (0x1cL<<14) /* Bit 16..14: Treat as Base or Size */
-#define PCI_ROMSIZE (0x38L<<11) /* Bit 13..11: ROM Size Requirements */
- /* Bit 10.. 1: reserved */
-#define PCI_ROMEN BIT_0 /* Address Decode enable */
-
-/* Device Dependent Region */
-/* PCI_OUR_REG_1 32 bit Our Register 1 */
- /* Bit 31..29: reserved */
-#define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode (YUKON only) */
-#define PCI_TEST_CAL BIT_27 /* Test PCI buffer calib. (YUKON only) */
-#define PCI_EN_CAL BIT_26 /* Enable PCI buffer calib. (YUKON only) */
-#define PCI_VIO BIT_25 /* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */
-#define PCI_DIS_BOOT BIT_24 /* Disable BOOT via ROM */
-#define PCI_EN_IO BIT_23 /* Mapping to I/O space */
-#define PCI_EN_FPROM BIT_22 /* Enable FLASH mapping to memory */
- /* 1 = Map Flash to memory */
- /* 0 = Disable addr. dec */
-#define PCI_PAGESIZE (3L<<20) /* Bit 21..20: FLASH Page Size */
-#define PCI_PAGE_16 (0L<<20) /* 16 k pages */
-#define PCI_PAGE_32K (1L<<20) /* 32 k pages */
-#define PCI_PAGE_64K (2L<<20) /* 64 k pages */
-#define PCI_PAGE_128K (3L<<20) /* 128 k pages */
- /* Bit 19: reserved */
-#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */
-#define PCI_NOTAR BIT_15 /* No turnaround cycle */
-#define PCI_FORCE_BE BIT_14 /* Assert all BEs on MR */
-#define PCI_DIS_MRL BIT_13 /* Disable Mem Read Line */
-#define PCI_DIS_MRM BIT_12 /* Disable Mem Read Multiple */
-#define PCI_DIS_MWI BIT_11 /* Disable Mem Write & Invalidate */
-#define PCI_DISC_CLS BIT_10 /* Disc: cacheLsz bound */
-#define PCI_BURST_DIS BIT_9 /* Burst Disable */
-#define PCI_DIS_PCI_CLK BIT_8 /* Disable PCI clock driving */
-#define PCI_SKEW_DAS (0xfL<<4) /* Bit 7.. 4: Skew Ctrl, DAS Ext */
-#define PCI_SKEW_BASE 0xfL /* Bit 3.. 0: Skew Ctrl, Base */
-
-
-/* PCI_OUR_REG_2 32 bit Our Register 2 */
-#define PCI_VPD_WR_THR (0xffL<<24) /* Bit 31..24: VPD Write Threshold */
-#define PCI_DEV_SEL (0x7fL<<17) /* Bit 23..17: EEPROM Device Select */
-#define PCI_VPD_ROM_SZ (7L<<14) /* Bit 16..14: VPD ROM Size */
- /* Bit 13..12: reserved */
-#define PCI_PATCH_DIR (0xfL<<8) /* Bit 11.. 8: Ext Patches dir 3..0 */
-#define PCI_PATCH_DIR_3 BIT_11
-#define PCI_PATCH_DIR_2 BIT_10
-#define PCI_PATCH_DIR_1 BIT_9
-#define PCI_PATCH_DIR_0 BIT_8
-#define PCI_EXT_PATCHS (0xfL<<4) /* Bit 7.. 4: Extended Patches 3..0 */
-#define PCI_EXT_PATCH_3 BIT_7
-#define PCI_EXT_PATCH_2 BIT_6
-#define PCI_EXT_PATCH_1 BIT_5
-#define PCI_EXT_PATCH_0 BIT_4
-#define PCI_EN_DUMMY_RD BIT_3 /* Enable Dummy Read */
-#define PCI_REV_DESC BIT_2 /* Reverse Desc. Bytes */
- /* Bit 1: reserved */
-#define PCI_USEDATA64 BIT_0 /* Use 64Bit Data bus ext */
-
-
-/* Power Management Region */
-/* PCI_PM_CAP_REG 16 bit Power Management Capabilities */
-#define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event Support Mask */
-#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if Vaux) */
-#define PCI_PME_D3H_SUP BIT_14S /* PME from D3hot Support */
-#define PCI_PME_D2_SUP BIT_13S /* PME from D2 Support */
-#define PCI_PME_D1_SUP BIT_12S /* PME from D1 Support */
-#define PCI_PME_D0_SUP BIT_11S /* PME from D0 Support */
-#define PCI_PM_D2_SUP BIT_10S /* D2 Support in 33 MHz mode */
-#define PCI_PM_D1_SUP BIT_9S /* D1 Support */
- /* Bit 8.. 6: reserved */
-#define PCI_PM_DSI BIT_5S /* Device Specific Initialization */
-#define PCI_PM_APS BIT_4S /* Auxialiary Power Source */
-#define PCI_PME_CLOCK BIT_3S /* PM Event Clock */
-#define PCI_PM_VER_MSK 7 /* Bit 2.. 0: PM PCI Spec. version */
-
-/* PCI_PM_CTL_STS 16 bit Power Management Control/Status */
-#define PCI_PME_STATUS BIT_15S /* PME Status (YUKON only) */
-#define PCI_PM_DAT_SCL (3<<13) /* Bit 14..13: Data Reg. scaling factor */
-#define PCI_PM_DAT_SEL (0xf<<9) /* Bit 12.. 9: PM data selector field */
-#define PCI_PME_EN BIT_8S /* Enable PME# generation (YUKON only) */
- /* Bit 7.. 2: reserved */
-#define PCI_PM_STATE_MSK 3 /* Bit 1.. 0: Power Management State */
-
-#define PCI_PM_STATE_D0 0 /* D0: Operational (default) */
-#define PCI_PM_STATE_D1 1 /* D1: (YUKON only) */
-#define PCI_PM_STATE_D2 2 /* D2: (YUKON only) */
-#define PCI_PM_STATE_D3 3 /* D3: HOT, Power Down and Reset */
-
-/* VPD Region */
-/* PCI_VPD_ADR_REG 16 bit VPD Address Register */
-#define PCI_VPD_FLAG BIT_15S /* starts VPD rd/wr cycle */
-#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD address mask */
-
-/* Control Register File (Address Map) */
-
-/*
- * Bank 0
- */
-#define B0_RAP 0x0000 /* 8 bit Register Address Port */
- /* 0x0001 - 0x0003: reserved */
-#define B0_CTST 0x0004 /* 16 bit Control/Status register */
-#define B0_LED 0x0006 /* 8 Bit LED register */
-#define B0_POWER_CTRL 0x0007 /* 8 Bit Power Control reg (YUKON only) */
-#define B0_ISRC 0x0008 /* 32 bit Interrupt Source Register */
-#define B0_IMSK 0x000c /* 32 bit Interrupt Mask Register */
-#define B0_HWE_ISRC 0x0010 /* 32 bit HW Error Interrupt Src Reg */
-#define B0_HWE_IMSK 0x0014 /* 32 bit HW Error Interrupt Mask Reg */
-#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg */
- /* 0x001c: reserved */
-
-/* B0 XMAC 1 registers (GENESIS only) */
-#define B0_XM1_IMSK 0x0020 /* 16 bit r/w XMAC 1 Interrupt Mask Register*/
- /* 0x0022 - 0x0027: reserved */
-#define B0_XM1_ISRC 0x0028 /* 16 bit ro XMAC 1 Interrupt Status Reg */
- /* 0x002a - 0x002f: reserved */
-#define B0_XM1_PHY_ADDR 0x0030 /* 16 bit r/w XMAC 1 PHY Address Register */
- /* 0x0032 - 0x0033: reserved */
-#define B0_XM1_PHY_DATA 0x0034 /* 16 bit r/w XMAC 1 PHY Data Register */
- /* 0x0036 - 0x003f: reserved */
-
-/* B0 XMAC 2 registers (GENESIS only) */
-#define B0_XM2_IMSK 0x0040 /* 16 bit r/w XMAC 2 Interrupt Mask Register*/
- /* 0x0042 - 0x0047: reserved */
-#define B0_XM2_ISRC 0x0048 /* 16 bit ro XMAC 2 Interrupt Status Reg */
- /* 0x004a - 0x004f: reserved */
-#define B0_XM2_PHY_ADDR 0x0050 /* 16 bit r/w XMAC 2 PHY Address Register */
- /* 0x0052 - 0x0053: reserved */
-#define B0_XM2_PHY_DATA 0x0054 /* 16 bit r/w XMAC 2 PHY Data Register */
- /* 0x0056 - 0x005f: reserved */
-
-/* BMU Control Status Registers */
-#define B0_R1_CSR 0x0060 /* 32 bit BMU Ctrl/Stat Rx Queue 1 */
-#define B0_R2_CSR 0x0064 /* 32 bit BMU Ctrl/Stat Rx Queue 2 */
-#define B0_XS1_CSR 0x0068 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
-#define B0_XA1_CSR 0x006c /* 32 bit BMU Ctrl/Stat Async Tx Queue 1*/
-#define B0_XS2_CSR 0x0070 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
-#define B0_XA2_CSR 0x0074 /* 32 bit BMU Ctrl/Stat Async Tx Queue 2*/
- /* 0x0078 - 0x007f: reserved */
-
-/*
- * Bank 1
- * - completely empty (this is the RAP Block window)
- * Note: if RAP = 1 this page is reserved
- */
-
-/*
- * Bank 2
- */
-/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */
-#define B2_MAC_1 0x0100 /* NA reg MAC Address 1 */
- /* 0x0106 - 0x0107: reserved */
-#define B2_MAC_2 0x0108 /* NA reg MAC Address 2 */
- /* 0x010e - 0x010f: reserved */
-#define B2_MAC_3 0x0110 /* NA reg MAC Address 3 */
- /* 0x0116 - 0x0117: reserved */
-#define B2_CONN_TYP 0x0118 /* 8 bit Connector type */
-#define B2_PMD_TYP 0x0119 /* 8 bit PMD type */
-#define B2_MAC_CFG 0x011a /* 8 bit MAC Configuration / Chip Revision */
-#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */
- /* Eprom registers are currently of no use */
-#define B2_E_0 0x011c /* 8 bit EPROM Byte 0 (ext. SRAM size */
-#define B2_E_1 0x011d /* 8 bit EPROM Byte 1 (PHY type) */
-#define B2_E_2 0x011e /* 8 bit EPROM Byte 2 */
-#define B2_E_3 0x011f /* 8 bit EPROM Byte 3 */
-#define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */
-#define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */
- /* 0x0125 - 0x0127: reserved */
-#define B2_LD_CTRL 0x0128 /* 8 bit EPROM loader control register */
-#define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */
- /* 0x012a - 0x012f: reserved */
-#define B2_TI_INI 0x0130 /* 32 bit Timer Init Value */
-#define B2_TI_VAL 0x0134 /* 32 bit Timer Value */
-#define B2_TI_CTRL 0x0138 /* 8 bit Timer Control */
-#define B2_TI_TEST 0x0139 /* 8 Bit Timer Test */
- /* 0x013a - 0x013f: reserved */
-#define B2_IRQM_INI 0x0140 /* 32 bit IRQ Moderation Timer Init Reg.*/
-#define B2_IRQM_VAL 0x0144 /* 32 bit IRQ Moderation Timer Value */
-#define B2_IRQM_CTRL 0x0148 /* 8 bit IRQ Moderation Timer Control */
-#define B2_IRQM_TEST 0x0149 /* 8 bit IRQ Moderation Timer Test */
-#define B2_IRQM_MSK 0x014c /* 32 bit IRQ Moderation Mask */
-#define B2_IRQM_HWE_MSK 0x0150 /* 32 bit IRQ Moderation HW Error Mask */
- /* 0x0154 - 0x0157: reserved */
-#define B2_TST_CTRL1 0x0158 /* 8 bit Test Control Register 1 */
-#define B2_TST_CTRL2 0x0159 /* 8 bit Test Control Register 2 */
- /* 0x015a - 0x015b: reserved */
-#define B2_GP_IO 0x015c /* 32 bit General Purpose I/O Register */
-#define B2_I2C_CTRL 0x0160 /* 32 bit I2C HW Control Register */
-#define B2_I2C_DATA 0x0164 /* 32 bit I2C HW Data Register */
-#define B2_I2C_IRQ 0x0168 /* 32 bit I2C HW IRQ Register */
-#define B2_I2C_SW 0x016c /* 32 bit I2C SW Port Register */
-
-/* Blink Source Counter (GENESIS only) */
-#define B2_BSC_INI 0x0170 /* 32 bit Blink Source Counter Init Val */
-#define B2_BSC_VAL 0x0174 /* 32 bit Blink Source Counter Value */
-#define B2_BSC_CTRL 0x0178 /* 8 bit Blink Source Counter Control */
-#define B2_BSC_STAT 0x0179 /* 8 bit Blink Source Counter Status */
-#define B2_BSC_TST 0x017a /* 16 bit Blink Source Counter Test Reg */
- /* 0x017c - 0x017f: reserved */
-
-/*
- * Bank 3
- */
-/* RAM Random Registers */
-#define B3_RAM_ADDR 0x0180 /* 32 bit RAM Address, to read or write */
-#define B3_RAM_DATA_LO 0x0184 /* 32 bit RAM Data Word (low dWord) */
-#define B3_RAM_DATA_HI 0x0188 /* 32 bit RAM Data Word (high dWord) */
- /* 0x018c - 0x018f: reserved */
-
-/* RAM Interface Registers */
-/*
- * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
- * not usable in SW. Please notice these are NOT real timeouts, these are
- * the number of qWords transferred continuously.
- */
-#define B3_RI_WTO_R1 0x0190 /* 8 bit WR Timeout Queue R1 (TO0) */
-#define B3_RI_WTO_XA1 0x0191 /* 8 bit WR Timeout Queue XA1 (TO1) */
-#define B3_RI_WTO_XS1 0x0192 /* 8 bit WR Timeout Queue XS1 (TO2) */
-#define B3_RI_RTO_R1 0x0193 /* 8 bit RD Timeout Queue R1 (TO3) */
-#define B3_RI_RTO_XA1 0x0194 /* 8 bit RD Timeout Queue XA1 (TO4) */
-#define B3_RI_RTO_XS1 0x0195 /* 8 bit RD Timeout Queue XS1 (TO5) */
-#define B3_RI_WTO_R2 0x0196 /* 8 bit WR Timeout Queue R2 (TO6) */
-#define B3_RI_WTO_XA2 0x0197 /* 8 bit WR Timeout Queue XA2 (TO7) */
-#define B3_RI_WTO_XS2 0x0198 /* 8 bit WR Timeout Queue XS2 (TO8) */
-#define B3_RI_RTO_R2 0x0199 /* 8 bit RD Timeout Queue R2 (TO9) */
-#define B3_RI_RTO_XA2 0x019a /* 8 bit RD Timeout Queue XA2 (TO10)*/
-#define B3_RI_RTO_XS2 0x019b /* 8 bit RD Timeout Queue XS2 (TO11)*/
-#define B3_RI_TO_VAL 0x019c /* 8 bit Current Timeout Count Val */
- /* 0x019d - 0x019f: reserved */
-#define B3_RI_CTRL 0x01a0 /* 16 bit RAM Interface Control Register */
-#define B3_RI_TEST 0x01a2 /* 8 bit RAM Interface Test Register */
- /* 0x01a3 - 0x01af: reserved */
-
-/* MAC Arbiter Registers (GENESIS only) */
-/* these are the no. of qWord transferred continuously and NOT real timeouts */
-#define B3_MA_TOINI_RX1 0x01b0 /* 8 bit Timeout Init Val Rx Path MAC 1 */
-#define B3_MA_TOINI_RX2 0x01b1 /* 8 bit Timeout Init Val Rx Path MAC 2 */
-#define B3_MA_TOINI_TX1 0x01b2 /* 8 bit Timeout Init Val Tx Path MAC 1 */
-#define B3_MA_TOINI_TX2 0x01b3 /* 8 bit Timeout Init Val Tx Path MAC 2 */
-#define B3_MA_TOVAL_RX1 0x01b4 /* 8 bit Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_RX2 0x01b5 /* 8 bit Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_TX1 0x01b6 /* 8 bit Timeout Value Tx Path MAC 2 */
-#define B3_MA_TOVAL_TX2 0x01b7 /* 8 bit Timeout Value Tx Path MAC 2 */
-#define B3_MA_TO_CTRL 0x01b8 /* 16 bit MAC Arbiter Timeout Ctrl Reg */
-#define B3_MA_TO_TEST 0x01ba /* 16 bit MAC Arbiter Timeout Test Reg */
- /* 0x01bc - 0x01bf: reserved */
-#define B3_MA_RCINI_RX1 0x01c0 /* 8 bit Recovery Init Val Rx Path MAC 1 */
-#define B3_MA_RCINI_RX2 0x01c1 /* 8 bit Recovery Init Val Rx Path MAC 2 */
-#define B3_MA_RCINI_TX1 0x01c2 /* 8 bit Recovery Init Val Tx Path MAC 1 */
-#define B3_MA_RCINI_TX2 0x01c3 /* 8 bit Recovery Init Val Tx Path MAC 2 */
-#define B3_MA_RCVAL_RX1 0x01c4 /* 8 bit Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_RX2 0x01c5 /* 8 bit Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_TX1 0x01c6 /* 8 bit Recovery Value Tx Path MAC 2 */
-#define B3_MA_RCVAL_TX2 0x01c7 /* 8 bit Recovery Value Tx Path MAC 2 */
-#define B3_MA_RC_CTRL 0x01c8 /* 16 bit MAC Arbiter Recovery Ctrl Reg */
-#define B3_MA_RC_TEST 0x01ca /* 16 bit MAC Arbiter Recovery Test Reg */
- /* 0x01cc - 0x01cf: reserved */
-
-/* Packet Arbiter Registers (GENESIS only) */
-/* these are real timeouts */
-#define B3_PA_TOINI_RX1 0x01d0 /* 16 bit Timeout Init Val Rx Path MAC 1 */
- /* 0x01d2 - 0x01d3: reserved */
-#define B3_PA_TOINI_RX2 0x01d4 /* 16 bit Timeout Init Val Rx Path MAC 2 */
- /* 0x01d6 - 0x01d7: reserved */
-#define B3_PA_TOINI_TX1 0x01d8 /* 16 bit Timeout Init Val Tx Path MAC 1 */
- /* 0x01da - 0x01db: reserved */
-#define B3_PA_TOINI_TX2 0x01dc /* 16 bit Timeout Init Val Tx Path MAC 2 */
- /* 0x01de - 0x01df: reserved */
-#define B3_PA_TOVAL_RX1 0x01e0 /* 16 bit Timeout Val Rx Path MAC 1 */
- /* 0x01e2 - 0x01e3: reserved */
-#define B3_PA_TOVAL_RX2 0x01e4 /* 16 bit Timeout Val Rx Path MAC 2 */
- /* 0x01e6 - 0x01e7: reserved */
-#define B3_PA_TOVAL_TX1 0x01e8 /* 16 bit Timeout Val Tx Path MAC 1 */
- /* 0x01ea - 0x01eb: reserved */
-#define B3_PA_TOVAL_TX2 0x01ec /* 16 bit Timeout Val Tx Path MAC 2 */
- /* 0x01ee - 0x01ef: reserved */
-#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */
-#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */
- /* 0x01f4 - 0x01ff: reserved */
-
-/*
- * Bank 4 - 5
- */
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-#define TXA_ITI_INI 0x0200 /* 32 bit Tx Arb Interval Timer Init Val*/
-#define TXA_ITI_VAL 0x0204 /* 32 bit Tx Arb Interval Timer Value */
-#define TXA_LIM_INI 0x0208 /* 32 bit Tx Arb Limit Counter Init Val */
-#define TXA_LIM_VAL 0x020c /* 32 bit Tx Arb Limit Counter Value */
-#define TXA_CTRL 0x0210 /* 8 bit Tx Arbiter Control Register */
-#define TXA_TEST 0x0211 /* 8 bit Tx Arbiter Test Register */
-#define TXA_STAT 0x0212 /* 8 bit Tx Arbiter Status Register */
- /* 0x0213 - 0x027f: reserved */
- /* 0x0280 - 0x0292: MAC 2 */
- /* 0x0213 - 0x027f: reserved */
-
-/*
- * Bank 6
- */
-/* External registers (GENESIS only) */
-#define B6_EXT_REG 0x0300
-
-/*
- * Bank 7
- */
-/* This is a copy of the Configuration register file (lower half) */
-#define B7_CFG_SPC 0x0380
-
-/*
- * Bank 8 - 15
- */
-/* Receive and Transmit Queue Registers, use Q_ADDR() to access */
-#define B8_Q_REGS 0x0400
-
-/* Queue Register Offsets, use Q_ADDR() to access */
-#define Q_D 0x00 /* 8*32 bit Current Descriptor */
-#define Q_DA_L 0x20 /* 32 bit Current Descriptor Address Low dWord */
-#define Q_DA_H 0x24 /* 32 bit Current Descriptor Address High dWord */
-#define Q_AC_L 0x28 /* 32 bit Current Address Counter Low dWord */
-#define Q_AC_H 0x2c /* 32 bit Current Address Counter High dWord */
-#define Q_BC 0x30 /* 32 bit Current Byte Counter */
-#define Q_CSR 0x34 /* 32 bit BMU Control/Status Register */
-#define Q_F 0x38 /* 32 bit Flag Register */
-#define Q_T1 0x3c /* 32 bit Test Register 1 */
-#define Q_T1_TR 0x3c /* 8 bit Test Register 1 Transfer SM */
-#define Q_T1_WR 0x3d /* 8 bit Test Register 1 Write Descriptor SM */
-#define Q_T1_RD 0x3e /* 8 bit Test Register 1 Read Descriptor SM */
-#define Q_T1_SV 0x3f /* 8 bit Test Register 1 Supervisor SM */
-#define Q_T2 0x40 /* 32 bit Test Register 2 */
-#define Q_T3 0x44 /* 32 bit Test Register 3 */
- /* 0x48 - 0x7f: reserved */
-
-/*
- * Bank 16 - 23
- */
-/* RAM Buffer Registers */
-#define B16_RAM_REGS 0x0800
-
-/* RAM Buffer Register Offsets, use RB_ADDR() to access */
-#define RB_START 0x00 /* 32 bit RAM Buffer Start Address */
-#define RB_END 0x04 /* 32 bit RAM Buffer End Address */
-#define RB_WP 0x08 /* 32 bit RAM Buffer Write Pointer */
-#define RB_RP 0x0c /* 32 bit RAM Buffer Read Pointer */
-#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Pack */
-#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Pack */
-#define RB_RX_UTHP 0x18 /* 32 bit Rx Upper Threshold, High Prio */
-#define RB_RX_LTHP 0x1c /* 32 bit Rx Lower Threshold, High Prio */
- /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */
-#define RB_PC 0x20 /* 32 bit RAM Buffer Packet Counter */
-#define RB_LEV 0x24 /* 32 bit RAM Buffer Level Register */
-#define RB_CTRL 0x28 /* 8 bit RAM Buffer Control Register */
-#define RB_TST1 0x29 /* 8 bit RAM Buffer Test Register 1 */
-#define RB_TST2 0x2A /* 8 bit RAM Buffer Test Register 2 */
- /* 0x2c - 0x7f: reserved */
-
-/*
- * Bank 24
- */
-/*
- * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only)
- * use MR_ADDR() to access
- */
-#define RX_MFF_EA 0x0c00 /* 32 bit Receive MAC FIFO End Address */
-#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */
- /* 0x0c08 - 0x0c0b: reserved */
-#define RX_MFF_RP 0x0c0c /* 32 bit Receive MAC FIFO Read Pointer */
-#define RX_MFF_PC 0x0c10 /* 32 bit Receive MAC FIFO Packet Cnt */
-#define RX_MFF_LEV 0x0c14 /* 32 bit Receive MAC FIFO Level */
-#define RX_MFF_CTRL1 0x0c18 /* 16 bit Receive MAC FIFO Control Reg 1*/
-#define RX_MFF_STAT_TO 0x0c1a /* 8 bit Receive MAC Status Timeout */
-#define RX_MFF_TIST_TO 0x0c1b /* 8 bit Receive MAC Time Stamp Timeout */
-#define RX_MFF_CTRL2 0x0c1c /* 8 bit Receive MAC FIFO Control Reg 2*/
-#define RX_MFF_TST1 0x0c1d /* 8 bit Receive MAC FIFO Test Reg 1 */
-#define RX_MFF_TST2 0x0c1e /* 8 bit Receive MAC FIFO Test Reg 2 */
- /* 0x0c1f: reserved */
-#define RX_LED_INI 0x0c20 /* 32 bit Receive LED Cnt Init Value */
-#define RX_LED_VAL 0x0c24 /* 32 bit Receive LED Cnt Current Value */
-#define RX_LED_CTRL 0x0c28 /* 8 bit Receive LED Cnt Control Reg */
-#define RX_LED_TST 0x0c29 /* 8 bit Receive LED Cnt Test Register */
- /* 0x0c2a - 0x0c2f: reserved */
-#define LNK_SYNC_INI 0x0c30 /* 32 bit Link Sync Cnt Init Value */
-#define LNK_SYNC_VAL 0x0c34 /* 32 bit Link Sync Cnt Current Value */
-#define LNK_SYNC_CTRL 0x0c38 /* 8 bit Link Sync Cnt Control Register */
-#define LNK_SYNC_TST 0x0c39 /* 8 bit Link Sync Cnt Test Register */
- /* 0x0c3a - 0x0c3b: reserved */
-#define LNK_LED_REG 0x0c3c /* 8 bit Link LED Register */
- /* 0x0c3d - 0x0c3f: reserved */
-
-/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define RX_GMF_EA 0x0c40 /* 32 bit Rx GMAC FIFO End Address */
-#define RX_GMF_AF_THR 0x0c44 /* 32 bit Rx GMAC FIFO Almost Full Thresh. */
-#define RX_GMF_CTRL_T 0x0c48 /* 32 bit Rx GMAC FIFO Control/Test */
-#define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */
-#define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */
- /* 0x0c54 - 0x0c5f: reserved */
-#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */
- /* 0x0c64 - 0x0c67: reserved */
-#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */
- /* 0x0c6c - 0x0c6f: reserved */
-#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */
- /* 0x0c74 - 0x0c77: reserved */
-#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */
- /* 0x0c7c - 0x0c7f: reserved */
-
-/*
- * Bank 25
- */
- /* 0x0c80 - 0x0cbf: MAC 2 */
- /* 0x0cc0 - 0x0cff: reserved */
-
-/*
- * Bank 26
- */
-/*
- * Transmit MAC FIFO and Transmit LED Registers (GENESIS only),
- * use MR_ADDR() to access
- */
-#define TX_MFF_EA 0x0d00 /* 32 bit Transmit MAC FIFO End Address */
-#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */
-#define TX_MFF_WSP 0x0d08 /* 32 bit Transmit MAC FIFO WR Shadow Ptr */
-#define TX_MFF_RP 0x0d0c /* 32 bit Transmit MAC FIFO RD Pointer */
-#define TX_MFF_PC 0x0d10 /* 32 bit Transmit MAC FIFO Packet Cnt */
-#define TX_MFF_LEV 0x0d14 /* 32 bit Transmit MAC FIFO Level */
-#define TX_MFF_CTRL1 0x0d18 /* 16 bit Transmit MAC FIFO Ctrl Reg 1 */
-#define TX_MFF_WAF 0x0d1a /* 8 bit Transmit MAC Wait after flush */
- /* 0x0c1b: reserved */
-#define TX_MFF_CTRL2 0x0d1c /* 8 bit Transmit MAC FIFO Ctrl Reg 2 */
-#define TX_MFF_TST1 0x0d1d /* 8 bit Transmit MAC FIFO Test Reg 1 */
-#define TX_MFF_TST2 0x0d1e /* 8 bit Transmit MAC FIFO Test Reg 2 */
- /* 0x0d1f: reserved */
-#define TX_LED_INI 0x0d20 /* 32 bit Transmit LED Cnt Init Value */
-#define TX_LED_VAL 0x0d24 /* 32 bit Transmit LED Cnt Current Val */
-#define TX_LED_CTRL 0x0d28 /* 8 bit Transmit LED Cnt Control Reg */
-#define TX_LED_TST 0x0d29 /* 8 bit Transmit LED Cnt Test Reg */
- /* 0x0d2a - 0x0d3f: reserved */
-
-/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define TX_GMF_EA 0x0d40 /* 32 bit Tx GMAC FIFO End Address */
-#define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
-#define TX_GMF_CTRL_T 0x0d48 /* 32 bit Tx GMAC FIFO Control/Test */
- /* 0x0d4c - 0x0d5f: reserved */
-#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */
-#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Ptr. */
-#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */
- /* 0x0d6c - 0x0d6f: reserved */
-#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */
-#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */
-#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */
- /* 0x0d7c - 0x0d7f: reserved */
-
-/*
- * Bank 27
- */
- /* 0x0d80 - 0x0dbf: MAC 2 */
- /* 0x0daa - 0x0dff: reserved */
-
-/*
- * Bank 28
- */
-/* Descriptor Poll Timer Registers */
-#define B28_DPT_INI 0x0e00 /* 24 bit Descriptor Poll Timer Init Val */
-#define B28_DPT_VAL 0x0e04 /* 24 bit Descriptor Poll Timer Curr Val */
-#define B28_DPT_CTRL 0x0e08 /* 8 bit Descriptor Poll Timer Ctrl Reg */
- /* 0x0e09: reserved */
-#define B28_DPT_TST 0x0e0a /* 8 bit Descriptor Poll Timer Test Reg */
- /* 0x0e0b: reserved */
-
-/* Time Stamp Timer Registers (YUKON only) */
- /* 0x0e10: reserved */
-#define GMAC_TI_ST_VAL 0x0e14 /* 32 bit Time Stamp Timer Curr Val */
-#define GMAC_TI_ST_CTRL 0x0e18 /* 8 bit Time Stamp Timer Ctrl Reg */
- /* 0x0e19: reserved */
-#define GMAC_TI_ST_TST 0x0e1a /* 8 bit Time Stamp Timer Test Reg */
- /* 0x0e1b - 0x0e7f: reserved */
-
-/*
- * Bank 29
- */
- /* 0x0e80 - 0x0efc: reserved */
-
-/*
- * Bank 30
- */
-/* GMAC and GPHY Control Registers (YUKON only) */
-#define GMAC_CTRL 0x0f00 /* 32 bit GMAC Control Reg */
-#define GPHY_CTRL 0x0f04 /* 32 bit GPHY Control Reg */
-#define GMAC_IRQ_SRC 0x0f08 /* 8 bit GMAC Interrupt Source Reg */
- /* 0x0f09 - 0x0f0b: reserved */
-#define GMAC_IRQ_MSK 0x0f0c /* 8 bit GMAC Interrupt Mask Reg */
- /* 0x0f0d - 0x0f0f: reserved */
-#define GMAC_LINK_CTRL 0x0f10 /* 16 bit Link Control Reg */
- /* 0x0f14 - 0x0f1f: reserved */
-
-/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
-
-#define WOL_REG_OFFS 0x20 /* HW-Bug: Address is + 0x20 against spec. */
-
-#define WOL_CTRL_STAT 0x0f20 /* 16 bit WOL Control/Status Reg */
-#define WOL_MATCH_CTL 0x0f22 /* 8 bit WOL Match Control Reg */
-#define WOL_MATCH_RES 0x0f23 /* 8 bit WOL Match Result Reg */
-#define WOL_MAC_ADDR_LO 0x0f24 /* 32 bit WOL MAC Address Low */
-#define WOL_MAC_ADDR_HI 0x0f28 /* 16 bit WOL MAC Address High */
-#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Ptr */
-
-/* use this macro to access above registers */
-#define WOL_REG(Reg) ((Reg) + (pAC->GIni.GIWolOffs))
-
-
-/* WOL Pattern Length Registers (YUKON only) */
-
-#define WOL_PATT_LEN_LO 0x0f30 /* 32 bit WOL Pattern Length 3..0 */
-#define WOL_PATT_LEN_HI 0x0f34 /* 24 bit WOL Pattern Length 6..4 */
-
-/* WOL Pattern Counter Registers (YUKON only) */
-
-#define WOL_PATT_CNT_0 0x0f38 /* 32 bit WOL Pattern Counter 3..0 */
-#define WOL_PATT_CNT_4 0x0f3c /* 24 bit WOL Pattern Counter 6..4 */
- /* 0x0f40 - 0x0f7f: reserved */
-
-/*
- * Bank 31
- */
-/* 0x0f80 - 0x0fff: reserved */
-
-/*
- * Bank 32 - 33
- */
-#define WOL_PATT_RAM_1 0x1000 /* WOL Pattern RAM Link 1 */
-
-/*
- * Bank 0x22 - 0x3f
- */
-/* 0x1100 - 0x1fff: reserved */
-
-/*
- * Bank 0x40 - 0x4f
- */
-#define BASE_XMAC_1 0x2000 /* XMAC 1 registers */
-
-/*
- * Bank 0x50 - 0x5f
- */
-
-#define BASE_GMAC_1 0x2800 /* GMAC 1 registers */
-
-/*
- * Bank 0x60 - 0x6f
- */
-#define BASE_XMAC_2 0x3000 /* XMAC 2 registers */
-
-/*
- * Bank 0x70 - 0x7f
- */
-#define BASE_GMAC_2 0x3800 /* GMAC 2 registers */
-
-/*
- * Control Register Bit Definitions:
- */
-/* B0_RAP 8 bit Register Address Port */
- /* Bit 7: reserved */
-#define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */
-
-/* B0_CTST 16 bit Control/Status register */
- /* Bit 15..14: reserved */
-#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */
-#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */
-#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN enable (YUKON-Lite only) */
-#define CS_VAUX_AVAIL BIT_10S /* VAUX available (YUKON only) */
-#define CS_BUS_CLOCK BIT_9S /* Bus Clock 0/1 = 33/66 MHz */
-#define CS_BUS_SLOT_SZ BIT_8S /* Slot Size 0/1 = 32/64 bit slot */
-#define CS_ST_SW_IRQ BIT_7S /* Set IRQ SW Request */
-#define CS_CL_SW_IRQ BIT_6S /* Clear IRQ SW Request */
-#define CS_STOP_DONE BIT_5S /* Stop Master is finished */
-#define CS_STOP_MAST BIT_4S /* Command Bit to stop the master */
-#define CS_MRST_CLR BIT_3S /* Clear Master reset */
-#define CS_MRST_SET BIT_2S /* Set Master reset */
-#define CS_RST_CLR BIT_1S /* Clear Software reset */
-#define CS_RST_SET BIT_0S /* Set Software reset */
-
-/* B0_LED 8 Bit LED register */
- /* Bit 7.. 2: reserved */
-#define LED_STAT_ON BIT_1S /* Status LED on */
-#define LED_STAT_OFF BIT_0S /* Status LED off */
-
-/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */
-#define PC_VAUX_ENA BIT_7 /* Switch VAUX Enable */
-#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */
-#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */
-#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */
-#define PC_VAUX_ON BIT_3 /* Switch VAUX On */
-#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */
-#define PC_VCC_ON BIT_1 /* Switch VCC On */
-#define PC_VCC_OFF BIT_0 /* Switch VCC Off */
-
-/* B0_ISRC 32 bit Interrupt Source Register */
-/* B0_IMSK 32 bit Interrupt Mask Register */
-/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */
-/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */
-#define IS_ALL_MSK 0xbfffffffUL /* All Interrupt bits */
-#define IS_HW_ERR BIT_31 /* Interrupt HW Error */
- /* Bit 30: reserved */
-#define IS_PA_TO_RX1 BIT_29 /* Packet Arb Timeout Rx1 */
-#define IS_PA_TO_RX2 BIT_28 /* Packet Arb Timeout Rx2 */
-#define IS_PA_TO_TX1 BIT_27 /* Packet Arb Timeout Tx1 */
-#define IS_PA_TO_TX2 BIT_26 /* Packet Arb Timeout Tx2 */
-#define IS_I2C_READY BIT_25 /* IRQ on end of I2C Tx */
-#define IS_IRQ_SW BIT_24 /* SW forced IRQ */
-#define IS_EXT_REG BIT_23 /* IRQ from LM80 or PHY (GENESIS only) */
- /* IRQ from PHY (YUKON only) */
-#define IS_TIMINT BIT_22 /* IRQ from Timer */
-#define IS_MAC1 BIT_21 /* IRQ from MAC 1 */
-#define IS_LNK_SYNC_M1 BIT_20 /* Link Sync Cnt wrap MAC 1 */
-#define IS_MAC2 BIT_19 /* IRQ from MAC 2 */
-#define IS_LNK_SYNC_M2 BIT_18 /* Link Sync Cnt wrap MAC 2 */
-/* Receive Queue 1 */
-#define IS_R1_B BIT_17 /* Q_R1 End of Buffer */
-#define IS_R1_F BIT_16 /* Q_R1 End of Frame */
-#define IS_R1_C BIT_15 /* Q_R1 Encoding Error */
-/* Receive Queue 2 */
-#define IS_R2_B BIT_14 /* Q_R2 End of Buffer */
-#define IS_R2_F BIT_13 /* Q_R2 End of Frame */
-#define IS_R2_C BIT_12 /* Q_R2 Encoding Error */
-/* Synchronous Transmit Queue 1 */
-#define IS_XS1_B BIT_11 /* Q_XS1 End of Buffer */
-#define IS_XS1_F BIT_10 /* Q_XS1 End of Frame */
-#define IS_XS1_C BIT_9 /* Q_XS1 Encoding Error */
-/* Asynchronous Transmit Queue 1 */
-#define IS_XA1_B BIT_8 /* Q_XA1 End of Buffer */
-#define IS_XA1_F BIT_7 /* Q_XA1 End of Frame */
-#define IS_XA1_C BIT_6 /* Q_XA1 Encoding Error */
-/* Synchronous Transmit Queue 2 */
-#define IS_XS2_B BIT_5 /* Q_XS2 End of Buffer */
-#define IS_XS2_F BIT_4 /* Q_XS2 End of Frame */
-#define IS_XS2_C BIT_3 /* Q_XS2 Encoding Error */
-/* Asynchronous Transmit Queue 2 */
-#define IS_XA2_B BIT_2 /* Q_XA2 End of Buffer */
-#define IS_XA2_F BIT_1 /* Q_XA2 End of Frame */
-#define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */
-
-
-/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */
-/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */
-/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
-#define IS_ERR_MSK 0x00000fffL /* All Error bits */
- /* Bit 31..14: reserved */
-#define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */
-#define IS_IRQ_SENSOR BIT_12 /* IRQ from Sensor (YUKON only) */
-#define IS_IRQ_MST_ERR BIT_11 /* IRQ master error detected */
-#define IS_IRQ_STAT BIT_10 /* IRQ status exception */
-#define IS_NO_STAT_M1 BIT_9 /* No Rx Status from MAC 1 */
-#define IS_NO_STAT_M2 BIT_8 /* No Rx Status from MAC 2 */
-#define IS_NO_TIST_M1 BIT_7 /* No Time Stamp from MAC 1 */
-#define IS_NO_TIST_M2 BIT_6 /* No Time Stamp from MAC 2 */
-#define IS_RAM_RD_PAR BIT_5 /* RAM Read Parity Error */
-#define IS_RAM_WR_PAR BIT_4 /* RAM Write Parity Error */
-#define IS_M1_PAR_ERR BIT_3 /* MAC 1 Parity Error */
-#define IS_M2_PAR_ERR BIT_2 /* MAC 2 Parity Error */
-#define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */
-#define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */
-
-/* B2_CONN_TYP 8 bit Connector type */
-/* B2_PMD_TYP 8 bit PMD type */
-/* Values of connector and PMD type comply to SysKonnect internal std */
-
-/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
-#define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */
- /* Bit 3.. 2: reserved */
-#define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */
-#define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/
-
-/* B2_CHIP_ID 8 bit Chip Identification Number */
-#define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */
-#define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */
-#define CHIP_ID_YUKON_LITE 0xb1 /* Chip ID for YUKON-Lite (Rev. A1-A3) */
-#define CHIP_ID_YUKON_LP 0xb2 /* Chip ID for YUKON-LP */
-
-#define CHIP_REV_YU_LITE_A1 3 /* Chip Rev. for YUKON-Lite A1,A2 */
-#define CHIP_REV_YU_LITE_A3 7 /* Chip Rev. for YUKON-Lite A3 */
-
-/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */
-#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */
-
-/* B2_LD_CTRL 8 bit EPROM loader control register */
-/* Bits are currently reserved */
-
-/* B2_LD_TEST 8 bit EPROM loader test register */
- /* Bit 7.. 4: reserved */
-#define LD_T_ON BIT_3S /* Loader Test mode on */
-#define LD_T_OFF BIT_2S /* Loader Test mode off */
-#define LD_T_STEP BIT_1S /* Decrement FPROM addr. Counter */
-#define LD_START BIT_0S /* Start loading FPROM */
-
-/*
- * Timer Section
- */
-/* B2_TI_CTRL 8 bit Timer control */
-/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */
- /* Bit 7.. 3: reserved */
-#define TIM_START BIT_2S /* Start Timer */
-#define TIM_STOP BIT_1S /* Stop Timer */
-#define TIM_CLR_IRQ BIT_0S /* Clear Timer IRQ (!IRQM) */
-
-/* B2_TI_TEST 8 Bit Timer Test */
-/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */
-/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */
- /* Bit 7.. 3: reserved */
-#define TIM_T_ON BIT_2S /* Test mode on */
-#define TIM_T_OFF BIT_1S /* Test mode off */
-#define TIM_T_STEP BIT_0S /* Test step */
-
-/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */
-/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */
- /* Bit 31..24: reserved */
-#define DPT_MSK 0x00ffffffL /* Bit 23.. 0: Desc Poll Timer Bits */
-
-/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */
- /* Bit 7.. 2: reserved */
-#define DPT_START BIT_1S /* Start Descriptor Poll Timer */
-#define DPT_STOP BIT_0S /* Stop Descriptor Poll Timer */
-
-/* B2_E_3 8 bit lower 4 bits used for HW self test result */
-#define B2_E3_RES_MASK 0x0f
-
-/* B2_TST_CTRL1 8 bit Test Control Register 1 */
-#define TST_FRC_DPERR_MR BIT_7S /* force DATAPERR on MST RD */
-#define TST_FRC_DPERR_MW BIT_6S /* force DATAPERR on MST WR */
-#define TST_FRC_DPERR_TR BIT_5S /* force DATAPERR on TRG RD */
-#define TST_FRC_DPERR_TW BIT_4S /* force DATAPERR on TRG WR */
-#define TST_FRC_APERR_M BIT_3S /* force ADDRPERR on MST */
-#define TST_FRC_APERR_T BIT_2S /* force ADDRPERR on TRG */
-#define TST_CFG_WRITE_ON BIT_1S /* Enable Config Reg WR */
-#define TST_CFG_WRITE_OFF BIT_0S /* Disable Config Reg WR */
-
-/* B2_TST_CTRL2 8 bit Test Control Register 2 */
- /* Bit 7.. 4: reserved */
- /* force the following error on the next master read/write */
-#define TST_FRC_DPERR_MR64 BIT_3S /* DataPERR RD 64 */
-#define TST_FRC_DPERR_MW64 BIT_2S /* DataPERR WR 64 */
-#define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */
-#define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */
-
-/* B2_GP_IO 32 bit General Purpose I/O Register */
- /* Bit 31..26: reserved */
-#define GP_DIR_9 BIT_25 /* IO_9 direct, 0=In/1=Out */
-#define GP_DIR_8 BIT_24 /* IO_8 direct, 0=In/1=Out */
-#define GP_DIR_7 BIT_23 /* IO_7 direct, 0=In/1=Out */
-#define GP_DIR_6 BIT_22 /* IO_6 direct, 0=In/1=Out */
-#define GP_DIR_5 BIT_21 /* IO_5 direct, 0=In/1=Out */
-#define GP_DIR_4 BIT_20 /* IO_4 direct, 0=In/1=Out */
-#define GP_DIR_3 BIT_19 /* IO_3 direct, 0=In/1=Out */
-#define GP_DIR_2 BIT_18 /* IO_2 direct, 0=In/1=Out */
-#define GP_DIR_1 BIT_17 /* IO_1 direct, 0=In/1=Out */
-#define GP_DIR_0 BIT_16 /* IO_0 direct, 0=In/1=Out */
- /* Bit 15..10: reserved */
-#define GP_IO_9 BIT_9 /* IO_9 pin */
-#define GP_IO_8 BIT_8 /* IO_8 pin */
-#define GP_IO_7 BIT_7 /* IO_7 pin */
-#define GP_IO_6 BIT_6 /* IO_6 pin */
-#define GP_IO_5 BIT_5 /* IO_5 pin */
-#define GP_IO_4 BIT_4 /* IO_4 pin */
-#define GP_IO_3 BIT_3 /* IO_3 pin */
-#define GP_IO_2 BIT_2 /* IO_2 pin */
-#define GP_IO_1 BIT_1 /* IO_1 pin */
-#define GP_IO_0 BIT_0 /* IO_0 pin */
-
-/* B2_I2C_CTRL 32 bit I2C HW Control Register */
-#define I2C_FLAG BIT_31 /* Start read/write if WR */
-#define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be RD/WR */
-#define I2C_DEV_SEL (0x7fL<<9) /* Bit 15.. 9: I2C Device Select */
- /* Bit 8.. 5: reserved */
-#define I2C_BURST_LEN BIT_4 /* Burst Len, 1/4 bytes */
-#define I2C_DEV_SIZE (7<<1) /* Bit 3.. 1: I2C Device Size */
-#define I2C_025K_DEV (0<<1) /* 0: 256 Bytes or smal. */
-#define I2C_05K_DEV (1<<1) /* 1: 512 Bytes */
-#define I2C_1K_DEV (2<<1) /* 2: 1024 Bytes */
-#define I2C_2K_DEV (3<<1) /* 3: 2048 Bytes */
-#define I2C_4K_DEV (4<<1) /* 4: 4096 Bytes */
-#define I2C_8K_DEV (5<<1) /* 5: 8192 Bytes */
-#define I2C_16K_DEV (6<<1) /* 6: 16384 Bytes */
-#define I2C_32K_DEV (7<<1) /* 7: 32768 Bytes */
-#define I2C_STOP BIT_0 /* Interrupt I2C transfer */
-
-/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */
- /* Bit 31.. 1 reserved */
-#define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */
-
-/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */
- /* Bit 7.. 3: reserved */
-#define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */
-#define I2C_DATA BIT_1S /* I2C Data Port */
-#define I2C_CLK BIT_0S /* I2C Clock Port */
-
-/*
- * I2C Address
- */
-#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/
-
-
-/* B2_BSC_CTRL 8 bit Blink Source Counter Control */
- /* Bit 7.. 2: reserved */
-#define BSC_START BIT_1S /* Start Blink Source Counter */
-#define BSC_STOP BIT_0S /* Stop Blink Source Counter */
-
-/* B2_BSC_STAT 8 bit Blink Source Counter Status */
- /* Bit 7.. 1: reserved */
-#define BSC_SRC BIT_0S /* Blink Source, 0=Off / 1=On */
-
-/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */
-#define BSC_T_ON BIT_2S /* Test mode on */
-#define BSC_T_OFF BIT_1S /* Test mode off */
-#define BSC_T_STEP BIT_0S /* Test step */
-
-
-/* B3_RAM_ADDR 32 bit RAM Address, to read or write */
- /* Bit 31..19: reserved */
-#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */
-
-/* RAM Interface Registers */
-/* B3_RI_CTRL 16 bit RAM Iface Control Register */
- /* Bit 15..10: reserved */
-#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */
-#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/
- /* Bit 7.. 2: reserved */
-#define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */
-#define RI_RST_SET BIT_0S /* Set RAM Interface Reset */
-
-/* B3_RI_TEST 8 bit RAM Iface Test Register */
- /* Bit 15.. 4: reserved */
-#define RI_T_EV BIT_3S /* Timeout Event occured */
-#define RI_T_ON BIT_2S /* Timeout Timer Test On */
-#define RI_T_OFF BIT_1S /* Timeout Timer Test Off */
-#define RI_T_STEP BIT_0S /* Timeout Timer Step */
-
-/* MAC Arbiter Registers */
-/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */
- /* Bit 15.. 4: reserved */
-#define MA_FOE_ON BIT_3S /* XMAC Fast Output Enable ON */
-#define MA_FOE_OFF BIT_2S /* XMAC Fast Output Enable OFF */
-#define MA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */
-#define MA_RST_SET BIT_0S /* Set MAC Arbiter Reset */
-
-/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */
- /* Bit 15.. 8: reserved */
-#define MA_ENA_REC_TX2 BIT_7S /* Enable Recovery Timer TX2 */
-#define MA_DIS_REC_TX2 BIT_6S /* Disable Recovery Timer TX2 */
-#define MA_ENA_REC_TX1 BIT_5S /* Enable Recovery Timer TX1 */
-#define MA_DIS_REC_TX1 BIT_4S /* Disable Recovery Timer TX1 */
-#define MA_ENA_REC_RX2 BIT_3S /* Enable Recovery Timer RX2 */
-#define MA_DIS_REC_RX2 BIT_2S /* Disable Recovery Timer RX2 */
-#define MA_ENA_REC_RX1 BIT_1S /* Enable Recovery Timer RX1 */
-#define MA_DIS_REC_RX1 BIT_0S /* Disable Recovery Timer RX1 */
-
-/* Packet Arbiter Registers */
-/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */
- /* Bit 15..14: reserved */
-#define PA_CLR_TO_TX2 BIT_13S /* Clear IRQ Packet Timeout TX2 */
-#define PA_CLR_TO_TX1 BIT_12S /* Clear IRQ Packet Timeout TX1 */
-#define PA_CLR_TO_RX2 BIT_11S /* Clear IRQ Packet Timeout RX2 */
-#define PA_CLR_TO_RX1 BIT_10S /* Clear IRQ Packet Timeout RX1 */
-#define PA_ENA_TO_TX2 BIT_9S /* Enable Timeout Timer TX2 */
-#define PA_DIS_TO_TX2 BIT_8S /* Disable Timeout Timer TX2 */
-#define PA_ENA_TO_TX1 BIT_7S /* Enable Timeout Timer TX1 */
-#define PA_DIS_TO_TX1 BIT_6S /* Disable Timeout Timer TX1 */
-#define PA_ENA_TO_RX2 BIT_5S /* Enable Timeout Timer RX2 */
-#define PA_DIS_TO_RX2 BIT_4S /* Disable Timeout Timer RX2 */
-#define PA_ENA_TO_RX1 BIT_3S /* Enable Timeout Timer RX1 */
-#define PA_DIS_TO_RX1 BIT_2S /* Disable Timeout Timer RX1 */
-#define PA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */
-#define PA_RST_SET BIT_0S /* Set MAC Arbiter Reset */
-
-#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
- PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
-
-/* Rx/Tx Path related Arbiter Test Registers */
-/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */
-/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */
-/* B3_PA_TEST 16 bit Packet Arbiter Test Register */
-/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
-#define TX2_T_EV BIT_15S /* TX2 Timeout/Recv Event occured */
-#define TX2_T_ON BIT_14S /* TX2 Timeout/Recv Timer Test On */
-#define TX2_T_OFF BIT_13S /* TX2 Timeout/Recv Timer Tst Off */
-#define TX2_T_STEP BIT_12S /* TX2 Timeout/Recv Timer Step */
-#define TX1_T_EV BIT_11S /* TX1 Timeout/Recv Event occured */
-#define TX1_T_ON BIT_10S /* TX1 Timeout/Recv Timer Test On */
-#define TX1_T_OFF BIT_9S /* TX1 Timeout/Recv Timer Tst Off */
-#define TX1_T_STEP BIT_8S /* TX1 Timeout/Recv Timer Step */
-#define RX2_T_EV BIT_7S /* RX2 Timeout/Recv Event occured */
-#define RX2_T_ON BIT_6S /* RX2 Timeout/Recv Timer Test On */
-#define RX2_T_OFF BIT_5S /* RX2 Timeout/Recv Timer Tst Off */
-#define RX2_T_STEP BIT_4S /* RX2 Timeout/Recv Timer Step */
-#define RX1_T_EV BIT_3S /* RX1 Timeout/Recv Event occured */
-#define RX1_T_ON BIT_2S /* RX1 Timeout/Recv Timer Test On */
-#define RX1_T_OFF BIT_1S /* RX1 Timeout/Recv Timer Tst Off */
-#define RX1_T_STEP BIT_0S /* RX1 Timeout/Recv Timer Step */
-
-
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */
-/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */
-/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */
-/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */
- /* Bit 31..24: reserved */
-#define TXA_MAX_VAL 0x00ffffffUL/* Bit 23.. 0: Max TXA Timer/Cnt Val */
-
-/* TXA_CTRL 8 bit Tx Arbiter Control Register */
-#define TXA_ENA_FSYNC BIT_7S /* Enable force of sync Tx queue */
-#define TXA_DIS_FSYNC BIT_6S /* Disable force of sync Tx queue */
-#define TXA_ENA_ALLOC BIT_5S /* Enable alloc of free bandwidth */
-#define TXA_DIS_ALLOC BIT_4S /* Disable alloc of free bandwidth */
-#define TXA_START_RC BIT_3S /* Start sync Rate Control */
-#define TXA_STOP_RC BIT_2S /* Stop sync Rate Control */
-#define TXA_ENA_ARB BIT_1S /* Enable Tx Arbiter */
-#define TXA_DIS_ARB BIT_0S /* Disable Tx Arbiter */
-
-/* TXA_TEST 8 bit Tx Arbiter Test Register */
- /* Bit 7.. 6: reserved */
-#define TXA_INT_T_ON BIT_5S /* Tx Arb Interval Timer Test On */
-#define TXA_INT_T_OFF BIT_4S /* Tx Arb Interval Timer Test Off */
-#define TXA_INT_T_STEP BIT_3S /* Tx Arb Interval Timer Step */
-#define TXA_LIM_T_ON BIT_2S /* Tx Arb Limit Timer Test On */
-#define TXA_LIM_T_OFF BIT_1S /* Tx Arb Limit Timer Test Off */
-#define TXA_LIM_T_STEP BIT_0S /* Tx Arb Limit Timer Step */
-
-/* TXA_STAT 8 bit Tx Arbiter Status Register */
- /* Bit 7.. 1: reserved */
-#define TXA_PRIO_XS BIT_0S /* sync queue has prio to send */
-
-/* Q_BC 32 bit Current Byte Counter */
- /* Bit 31..16: reserved */
-#define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */
-
-/* BMU Control Status Registers */
-/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */
-/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */
-/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
-/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */
-/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
-/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */
-/* Q_CSR 32 bit BMU Control/Status Register */
- /* Bit 31..25: reserved */
-#define CSR_SV_IDLE BIT_24 /* BMU SM Idle */
- /* Bit 23..22: reserved */
-#define CSR_DESC_CLR BIT_21 /* Clear Reset for Descr */
-#define CSR_DESC_SET BIT_20 /* Set Reset for Descr */
-#define CSR_FIFO_CLR BIT_19 /* Clear Reset for FIFO */
-#define CSR_FIFO_SET BIT_18 /* Set Reset for FIFO */
-#define CSR_HPI_RUN BIT_17 /* Release HPI SM */
-#define CSR_HPI_RST BIT_16 /* Reset HPI SM to Idle */
-#define CSR_SV_RUN BIT_15 /* Release Supervisor SM */
-#define CSR_SV_RST BIT_14 /* Reset Supervisor SM */
-#define CSR_DREAD_RUN BIT_13 /* Release Descr Read SM */
-#define CSR_DREAD_RST BIT_12 /* Reset Descr Read SM */
-#define CSR_DWRITE_RUN BIT_11 /* Release Descr Write SM */
-#define CSR_DWRITE_RST BIT_10 /* Reset Descr Write SM */
-#define CSR_TRANS_RUN BIT_9 /* Release Transfer SM */
-#define CSR_TRANS_RST BIT_8 /* Reset Transfer SM */
-#define CSR_ENA_POL BIT_7 /* Enable Descr Polling */
-#define CSR_DIS_POL BIT_6 /* Disable Descr Polling */
-#define CSR_STOP BIT_5 /* Stop Rx/Tx Queue */
-#define CSR_START BIT_4 /* Start Rx/Tx Queue */
-#define CSR_IRQ_CL_P BIT_3 /* (Rx) Clear Parity IRQ */
-#define CSR_IRQ_CL_B BIT_2 /* Clear EOB IRQ */
-#define CSR_IRQ_CL_F BIT_1 /* Clear EOF IRQ */
-#define CSR_IRQ_CL_C BIT_0 /* Clear ERR IRQ */
-
-#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
- CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
- CSR_TRANS_RST)
-#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
- CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
- CSR_TRANS_RUN)
-
-/* Q_F 32 bit Flag Register */
- /* Bit 31..28: reserved */
-#define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */
-#define F_EMPTY BIT_27 /* Tx FIFO: empty flag */
-#define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */
-#define F_WM_REACHED BIT_25 /* Watermark reached */
- /* reserved */
-#define F_FIFO_LEVEL (0x1fL<<16) /* Bit 23..16: # of Qwords in FIFO */
- /* Bit 15..11: reserved */
-#define F_WATER_MARK 0x0007ffL /* Bit 10.. 0: Watermark */
-
-/* Q_T1 32 bit Test Register 1 */
-/* Holds four State Machine control Bytes */
-#define SM_CTRL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */
-#define SM_CTRL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */
-#define SM_CTRL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */
-#define SM_CTRL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */
-
-/* Q_T1_TR 8 bit Test Register 1 Transfer SM */
-/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */
-/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */
-/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */
-
-/* The control status byte of each machine looks like ... */
-#define SM_STATE 0xf0 /* Bit 7.. 4: State which shall be loaded */
-#define SM_LOAD BIT_3S /* Load the SM with SM_STATE */
-#define SM_TEST_ON BIT_2S /* Switch on SM Test Mode */
-#define SM_TEST_OFF BIT_1S /* Go off the Test Mode */
-#define SM_STEP BIT_0S /* Step the State Machine */
-/* The encoding of the states is not supported by the Diagnostics Tool */
-
-/* Q_T2 32 bit Test Register 2 */
- /* Bit 31.. 8: reserved */
-#define T2_AC_T_ON BIT_7 /* Address Counter Test Mode on */
-#define T2_AC_T_OFF BIT_6 /* Address Counter Test Mode off */
-#define T2_BC_T_ON BIT_5 /* Byte Counter Test Mode on */
-#define T2_BC_T_OFF BIT_4 /* Byte Counter Test Mode off */
-#define T2_STEP04 BIT_3 /* Inc AC/Dec BC by 4 */
-#define T2_STEP03 BIT_2 /* Inc AC/Dec BC by 3 */
-#define T2_STEP02 BIT_1 /* Inc AC/Dec BC by 2 */
-#define T2_STEP01 BIT_0 /* Inc AC/Dec BC by 1 */
-
-/* Q_T3 32 bit Test Register 3 */
- /* Bit 31.. 7: reserved */
-#define T3_MUX_MSK (7<<4) /* Bit 6.. 4: Mux Position */
- /* Bit 3: reserved */
-#define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */
-
-/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
-/* RB_START 32 bit RAM Buffer Start Address */
-/* RB_END 32 bit RAM Buffer End Address */
-/* RB_WP 32 bit RAM Buffer Write Pointer */
-/* RB_RP 32 bit RAM Buffer Read Pointer */
-/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */
-/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */
-/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */
-/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */
-/* RB_PC 32 bit RAM Buffer Packet Counter */
-/* RB_LEV 32 bit RAM Buffer Level Register */
- /* Bit 31..19: reserved */
-#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */
-
-/* RB_TST2 8 bit RAM Buffer Test Register 2 */
- /* Bit 7.. 4: reserved */
-#define RB_PC_DEC BIT_3S /* Packet Counter Decrem */
-#define RB_PC_T_ON BIT_2S /* Packet Counter Test On */
-#define RB_PC_T_OFF BIT_1S /* Packet Counter Tst Off */
-#define RB_PC_INC BIT_0S /* Packet Counter Increm */
-
-/* RB_TST1 8 bit RAM Buffer Test Register 1 */
- /* Bit 7: reserved */
-#define RB_WP_T_ON BIT_6S /* Write Pointer Test On */
-#define RB_WP_T_OFF BIT_5S /* Write Pointer Test Off */
-#define RB_WP_INC BIT_4S /* Write Pointer Increm */
- /* Bit 3: reserved */
-#define RB_RP_T_ON BIT_2S /* Read Pointer Test On */
-#define RB_RP_T_OFF BIT_1S /* Read Pointer Test Off */
-#define RB_RP_DEC BIT_0S /* Read Pointer Decrement */
-
-/* RB_CTRL 8 bit RAM Buffer Control Register */
- /* Bit 7.. 6: reserved */
-#define RB_ENA_STFWD BIT_5S /* Enable Store & Forward */
-#define RB_DIS_STFWD BIT_4S /* Disable Store & Forward */
-#define RB_ENA_OP_MD BIT_3S /* Enable Operation Mode */
-#define RB_DIS_OP_MD BIT_2S /* Disable Operation Mode */
-#define RB_RST_CLR BIT_1S /* Clear RAM Buf STM Reset */
-#define RB_RST_SET BIT_0S /* Set RAM Buf STM Reset */
-
-
-/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
-
-/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */
-/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */
-/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */
-/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */
-/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */
-/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */
-/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */
-/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */
-/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */
-/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */
-/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */
- /* Bit 31.. 6: reserved */
-#define MFF_MSK 0x007fL /* Bit 5.. 0: MAC FIFO Address/Ptr Bits */
-
-/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */
- /* Bit 15..14: reserved */
-#define MFF_ENA_RDY_PAT BIT_13S /* Enable Ready Patch */
-#define MFF_DIS_RDY_PAT BIT_12S /* Disable Ready Patch */
-#define MFF_ENA_TIM_PAT BIT_11S /* Enable Timing Patch */
-#define MFF_DIS_TIM_PAT BIT_10S /* Disable Timing Patch */
-#define MFF_ENA_ALM_FUL BIT_9S /* Enable AlmostFull Sign */
-#define MFF_DIS_ALM_FUL BIT_8S /* Disable AlmostFull Sign */
-#define MFF_ENA_PAUSE BIT_7S /* Enable Pause Signaling */
-#define MFF_DIS_PAUSE BIT_6S /* Disable Pause Signaling */
-#define MFF_ENA_FLUSH BIT_5S /* Enable Frame Flushing */
-#define MFF_DIS_FLUSH BIT_4S /* Disable Frame Flushing */
-#define MFF_ENA_TIST BIT_3S /* Enable Time Stamp Gener */
-#define MFF_DIS_TIST BIT_2S /* Disable Time Stamp Gener */
-#define MFF_CLR_INTIST BIT_1S /* Clear IRQ No Time Stamp */
-#define MFF_CLR_INSTAT BIT_0S /* Clear IRQ No Status */
-
-#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
-
-/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */
-#define MFF_CLR_PERR BIT_15S /* Clear Parity Error IRQ */
- /* Bit 14: reserved */
-#define MFF_ENA_PKT_REC BIT_13S /* Enable Packet Recovery */
-#define MFF_DIS_PKT_REC BIT_12S /* Disable Packet Recovery */
-/* MFF_ENA_TIM_PAT (see RX_MFF_CTRL1) Bit 11: Enable Timing Patch */
-/* MFF_DIS_TIM_PAT (see RX_MFF_CTRL1) Bit 10: Disable Timing Patch */
-/* MFF_ENA_ALM_FUL (see RX_MFF_CTRL1) Bit 9: Enable Almost Full Sign */
-/* MFF_DIS_ALM_FUL (see RX_MFF_CTRL1) Bit 8: Disable Almost Full Sign */
-#define MFF_ENA_W4E BIT_7S /* Enable Wait for Empty */
-#define MFF_DIS_W4E BIT_6S /* Disable Wait for Empty */
-/* MFF_ENA_FLUSH (see RX_MFF_CTRL1) Bit 5: Enable Frame Flushing */
-/* MFF_DIS_FLUSH (see RX_MFF_CTRL1) Bit 4: Disable Frame Flushing */
-#define MFF_ENA_LOOPB BIT_3S /* Enable Loopback */
-#define MFF_DIS_LOOPB BIT_2S /* Disable Loopback */
-#define MFF_CLR_MAC_RST BIT_1S /* Clear XMAC Reset */
-#define MFF_SET_MAC_RST BIT_0S /* Set XMAC Reset */
-
-#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
-
-/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */
-/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */
- /* Bit 7: reserved */
-#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Ptr TestOn */
-#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Ptr TstOff */
-#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Ptr Increment */
-#define MFF_PC_DEC BIT_3S /* Packet Counter Decrement */
-#define MFF_PC_T_ON BIT_2S /* Packet Counter Test On */
-#define MFF_PC_T_OFF BIT_1S /* Packet Counter Test Off */
-#define MFF_PC_INC BIT_0S /* Packet Counter Increment */
-
-/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */
-/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */
- /* Bit 7: reserved */
-#define MFF_WP_T_ON BIT_6S /* Write Pointer Test On */
-#define MFF_WP_T_OFF BIT_5S /* Write Pointer Test Off */
-#define MFF_WP_INC BIT_4S /* Write Pointer Increm */
- /* Bit 3: reserved */
-#define MFF_RP_T_ON BIT_2S /* Read Pointer Test On */
-#define MFF_RP_T_OFF BIT_1S /* Read Pointer Test Off */
-#define MFF_RP_DEC BIT_0S /* Read Pointer Decrement */
-
-/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */
-/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */
- /* Bit 7..4: reserved */
-#define MFF_ENA_OP_MD BIT_3S /* Enable Operation Mode */
-#define MFF_DIS_OP_MD BIT_2S /* Disable Operation Mode */
-#define MFF_RST_CLR BIT_1S /* Clear MAC FIFO Reset */
-#define MFF_RST_SET BIT_0S /* Set MAC FIFO Reset */
-
-
-/* Link LED Counter Registers (GENESIS only) */
-
-/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */
-/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */
-/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */
- /* Bit 7.. 3: reserved */
-#define LED_START BIT_2S /* Start Timer */
-#define LED_STOP BIT_1S /* Stop Timer */
-#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED on */
-#define LED_CLR_IRQ BIT_0S /* Lnk: Clear Link IRQ */
-
-/* RX_LED_TST 8 bit Receive LED Cnt Test Register */
-/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */
-/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */
- /* Bit 7.. 3: reserved */
-#define LED_T_ON BIT_2S /* LED Counter Test mode On */
-#define LED_T_OFF BIT_1S /* LED Counter Test mode Off */
-#define LED_T_STEP BIT_0S /* LED Counter Step */
-
-/* LNK_LED_REG 8 bit Link LED Register */
- /* Bit 7.. 6: reserved */
-#define LED_BLK_ON BIT_5S /* Link LED Blinking On */
-#define LED_BLK_OFF BIT_4S /* Link LED Blinking Off */
-#define LED_SYNC_ON BIT_3S /* Use Sync Wire to switch LED */
-#define LED_SYNC_OFF BIT_2S /* Disable Sync Wire Input */
-#define LED_ON BIT_1S /* switch LED on */
-#define LED_OFF BIT_0S /* switch LED off */
-
-/* Receive and Transmit GMAC FIFO Registers (YUKON only) */
-
-/* RX_GMF_EA 32 bit Rx GMAC FIFO End Address */
-/* RX_GMF_AF_THR 32 bit Rx GMAC FIFO Almost Full Thresh. */
-/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */
-/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */
-/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */
-/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */
-/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */
-/* TX_GMF_AE_THR 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
-/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */
-/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Ptr. */
-/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */
-/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */
-/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */
-/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */
-
-/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */
- /* Bits 31..15: reserved */
-#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */
-#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */
-#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */
- /* Bit 11: reserved */
-#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */
-#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */
-#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */
-#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */
-#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */
-#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */
-#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */
-#define GMF_OPER_ON BIT_3 /* Operational Mode On */
-#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */
-#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */
-#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */
-
-/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
- /* Bits 31..19: reserved */
-#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */
-#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */
-#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */
- /* Bits 15..7: same as for RX_GMF_CTRL_T */
-#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */
-#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */
-#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */
- /* Bits 3..0: same as for RX_GMF_CTRL_T */
-
-#define GMF_RX_CTRL_DEF (GMF_OPER_ON | GMF_RX_F_FL_ON)
-#define GMF_TX_CTRL_DEF GMF_OPER_ON
-
-#define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */
-
-/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */
- /* Bit 7.. 3: reserved */
-#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */
-#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */
-#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */
-
-/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
- /* Bits 31.. 8: reserved */
-#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */
-#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */
-#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */
-#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */
-#define GMC_PAUSE_ON BIT_3 /* Pause On */
-#define GMC_PAUSE_OFF BIT_2 /* Pause Off */
-#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */
-#define GMC_RST_SET BIT_0 /* Set GMAC Reset */
-
-/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */
- /* Bits 31..29: reserved */
-#define GPC_SEL_BDT BIT_28 /* Select Bi-Dir. Transfer for MDC/MDIO */
-#define GPC_INT_POL_HI BIT_27 /* IRQ Polarity is Active HIGH */
-#define GPC_75_OHM BIT_26 /* Use 75 Ohm Termination instead of 50 */
-#define GPC_DIS_FC BIT_25 /* Disable Automatic Fiber/Copper Detection */
-#define GPC_DIS_SLEEP BIT_24 /* Disable Energy Detect */
-#define GPC_HWCFG_M_3 BIT_23 /* HWCFG_MODE[3] */
-#define GPC_HWCFG_M_2 BIT_22 /* HWCFG_MODE[2] */
-#define GPC_HWCFG_M_1 BIT_21 /* HWCFG_MODE[1] */
-#define GPC_HWCFG_M_0 BIT_20 /* HWCFG_MODE[0] */
-#define GPC_ANEG_0 BIT_19 /* ANEG[0] */
-#define GPC_ENA_XC BIT_18 /* Enable MDI crossover */
-#define GPC_DIS_125 BIT_17 /* Disable 125 MHz clock */
-#define GPC_ANEG_3 BIT_16 /* ANEG[3] */
-#define GPC_ANEG_2 BIT_15 /* ANEG[2] */
-#define GPC_ANEG_1 BIT_14 /* ANEG[1] */
-#define GPC_ENA_PAUSE BIT_13 /* Enable Pause (SYM_OR_REM) */
-#define GPC_PHYADDR_4 BIT_12 /* Bit 4 of Phy Addr */
-#define GPC_PHYADDR_3 BIT_11 /* Bit 3 of Phy Addr */
-#define GPC_PHYADDR_2 BIT_10 /* Bit 2 of Phy Addr */
-#define GPC_PHYADDR_1 BIT_9 /* Bit 1 of Phy Addr */
-#define GPC_PHYADDR_0 BIT_8 /* Bit 0 of Phy Addr */
- /* Bits 7..2: reserved */
-#define GPC_RST_CLR BIT_1 /* Clear GPHY Reset */
-#define GPC_RST_SET BIT_0 /* Set GPHY Reset */
-
-#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \
- GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_HWCFG_GMII_FIB ( GPC_HWCFG_M_2 | \
- GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | \
- GPC_ANEG_1 | GPC_ANEG_0)
-
-/* forced speed and duplex mode (don't mix with other ANEG bits) */
-#define GPC_FRC10MBIT_HALF 0
-#define GPC_FRC10MBIT_FULL GPC_ANEG_0
-#define GPC_FRC100MBIT_HALF GPC_ANEG_1
-#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1)
-
-/* auto-negotiation with limited advertised speeds */
-/* mix only with master/slave settings (for copper) */
-#define GPC_ADV_1000_HALF GPC_ANEG_2
-#define GPC_ADV_1000_FULL GPC_ANEG_3
-#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3)
-
-/* master/slave settings */
-/* only for copper with 1000 Mbps */
-#define GPC_FORCE_MASTER 0
-#define GPC_FORCE_SLAVE GPC_ANEG_0
-#define GPC_PREF_MASTER GPC_ANEG_1
-#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0)
-
-/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */
-/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */
-#define GM_IS_TX_CO_OV BIT_5 /* Transmit Counter Overflow IRQ */
-#define GM_IS_RX_CO_OV BIT_4 /* Receive Counter Overflow IRQ */
-#define GM_IS_TX_FF_UR BIT_3 /* Transmit FIFO Underrun */
-#define GM_IS_TX_COMPL BIT_2 /* Frame Transmission Complete */
-#define GM_IS_RX_FF_OR BIT_1 /* Receive FIFO Overrun */
-#define GM_IS_RX_COMPL BIT_0 /* Frame Reception Complete */
-
-#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \
- GM_IS_TX_FF_UR)
-
-/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
- /* Bits 15.. 2: reserved */
-#define GMLC_RST_CLR BIT_1S /* Clear GMAC Link Reset */
-#define GMLC_RST_SET BIT_0S /* Set GMAC Link Reset */
-
-
-/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */
-#define WOL_CTL_LINK_CHG_OCC BIT_15S
-#define WOL_CTL_MAGIC_PKT_OCC BIT_14S
-#define WOL_CTL_PATTERN_OCC BIT_13S
-
-#define WOL_CTL_CLEAR_RESULT BIT_12S
-
-#define WOL_CTL_ENA_PME_ON_LINK_CHG BIT_11S
-#define WOL_CTL_DIS_PME_ON_LINK_CHG BIT_10S
-#define WOL_CTL_ENA_PME_ON_MAGIC_PKT BIT_9S
-#define WOL_CTL_DIS_PME_ON_MAGIC_PKT BIT_8S
-#define WOL_CTL_ENA_PME_ON_PATTERN BIT_7S
-#define WOL_CTL_DIS_PME_ON_PATTERN BIT_6S
-
-#define WOL_CTL_ENA_LINK_CHG_UNIT BIT_5S
-#define WOL_CTL_DIS_LINK_CHG_UNIT BIT_4S
-#define WOL_CTL_ENA_MAGIC_PKT_UNIT BIT_3S
-#define WOL_CTL_DIS_MAGIC_PKT_UNIT BIT_2S
-#define WOL_CTL_ENA_PATTERN_UNIT BIT_1S
-#define WOL_CTL_DIS_PATTERN_UNIT BIT_0S
-
-#define WOL_CTL_DEFAULT \
- (WOL_CTL_DIS_PME_ON_LINK_CHG | \
- WOL_CTL_DIS_PME_ON_PATTERN | \
- WOL_CTL_DIS_PME_ON_MAGIC_PKT | \
- WOL_CTL_DIS_LINK_CHG_UNIT | \
- WOL_CTL_DIS_PATTERN_UNIT | \
- WOL_CTL_DIS_MAGIC_PKT_UNIT)
-
-/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */
-#define WOL_CTL_PATT_ENA(x) (BIT_0 << (x))
-
-#define SK_NUM_WOL_PATTERN 7
-#define SK_PATTERN_PER_WORD 4
-#define SK_BITMASK_PATTERN 7
-#define SK_POW_PATTERN_LENGTH 128
-
-#define WOL_LENGTH_MSK 0x7f
-#define WOL_LENGTH_SHIFT 8
-
-
-/* Receive and Transmit Descriptors ******************************************/
-
-/* Transmit Descriptor struct */
-typedef struct s_HwTxd {
- SK_U32 volatile TxCtrl; /* Transmit Buffer Control Field */
- SK_U32 TxNext; /* Physical Address Pointer to the next TxD */
- SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower dword */
- SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper dword */
- SK_U32 TxStat; /* Transmit Frame Status Word */
-#ifndef SK_USE_REV_DESC
- SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */
- SK_U16 TxRes1; /* 16 bit reserved field */
- SK_U16 TxTcpWp; /* TCP Checksum Write Position */
- SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
-#else /* SK_USE_REV_DESC */
- SK_U16 TxRes1; /* 16 bit reserved field */
- SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */
- SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
- SK_U16 TxTcpWp; /* TCP Checksum Write Position */
-#endif /* SK_USE_REV_DESC */
- SK_U32 TxRes2; /* 32 bit reserved field */
-} SK_HWTXD;
-
-/* Receive Descriptor struct */
-typedef struct s_HwRxd {
- SK_U32 volatile RxCtrl; /* Receive Buffer Control Field */
- SK_U32 RxNext; /* Physical Address Pointer to the next RxD */
- SK_U32 RxAdrLo; /* Physical Rx Buffer Address lower dword */
- SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper dword */
- SK_U32 RxStat; /* Receive Frame Status Word */
- SK_U32 RxTiSt; /* Receive Time Stamp (from XMAC on GENESIS) */
-#ifndef SK_USE_REV_DESC
- SK_U16 RxTcpSum1; /* TCP Checksum 1 */
- SK_U16 RxTcpSum2; /* TCP Checksum 2 */
- SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
- SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
-#else /* SK_USE_REV_DESC */
- SK_U16 RxTcpSum2; /* TCP Checksum 2 */
- SK_U16 RxTcpSum1; /* TCP Checksum 1 */
- SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
- SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
-#endif /* SK_USE_REV_DESC */
-} SK_HWRXD;
-
-/*
- * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2)
- * should set the define SK_USE_REV_DESC.
- * Structures are 'normaly' not endianess dependent. But in
- * this case the SK_U16 fields are bound to bit positions inside the
- * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord.
- * The bit positions inside a DWord are of course endianess dependent and
- * swaps if the DWord is swapped by the hardware.
- */
-
-
-/* Descriptor Bit Definition */
-/* TxCtrl Transmit Buffer Control Field */
-/* RxCtrl Receive Buffer Control Field */
-#define BMU_OWN BIT_31 /* OWN bit: 0=host/1=BMU */
-#define BMU_STF BIT_30 /* Start of Frame */
-#define BMU_EOF BIT_29 /* End of Frame */
-#define BMU_IRQ_EOB BIT_28 /* Req "End of Buffer" IRQ */
-#define BMU_IRQ_EOF BIT_27 /* Req "End of Frame" IRQ */
-/* TxCtrl specific bits */
-#define BMU_STFWD BIT_26 /* (Tx) Store & Forward Frame */
-#define BMU_NO_FCS BIT_25 /* (Tx) Disable MAC FCS (CRC) generation */
-#define BMU_SW BIT_24 /* (Tx) 1 bit res. for SW use */
-/* RxCtrl specific bits */
-#define BMU_DEV_0 BIT_26 /* (Rx) Transfer data to Dev0 */
-#define BMU_STAT_VAL BIT_25 /* (Rx) Rx Status Valid */
-#define BMU_TIST_VAL BIT_24 /* (Rx) Rx TimeStamp Valid */
- /* Bit 23..16: BMU Check Opcodes */
-#define BMU_CHECK (0x55L<<16) /* Default BMU check */
-#define BMU_TCP_CHECK (0x56L<<16) /* Descr with TCP ext */
-#define BMU_UDP_CHECK (0x57L<<16) /* Descr with UDP ext (YUKON only) */
-#define BMU_BBC 0xffffL /* Bit 15.. 0: Buffer Byte Counter */
-
-/* TxStat Transmit Frame Status Word */
-/* RxStat Receive Frame Status Word */
-/*
- *Note: TxStat is reserved for ASIC loopback mode only
- *
- * The Bits of the Status words are defined in xmac_ii.h
- * (see XMR_FS bits)
- */
-
-/* macros ********************************************************************/
-
-/* Receive and Transmit Queues */
-#define Q_R1 0x0000 /* Receive Queue 1 */
-#define Q_R2 0x0080 /* Receive Queue 2 */
-#define Q_XS1 0x0200 /* Synchronous Transmit Queue 1 */
-#define Q_XA1 0x0280 /* Asynchronous Transmit Queue 1 */
-#define Q_XS2 0x0300 /* Synchronous Transmit Queue 2 */
-#define Q_XA2 0x0380 /* Asynchronous Transmit Queue 2 */
-
-/*
- * Macro Q_ADDR()
- *
- * Use this macro to access the Receive and Transmit Queue Registers.
- *
- * para:
- * Queue Queue to access.
- * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- * Offs Queue register offset.
- * Values: Q_D, Q_DA_L ... Q_T2, Q_T3
- *
- * usage SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal)
- */
-#define Q_ADDR(Queue, Offs) (B8_Q_REGS + (Queue) + (Offs))
-
-/*
- * Macro RB_ADDR()
- *
- * Use this macro to access the RAM Buffer Registers.
- *
- * para:
- * Queue Queue to access.
- * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- * Offs Queue register offset.
- * Values: RB_START, RB_END ... RB_LEV, RB_CTRL
- *
- * usage SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal)
- */
-#define RB_ADDR(Queue, Offs) (B16_RAM_REGS + (Queue) + (Offs))
-
-
-/* MAC Related Registers */
-#define MAC_1 0 /* belongs to the port near the slot */
-#define MAC_2 1 /* belongs to the port far away from the slot */
-
-/*
- * Macro MR_ADDR()
- *
- * Use this macro to access a MAC Related Registers inside the ASIC.
- *
- * para:
- * Mac MAC to access.
- * Values: MAC_1, MAC_2
- * Offs MAC register offset.
- * Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG,
- * TX_MFF_EA, TX_MFF_WP ... TX_LED_TST
- *
- * usage SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
- */
-#define MR_ADDR(Mac, Offs) (((Mac) << 7) + (Offs))
-
-#ifdef SK_LITTLE_ENDIAN
-#define XM_WORD_LO 0
-#define XM_WORD_HI 1
-#else /* !SK_LITTLE_ENDIAN */
-#define XM_WORD_LO 1
-#define XM_WORD_HI 0
-#endif /* !SK_LITTLE_ENDIAN */
-
-
-/*
- * macros to access the XMAC (GENESIS only)
- *
- * XM_IN16(), to read a 16 bit register (e.g. XM_MMU_CMD)
- * XM_OUT16(), to write a 16 bit register (e.g. XM_MMU_CMD)
- * XM_IN32(), to read a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_OUT32(), to write a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_INADDR(), to read a network address register (e.g. XM_SRC_CHK)
- * XM_OUTADDR(), to write a network address register (e.g. XM_SRC_CHK)
- * XM_INHASH(), to read the XM_HSM_CHK register
- * XM_OUTHASH() to write the XM_HSM_CHK register
- *
- * para:
- * Mac XMAC to access values: MAC_1 or MAC_2
- * IoC I/O context needed for SK I/O macros
- * Reg XMAC Register to read or write
- * (p)Val Value or pointer to the value which should be read or written
- *
- * usage: XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value);
- */
-
-#define XMA(Mac, Reg) \
- ((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1))
-
-#define XM_IN16(IoC, Mac, Reg, pVal) \
- SK_IN16((IoC), XMA((Mac), (Reg)), (pVal))
-
-#define XM_OUT16(IoC, Mac, Reg, Val) \
- SK_OUT16((IoC), XMA((Mac), (Reg)), (Val))
-
-#define XM_IN32(IoC, Mac, Reg, pVal) { \
- SK_IN16((IoC), XMA((Mac), (Reg)), \
- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \
- SK_IN16((IoC), XMA((Mac), (Reg+2)), \
- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \
-}
-
-#define XM_OUT32(IoC, Mac, Reg, Val) { \
- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \
- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */
-
-#define XM_INADDR(IoC, Mac, Reg, pVal) { \
- SK_U16 Word; \
- SK_U8 *pByte; \
- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
- SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \
- pByte[0] = (SK_U8)(Word & 0x00ff); \
- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \
- pByte[2] = (SK_U8)(Word & 0x00ff); \
- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \
- pByte[4] = (SK_U8)(Word & 0x00ff); \
- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
-}
-
-#define XM_OUTADDR(IoC, Mac, Reg, pVal) { \
- SK_U8 SK_FAR *pByte; \
- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \
- (((SK_U16)(pByte[0]) & 0x00ff) | \
- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \
- (((SK_U16)(pByte[2]) & 0x00ff) | \
- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \
- (((SK_U16)(pByte[4]) & 0x00ff) | \
- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
-}
-
-#define XM_INHASH(IoC, Mac, Reg, pVal) { \
- SK_U16 Word; \
- SK_U8 SK_FAR *pByte; \
- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
- SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \
- pByte[0] = (SK_U8)(Word & 0x00ff); \
- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \
- pByte[2] = (SK_U8)(Word & 0x00ff); \
- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \
- pByte[4] = (SK_U8)(Word & 0x00ff); \
- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word); \
- pByte[6] = (SK_U8)(Word & 0x00ff); \
- pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \
-}
-
-#define XM_OUTHASH(IoC, Mac, Reg, pVal) { \
- SK_U8 SK_FAR *pByte; \
- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \
- (((SK_U16)(pByte[0]) & 0x00ff)| \
- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \
- (((SK_U16)(pByte[2]) & 0x00ff)| \
- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \
- (((SK_U16)(pByte[4]) & 0x00ff)| \
- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16) \
- (((SK_U16)(pByte[6]) & 0x00ff)| \
- (((SK_U16)(pByte[7]) << 8) & 0xff00))); \
-}
-
-/*
- * macros to access the GMAC (YUKON only)
- *
- * GM_IN16(), to read a 16 bit register (e.g. GM_GP_STAT)
- * GM_OUT16(), to write a 16 bit register (e.g. GM_GP_CTRL)
- * GM_IN32(), to read a 32 bit register (e.g. GM_)
- * GM_OUT32(), to write a 32 bit register (e.g. GM_)
- * GM_INADDR(), to read a network address register (e.g. GM_SRC_ADDR_1L)
- * GM_OUTADDR(), to write a network address register (e.g. GM_SRC_ADDR_2L)
- * GM_INHASH(), to read the GM_MC_ADDR_H1 register
- * GM_OUTHASH() to write the GM_MC_ADDR_H1 register
- *
- * para:
- * Mac GMAC to access values: MAC_1 or MAC_2
- * IoC I/O context needed for SK I/O macros
- * Reg GMAC Register to read or write
- * (p)Val Value or pointer to the value which should be read or written
- *
- * usage: GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value);
- */
-
-#define GMA(Mac, Reg) \
- ((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg))
-
-#define GM_IN16(IoC, Mac, Reg, pVal) \
- SK_IN16((IoC), GMA((Mac), (Reg)), (pVal))
-
-#define GM_OUT16(IoC, Mac, Reg, Val) \
- SK_OUT16((IoC), GMA((Mac), (Reg)), (Val))
-
-#define GM_IN32(IoC, Mac, Reg, pVal) { \
- SK_IN16((IoC), GMA((Mac), (Reg)), \
- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \
- SK_IN16((IoC), GMA((Mac), (Reg+4)), \
- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \
-}
-
-#define GM_OUT32(IoC, Mac, Reg, Val) { \
- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \
- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-#define GM_INADDR(IoC, Mac, Reg, pVal) { \
- SK_U16 Word; \
- SK_U8 *pByte; \
- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
- SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \
- pByte[0] = (SK_U8)(Word & 0x00ff); \
- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \
- pByte[2] = (SK_U8)(Word & 0x00ff); \
- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \
- pByte[4] = (SK_U8)(Word & 0x00ff); \
- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
-}
-
-#define GM_OUTADDR(IoC, Mac, Reg, pVal) { \
- SK_U8 SK_FAR *pByte; \
- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \
- (((SK_U16)(pByte[0]) & 0x00ff) | \
- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \
- (((SK_U16)(pByte[2]) & 0x00ff) | \
- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \
- (((SK_U16)(pByte[4]) & 0x00ff) | \
- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
-}
-
-#define GM_INHASH(IoC, Mac, Reg, pVal) { \
- SK_U16 Word; \
- SK_U8 *pByte; \
- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
- SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \
- pByte[0] = (SK_U8)(Word & 0x00ff); \
- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \
- pByte[2] = (SK_U8)(Word & 0x00ff); \
- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \
- pByte[4] = (SK_U8)(Word & 0x00ff); \
- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word); \
- pByte[6] = (SK_U8)(Word & 0x00ff); \
- pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \
-}
-
-#define GM_OUTHASH(IoC, Mac, Reg, pVal) { \
- SK_U8 *pByte; \
- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \
- (((SK_U16)(pByte[0]) & 0x00ff)| \
- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \
- (((SK_U16)(pByte[2]) & 0x00ff)| \
- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \
- (((SK_U16)(pByte[4]) & 0x00ff)| \
- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16) \
- (((SK_U16)(pByte[6]) & 0x00ff)| \
- (((SK_U16)(pByte[7]) << 8) & 0xff00))); \
-}
-
-/*
- * Different MAC Types
- */
-#define SK_MAC_XMAC 0 /* Xaqti XMAC II */
-#define SK_MAC_GMAC 1 /* Marvell GMAC */
-
-/*
- * Different PHY Types
- */
-#define SK_PHY_XMAC 0 /* integrated in XMAC II */
-#define SK_PHY_BCOM 1 /* Broadcom BCM5400 */
-#define SK_PHY_LONE 2 /* Level One LXT1000 */
-#define SK_PHY_NAT 3 /* National DP83891 */
-#define SK_PHY_MARV_COPPER 4 /* Marvell 88E1011S */
-#define SK_PHY_MARV_FIBER 5 /* Marvell 88E1011S working on fiber */
-
-/*
- * PHY addresses (bits 12..8 of PHY address reg)
- */
-#define PHY_ADDR_XMAC (0<<8)
-#define PHY_ADDR_BCOM (1<<8)
-#define PHY_ADDR_LONE (3<<8)
-#define PHY_ADDR_NAT (0<<8)
-
-/* GPHY address (bits 15..11 of SMI control reg) */
-#define PHY_ADDR_MARV 0
-
-/*
- * macros to access the PHY
- *
- * PHY_READ() read a 16 bit value from the PHY
- * PHY_WRITE() write a 16 bit value to the PHY
- *
- * para:
- * IoC I/O context needed for SK I/O macros
- * pPort Pointer to port struct for PhyAddr
- * Mac XMAC to access values: MAC_1 or MAC_2
- * PhyReg PHY Register to read or write
- * (p)Val Value or pointer to the value which should be read or
- * written.
- *
- * usage: PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value);
- * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never
- * comes back. This is checked in DEBUG mode.
- */
-#ifndef DEBUG
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \
- SK_U16 Mmu; \
- \
- XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
- if ((pPort)->PhyType != SK_PHY_XMAC) { \
- do { \
- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
- } while ((Mmu & XM_MMU_PHY_RDY) == 0); \
- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
- } \
-}
-#else
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \
- SK_U16 Mmu; \
- int __i = 0; \
- \
- XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
- if ((pPort)->PhyType != SK_PHY_XMAC) { \
- do { \
- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
- __i++; \
- if (__i > 100000) { \
- SK_DBG_PRINTF("*****************************\n"); \
- SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n"); \
- SK_DBG_PRINTF("*****************************\n"); \
- break; \
- } \
- } while ((Mmu & XM_MMU_PHY_RDY) == 0); \
- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
- } \
-}
-#endif /* DEBUG */
-
-#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) { \
- SK_U16 Mmu; \
- \
- if ((pPort)->PhyType != SK_PHY_XMAC) { \
- do { \
- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
- } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \
- } \
- XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
- XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val)); \
- if ((pPort)->PhyType != SK_PHY_XMAC) { \
- do { \
- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
- } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \
- } \
-}
-
-/*
- * Macro PCI_C()
- *
- * Use this macro to access PCI config register from the I/O space.
- *
- * para:
- * Addr PCI configuration register to access.
- * Values: PCI_VENDOR_ID ... PCI_VPD_ADR_REG,
- *
- * usage SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal);
- */
-#define PCI_C(Addr) (B7_CFG_SPC + (Addr)) /* PCI Config Space */
-
-/*
- * Macro SK_HW_ADDR(Base, Addr)
- *
- * Calculates the effective HW address
- *
- * para:
- * Base I/O or memory base address
- * Addr Address offset
- *
- * usage: May be used in SK_INxx and SK_OUTxx macros
- * #define SK_IN8(pAC, Addr, pVal) ...\
- * *pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr)))
- */
-#ifdef SK_MEM_MAPPED_IO
-#define SK_HW_ADDR(Base, Addr) ((Base) + (Addr))
-#else /* SK_MEM_MAPPED_IO */
-#define SK_HW_ADDR(Base, Addr) \
- ((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0)))
-#endif /* SK_MEM_MAPPED_IO */
-
-#define SZ_LONG (sizeof(SK_U32))
-
-/*
- * Macro SK_HWAC_LINK_LED()
- *
- * Use this macro to set the link LED mode.
- * para:
- * pAC Pointer to adapter context struct
- * IoC I/O context needed for SK I/O macros
- * Port Port number
- * Mode Mode to set for this LED
- */
-#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \
- SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode);
-
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_SKGEHW_H */
diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h
deleted file mode 100644
index e6b0016a695..00000000000
--- a/drivers/net/sk98lin/h/skgehwt.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/******************************************************************************
- *
- * Name: skhwt.h
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.7 $
- * Date: $Date: 2003/09/16 12:55:08 $
- * Purpose: Defines for the hardware timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEHWT.H contains all defines and types for the timer functions
- */
-
-#ifndef _SKGEHWT_H_
-#define _SKGEHWT_H_
-
-/*
- * SK Hardware Timer
- * - needed wherever the HWT module is used
- * - use in Adapters context name pAC->Hwt
- */
-typedef struct s_Hwt {
- SK_U32 TStart; /* HWT start */
- SK_U32 TStop; /* HWT stop */
- int TActive; /* HWT: flag : active/inactive */
-} SK_HWT;
-
-extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time);
-extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc);
-extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc);
-#endif /* _SKGEHWT_H_ */
diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h
deleted file mode 100644
index d9b6f6d8dfe..00000000000
--- a/drivers/net/sk98lin/h/skgei2c.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/******************************************************************************
- *
- * Name: skgei2c.h
- * Project: Gigabit Ethernet Adapters, TWSI-Module
- * Version: $Revision: 1.25 $
- * Date: $Date: 2003/10/20 09:06:05 $
- * Purpose: Special defines for TWSI
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEI2C.H contains all SK-98xx specific defines for the TWSI handling
- */
-
-#ifndef _INC_SKGEI2C_H_
-#define _INC_SKGEI2C_H_
-
-/*
- * Macros to access the B2_I2C_CTRL
- */
-#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
- SK_OUT32(IoC, B2_I2C_CTRL,\
- (flag ? 0x80000000UL : 0x0L) | \
- (((SK_U32)reg << 16) & I2C_ADDR) | \
- (((SK_U32)dev << 9) & I2C_DEV_SEL) | \
- (dev_size & I2C_DEV_SIZE) | \
- ((burst << 4) & I2C_BURST_LEN))
-
-#define SK_I2C_STOP(IoC) { \
- SK_U32 I2cCtrl; \
- SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \
- SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \
-}
-
-#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
-
-/*
- * Macros to access the TWSI SW Registers
- */
-#define SK_I2C_SET_BIT(IoC, SetBits) { \
- SK_U8 OrgBits; \
- SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
- SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \
-}
-
-#define SK_I2C_CLR_BIT(IoC, ClrBits) { \
- SK_U8 OrgBits; \
- SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
- SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \
-}
-
-#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw)
-
-/*
- * define the possible sensor states
- */
-#define SK_SEN_IDLE 0 /* Idle: sensor not read */
-#define SK_SEN_VALUE 1 /* Value Read cycle */
-#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */
-
-/*
- * Conversion factor to convert read Voltage sensor to milli Volt
- * Conversion factor to convert read Temperature sensor to 10th degree Celsius
- */
-#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */
-#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */
-#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for ext. val. */
-
-/*
- * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
- * assuming: 6500rpm, 4 pulses, divisor 1
- */
-#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2))
-
-/*
- * Define sensor management data
- * Maximum is reached on Genesis copper dual port and Yukon-64
- * Board specific maximum is in pAC->I2c.MaxSens
- */
-#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */
-#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */
-
-/*
- * To watch the state machine (SM) use the timer in two ways
- * instead of one as hitherto
- */
-#define SK_TIMER_WATCH_SM 0 /* Watch the SM to finish in a spec. time */
-#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */
-
-/*
- * Defines for the individual thresholds
- */
-
-/* Temperature sensor */
-#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */
-#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */
-#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */
-#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */
-
-/* VCC which should be 5 V */
-#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */
-#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */
-#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */
-#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */
-
-/*
- * VIO may be 5 V or 3.3 V. Initialization takes two parts:
- * 1. Initialize lowest lower limit and highest higher limit.
- * 2. After the first value is read correct the upper or the lower limit to
- * the appropriate C constant.
- *
- * Warning limits are +-5% of the exepected voltage.
- * Error limits are +-10% of the expected voltage.
- */
-
-/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
-
-#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */
-#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */
- /* 5000 mVolt */
-#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */
-#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */
-
-#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */
-
-/* correction values for the second pass */
-#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */
-#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */
- /* 3300 mVolt */
-#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */
-#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */
-
-/*
- * VDD voltage
- */
-#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */
-#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */
-#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */
-#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */
-
-/*
- * PHY PLL 3V3 voltage
- */
-#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */
-#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */
-#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */
-#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */
-
-/*
- * VAUX (YUKON only)
- */
-#define SK_SEN_VAUX_3V3_HIGH_ERR 3630 /* Voltage VAUX High Err Threshold */
-#define SK_SEN_VAUX_3V3_HIGH_WARN 3476 /* Voltage VAUX High Warn Threshold */
-#define SK_SEN_VAUX_3V3_LOW_WARN 3146 /* Voltage VAUX Low Warn Threshold */
-#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */
-#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */
-#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */
-
-/*
- * PHY 2V5 voltage
- */
-#define SK_SEN_PHY_2V5_HIGH_ERR 2750 /* Voltage PHY High Err Threshold */
-#define SK_SEN_PHY_2V5_HIGH_WARN 2640 /* Voltage PHY High Warn Threshold */
-#define SK_SEN_PHY_2V5_LOW_WARN 2376 /* Voltage PHY Low Warn Threshold */
-#define SK_SEN_PHY_2V5_LOW_ERR 2222 /* Voltage PHY Low Err Threshold */
-
-/*
- * ASIC Core 1V5 voltage (YUKON only)
- */
-#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */
-#define SK_SEN_CORE_1V5_HIGH_WARN 1575 /* Voltage ASIC Core High Warn Threshold */
-#define SK_SEN_CORE_1V5_LOW_WARN 1425 /* Voltage ASIC Core Low Warn Threshold */
-#define SK_SEN_CORE_1V5_LOW_ERR 1350 /* Voltage ASIC Core Low Err Threshold */
-
-/*
- * FAN 1 speed
- */
-/* assuming: 6500rpm +-15%, 4 pulses,
- * warning at: 80 %
- * error at: 70 %
- * no upper limit
- */
-#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */
-#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */
-#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */
-#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */
-
-/*
- * Some Voltages need dynamic thresholds
- */
-#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */
-#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */
-#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */
-
-extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
-#endif /* n_INC_SKGEI2C_H */
diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h
deleted file mode 100644
index 143e635ec24..00000000000
--- a/drivers/net/sk98lin/h/skgeinit.h
+++ /dev/null
@@ -1,797 +0,0 @@
-/******************************************************************************
- *
- * Name: skgeinit.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.83 $
- * Date: $Date: 2003/09/16 14:07:37 $
- * Purpose: Structures and prototypes for the GE Init Module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEINIT_H_
-#define __INC_SKGEINIT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_TEST_VAL 0x11335577UL
-
-/* modifying Link LED behaviour (used with SkGeLinkLED()) */
-#define SK_LNK_OFF LED_OFF
-#define SK_LNK_ON (LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LNK_BLINK (LED_ON | LED_BLK_ON | LED_SYNC_ON)
-#define SK_LNK_PERM (LED_ON | LED_BLK_OFF | LED_SYNC_ON)
-#define SK_LNK_TST (LED_ON | LED_BLK_ON | LED_SYNC_OFF)
-
-/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */
-#define SK_LED_OFF LED_OFF
-#define SK_LED_ACTIVE (LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LED_STANDBY (LED_ON | LED_BLK_ON | LED_SYNC_OFF)
-
-/* addressing LED Registers in SkGeXmitLED() */
-#define XMIT_LED_INI 0
-#define XMIT_LED_CNT (RX_LED_VAL - RX_LED_INI)
-#define XMIT_LED_CTRL (RX_LED_CTRL- RX_LED_INI)
-#define XMIT_LED_TST (RX_LED_TST - RX_LED_INI)
-
-/* parameter 'Mode' when calling SkGeXmitLED() */
-#define SK_LED_DIS 0
-#define SK_LED_ENA 1
-#define SK_LED_TST 2
-
-/* Counter and Timer constants, for a host clock of 62.5 MHz */
-#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */
-#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */
-
-#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */
-
-#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */
- /* 215 ms at 78.12 MHz */
-
-#define SK_FACT_62 100 /* is given in percent */
-#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */
-#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */
-
-/* Timeout values */
-#define SK_MAC_TO_53 72 /* MAC arbiter timeout */
-#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */
-#define SK_PKT_TO_MAX 0xffff /* Maximum value */
-#define SK_RI_TO_53 36 /* RAM interface timeout */
-
-#define SK_PHY_ACC_TO 600000 /* PHY access timeout */
-
-/* RAM Buffer High Pause Threshold values */
-#define SK_RB_ULPP ( 8 * 1024) /* Upper Level in kB/8 */
-#define SK_RB_LLPP_S (10 * 1024) /* Lower Level for small Queues */
-#define SK_RB_LLPP_B (16 * 1024) /* Lower Level for big Queues */
-
-#ifndef SK_BMU_RX_WM
-#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */
-#endif
-#ifndef SK_BMU_TX_WM
-#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */
-#endif
-
-/* XMAC II Rx High Watermark */
-#define SK_XM_RX_HI_WM 0x05aa /* 1450 */
-
-/* XMAC II Tx Threshold */
-#define SK_XM_THR_REDL 0x01fb /* .. for redundant link usage */
-#define SK_XM_THR_SL 0x01fb /* .. for single link adapters */
-#define SK_XM_THR_MULL 0x01fb /* .. for multiple link usage */
-#define SK_XM_THR_JUMBO 0x03fc /* .. for jumbo frame usage */
-
-/* values for GIPortUsage */
-#define SK_RED_LINK 1 /* redundant link usage */
-#define SK_MUL_LINK 2 /* multiple link usage */
-#define SK_JUMBO_LINK 3 /* driver uses jumbo frames */
-
-/* Minimum RAM Buffer Rx Queue Size */
-#define SK_MIN_RXQ_SIZE 16 /* 16 kB */
-
-/* Minimum RAM Buffer Tx Queue Size */
-#define SK_MIN_TXQ_SIZE 16 /* 16 kB */
-
-/* Queue Size units */
-#define QZ_UNITS 0x7
-#define QZ_STEP 8
-
-/* Percentage of queue size from whole memory */
-/* 80 % for receive */
-#define RAM_QUOTA_RX 80L
-/* 0% for sync transfer */
-#define RAM_QUOTA_SYNC 0L
-/* the rest (20%) is taken for async transfer */
-
-/* Get the rounded queue size in Bytes in 8k steps */
-#define ROUND_QUEUE_SIZE(SizeInBytes) \
- ((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) & \
- ~(QZ_STEP-1))
-
-/* Get the rounded queue size in KBytes in 8k steps */
-#define ROUND_QUEUE_SIZE_KB(Kilobytes) \
- ROUND_QUEUE_SIZE((Kilobytes) * 1024L)
-
-/* Types of RAM Buffer Queues */
-#define SK_RX_SRAM_Q 1 /* small receive queue */
-#define SK_RX_BRAM_Q 2 /* big receive queue */
-#define SK_TX_RAM_Q 3 /* small or big transmit queue */
-
-/* parameter 'Dir' when calling SkGeStopPort() */
-#define SK_STOP_TX 1 /* Stops the transmit path, resets the XMAC */
-#define SK_STOP_RX 2 /* Stops the receive path */
-#define SK_STOP_ALL 3 /* Stops Rx and Tx path, resets the XMAC */
-
-/* parameter 'RstMode' when calling SkGeStopPort() */
-#define SK_SOFT_RST 1 /* perform a software reset */
-#define SK_HARD_RST 2 /* perform a hardware reset */
-
-/* Init Levels */
-#define SK_INIT_DATA 0 /* Init level 0: init data structures */
-#define SK_INIT_IO 1 /* Init level 1: init with IOs */
-#define SK_INIT_RUN 2 /* Init level 2: init for run time */
-
-/* Link Mode Parameter */
-#define SK_LMODE_HALF 1 /* Half Duplex Mode */
-#define SK_LMODE_FULL 2 /* Full Duplex Mode */
-#define SK_LMODE_AUTOHALF 3 /* AutoHalf Duplex Mode */
-#define SK_LMODE_AUTOFULL 4 /* AutoFull Duplex Mode */
-#define SK_LMODE_AUTOBOTH 5 /* AutoBoth Duplex Mode */
-#define SK_LMODE_AUTOSENSE 6 /* configured mode auto sensing */
-#define SK_LMODE_INDETERMINATED 7 /* indeterminated */
-
-/* Auto-negotiation timeout in 100ms granularity */
-#define SK_AND_MAX_TO 6 /* Wait 600 msec before link comes up */
-
-/* Auto-negotiation error codes */
-#define SK_AND_OK 0 /* no error */
-#define SK_AND_OTHER 1 /* other error than below */
-#define SK_AND_DUP_CAP 2 /* Duplex capabilities error */
-
-
-/* Link Speed Capabilities */
-#define SK_LSPEED_CAP_AUTO (1<<0) /* Automatic resolution */
-#define SK_LSPEED_CAP_10MBPS (1<<1) /* 10 Mbps */
-#define SK_LSPEED_CAP_100MBPS (1<<2) /* 100 Mbps */
-#define SK_LSPEED_CAP_1000MBPS (1<<3) /* 1000 Mbps */
-#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Speed Parameter */
-#define SK_LSPEED_AUTO 1 /* Automatic resolution */
-#define SK_LSPEED_10MBPS 2 /* 10 Mbps */
-#define SK_LSPEED_100MBPS 3 /* 100 Mbps */
-#define SK_LSPEED_1000MBPS 4 /* 1000 Mbps */
-#define SK_LSPEED_INDETERMINATED 5 /* indeterminated */
-
-/* Link Speed Current State */
-#define SK_LSPEED_STAT_UNKNOWN 1
-#define SK_LSPEED_STAT_10MBPS 2
-#define SK_LSPEED_STAT_100MBPS 3
-#define SK_LSPEED_STAT_1000MBPS 4
-#define SK_LSPEED_STAT_INDETERMINATED 5
-
-
-/* Link Capability Parameter */
-#define SK_LMODE_CAP_HALF (1<<0) /* Half Duplex Mode */
-#define SK_LMODE_CAP_FULL (1<<1) /* Full Duplex Mode */
-#define SK_LMODE_CAP_AUTOHALF (1<<2) /* AutoHalf Duplex Mode */
-#define SK_LMODE_CAP_AUTOFULL (1<<3) /* AutoFull Duplex Mode */
-#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Mode Current State */
-#define SK_LMODE_STAT_UNKNOWN 1 /* Unknown Duplex Mode */
-#define SK_LMODE_STAT_HALF 2 /* Half Duplex Mode */
-#define SK_LMODE_STAT_FULL 3 /* Full Duplex Mode */
-#define SK_LMODE_STAT_AUTOHALF 4 /* Half Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_AUTOFULL 5 /* Full Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_INDETERMINATED 6 /* indeterminated */
-
-/* Flow Control Mode Parameter (and capabilities) */
-#define SK_FLOW_MODE_NONE 1 /* No Flow-Control */
-#define SK_FLOW_MODE_LOC_SEND 2 /* Local station sends PAUSE */
-#define SK_FLOW_MODE_SYMMETRIC 3 /* Both stations may send PAUSE */
-#define SK_FLOW_MODE_SYM_OR_REM 4 /* Both stations may send PAUSE or
- * just the remote station may send PAUSE
- */
-#define SK_FLOW_MODE_INDETERMINATED 5 /* indeterminated */
-
-/* Flow Control Status Parameter */
-#define SK_FLOW_STAT_NONE 1 /* No Flow Control */
-#define SK_FLOW_STAT_REM_SEND 2 /* Remote Station sends PAUSE */
-#define SK_FLOW_STAT_LOC_SEND 3 /* Local station sends PAUSE */
-#define SK_FLOW_STAT_SYMMETRIC 4 /* Both station may send PAUSE */
-#define SK_FLOW_STAT_INDETERMINATED 5 /* indeterminated */
-
-/* Master/Slave Mode Capabilities */
-#define SK_MS_CAP_AUTO (1<<0) /* Automatic resolution */
-#define SK_MS_CAP_MASTER (1<<1) /* This station is master */
-#define SK_MS_CAP_SLAVE (1<<2) /* This station is slave */
-#define SK_MS_CAP_INDETERMINATED (1<<3) /* indeterminated */
-
-/* Set Master/Slave Mode Parameter (and capabilities) */
-#define SK_MS_MODE_AUTO 1 /* Automatic resolution */
-#define SK_MS_MODE_MASTER 2 /* This station is master */
-#define SK_MS_MODE_SLAVE 3 /* This station is slave */
-#define SK_MS_MODE_INDETERMINATED 4 /* indeterminated */
-
-/* Master/Slave Status Parameter */
-#define SK_MS_STAT_UNSET 1 /* The M/S status is not set */
-#define SK_MS_STAT_MASTER 2 /* This station is master */
-#define SK_MS_STAT_SLAVE 3 /* This station is slave */
-#define SK_MS_STAT_FAULT 4 /* M/S resolution failed */
-#define SK_MS_STAT_INDETERMINATED 5 /* indeterminated */
-
-/* parameter 'Mode' when calling SkXmSetRxCmd() */
-#define SK_STRIP_FCS_ON (1<<0) /* Enable FCS stripping of Rx frames */
-#define SK_STRIP_FCS_OFF (1<<1) /* Disable FCS stripping of Rx frames */
-#define SK_STRIP_PAD_ON (1<<2) /* Enable pad byte stripping of Rx fr */
-#define SK_STRIP_PAD_OFF (1<<3) /* Disable pad byte stripping of Rx fr */
-#define SK_LENERR_OK_ON (1<<4) /* Don't chk fr for in range len error */
-#define SK_LENERR_OK_OFF (1<<5) /* Check frames for in range len error */
-#define SK_BIG_PK_OK_ON (1<<6) /* Don't set Rx Error bit for big frames */
-#define SK_BIG_PK_OK_OFF (1<<7) /* Set Rx Error bit for big frames */
-#define SK_SELF_RX_ON (1<<8) /* Enable Rx of own packets */
-#define SK_SELF_RX_OFF (1<<9) /* Disable Rx of own packets */
-
-/* parameter 'Para' when calling SkMacSetRxTxEn() */
-#define SK_MAC_LOOPB_ON (1<<0) /* Enable MAC Loopback Mode */
-#define SK_MAC_LOOPB_OFF (1<<1) /* Disable MAC Loopback Mode */
-#define SK_PHY_LOOPB_ON (1<<2) /* Enable PHY Loopback Mode */
-#define SK_PHY_LOOPB_OFF (1<<3) /* Disable PHY Loopback Mode */
-#define SK_PHY_FULLD_ON (1<<4) /* Enable GMII Full Duplex */
-#define SK_PHY_FULLD_OFF (1<<5) /* Disable GMII Full Duplex */
-
-/* States of PState */
-#define SK_PRT_RESET 0 /* the port is reset */
-#define SK_PRT_STOP 1 /* the port is stopped (similar to SW reset) */
-#define SK_PRT_INIT 2 /* the port is initialized */
-#define SK_PRT_RUN 3 /* the port has an active link */
-
-/* PHY power down modes */
-#define PHY_PM_OPERATIONAL_MODE 0 /* PHY operational mode */
-#define PHY_PM_DEEP_SLEEP 1 /* coma mode --> minimal power */
-#define PHY_PM_IEEE_POWER_DOWN 2 /* IEEE 22.2.4.1.5 compl. power down */
-#define PHY_PM_ENERGY_DETECT 3 /* energy detect */
-#define PHY_PM_ENERGY_DETECT_PLUS 4 /* energy detect plus */
-
-/* Default receive frame limit for Workaround of XMAC Errata */
-#define SK_DEF_RX_WA_LIM SK_CONSTU64(100)
-
-/* values for GILedBlinkCtrl (LED Blink Control) */
-#define SK_ACT_LED_BLINK (1<<0) /* Active LED blinking */
-#define SK_DUP_LED_NORMAL (1<<1) /* Duplex LED normal */
-#define SK_LED_LINK100_ON (1<<2) /* Link 100M LED on */
-
-/* Link Partner Status */
-#define SK_LIPA_UNKNOWN 0 /* Link partner is in unknown state */
-#define SK_LIPA_MANUAL 1 /* Link partner is in detected manual state */
-#define SK_LIPA_AUTO 2 /* Link partner is in auto-negotiation state */
-
-/* Maximum Restarts before restart is ignored (3Com WA) */
-#define SK_MAX_LRESTART 3 /* Max. 3 times the link is restarted */
-
-/* Max. Auto-neg. timeouts before link detection in sense mode is reset */
-#define SK_MAX_ANEG_TO 10 /* Max. 10 times the sense mode is reset */
-
-/* structures *****************************************************************/
-
-/*
- * MAC specific functions
- */
-typedef struct s_GeMacFunc {
- int (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
- int (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
- SK_U16 StatAddr, SK_U32 SK_FAR *pVal);
- int (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
- int (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
- SK_U16 IStatus, SK_U64 SK_FAR *pVal);
-} SK_GEMACFUNC;
-
-/*
- * Port Structure
- */
-typedef struct s_GePort {
-#ifndef SK_DIAG
- SK_TIMER PWaTimer; /* Workaround Timer */
- SK_TIMER HalfDupChkTimer;
-#endif /* SK_DIAG */
- SK_U32 PPrevShorts; /* Previous Short Counter checking */
- SK_U32 PPrevFcs; /* Previous FCS Error Counter checking */
- SK_U64 PPrevRx; /* Previous RxOk Counter checking */
- SK_U64 PRxLim; /* Previous RxOk Counter checking */
- SK_U64 LastOctets; /* For half duplex hang check */
- int PLinkResCt; /* Link Restart Counter */
- int PAutoNegTimeOut;/* Auto-negotiation timeout current value */
- int PAutoNegTOCt; /* Auto-negotiation Timeout Counter */
- int PRxQSize; /* Port Rx Queue Size in kB */
- int PXSQSize; /* Port Synchronous Transmit Queue Size in kB */
- int PXAQSize; /* Port Asynchronous Transmit Queue Size in kB */
- SK_U32 PRxQRamStart; /* Receive Queue RAM Buffer Start Address */
- SK_U32 PRxQRamEnd; /* Receive Queue RAM Buffer End Address */
- SK_U32 PXsQRamStart; /* Sync Tx Queue RAM Buffer Start Address */
- SK_U32 PXsQRamEnd; /* Sync Tx Queue RAM Buffer End Address */
- SK_U32 PXaQRamStart; /* Async Tx Queue RAM Buffer Start Address */
- SK_U32 PXaQRamEnd; /* Async Tx Queue RAM Buffer End Address */
- SK_U32 PRxOverCnt; /* Receive Overflow Counter */
- int PRxQOff; /* Rx Queue Address Offset */
- int PXsQOff; /* Synchronous Tx Queue Address Offset */
- int PXaQOff; /* Asynchronous Tx Queue Address Offset */
- int PhyType; /* PHY used on this port */
- int PState; /* Port status (reset, stop, init, run) */
- SK_U16 PhyId1; /* PHY Id1 on this port */
- SK_U16 PhyAddr; /* MDIO/MDC PHY address */
- SK_U16 PIsave; /* Saved Interrupt status word */
- SK_U16 PSsave; /* Saved PHY status word */
- SK_U16 PGmANegAdv; /* Saved GPhy AutoNegAdvertisment register */
- SK_BOOL PHWLinkUp; /* The hardware Link is up (wiring) */
- SK_BOOL PLinkBroken; /* Is Link broken ? */
- SK_BOOL PCheckPar; /* Do we check for parity errors ? */
- SK_BOOL HalfDupTimerActive;
- SK_U8 PLinkCap; /* Link Capabilities */
- SK_U8 PLinkModeConf; /* Link Mode configured */
- SK_U8 PLinkMode; /* Link Mode currently used */
- SK_U8 PLinkModeStatus;/* Link Mode Status */
- SK_U8 PLinkSpeedCap; /* Link Speed Capabilities(10/100/1000 Mbps) */
- SK_U8 PLinkSpeed; /* configured Link Speed (10/100/1000 Mbps) */
- SK_U8 PLinkSpeedUsed; /* current Link Speed (10/100/1000 Mbps) */
- SK_U8 PFlowCtrlCap; /* Flow Control Capabilities */
- SK_U8 PFlowCtrlMode; /* Flow Control Mode */
- SK_U8 PFlowCtrlStatus;/* Flow Control Status */
- SK_U8 PMSCap; /* Master/Slave Capabilities */
- SK_U8 PMSMode; /* Master/Slave Mode */
- SK_U8 PMSStatus; /* Master/Slave Status */
- SK_BOOL PAutoNegFail; /* Auto-negotiation fail flag */
- SK_U8 PLipaAutoNeg; /* Auto-negotiation possible with Link Partner */
- SK_U8 PCableLen; /* Cable Length */
- SK_U8 PMdiPairLen[4]; /* MDI[0..3] Pair Length */
- SK_U8 PMdiPairSts[4]; /* MDI[0..3] Pair Diagnostic Status */
- SK_U8 PPhyPowerState; /* PHY current power state */
- int PMacColThres; /* MAC Collision Threshold */
- int PMacJamLen; /* MAC Jam length */
- int PMacJamIpgVal; /* MAC Jam IPG */
- int PMacJamIpgData; /* MAC IPG Jam to Data */
- int PMacIpgData; /* MAC Data IPG */
- SK_BOOL PMacLimit4; /* reset collision counter and backoff algorithm */
-} SK_GEPORT;
-
-/*
- * Gigabit Ethernet Initialization Struct
- * (has to be included in the adapter context)
- */
-typedef struct s_GeInit {
- int GIChipId; /* Chip Identification Number */
- int GIChipRev; /* Chip Revision Number */
- SK_U8 GIPciHwRev; /* PCI HW Revision Number */
- SK_BOOL GIGenesis; /* Genesis adapter ? */
- SK_BOOL GIYukon; /* YUKON-A1/Bx chip */
- SK_BOOL GIYukonLite; /* YUKON-Lite chip */
- SK_BOOL GICopperType; /* Copper Type adapter ? */
- SK_BOOL GIPciSlot64; /* 64-bit PCI Slot */
- SK_BOOL GIPciClock66; /* 66 MHz PCI Clock */
- SK_BOOL GIVauxAvail; /* VAUX available (YUKON) */
- SK_BOOL GIYukon32Bit; /* 32-Bit YUKON adapter */
- SK_U16 GILedBlinkCtrl; /* LED Blink Control */
- int GIMacsFound; /* Number of MACs found on this adapter */
- int GIMacType; /* MAC Type used on this adapter */
- int GIHstClkFact; /* Host Clock Factor (62.5 / HstClk * 100) */
- int GIPortUsage; /* Driver Port Usage */
- int GILevel; /* Initialization Level completed */
- int GIRamSize; /* The RAM size of the adapter in kB */
- int GIWolOffs; /* WOL Register Offset (HW-Bug in Rev. A) */
- SK_U32 GIRamOffs; /* RAM Address Offset for addr calculation */
- SK_U32 GIPollTimerVal; /* Descr. Poll Timer Init Val (HstClk ticks) */
- SK_U32 GIValIrqMask; /* Value for Interrupt Mask */
- SK_U32 GITimeStampCnt; /* Time Stamp High Counter (YUKON only) */
- SK_GEPORT GP[SK_MAX_MACS];/* Port Dependent Information */
- SK_GEMACFUNC GIFunc; /* MAC depedent functions */
-} SK_GEINIT;
-
-/*
- * Error numbers and messages for skxmac2.c and skgeinit.c
- */
-#define SKERR_HWI_E001 (SK_ERRBASE_HWINIT)
-#define SKERR_HWI_E001MSG "SkXmClrExactAddr() has got illegal parameters"
-#define SKERR_HWI_E002 (SKERR_HWI_E001+1)
-#define SKERR_HWI_E002MSG "SkGeInit(): Level 1 call missing"
-#define SKERR_HWI_E003 (SKERR_HWI_E002+1)
-#define SKERR_HWI_E003MSG "SkGeInit() called with illegal init Level"
-#define SKERR_HWI_E004 (SKERR_HWI_E003+1)
-#define SKERR_HWI_E004MSG "SkGeInitPort(): Queue Size illegal configured"
-#define SKERR_HWI_E005 (SKERR_HWI_E004+1)
-#define SKERR_HWI_E005MSG "SkGeInitPort(): cannot init running ports"
-#define SKERR_HWI_E006 (SKERR_HWI_E005+1)
-#define SKERR_HWI_E006MSG "SkGeMacInit(): PState does not match HW state"
-#define SKERR_HWI_E007 (SKERR_HWI_E006+1)
-#define SKERR_HWI_E007MSG "SkXmInitDupMd() called with invalid Dup Mode"
-#define SKERR_HWI_E008 (SKERR_HWI_E007+1)
-#define SKERR_HWI_E008MSG "SkXmSetRxCmd() called with invalid Mode"
-#define SKERR_HWI_E009 (SKERR_HWI_E008+1)
-#define SKERR_HWI_E009MSG "SkGeCfgSync() called although PXSQSize zero"
-#define SKERR_HWI_E010 (SKERR_HWI_E009+1)
-#define SKERR_HWI_E010MSG "SkGeCfgSync() called with invalid parameters"
-#define SKERR_HWI_E011 (SKERR_HWI_E010+1)
-#define SKERR_HWI_E011MSG "SkGeInitPort(): Receive Queue Size too small"
-#define SKERR_HWI_E012 (SKERR_HWI_E011+1)
-#define SKERR_HWI_E012MSG "SkGeInitPort(): invalid Queue Size specified"
-#define SKERR_HWI_E013 (SKERR_HWI_E012+1)
-#define SKERR_HWI_E013MSG "SkGeInitPort(): cfg changed for running queue"
-#define SKERR_HWI_E014 (SKERR_HWI_E013+1)
-#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown GIPortUsage specified"
-#define SKERR_HWI_E015 (SKERR_HWI_E014+1)
-#define SKERR_HWI_E015MSG "Illegal Link mode parameter"
-#define SKERR_HWI_E016 (SKERR_HWI_E015+1)
-#define SKERR_HWI_E016MSG "Illegal Flow control mode parameter"
-#define SKERR_HWI_E017 (SKERR_HWI_E016+1)
-#define SKERR_HWI_E017MSG "Illegal value specified for GIPollTimerVal"
-#define SKERR_HWI_E018 (SKERR_HWI_E017+1)
-#define SKERR_HWI_E018MSG "FATAL: SkGeStopPort() does not terminate (Tx)"
-#define SKERR_HWI_E019 (SKERR_HWI_E018+1)
-#define SKERR_HWI_E019MSG "Illegal Speed parameter"
-#define SKERR_HWI_E020 (SKERR_HWI_E019+1)
-#define SKERR_HWI_E020MSG "Illegal Master/Slave parameter"
-#define SKERR_HWI_E021 (SKERR_HWI_E020+1)
-#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter"
-#define SKERR_HWI_E022 (SKERR_HWI_E021+1)
-#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address"
-#define SKERR_HWI_E023 (SKERR_HWI_E022+1)
-#define SKERR_HWI_E023MSG "SkGeInitPort(): Transmit Queue Size too small"
-#define SKERR_HWI_E024 (SKERR_HWI_E023+1)
-#define SKERR_HWI_E024MSG "FATAL: SkGeStopPort() does not terminate (Rx)"
-#define SKERR_HWI_E025 (SKERR_HWI_E024+1)
-#define SKERR_HWI_E025MSG ""
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_KR_PROTO
-
-/*
- * public functions in skgeinit.c
- */
-extern void SkGePollTxD(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL PollTxD);
-
-extern void SkGeYellowLED(
- SK_AC *pAC,
- SK_IOC IoC,
- int State);
-
-extern int SkGeCfgSync(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_U32 IntTime,
- SK_U32 LimCount,
- int SyncMode);
-
-extern void SkGeLoadLnkSyncCnt(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_U32 CntVal);
-
-extern void SkGeStopPort(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Dir,
- int RstMode);
-
-extern int SkGeInit(
- SK_AC *pAC,
- SK_IOC IoC,
- int Level);
-
-extern void SkGeDeInit(
- SK_AC *pAC,
- SK_IOC IoC);
-
-extern int SkGeInitPort(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkGeXmitLED(
- SK_AC *pAC,
- SK_IOC IoC,
- int Led,
- int Mode);
-
-extern int SkGeInitAssignRamToQueues(
- SK_AC *pAC,
- int ActivePort,
- SK_BOOL DualNet);
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacSoftRst(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacHardRst(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkXmInitMac(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkGmInitMac(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacInitPhy(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL DoLoop);
-
-extern void SkMacIrqDisable(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacFlushTxFifo(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacIrq(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern int SkMacAutoNegDone(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacAutoNegLipaPhy(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_U16 IStatus);
-
-extern int SkMacRxTxEnable(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacPromiscMode(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-
-extern void SkMacHashing(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-
-extern void SkXmPhyRead(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 SK_FAR *pVal);
-
-extern void SkXmPhyWrite(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 Val);
-
-extern void SkGmPhyRead(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 SK_FAR *pVal);
-
-extern void SkGmPhyWrite(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 Val);
-
-extern void SkXmClrExactAddr(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int StartNum,
- int StopNum);
-
-extern void SkXmAutoNegLipaXmac(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_U16 IStatus);
-
-extern int SkXmUpdateStats(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port);
-
-extern int SkGmUpdateStats(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port);
-
-extern int SkXmMacStatistic(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port,
- SK_U16 StatAddr,
- SK_U32 SK_FAR *pVal);
-
-extern int SkGmMacStatistic(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port,
- SK_U16 StatAddr,
- SK_U32 SK_FAR *pVal);
-
-extern int SkXmResetCounter(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port);
-
-extern int SkGmResetCounter(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port);
-
-extern int SkXmOverflowStatus(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port,
- SK_U16 IStatus,
- SK_U64 SK_FAR *pStatus);
-
-extern int SkGmOverflowStatus(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port,
- SK_U16 MacStatus,
- SK_U64 SK_FAR *pStatus);
-
-extern int SkGmCableDiagStatus(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL StartTest);
-
-#ifdef SK_DIAG
-extern void SkGePhyRead(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 *pVal);
-
-extern void SkGePhyWrite(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 Val);
-
-extern void SkMacSetRxCmd(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Mode);
-extern void SkMacCrcGener(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-extern void SkMacTimeStamp(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-extern void SkXmSendCont(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-#endif /* SK_DIAG */
-
-#else /* SK_KR_PROTO */
-
-/*
- * public functions in skgeinit.c
- */
-extern void SkGePollTxD();
-extern void SkGeYellowLED();
-extern int SkGeCfgSync();
-extern void SkGeLoadLnkSyncCnt();
-extern void SkGeStopPort();
-extern int SkGeInit();
-extern void SkGeDeInit();
-extern int SkGeInitPort();
-extern void SkGeXmitLED();
-extern int SkGeInitAssignRamToQueues();
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable();
-extern void SkMacSoftRst();
-extern void SkMacHardRst();
-extern void SkMacInitPhy();
-extern int SkMacRxTxEnable();
-extern void SkMacPromiscMode();
-extern void SkMacHashing();
-extern void SkMacIrqDisable();
-extern void SkMacFlushTxFifo();
-extern void SkMacIrq();
-extern int SkMacAutoNegDone();
-extern void SkMacAutoNegLipaPhy();
-extern void SkXmInitMac();
-extern void SkXmPhyRead();
-extern void SkXmPhyWrite();
-extern void SkGmInitMac();
-extern void SkGmPhyRead();
-extern void SkGmPhyWrite();
-extern void SkXmClrExactAddr();
-extern void SkXmAutoNegLipaXmac();
-extern int SkXmUpdateStats();
-extern int SkGmUpdateStats();
-extern int SkXmMacStatistic();
-extern int SkGmMacStatistic();
-extern int SkXmResetCounter();
-extern int SkGmResetCounter();
-extern int SkXmOverflowStatus();
-extern int SkGmOverflowStatus();
-extern int SkGmCableDiagStatus();
-
-#ifdef SK_DIAG
-extern void SkGePhyRead();
-extern void SkGePhyWrite();
-extern void SkMacSetRxCmd();
-extern void SkMacCrcGener();
-extern void SkMacTimeStamp();
-extern void SkXmSendCont();
-#endif /* SK_DIAG */
-
-#endif /* SK_KR_PROTO */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_SKGEINIT_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
deleted file mode 100644
index ddd304f1a48..00000000000
--- a/drivers/net/sk98lin/h/skgepnm2.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*****************************************************************************
- *
- * Name: skgepnm2.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.36 $
- * Date: $Date: 2003/05/23 12:45:13 $
- * Purpose: Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNM2_H_
-#define _SKGEPNM2_H_
-
-/*
- * General definitions
- */
-#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */
-#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */
-
-#define SK_PNMI_BUS_PCI 1 /* PCI bus*/
-
-/*
- * Actions
- */
-#define SK_PNMI_ACT_IDLE 1
-#define SK_PNMI_ACT_RESET 2
-#define SK_PNMI_ACT_SELFTEST 3
-#define SK_PNMI_ACT_RESETCNT 4
-
-/*
- * VPD releated defines
- */
-
-#define SK_PNMI_VPD_RW 1
-#define SK_PNMI_VPD_RO 2
-
-#define SK_PNMI_VPD_OK 0
-#define SK_PNMI_VPD_NOTFOUND 1
-#define SK_PNMI_VPD_CUT 2
-#define SK_PNMI_VPD_TIMEOUT 3
-#define SK_PNMI_VPD_FULL 4
-#define SK_PNMI_VPD_NOWRITE 5
-#define SK_PNMI_VPD_FATAL 6
-
-#define SK_PNMI_VPD_IGNORE 0
-#define SK_PNMI_VPD_CREATE 1
-#define SK_PNMI_VPD_DELETE 2
-
-
-/*
- * RLMT related defines
- */
-#define SK_PNMI_DEF_RLMT_CHG_THRES 240 /* 4 changes per minute */
-
-
-/*
- * VCT internal status values
- */
-#define SK_PNMI_VCT_PENDING 32
-#define SK_PNMI_VCT_TEST_DONE 64
-#define SK_PNMI_VCT_LINK 128
-
-/*
- * Internal table definitions
- */
-#define SK_PNMI_GET 0
-#define SK_PNMI_PRESET 1
-#define SK_PNMI_SET 2
-
-#define SK_PNMI_RO 0
-#define SK_PNMI_RW 1
-#define SK_PNMI_WO 2
-
-typedef struct s_OidTabEntry {
- SK_U32 Id;
- SK_U32 InstanceNo;
- unsigned int StructSize;
- unsigned int Offset;
- int Access;
- int (* Func)(SK_AC *pAc, SK_IOC pIo, int action,
- SK_U32 Id, char* pBuf, unsigned int* pLen,
- SK_U32 Instance, unsigned int TableIndex,
- SK_U32 NetNumber);
- SK_U16 Param;
-} SK_PNMI_TAB_ENTRY;
-
-
-/*
- * Trap lengths
- */
-#define SK_PNMI_TRAP_SIMPLE_LEN 17
-#define SK_PNMI_TRAP_SENSOR_LEN_BASE 46
-#define SK_PNMI_TRAP_RLMT_CHANGE_LEN 23
-#define SK_PNMI_TRAP_RLMT_PORT_LEN 23
-
-/*
- * Number of MAC types supported
- */
-#define SK_PNMI_MAC_TYPES (SK_MAC_GMAC + 1)
-
-/*
- * MAC statistic data list (overall set for MAC types used)
- */
-enum SK_MACSTATS {
- SK_PNMI_HTX = 0,
- SK_PNMI_HTX_OCTET,
- SK_PNMI_HTX_OCTETHIGH = SK_PNMI_HTX_OCTET,
- SK_PNMI_HTX_OCTETLOW,
- SK_PNMI_HTX_BROADCAST,
- SK_PNMI_HTX_MULTICAST,
- SK_PNMI_HTX_UNICAST,
- SK_PNMI_HTX_BURST,
- SK_PNMI_HTX_PMACC,
- SK_PNMI_HTX_MACC,
- SK_PNMI_HTX_COL,
- SK_PNMI_HTX_SINGLE_COL,
- SK_PNMI_HTX_MULTI_COL,
- SK_PNMI_HTX_EXCESS_COL,
- SK_PNMI_HTX_LATE_COL,
- SK_PNMI_HTX_DEFFERAL,
- SK_PNMI_HTX_EXCESS_DEF,
- SK_PNMI_HTX_UNDERRUN,
- SK_PNMI_HTX_CARRIER,
- SK_PNMI_HTX_UTILUNDER,
- SK_PNMI_HTX_UTILOVER,
- SK_PNMI_HTX_64,
- SK_PNMI_HTX_127,
- SK_PNMI_HTX_255,
- SK_PNMI_HTX_511,
- SK_PNMI_HTX_1023,
- SK_PNMI_HTX_MAX,
- SK_PNMI_HTX_LONGFRAMES,
- SK_PNMI_HTX_SYNC,
- SK_PNMI_HTX_SYNC_OCTET,
- SK_PNMI_HTX_RESERVED,
-
- SK_PNMI_HRX,
- SK_PNMI_HRX_OCTET,
- SK_PNMI_HRX_OCTETHIGH = SK_PNMI_HRX_OCTET,
- SK_PNMI_HRX_OCTETLOW,
- SK_PNMI_HRX_BADOCTET,
- SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET,
- SK_PNMI_HRX_BADOCTETLOW,
- SK_PNMI_HRX_BROADCAST,
- SK_PNMI_HRX_MULTICAST,
- SK_PNMI_HRX_UNICAST,
- SK_PNMI_HRX_PMACC,
- SK_PNMI_HRX_MACC,
- SK_PNMI_HRX_PMACC_ERR,
- SK_PNMI_HRX_MACC_UNKWN,
- SK_PNMI_HRX_BURST,
- SK_PNMI_HRX_MISSED,
- SK_PNMI_HRX_FRAMING,
- SK_PNMI_HRX_UNDERSIZE,
- SK_PNMI_HRX_OVERFLOW,
- SK_PNMI_HRX_JABBER,
- SK_PNMI_HRX_CARRIER,
- SK_PNMI_HRX_IRLENGTH,
- SK_PNMI_HRX_SYMBOL,
- SK_PNMI_HRX_SHORTS,
- SK_PNMI_HRX_RUNT,
- SK_PNMI_HRX_TOO_LONG,
- SK_PNMI_HRX_FCS,
- SK_PNMI_HRX_CEXT,
- SK_PNMI_HRX_UTILUNDER,
- SK_PNMI_HRX_UTILOVER,
- SK_PNMI_HRX_64,
- SK_PNMI_HRX_127,
- SK_PNMI_HRX_255,
- SK_PNMI_HRX_511,
- SK_PNMI_HRX_1023,
- SK_PNMI_HRX_MAX,
- SK_PNMI_HRX_LONGFRAMES,
-
- SK_PNMI_HRX_RESERVED,
-
- SK_PNMI_MAX_IDX /* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */
-};
-
-/*
- * MAC specific data
- */
-typedef struct s_PnmiStatAddr {
- SK_U16 Reg; /* MAC register containing the value */
- SK_BOOL GetOffset; /* TRUE: Offset managed by PNMI (call GetStatVal())*/
-} SK_PNMI_STATADDR;
-
-
-/*
- * SK_PNMI_STRUCT_DATA copy offset evaluation macros
- */
-#define SK_PNMI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_MAI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_VPD_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e))
-#define SK_PNMI_SEN_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e))
-#define SK_PNMI_CHK_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e))
-#define SK_PNMI_STA_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e))
-#define SK_PNMI_CNF_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e))
-#define SK_PNMI_RLM_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e))
-#define SK_PNMI_MON_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e))
-#define SK_PNMI_TRP_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e))
-
-#define SK_PNMI_SET_STAT(b,s,o) {SK_U32 Val32; char *pVal; \
- Val32 = (s); \
- pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
- &(((SK_PNMI_STRUCT_DATA *)0)-> \
- ReturnStatus.ErrorStatus)); \
- SK_PNMI_STORE_U32(pVal, Val32); \
- Val32 = (o); \
- pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
- &(((SK_PNMI_STRUCT_DATA *)0)-> \
- ReturnStatus.ErrorOffset)); \
- SK_PNMI_STORE_U32(pVal, Val32);}
-
-/*
- * Time macros
- */
-#ifndef SK_PNMI_HUNDREDS_SEC
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t) (t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC))
-#endif /* !SK_TICKS_PER_SEC */
-#endif /* !SK_PNMI_HUNDREDS_SEC */
-
-/*
- * Macros to work around alignment problems
- */
-#ifndef SK_PNMI_STORE_U16
-#define SK_PNMI_STORE_U16(p,v) {*(char *)(p) = *((char *)&(v)); \
- *((char *)(p) + 1) = \
- *(((char *)&(v)) + 1);}
-#endif
-
-#ifndef SK_PNMI_STORE_U32
-#define SK_PNMI_STORE_U32(p,v) {*(char *)(p) = *((char *)&(v)); \
- *((char *)(p) + 1) = \
- *(((char *)&(v)) + 1); \
- *((char *)(p) + 2) = \
- *(((char *)&(v)) + 2); \
- *((char *)(p) + 3) = \
- *(((char *)&(v)) + 3);}
-#endif
-
-#ifndef SK_PNMI_STORE_U64
-#define SK_PNMI_STORE_U64(p,v) {*(char *)(p) = *((char *)&(v)); \
- *((char *)(p) + 1) = \
- *(((char *)&(v)) + 1); \
- *((char *)(p) + 2) = \
- *(((char *)&(v)) + 2); \
- *((char *)(p) + 3) = \
- *(((char *)&(v)) + 3); \
- *((char *)(p) + 4) = \
- *(((char *)&(v)) + 4); \
- *((char *)(p) + 5) = \
- *(((char *)&(v)) + 5); \
- *((char *)(p) + 6) = \
- *(((char *)&(v)) + 6); \
- *((char *)(p) + 7) = \
- *(((char *)&(v)) + 7);}
-#endif
-
-#ifndef SK_PNMI_READ_U16
-#define SK_PNMI_READ_U16(p,v) {*((char *)&(v)) = *(char *)(p); \
- *(((char *)&(v)) + 1) = \
- *((char *)(p) + 1);}
-#endif
-
-#ifndef SK_PNMI_READ_U32
-#define SK_PNMI_READ_U32(p,v) {*((char *)&(v)) = *(char *)(p); \
- *(((char *)&(v)) + 1) = \
- *((char *)(p) + 1); \
- *(((char *)&(v)) + 2) = \
- *((char *)(p) + 2); \
- *(((char *)&(v)) + 3) = \
- *((char *)(p) + 3);}
-#endif
-
-#ifndef SK_PNMI_READ_U64
-#define SK_PNMI_READ_U64(p,v) {*((char *)&(v)) = *(char *)(p); \
- *(((char *)&(v)) + 1) = \
- *((char *)(p) + 1); \
- *(((char *)&(v)) + 2) = \
- *((char *)(p) + 2); \
- *(((char *)&(v)) + 3) = \
- *((char *)(p) + 3); \
- *(((char *)&(v)) + 4) = \
- *((char *)(p) + 4); \
- *(((char *)&(v)) + 5) = \
- *((char *)(p) + 5); \
- *(((char *)&(v)) + 6) = \
- *((char *)(p) + 6); \
- *(((char *)&(v)) + 7) = \
- *((char *)(p) + 7);}
-#endif
-
-/*
- * Macros for Debug
- */
-#ifdef DEBUG
-
-#define SK_PNMI_CHECKFLAGS(vSt) {if (pAC->Pnmi.MacUpdatedFlag > 0 || \
- pAC->Pnmi.RlmtUpdatedFlag > 0 || \
- pAC->Pnmi.SirqUpdatedFlag > 0) { \
- SK_DBG_MSG(pAC, \
- SK_DBGMOD_PNMI, \
- SK_DBGCAT_CTRL, \
- ("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \
- vSt, \
- pAC->Pnmi.MacUpdatedFlag, \
- pAC->Pnmi.RlmtUpdatedFlag, \
- pAC->Pnmi.SirqUpdatedFlag))}}
-
-#else /* !DEBUG */
-
-#define SK_PNMI_CHECKFLAGS(vSt) /* Nothing */
-
-#endif /* !DEBUG */
-
-#endif /* _SKGEPNM2_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h
deleted file mode 100644
index 1ed214ccb25..00000000000
--- a/drivers/net/sk98lin/h/skgepnmi.h
+++ /dev/null
@@ -1,962 +0,0 @@
-/*****************************************************************************
- *
- * Name: skgepnmi.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.62 $
- * Date: $Date: 2003/08/15 12:31:52 $
- * Purpose: Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNMI_H_
-#define _SKGEPNMI_H_
-
-/*
- * Include dependencies
- */
-#include "h/sktypes.h"
-#include "h/skerror.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skaddr.h"
-#include "h/skrlmt.h"
-#include "h/skvpd.h"
-
-/*
- * Management Database Version
- */
-#define SK_PNMI_MDB_VERSION 0x00030001 /* 3.1 */
-
-
-/*
- * Event definitions
- */
-#define SK_PNMI_EVT_SIRQ_OVERFLOW 1 /* Counter overflow */
-#define SK_PNMI_EVT_SEN_WAR_LOW 2 /* Lower war thres exceeded */
-#define SK_PNMI_EVT_SEN_WAR_UPP 3 /* Upper war thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_LOW 4 /* Lower err thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_UPP 5 /* Upper err thres exceeded */
-#define SK_PNMI_EVT_CHG_EST_TIMER 6 /* Timer event for RLMT Chg */
-#define SK_PNMI_EVT_UTILIZATION_TIMER 7 /* Timer event for Utiliza. */
-#define SK_PNMI_EVT_CLEAR_COUNTER 8 /* Clear statistic counters */
-#define SK_PNMI_EVT_XMAC_RESET 9 /* XMAC will be reset */
-
-#define SK_PNMI_EVT_RLMT_PORT_UP 10 /* Port came logically up */
-#define SK_PNMI_EVT_RLMT_PORT_DOWN 11 /* Port went logically down */
-#define SK_PNMI_EVT_RLMT_SEGMENTATION 13 /* Two SP root bridges found */
-#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN 14 /* Port went logically down */
-#define SK_PNMI_EVT_RLMT_ACTIVE_UP 15 /* Port came logically up */
-#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* 1. Parameter is number of nets
- 1 = single net; 2 = dual net */
-#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */
-
-
-/*
- * Return values
- */
-#define SK_PNMI_ERR_OK 0
-#define SK_PNMI_ERR_GENERAL 1
-#define SK_PNMI_ERR_TOO_SHORT 2
-#define SK_PNMI_ERR_BAD_VALUE 3
-#define SK_PNMI_ERR_READ_ONLY 4
-#define SK_PNMI_ERR_UNKNOWN_OID 5
-#define SK_PNMI_ERR_UNKNOWN_INST 6
-#define SK_PNMI_ERR_UNKNOWN_NET 7
-#define SK_PNMI_ERR_NOT_SUPPORTED 10
-
-
-/*
- * Return values of driver reset function SK_DRIVER_RESET() and
- * driver event function SK_DRIVER_EVENT()
- */
-#define SK_PNMI_ERR_OK 0
-#define SK_PNMI_ERR_FAIL 1
-
-
-/*
- * Return values of driver test function SK_DRIVER_SELFTEST()
- */
-#define SK_PNMI_TST_UNKNOWN (1 << 0)
-#define SK_PNMI_TST_TRANCEIVER (1 << 1)
-#define SK_PNMI_TST_ASIC (1 << 2)
-#define SK_PNMI_TST_SENSOR (1 << 3)
-#define SK_PNMI_TST_POWERMGMT (1 << 4)
-#define SK_PNMI_TST_PCI (1 << 5)
-#define SK_PNMI_TST_MAC (1 << 6)
-
-
-/*
- * RLMT specific definitions
- */
-#define SK_PNMI_RLMT_STATUS_STANDBY 1
-#define SK_PNMI_RLMT_STATUS_ACTIVE 2
-#define SK_PNMI_RLMT_STATUS_ERROR 3
-
-#define SK_PNMI_RLMT_LSTAT_PHY_DOWN 1
-#define SK_PNMI_RLMT_LSTAT_AUTONEG 2
-#define SK_PNMI_RLMT_LSTAT_LOG_DOWN 3
-#define SK_PNMI_RLMT_LSTAT_LOG_UP 4
-#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5
-
-#define SK_PNMI_RLMT_MODE_CHK_LINK (SK_RLMT_CHECK_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_RX (SK_RLMT_CHECK_LOC_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_SPT (SK_RLMT_CHECK_SEG)
-/* #define SK_PNMI_RLMT_MODE_CHK_EX */
-
-/*
- * OID definition
- */
-#ifndef _NDIS_ /* Check, whether NDIS already included OIDs */
-
-#define OID_GEN_XMIT_OK 0x00020101
-#define OID_GEN_RCV_OK 0x00020102
-#define OID_GEN_XMIT_ERROR 0x00020103
-#define OID_GEN_RCV_ERROR 0x00020104
-#define OID_GEN_RCV_NO_BUFFER 0x00020105
-
-/* #define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 */
-#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
-/* #define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 */
-#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
-/* #define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 */
-#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
-/* #define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 */
-#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
-/* #define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 */
-#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
-/* #define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B */
-#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
-#define OID_GEN_RCV_CRC_ERROR 0x0002020D
-#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
-
-#define OID_802_3_PERMANENT_ADDRESS 0x01010101
-#define OID_802_3_CURRENT_ADDRESS 0x01010102
-/* #define OID_802_3_MULTICAST_LIST 0x01010103 */
-/* #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 */
-/* #define OID_802_3_MAC_OPTIONS 0x01010105 */
-
-#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
-#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
-#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
-#define OID_802_3_XMIT_DEFERRED 0x01020201
-#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
-#define OID_802_3_RCV_OVERRUN 0x01020203
-#define OID_802_3_XMIT_UNDERRUN 0x01020204
-#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
-#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
-
-/*
- * PnP and PM OIDs
- */
-#ifdef SK_POWER_MGMT
-#define OID_PNP_CAPABILITIES 0xFD010100
-#define OID_PNP_SET_POWER 0xFD010101
-#define OID_PNP_QUERY_POWER 0xFD010102
-#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
-#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
-#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
-#endif /* SK_POWER_MGMT */
-
-#endif /* _NDIS_ */
-
-#define OID_SKGE_MDB_VERSION 0xFF010100
-#define OID_SKGE_SUPPORTED_LIST 0xFF010101
-#define OID_SKGE_VPD_FREE_BYTES 0xFF010102
-#define OID_SKGE_VPD_ENTRIES_LIST 0xFF010103
-#define OID_SKGE_VPD_ENTRIES_NUMBER 0xFF010104
-#define OID_SKGE_VPD_KEY 0xFF010105
-#define OID_SKGE_VPD_VALUE 0xFF010106
-#define OID_SKGE_VPD_ACCESS 0xFF010107
-#define OID_SKGE_VPD_ACTION 0xFF010108
-
-#define OID_SKGE_PORT_NUMBER 0xFF010110
-#define OID_SKGE_DEVICE_TYPE 0xFF010111
-#define OID_SKGE_DRIVER_DESCR 0xFF010112
-#define OID_SKGE_DRIVER_VERSION 0xFF010113
-#define OID_SKGE_HW_DESCR 0xFF010114
-#define OID_SKGE_HW_VERSION 0xFF010115
-#define OID_SKGE_CHIPSET 0xFF010116
-#define OID_SKGE_ACTION 0xFF010117
-#define OID_SKGE_RESULT 0xFF010118
-#define OID_SKGE_BUS_TYPE 0xFF010119
-#define OID_SKGE_BUS_SPEED 0xFF01011A
-#define OID_SKGE_BUS_WIDTH 0xFF01011B
-/* 0xFF01011C unused */
-#define OID_SKGE_DIAG_ACTION 0xFF01011D
-#define OID_SKGE_DIAG_RESULT 0xFF01011E
-#define OID_SKGE_MTU 0xFF01011F
-#define OID_SKGE_PHYS_CUR_ADDR 0xFF010120
-#define OID_SKGE_PHYS_FAC_ADDR 0xFF010121
-#define OID_SKGE_PMD 0xFF010122
-#define OID_SKGE_CONNECTOR 0xFF010123
-#define OID_SKGE_LINK_CAP 0xFF010124
-#define OID_SKGE_LINK_MODE 0xFF010125
-#define OID_SKGE_LINK_MODE_STATUS 0xFF010126
-#define OID_SKGE_LINK_STATUS 0xFF010127
-#define OID_SKGE_FLOWCTRL_CAP 0xFF010128
-#define OID_SKGE_FLOWCTRL_MODE 0xFF010129
-#define OID_SKGE_FLOWCTRL_STATUS 0xFF01012A
-#define OID_SKGE_PHY_OPERATION_CAP 0xFF01012B
-#define OID_SKGE_PHY_OPERATION_MODE 0xFF01012C
-#define OID_SKGE_PHY_OPERATION_STATUS 0xFF01012D
-#define OID_SKGE_MULTICAST_LIST 0xFF01012E
-#define OID_SKGE_CURRENT_PACKET_FILTER 0xFF01012F
-
-#define OID_SKGE_TRAP 0xFF010130
-#define OID_SKGE_TRAP_NUMBER 0xFF010131
-
-#define OID_SKGE_RLMT_MODE 0xFF010140
-#define OID_SKGE_RLMT_PORT_NUMBER 0xFF010141
-#define OID_SKGE_RLMT_PORT_ACTIVE 0xFF010142
-#define OID_SKGE_RLMT_PORT_PREFERRED 0xFF010143
-#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160
-
-#define OID_SKGE_SPEED_CAP 0xFF010170
-#define OID_SKGE_SPEED_MODE 0xFF010171
-#define OID_SKGE_SPEED_STATUS 0xFF010172
-
-#define OID_SKGE_BOARDLEVEL 0xFF010180
-
-#define OID_SKGE_SENSOR_NUMBER 0xFF020100
-#define OID_SKGE_SENSOR_INDEX 0xFF020101
-#define OID_SKGE_SENSOR_DESCR 0xFF020102
-#define OID_SKGE_SENSOR_TYPE 0xFF020103
-#define OID_SKGE_SENSOR_VALUE 0xFF020104
-#define OID_SKGE_SENSOR_WAR_THRES_LOW 0xFF020105
-#define OID_SKGE_SENSOR_WAR_THRES_UPP 0xFF020106
-#define OID_SKGE_SENSOR_ERR_THRES_LOW 0xFF020107
-#define OID_SKGE_SENSOR_ERR_THRES_UPP 0xFF020108
-#define OID_SKGE_SENSOR_STATUS 0xFF020109
-#define OID_SKGE_SENSOR_WAR_CTS 0xFF02010A
-#define OID_SKGE_SENSOR_ERR_CTS 0xFF02010B
-#define OID_SKGE_SENSOR_WAR_TIME 0xFF02010C
-#define OID_SKGE_SENSOR_ERR_TIME 0xFF02010D
-
-#define OID_SKGE_CHKSM_NUMBER 0xFF020110
-#define OID_SKGE_CHKSM_RX_OK_CTS 0xFF020111
-#define OID_SKGE_CHKSM_RX_UNABLE_CTS 0xFF020112
-#define OID_SKGE_CHKSM_RX_ERR_CTS 0xFF020113
-#define OID_SKGE_CHKSM_TX_OK_CTS 0xFF020114
-#define OID_SKGE_CHKSM_TX_UNABLE_CTS 0xFF020115
-
-#define OID_SKGE_STAT_TX 0xFF020120
-#define OID_SKGE_STAT_TX_OCTETS 0xFF020121
-#define OID_SKGE_STAT_TX_BROADCAST 0xFF020122
-#define OID_SKGE_STAT_TX_MULTICAST 0xFF020123
-#define OID_SKGE_STAT_TX_UNICAST 0xFF020124
-#define OID_SKGE_STAT_TX_LONGFRAMES 0xFF020125
-#define OID_SKGE_STAT_TX_BURST 0xFF020126
-#define OID_SKGE_STAT_TX_PFLOWC 0xFF020127
-#define OID_SKGE_STAT_TX_FLOWC 0xFF020128
-#define OID_SKGE_STAT_TX_SINGLE_COL 0xFF020129
-#define OID_SKGE_STAT_TX_MULTI_COL 0xFF02012A
-#define OID_SKGE_STAT_TX_EXCESS_COL 0xFF02012B
-#define OID_SKGE_STAT_TX_LATE_COL 0xFF02012C
-#define OID_SKGE_STAT_TX_DEFFERAL 0xFF02012D
-#define OID_SKGE_STAT_TX_EXCESS_DEF 0xFF02012E
-#define OID_SKGE_STAT_TX_UNDERRUN 0xFF02012F
-#define OID_SKGE_STAT_TX_CARRIER 0xFF020130
-/* #define OID_SKGE_STAT_TX_UTIL 0xFF020131 */
-#define OID_SKGE_STAT_TX_64 0xFF020132
-#define OID_SKGE_STAT_TX_127 0xFF020133
-#define OID_SKGE_STAT_TX_255 0xFF020134
-#define OID_SKGE_STAT_TX_511 0xFF020135
-#define OID_SKGE_STAT_TX_1023 0xFF020136
-#define OID_SKGE_STAT_TX_MAX 0xFF020137
-#define OID_SKGE_STAT_TX_SYNC 0xFF020138
-#define OID_SKGE_STAT_TX_SYNC_OCTETS 0xFF020139
-#define OID_SKGE_STAT_RX 0xFF02013A
-#define OID_SKGE_STAT_RX_OCTETS 0xFF02013B
-#define OID_SKGE_STAT_RX_BROADCAST 0xFF02013C
-#define OID_SKGE_STAT_RX_MULTICAST 0xFF02013D
-#define OID_SKGE_STAT_RX_UNICAST 0xFF02013E
-#define OID_SKGE_STAT_RX_PFLOWC 0xFF02013F
-#define OID_SKGE_STAT_RX_FLOWC 0xFF020140
-#define OID_SKGE_STAT_RX_PFLOWC_ERR 0xFF020141
-#define OID_SKGE_STAT_RX_FLOWC_UNKWN 0xFF020142
-#define OID_SKGE_STAT_RX_BURST 0xFF020143
-#define OID_SKGE_STAT_RX_MISSED 0xFF020144
-#define OID_SKGE_STAT_RX_FRAMING 0xFF020145
-#define OID_SKGE_STAT_RX_OVERFLOW 0xFF020146
-#define OID_SKGE_STAT_RX_JABBER 0xFF020147
-#define OID_SKGE_STAT_RX_CARRIER 0xFF020148
-#define OID_SKGE_STAT_RX_IR_LENGTH 0xFF020149
-#define OID_SKGE_STAT_RX_SYMBOL 0xFF02014A
-#define OID_SKGE_STAT_RX_SHORTS 0xFF02014B
-#define OID_SKGE_STAT_RX_RUNT 0xFF02014C
-#define OID_SKGE_STAT_RX_CEXT 0xFF02014D
-#define OID_SKGE_STAT_RX_TOO_LONG 0xFF02014E
-#define OID_SKGE_STAT_RX_FCS 0xFF02014F
-/* #define OID_SKGE_STAT_RX_UTIL 0xFF020150 */
-#define OID_SKGE_STAT_RX_64 0xFF020151
-#define OID_SKGE_STAT_RX_127 0xFF020152
-#define OID_SKGE_STAT_RX_255 0xFF020153
-#define OID_SKGE_STAT_RX_511 0xFF020154
-#define OID_SKGE_STAT_RX_1023 0xFF020155
-#define OID_SKGE_STAT_RX_MAX 0xFF020156
-#define OID_SKGE_STAT_RX_LONGFRAMES 0xFF020157
-
-#define OID_SKGE_RLMT_CHANGE_CTS 0xFF020160
-#define OID_SKGE_RLMT_CHANGE_TIME 0xFF020161
-#define OID_SKGE_RLMT_CHANGE_ESTIM 0xFF020162
-#define OID_SKGE_RLMT_CHANGE_THRES 0xFF020163
-
-#define OID_SKGE_RLMT_PORT_INDEX 0xFF020164
-#define OID_SKGE_RLMT_STATUS 0xFF020165
-#define OID_SKGE_RLMT_TX_HELLO_CTS 0xFF020166
-#define OID_SKGE_RLMT_RX_HELLO_CTS 0xFF020167
-#define OID_SKGE_RLMT_TX_SP_REQ_CTS 0xFF020168
-#define OID_SKGE_RLMT_RX_SP_CTS 0xFF020169
-
-#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150
-#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151
-#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152
-#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153
-#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154
-#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155
-
-#define OID_SKGE_TX_SW_QUEUE_LEN 0xFF020170
-#define OID_SKGE_TX_SW_QUEUE_MAX 0xFF020171
-#define OID_SKGE_TX_RETRY 0xFF020172
-#define OID_SKGE_RX_INTR_CTS 0xFF020173
-#define OID_SKGE_TX_INTR_CTS 0xFF020174
-#define OID_SKGE_RX_NO_BUF_CTS 0xFF020175
-#define OID_SKGE_TX_NO_BUF_CTS 0xFF020176
-#define OID_SKGE_TX_USED_DESCR_NO 0xFF020177
-#define OID_SKGE_RX_DELIVERED_CTS 0xFF020178
-#define OID_SKGE_RX_OCTETS_DELIV_CTS 0xFF020179
-#define OID_SKGE_RX_HW_ERROR_CTS 0xFF02017A
-#define OID_SKGE_TX_HW_ERROR_CTS 0xFF02017B
-#define OID_SKGE_IN_ERRORS_CTS 0xFF02017C
-#define OID_SKGE_OUT_ERROR_CTS 0xFF02017D
-#define OID_SKGE_ERR_RECOVERY_CTS 0xFF02017E
-#define OID_SKGE_SYSUPTIME 0xFF02017F
-
-#define OID_SKGE_ALL_DATA 0xFF020190
-
-/* Defines for VCT. */
-#define OID_SKGE_VCT_GET 0xFF020200
-#define OID_SKGE_VCT_SET 0xFF020201
-#define OID_SKGE_VCT_STATUS 0xFF020202
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define OID_SKGE_DIAG_MODE 0xFF020204
-#endif /* SK_DIAG_SUPPORT */
-
-/* New OIDs */
-#define OID_SKGE_DRIVER_RELDATE 0xFF020210
-#define OID_SKGE_DRIVER_FILENAME 0xFF020211
-#define OID_SKGE_CHIPID 0xFF020212
-#define OID_SKGE_RAMSIZE 0xFF020213
-#define OID_SKGE_VAUXAVAIL 0xFF020214
-#define OID_SKGE_PHY_TYPE 0xFF020215
-#define OID_SKGE_PHY_LP_MODE 0xFF020216
-
-/* VCT struct to store a backup copy of VCT data after a port reset. */
-typedef struct s_PnmiVct {
- SK_U8 VctStatus;
- SK_U8 PCableLen;
- SK_U32 PMdiPairLen[4];
- SK_U8 PMdiPairSts[4];
-} SK_PNMI_VCT;
-
-
-/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */
-#define SK_PNMI_VCT_NONE 0
-#define SK_PNMI_VCT_OLD_VCT_DATA 1
-#define SK_PNMI_VCT_NEW_VCT_DATA 2
-#define SK_PNMI_VCT_OLD_DSP_DATA 4
-#define SK_PNMI_VCT_NEW_DSP_DATA 8
-#define SK_PNMI_VCT_RUNNING 16
-
-
-/* VCT cable test status. */
-#define SK_PNMI_VCT_NORMAL_CABLE 0
-#define SK_PNMI_VCT_SHORT_CABLE 1
-#define SK_PNMI_VCT_OPEN_CABLE 2
-#define SK_PNMI_VCT_TEST_FAIL 3
-#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4
-
-#define OID_SKGE_TRAP_SEN_WAR_LOW 500
-#define OID_SKGE_TRAP_SEN_WAR_UPP 501
-#define OID_SKGE_TRAP_SEN_ERR_LOW 502
-#define OID_SKGE_TRAP_SEN_ERR_UPP 503
-#define OID_SKGE_TRAP_RLMT_CHANGE_THRES 520
-#define OID_SKGE_TRAP_RLMT_CHANGE_PORT 521
-#define OID_SKGE_TRAP_RLMT_PORT_DOWN 522
-#define OID_SKGE_TRAP_RLMT_PORT_UP 523
-#define OID_SKGE_TRAP_RLMT_SEGMENTATION 524
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define SK_DIAG_ATTACHED 2
-#define SK_DIAG_RUNNING 1
-#define SK_DIAG_IDLE 0
-#endif /* SK_DIAG_SUPPORT */
-
-/*
- * Generic PNMI IOCTL subcommand definitions.
- */
-#define SK_GET_SINGLE_VAR 1
-#define SK_SET_SINGLE_VAR 2
-#define SK_PRESET_SINGLE_VAR 3
-#define SK_GET_FULL_MIB 4
-#define SK_SET_FULL_MIB 5
-#define SK_PRESET_FULL_MIB 6
-
-
-/*
- * Define error numbers and messages for syslog
- */
-#define SK_PNMI_ERR001 (SK_ERRBASE_PNMI + 1)
-#define SK_PNMI_ERR001MSG "SkPnmiGetStruct: Unknown OID"
-#define SK_PNMI_ERR002 (SK_ERRBASE_PNMI + 2)
-#define SK_PNMI_ERR002MSG "SkPnmiGetStruct: Cannot read VPD keys"
-#define SK_PNMI_ERR003 (SK_ERRBASE_PNMI + 3)
-#define SK_PNMI_ERR003MSG "OidStruct: Called with wrong OID"
-#define SK_PNMI_ERR004 (SK_ERRBASE_PNMI + 4)
-#define SK_PNMI_ERR004MSG "OidStruct: Called with wrong action"
-#define SK_PNMI_ERR005 (SK_ERRBASE_PNMI + 5)
-#define SK_PNMI_ERR005MSG "Perform: Cannot reset driver"
-#define SK_PNMI_ERR006 (SK_ERRBASE_PNMI + 6)
-#define SK_PNMI_ERR006MSG "Perform: Unknown OID action command"
-#define SK_PNMI_ERR007 (SK_ERRBASE_PNMI + 7)
-#define SK_PNMI_ERR007MSG "General: Driver description not initialized"
-#define SK_PNMI_ERR008 (SK_ERRBASE_PNMI + 8)
-#define SK_PNMI_ERR008MSG "Addr: Tried to get unknown OID"
-#define SK_PNMI_ERR009 (SK_ERRBASE_PNMI + 9)
-#define SK_PNMI_ERR009MSG "Addr: Unknown OID"
-#define SK_PNMI_ERR010 (SK_ERRBASE_PNMI + 10)
-#define SK_PNMI_ERR010MSG "CsumStat: Unknown OID"
-#define SK_PNMI_ERR011 (SK_ERRBASE_PNMI + 11)
-#define SK_PNMI_ERR011MSG "SensorStat: Sensor descr string too long"
-#define SK_PNMI_ERR012 (SK_ERRBASE_PNMI + 12)
-#define SK_PNMI_ERR012MSG "SensorStat: Unknown OID"
-#define SK_PNMI_ERR013 (SK_ERRBASE_PNMI + 13)
-#define SK_PNMI_ERR013MSG ""
-#define SK_PNMI_ERR014 (SK_ERRBASE_PNMI + 14)
-#define SK_PNMI_ERR014MSG "Vpd: Cannot read VPD keys"
-#define SK_PNMI_ERR015 (SK_ERRBASE_PNMI + 15)
-#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys to small"
-#define SK_PNMI_ERR016 (SK_ERRBASE_PNMI + 16)
-#define SK_PNMI_ERR016MSG "Vpd: Key string too long"
-#define SK_PNMI_ERR017 (SK_ERRBASE_PNMI + 17)
-#define SK_PNMI_ERR017MSG "Vpd: Invalid VPD status pointer"
-#define SK_PNMI_ERR018 (SK_ERRBASE_PNMI + 18)
-#define SK_PNMI_ERR018MSG "Vpd: VPD data not valid"
-#define SK_PNMI_ERR019 (SK_ERRBASE_PNMI + 19)
-#define SK_PNMI_ERR019MSG "Vpd: VPD entries list string too long"
-#define SK_PNMI_ERR021 (SK_ERRBASE_PNMI + 21)
-#define SK_PNMI_ERR021MSG "Vpd: VPD data string too long"
-#define SK_PNMI_ERR022 (SK_ERRBASE_PNMI + 22)
-#define SK_PNMI_ERR022MSG "Vpd: VPD data string too long should be errored before"
-#define SK_PNMI_ERR023 (SK_ERRBASE_PNMI + 23)
-#define SK_PNMI_ERR023MSG "Vpd: Unknown OID in get action"
-#define SK_PNMI_ERR024 (SK_ERRBASE_PNMI + 24)
-#define SK_PNMI_ERR024MSG "Vpd: Unknown OID in preset/set action"
-#define SK_PNMI_ERR025 (SK_ERRBASE_PNMI + 25)
-#define SK_PNMI_ERR025MSG "Vpd: Cannot write VPD after modify entry"
-#define SK_PNMI_ERR026 (SK_ERRBASE_PNMI + 26)
-#define SK_PNMI_ERR026MSG "Vpd: Cannot update VPD"
-#define SK_PNMI_ERR027 (SK_ERRBASE_PNMI + 27)
-#define SK_PNMI_ERR027MSG "Vpd: Cannot delete VPD entry"
-#define SK_PNMI_ERR028 (SK_ERRBASE_PNMI + 28)
-#define SK_PNMI_ERR028MSG "Vpd: Cannot update VPD after delete entry"
-#define SK_PNMI_ERR029 (SK_ERRBASE_PNMI + 29)
-#define SK_PNMI_ERR029MSG "General: Driver description string too long"
-#define SK_PNMI_ERR030 (SK_ERRBASE_PNMI + 30)
-#define SK_PNMI_ERR030MSG "General: Driver version not initialized"
-#define SK_PNMI_ERR031 (SK_ERRBASE_PNMI + 31)
-#define SK_PNMI_ERR031MSG "General: Driver version string too long"
-#define SK_PNMI_ERR032 (SK_ERRBASE_PNMI + 32)
-#define SK_PNMI_ERR032MSG "General: Cannot read VPD Name for HW descr"
-#define SK_PNMI_ERR033 (SK_ERRBASE_PNMI + 33)
-#define SK_PNMI_ERR033MSG "General: HW description string too long"
-#define SK_PNMI_ERR034 (SK_ERRBASE_PNMI + 34)
-#define SK_PNMI_ERR034MSG "General: Unknown OID"
-#define SK_PNMI_ERR035 (SK_ERRBASE_PNMI + 35)
-#define SK_PNMI_ERR035MSG "Rlmt: Unknown OID"
-#define SK_PNMI_ERR036 (SK_ERRBASE_PNMI + 36)
-#define SK_PNMI_ERR036MSG ""
-#define SK_PNMI_ERR037 (SK_ERRBASE_PNMI + 37)
-#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event return not 0"
-#define SK_PNMI_ERR038 (SK_ERRBASE_PNMI + 38)
-#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0"
-#define SK_PNMI_ERR039 (SK_ERRBASE_PNMI + 39)
-#define SK_PNMI_ERR039MSG "RlmtStat: Unknown OID"
-#define SK_PNMI_ERR040 (SK_ERRBASE_PNMI + 40)
-#define SK_PNMI_ERR040MSG "PowerManagement: Unknown OID"
-#define SK_PNMI_ERR041 (SK_ERRBASE_PNMI + 41)
-#define SK_PNMI_ERR041MSG "MacPrivateConf: Unknown OID"
-#define SK_PNMI_ERR042 (SK_ERRBASE_PNMI + 42)
-#define SK_PNMI_ERR042MSG "MacPrivateConf: SK_HWEV_SET_ROLE returned not 0"
-#define SK_PNMI_ERR043 (SK_ERRBASE_PNMI + 43)
-#define SK_PNMI_ERR043MSG "MacPrivateConf: SK_HWEV_SET_LMODE returned not 0"
-#define SK_PNMI_ERR044 (SK_ERRBASE_PNMI + 44)
-#define SK_PNMI_ERR044MSG "MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0"
-#define SK_PNMI_ERR045 (SK_ERRBASE_PNMI + 45)
-#define SK_PNMI_ERR045MSG "MacPrivateConf: SK_HWEV_SET_SPEED returned not 0"
-#define SK_PNMI_ERR046 (SK_ERRBASE_PNMI + 46)
-#define SK_PNMI_ERR046MSG "Monitor: Unknown OID"
-#define SK_PNMI_ERR047 (SK_ERRBASE_PNMI + 47)
-#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returns not 0"
-#define SK_PNMI_ERR048 (SK_ERRBASE_PNMI + 48)
-#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returns not 0"
-#define SK_PNMI_ERR049 (SK_ERRBASE_PNMI + 49)
-#define SK_PNMI_ERR049MSG "SkPnmiInit: Invalid size of 'CounterOffset' struct!!"
-#define SK_PNMI_ERR050 (SK_ERRBASE_PNMI + 50)
-#define SK_PNMI_ERR050MSG "SkPnmiInit: Invalid size of 'StatAddr' table!!"
-#define SK_PNMI_ERR051 (SK_ERRBASE_PNMI + 51)
-#define SK_PNMI_ERR051MSG "SkPnmiEvent: Port switch suspicious"
-#define SK_PNMI_ERR052 (SK_ERRBASE_PNMI + 52)
-#define SK_PNMI_ERR052MSG ""
-#define SK_PNMI_ERR053 (SK_ERRBASE_PNMI + 53)
-#define SK_PNMI_ERR053MSG "General: Driver release date not initialized"
-#define SK_PNMI_ERR054 (SK_ERRBASE_PNMI + 54)
-#define SK_PNMI_ERR054MSG "General: Driver release date string too long"
-#define SK_PNMI_ERR055 (SK_ERRBASE_PNMI + 55)
-#define SK_PNMI_ERR055MSG "General: Driver file name not initialized"
-#define SK_PNMI_ERR056 (SK_ERRBASE_PNMI + 56)
-#define SK_PNMI_ERR056MSG "General: Driver file name string too long"
-
-/*
- * Management counter macros called by the driver
- */
-#define SK_PNMI_SET_DRIVER_DESCR(pAC,v) ((pAC)->Pnmi.pDriverDescription = \
- (char *)(v))
-
-#define SK_PNMI_SET_DRIVER_VER(pAC,v) ((pAC)->Pnmi.pDriverVersion = \
- (char *)(v))
-
-#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v) ((pAC)->Pnmi.pDriverReleaseDate = \
- (char *)(v))
-
-#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v) ((pAC)->Pnmi.pDriverFileName = \
- (char *)(v))
-
-#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \
- { \
- (pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \
- if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \
- (pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \
- } \
- }
-#define SK_PNMI_CNT_TX_RETRY(pAC,p) (((pAC)->Pnmi.Port[p].TxRetryCts)++)
-#define SK_PNMI_CNT_RX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].RxIntrCts)++)
-#define SK_PNMI_CNT_TX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].TxIntrCts)++)
-#define SK_PNMI_CNT_NO_RX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].RxNoBufCts)++)
-#define SK_PNMI_CNT_NO_TX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].TxNoBufCts)++)
-#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \
- ((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v));
-#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \
- { \
- ((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \
- (pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \
- }
-#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p) (((pAC)->Pnmi.Port[p].ErrRecoveryCts)++);
-
-#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \
- { \
- if ((p) < SK_MAX_MACS) { \
- ((pAC)->Pnmi.Port[p].StatSyncCts)++; \
- (pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \
- } \
- }
-
-#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \
- { \
- if ((p) < SK_MAX_MACS) { \
- ((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \
- } \
- }
-
-#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \
- { \
- if ((p) < SK_MAX_MACS) { \
- ((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \
- } \
- }
-
-#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \
- { \
- if ((p) < SK_MAX_MACS) { \
- ((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \
- } \
- }
-
-/*
- * Conversion Macros
- */
-#define SK_PNMI_PORT_INST2LOG(i) ((unsigned int)(i) - 1)
-#define SK_PNMI_PORT_LOG2INST(l) ((unsigned int)(l) + 1)
-#define SK_PNMI_PORT_PHYS2LOG(p) ((unsigned int)(p) + 1)
-#define SK_PNMI_PORT_LOG2PHYS(pAC,l) ((unsigned int)(l) - 1)
-#define SK_PNMI_PORT_PHYS2INST(pAC,p) \
- (pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2))
-#define SK_PNMI_PORT_INST2PHYS(pAC,i) ((unsigned int)(i) - 2)
-
-/*
- * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct
- */
-#define SK_PNMI_VPD_KEY_SIZE 5
-#define SK_PNMI_VPD_BUFSIZE (VPD_SIZE)
-#define SK_PNMI_VPD_ENTRIES (VPD_SIZE / 4)
-#define SK_PNMI_VPD_DATALEN 128 /* Number of data bytes */
-
-#define SK_PNMI_MULTICAST_LISTLEN 64
-#define SK_PNMI_SENSOR_ENTRIES (SK_MAX_SENSORS)
-#define SK_PNMI_CHECKSUM_ENTRIES 3
-#define SK_PNMI_MAC_ENTRIES (SK_MAX_MACS + 1)
-#define SK_PNMI_MONITOR_ENTRIES 20
-#define SK_PNMI_TRAP_ENTRIES 10
-#define SK_PNMI_TRAPLEN 128
-#define SK_PNMI_STRINGLEN1 80
-#define SK_PNMI_STRINGLEN2 25
-#define SK_PNMI_TRAP_QUEUE_LEN 512
-
-typedef struct s_PnmiVpd {
- char VpdKey[SK_PNMI_VPD_KEY_SIZE];
- char VpdValue[SK_PNMI_VPD_DATALEN];
- SK_U8 VpdAccess;
- SK_U8 VpdAction;
-} SK_PNMI_VPD;
-
-typedef struct s_PnmiSensor {
- SK_U8 SensorIndex;
- char SensorDescr[SK_PNMI_STRINGLEN2];
- SK_U8 SensorType;
- SK_U32 SensorValue;
- SK_U32 SensorWarningThresholdLow;
- SK_U32 SensorWarningThresholdHigh;
- SK_U32 SensorErrorThresholdLow;
- SK_U32 SensorErrorThresholdHigh;
- SK_U8 SensorStatus;
- SK_U64 SensorWarningCts;
- SK_U64 SensorErrorCts;
- SK_U64 SensorWarningTimestamp;
- SK_U64 SensorErrorTimestamp;
-} SK_PNMI_SENSOR;
-
-typedef struct s_PnmiChecksum {
- SK_U64 ChecksumRxOkCts;
- SK_U64 ChecksumRxUnableCts;
- SK_U64 ChecksumRxErrCts;
- SK_U64 ChecksumTxOkCts;
- SK_U64 ChecksumTxUnableCts;
-} SK_PNMI_CHECKSUM;
-
-typedef struct s_PnmiStat {
- SK_U64 StatTxOkCts;
- SK_U64 StatTxOctetsOkCts;
- SK_U64 StatTxBroadcastOkCts;
- SK_U64 StatTxMulticastOkCts;
- SK_U64 StatTxUnicastOkCts;
- SK_U64 StatTxLongFramesCts;
- SK_U64 StatTxBurstCts;
- SK_U64 StatTxPauseMacCtrlCts;
- SK_U64 StatTxMacCtrlCts;
- SK_U64 StatTxSingleCollisionCts;
- SK_U64 StatTxMultipleCollisionCts;
- SK_U64 StatTxExcessiveCollisionCts;
- SK_U64 StatTxLateCollisionCts;
- SK_U64 StatTxDeferralCts;
- SK_U64 StatTxExcessiveDeferralCts;
- SK_U64 StatTxFifoUnderrunCts;
- SK_U64 StatTxCarrierCts;
- SK_U64 Dummy1; /* StatTxUtilization */
- SK_U64 StatTx64Cts;
- SK_U64 StatTx127Cts;
- SK_U64 StatTx255Cts;
- SK_U64 StatTx511Cts;
- SK_U64 StatTx1023Cts;
- SK_U64 StatTxMaxCts;
- SK_U64 StatTxSyncCts;
- SK_U64 StatTxSyncOctetsCts;
- SK_U64 StatRxOkCts;
- SK_U64 StatRxOctetsOkCts;
- SK_U64 StatRxBroadcastOkCts;
- SK_U64 StatRxMulticastOkCts;
- SK_U64 StatRxUnicastOkCts;
- SK_U64 StatRxLongFramesCts;
- SK_U64 StatRxPauseMacCtrlCts;
- SK_U64 StatRxMacCtrlCts;
- SK_U64 StatRxPauseMacCtrlErrorCts;
- SK_U64 StatRxMacCtrlUnknownCts;
- SK_U64 StatRxBurstCts;
- SK_U64 StatRxMissedCts;
- SK_U64 StatRxFramingCts;
- SK_U64 StatRxFifoOverflowCts;
- SK_U64 StatRxJabberCts;
- SK_U64 StatRxCarrierCts;
- SK_U64 StatRxIRLengthCts;
- SK_U64 StatRxSymbolCts;
- SK_U64 StatRxShortsCts;
- SK_U64 StatRxRuntCts;
- SK_U64 StatRxCextCts;
- SK_U64 StatRxTooLongCts;
- SK_U64 StatRxFcsCts;
- SK_U64 Dummy2; /* StatRxUtilization */
- SK_U64 StatRx64Cts;
- SK_U64 StatRx127Cts;
- SK_U64 StatRx255Cts;
- SK_U64 StatRx511Cts;
- SK_U64 StatRx1023Cts;
- SK_U64 StatRxMaxCts;
-} SK_PNMI_STAT;
-
-typedef struct s_PnmiConf {
- char ConfMacCurrentAddr[6];
- char ConfMacFactoryAddr[6];
- SK_U8 ConfPMD;
- SK_U8 ConfConnector;
- SK_U32 ConfPhyType;
- SK_U32 ConfPhyMode;
- SK_U8 ConfLinkCapability;
- SK_U8 ConfLinkMode;
- SK_U8 ConfLinkModeStatus;
- SK_U8 ConfLinkStatus;
- SK_U8 ConfFlowCtrlCapability;
- SK_U8 ConfFlowCtrlMode;
- SK_U8 ConfFlowCtrlStatus;
- SK_U8 ConfPhyOperationCapability;
- SK_U8 ConfPhyOperationMode;
- SK_U8 ConfPhyOperationStatus;
- SK_U8 ConfSpeedCapability;
- SK_U8 ConfSpeedMode;
- SK_U8 ConfSpeedStatus;
-} SK_PNMI_CONF;
-
-typedef struct s_PnmiRlmt {
- SK_U32 RlmtIndex;
- SK_U32 RlmtStatus;
- SK_U64 RlmtTxHelloCts;
- SK_U64 RlmtRxHelloCts;
- SK_U64 RlmtTxSpHelloReqCts;
- SK_U64 RlmtRxSpHelloCts;
-} SK_PNMI_RLMT;
-
-typedef struct s_PnmiRlmtMonitor {
- SK_U32 RlmtMonitorIndex;
- char RlmtMonitorAddr[6];
- SK_U64 RlmtMonitorErrorCts;
- SK_U64 RlmtMonitorTimestamp;
- SK_U8 RlmtMonitorAdmin;
-} SK_PNMI_RLMT_MONITOR;
-
-typedef struct s_PnmiRequestStatus {
- SK_U32 ErrorStatus;
- SK_U32 ErrorOffset;
-} SK_PNMI_REQUEST_STATUS;
-
-typedef struct s_PnmiStrucData {
- SK_U32 MgmtDBVersion;
- SK_PNMI_REQUEST_STATUS ReturnStatus;
- SK_U32 VpdFreeBytes;
- char VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE];
- SK_U32 VpdEntriesNumber;
- SK_PNMI_VPD Vpd[SK_PNMI_VPD_ENTRIES];
- SK_U32 PortNumber;
- SK_U32 DeviceType;
- char DriverDescr[SK_PNMI_STRINGLEN1];
- char DriverVersion[SK_PNMI_STRINGLEN2];
- char DriverReleaseDate[SK_PNMI_STRINGLEN1];
- char DriverFileName[SK_PNMI_STRINGLEN1];
- char HwDescr[SK_PNMI_STRINGLEN1];
- char HwVersion[SK_PNMI_STRINGLEN2];
- SK_U16 Chipset;
- SK_U32 ChipId;
- SK_U8 VauxAvail;
- SK_U32 RamSize;
- SK_U32 MtuSize;
- SK_U32 Action;
- SK_U32 TestResult;
- SK_U8 BusType;
- SK_U8 BusSpeed;
- SK_U8 BusWidth;
- SK_U8 SensorNumber;
- SK_PNMI_SENSOR Sensor[SK_PNMI_SENSOR_ENTRIES];
- SK_U8 ChecksumNumber;
- SK_PNMI_CHECKSUM Checksum[SK_PNMI_CHECKSUM_ENTRIES];
- SK_PNMI_STAT Stat[SK_PNMI_MAC_ENTRIES];
- SK_PNMI_CONF Conf[SK_PNMI_MAC_ENTRIES];
- SK_U8 RlmtMode;
- SK_U32 RlmtPortNumber;
- SK_U8 RlmtPortActive;
- SK_U8 RlmtPortPreferred;
- SK_U64 RlmtChangeCts;
- SK_U64 RlmtChangeTime;
- SK_U64 RlmtChangeEstimate;
- SK_U64 RlmtChangeThreshold;
- SK_PNMI_RLMT Rlmt[SK_MAX_MACS];
- SK_U32 RlmtMonitorNumber;
- SK_PNMI_RLMT_MONITOR RlmtMonitor[SK_PNMI_MONITOR_ENTRIES];
- SK_U32 TrapNumber;
- SK_U8 Trap[SK_PNMI_TRAP_QUEUE_LEN];
- SK_U64 TxSwQueueLen;
- SK_U64 TxSwQueueMax;
- SK_U64 TxRetryCts;
- SK_U64 RxIntrCts;
- SK_U64 TxIntrCts;
- SK_U64 RxNoBufCts;
- SK_U64 TxNoBufCts;
- SK_U64 TxUsedDescrNo;
- SK_U64 RxDeliveredCts;
- SK_U64 RxOctetsDeliveredCts;
- SK_U64 RxHwErrorsCts;
- SK_U64 TxHwErrorsCts;
- SK_U64 InErrorsCts;
- SK_U64 OutErrorsCts;
- SK_U64 ErrRecoveryCts;
- SK_U64 SysUpTime;
-} SK_PNMI_STRUCT_DATA;
-
-#define SK_PNMI_STRUCT_SIZE (sizeof(SK_PNMI_STRUCT_DATA))
-#define SK_PNMI_MIN_STRUCT_SIZE ((unsigned int)(SK_UPTR)\
- &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes))
- /*
- * ReturnStatus field
- * must be located
- * before VpdFreeBytes
- */
-
-/*
- * Various definitions
- */
-#define SK_PNMI_MAX_PROTOS 3
-
-#define SK_PNMI_CNT_NO 66 /* Must have the value of the enum
- * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK
- * for check while init phase 1
- */
-
-/*
- * Estimate data structure
- */
-typedef struct s_PnmiEstimate {
- unsigned int EstValueIndex;
- SK_U64 EstValue[7];
- SK_U64 Estimate;
- SK_TIMER EstTimer;
-} SK_PNMI_ESTIMATE;
-
-
-/*
- * VCT timer data structure
- */
-typedef struct s_VctTimer {
- SK_TIMER VctTimer;
-} SK_PNMI_VCT_TIMER;
-
-
-/*
- * PNMI specific adapter context structure
- */
-typedef struct s_PnmiPort {
- SK_U64 StatSyncCts;
- SK_U64 StatSyncOctetsCts;
- SK_U64 StatRxLongFrameCts;
- SK_U64 StatRxFrameTooLongCts;
- SK_U64 StatRxPMaccErr;
- SK_U64 TxSwQueueLen;
- SK_U64 TxSwQueueMax;
- SK_U64 TxRetryCts;
- SK_U64 RxIntrCts;
- SK_U64 TxIntrCts;
- SK_U64 RxNoBufCts;
- SK_U64 TxNoBufCts;
- SK_U64 TxUsedDescrNo;
- SK_U64 RxDeliveredCts;
- SK_U64 RxOctetsDeliveredCts;
- SK_U64 RxHwErrorsCts;
- SK_U64 TxHwErrorsCts;
- SK_U64 InErrorsCts;
- SK_U64 OutErrorsCts;
- SK_U64 ErrRecoveryCts;
- SK_U64 RxShortZeroMark;
- SK_U64 CounterOffset[SK_PNMI_CNT_NO];
- SK_U32 CounterHigh[SK_PNMI_CNT_NO];
- SK_BOOL ActiveFlag;
- SK_U8 Align[3];
-} SK_PNMI_PORT;
-
-
-typedef struct s_PnmiData {
- SK_PNMI_PORT Port [SK_MAX_MACS];
- SK_PNMI_PORT BufPort [SK_MAX_MACS]; /* 2002-09-13 pweber */
- SK_U64 VirtualCounterOffset[SK_PNMI_CNT_NO];
- SK_U32 TestResult;
- char HwVersion[10];
- SK_U16 Align01;
-
- char *pDriverDescription;
- char *pDriverVersion;
- char *pDriverReleaseDate;
- char *pDriverFileName;
-
- int MacUpdatedFlag;
- int RlmtUpdatedFlag;
- int SirqUpdatedFlag;
-
- SK_U64 RlmtChangeCts;
- SK_U64 RlmtChangeTime;
- SK_PNMI_ESTIMATE RlmtChangeEstimate;
- SK_U64 RlmtChangeThreshold;
-
- SK_U64 StartUpTime;
- SK_U32 DeviceType;
- char PciBusSpeed;
- char PciBusWidth;
- char Chipset;
- char PMD;
- char Connector;
- SK_BOOL DualNetActiveFlag;
- SK_U16 Align02;
-
- char TrapBuf[SK_PNMI_TRAP_QUEUE_LEN];
- unsigned int TrapBufFree;
- unsigned int TrapQueueBeg;
- unsigned int TrapQueueEnd;
- unsigned int TrapBufPad;
- unsigned int TrapUnique;
- SK_U8 VctStatus[SK_MAX_MACS];
- SK_PNMI_VCT VctBackup[SK_MAX_MACS];
- SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS];
-#ifdef SK_DIAG_SUPPORT
- SK_U32 DiagAttached;
-#endif /* SK_DIAG_SUPPORT */
-} SK_PNMI;
-
-
-/*
- * Function prototypes
- */
-extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level);
-extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
- unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event,
- SK_EVPARA Param);
-extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
- unsigned int * pLen, SK_U32 NetIndex);
-
-#endif
diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h
deleted file mode 100644
index 3eec6274e41..00000000000
--- a/drivers/net/sk98lin/h/skgesirq.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/******************************************************************************
- *
- * Name: skgesirq.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.30 $
- * Date: $Date: 2003/07/04 12:34:13 $
- * Purpose: SK specific Gigabit Ethernet special IRQ functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKGESIRQ_H_
-#define _INC_SKGESIRQ_H_
-
-/* Define return codes of SkGePortCheckUp and CheckShort */
-#define SK_HW_PS_NONE 0 /* No action needed */
-#define SK_HW_PS_RESTART 1 /* Restart needed */
-#define SK_HW_PS_LINK 2 /* Link Up actions needed */
-
-/*
- * Define the Event the special IRQ/INI module can handle
- */
-#define SK_HWEV_WATIM 1 /* Timeout for WA Errata #2 XMAC */
-#define SK_HWEV_PORT_START 2 /* Port Start Event by RLMT */
-#define SK_HWEV_PORT_STOP 3 /* Port Stop Event by RLMT */
-#define SK_HWEV_CLEAR_STAT 4 /* Clear Statistics by PNMI */
-#define SK_HWEV_UPDATE_STAT 5 /* Update Statistics by PNMI */
-#define SK_HWEV_SET_LMODE 6 /* Set Link Mode by PNMI */
-#define SK_HWEV_SET_FLOWMODE 7 /* Set Flow Control Mode by PNMI */
-#define SK_HWEV_SET_ROLE 8 /* Set Master/Slave (Role) by PNMI */
-#define SK_HWEV_SET_SPEED 9 /* Set Link Speed by PNMI */
-#define SK_HWEV_HALFDUP_CHK 10 /* Half Duplex Hangup Workaround */
-
-#define SK_WA_ACT_TIME (5000000UL) /* 5 sec */
-#define SK_WA_INA_TIME (100000UL) /* 100 msec */
-
-#define SK_HALFDUP_CHK_TIME (10000UL) /* 10 msec */
-
-/*
- * Define the error numbers and messages
- */
-#define SKERR_SIRQ_E001 (SK_ERRBASE_SIRQ+0)
-#define SKERR_SIRQ_E001MSG "Unknown event"
-#define SKERR_SIRQ_E002 (SKERR_SIRQ_E001+1)
-#define SKERR_SIRQ_E002MSG "Packet timeout RX1"
-#define SKERR_SIRQ_E003 (SKERR_SIRQ_E002+1)
-#define SKERR_SIRQ_E003MSG "Packet timeout RX2"
-#define SKERR_SIRQ_E004 (SKERR_SIRQ_E003+1)
-#define SKERR_SIRQ_E004MSG "MAC 1 not correctly initialized"
-#define SKERR_SIRQ_E005 (SKERR_SIRQ_E004+1)
-#define SKERR_SIRQ_E005MSG "MAC 2 not correctly initialized"
-#define SKERR_SIRQ_E006 (SKERR_SIRQ_E005+1)
-#define SKERR_SIRQ_E006MSG "CHECK failure R1"
-#define SKERR_SIRQ_E007 (SKERR_SIRQ_E006+1)
-#define SKERR_SIRQ_E007MSG "CHECK failure R2"
-#define SKERR_SIRQ_E008 (SKERR_SIRQ_E007+1)
-#define SKERR_SIRQ_E008MSG "CHECK failure XS1"
-#define SKERR_SIRQ_E009 (SKERR_SIRQ_E008+1)
-#define SKERR_SIRQ_E009MSG "CHECK failure XA1"
-#define SKERR_SIRQ_E010 (SKERR_SIRQ_E009+1)
-#define SKERR_SIRQ_E010MSG "CHECK failure XS2"
-#define SKERR_SIRQ_E011 (SKERR_SIRQ_E010+1)
-#define SKERR_SIRQ_E011MSG "CHECK failure XA2"
-#define SKERR_SIRQ_E012 (SKERR_SIRQ_E011+1)
-#define SKERR_SIRQ_E012MSG "unexpected IRQ Master error"
-#define SKERR_SIRQ_E013 (SKERR_SIRQ_E012+1)
-#define SKERR_SIRQ_E013MSG "unexpected IRQ Status error"
-#define SKERR_SIRQ_E014 (SKERR_SIRQ_E013+1)
-#define SKERR_SIRQ_E014MSG "Parity error on RAM (read)"
-#define SKERR_SIRQ_E015 (SKERR_SIRQ_E014+1)
-#define SKERR_SIRQ_E015MSG "Parity error on RAM (write)"
-#define SKERR_SIRQ_E016 (SKERR_SIRQ_E015+1)
-#define SKERR_SIRQ_E016MSG "Parity error MAC 1"
-#define SKERR_SIRQ_E017 (SKERR_SIRQ_E016+1)
-#define SKERR_SIRQ_E017MSG "Parity error MAC 2"
-#define SKERR_SIRQ_E018 (SKERR_SIRQ_E017+1)
-#define SKERR_SIRQ_E018MSG "Parity error RX 1"
-#define SKERR_SIRQ_E019 (SKERR_SIRQ_E018+1)
-#define SKERR_SIRQ_E019MSG "Parity error RX 2"
-#define SKERR_SIRQ_E020 (SKERR_SIRQ_E019+1)
-#define SKERR_SIRQ_E020MSG "MAC transmit FIFO underrun"
-#define SKERR_SIRQ_E021 (SKERR_SIRQ_E020+1)
-#define SKERR_SIRQ_E021MSG "Spurious TWSI interrupt"
-#define SKERR_SIRQ_E022 (SKERR_SIRQ_E021+1)
-#define SKERR_SIRQ_E022MSG "Cable pair swap error"
-#define SKERR_SIRQ_E023 (SKERR_SIRQ_E022+1)
-#define SKERR_SIRQ_E023MSG "Auto-negotiation error"
-#define SKERR_SIRQ_E024 (SKERR_SIRQ_E023+1)
-#define SKERR_SIRQ_E024MSG "FIFO overflow error"
-#define SKERR_SIRQ_E025 (SKERR_SIRQ_E024+1)
-#define SKERR_SIRQ_E025MSG "2 Pair Downshift detected"
-
-extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
-extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
-
-#endif /* _INC_SKGESIRQ_H_ */
diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h
deleted file mode 100644
index 6a63f4a15de..00000000000
--- a/drivers/net/sk98lin/h/ski2c.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/******************************************************************************
- *
- * Name: ski2c.h
- * Project: Gigabit Ethernet Adapters, TWSI-Module
- * Version: $Revision: 1.35 $
- * Date: $Date: 2003/10/20 09:06:30 $
- * Purpose: Defines to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKI2C.H contains all I2C specific defines
- */
-
-#ifndef _SKI2C_H_
-#define _SKI2C_H_
-
-typedef struct s_Sensor SK_SENSOR;
-
-#include "h/skgei2c.h"
-
-/*
- * Define the I2C events.
- */
-#define SK_I2CEV_IRQ 1 /* IRQ happened Event */
-#define SK_I2CEV_TIM 2 /* Timeout event */
-#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */
-
-/*
- * Define READ and WRITE Constants.
- */
-#define I2C_READ 0
-#define I2C_WRITE 1
-#define I2C_BURST 1
-#define I2C_SINGLE 0
-
-#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0)
-#define SKERR_I2C_E001MSG "Sensor index unknown"
-#define SKERR_I2C_E002 (SKERR_I2C_E001+1)
-#define SKERR_I2C_E002MSG "TWSI: transfer does not complete"
-#define SKERR_I2C_E003 (SKERR_I2C_E002+1)
-#define SKERR_I2C_E003MSG "LM80: NAK on device send"
-#define SKERR_I2C_E004 (SKERR_I2C_E003+1)
-#define SKERR_I2C_E004MSG "LM80: NAK on register send"
-#define SKERR_I2C_E005 (SKERR_I2C_E004+1)
-#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send"
-#define SKERR_I2C_E006 (SKERR_I2C_E005+1)
-#define SKERR_I2C_E006MSG "Unknown event"
-#define SKERR_I2C_E007 (SKERR_I2C_E006+1)
-#define SKERR_I2C_E007MSG "LM80 read out of state"
-#define SKERR_I2C_E008 (SKERR_I2C_E007+1)
-#define SKERR_I2C_E008MSG "Unexpected sensor read completed"
-#define SKERR_I2C_E009 (SKERR_I2C_E008+1)
-#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range"
-#define SKERR_I2C_E010 (SKERR_I2C_E009+1)
-#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range"
-#define SKERR_I2C_E011 (SKERR_I2C_E010+1)
-#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range"
-#define SKERR_I2C_E012 (SKERR_I2C_E011+1)
-#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range"
-#define SKERR_I2C_E013 (SKERR_I2C_E012+1)
-#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor"
-#define SKERR_I2C_E014 (SKERR_I2C_E013+1)
-#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range"
-#define SKERR_I2C_E015 (SKERR_I2C_E014+1)
-#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range"
-#define SKERR_I2C_E016 (SKERR_I2C_E015+1)
-#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete"
-
-/*
- * Define Timeout values
- */
-#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */
-#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */
-#define SK_I2C_TIM_WATCH 1000000L /* 1 second */
-
-/*
- * Define trap and error log hold times
- */
-#ifndef SK_SEN_ERR_TR_HOLD
-#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC)
-#endif
-#ifndef SK_SEN_ERR_LOG_HOLD
-#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC)
-#endif
-#ifndef SK_SEN_WARN_TR_HOLD
-#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC)
-#endif
-#ifndef SK_SEN_WARN_LOG_HOLD
-#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC)
-#endif
-
-/*
- * Defines for SenType
- */
-#define SK_SEN_UNKNOWN 0
-#define SK_SEN_TEMP 1
-#define SK_SEN_VOLT 2
-#define SK_SEN_FAN 3
-
-/*
- * Define for the SenErrorFlag
- */
-#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */
-#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */
-#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */
-#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */
-#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */
-
-/*
- * Define the Sensor struct
- */
-struct s_Sensor {
- char *SenDesc; /* Description */
- int SenType; /* Voltage or Temperature */
- SK_I32 SenValue; /* Current value of the sensor */
- SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */
- SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */
- SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */
- SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */
- int SenErrFlag; /* Sensor indicated an error */
- SK_BOOL SenInit; /* Is sensor initialized ? */
- SK_U64 SenErrCts; /* Error trap counter */
- SK_U64 SenWarnCts; /* Warning trap counter */
- SK_U64 SenBegErrTS; /* Begin error timestamp */
- SK_U64 SenBegWarnTS; /* Begin warning timestamp */
- SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */
- SK_U64 SenLastErrLogTS; /* Last error log timestamp */
- SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */
- SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */
- int SenState; /* Sensor State (see HW specific include) */
- int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
- /* Sensors read function */
- SK_U16 SenReg; /* Register Address for this sensor */
- SK_U8 SenDev; /* Device Selection for this sensor */
-};
-
-typedef struct s_I2c {
- SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */
- int CurrSens; /* Which sensor is currently queried */
- int MaxSens; /* Max. number of sensors */
- int TimerMode; /* Use the timer also to watch the state machine */
- int InitLevel; /* Initialized Level */
-#ifndef SK_DIAG
- int DummyReads; /* Number of non-checked dummy reads */
- SK_TIMER SenTimer; /* Sensors timer */
-#endif /* !SK_DIAG */
-} SK_I2C;
-
-extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
-#ifdef SK_DIAG
-extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
- int Burst);
-#else /* !SK_DIAG */
-extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
-extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
-#endif /* !SK_DIAG */
-#endif /* n_SKI2C_H */
-
diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h
deleted file mode 100644
index 2ec40d4fdf6..00000000000
--- a/drivers/net/sk98lin/h/skqueue.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/******************************************************************************
- *
- * Name: skqueue.h
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.16 $
- * Date: $Date: 2003/09/16 12:50:32 $
- * Purpose: Defines for the Event queue
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKQUEUE.H contains all defines and types for the event queue
- */
-
-#ifndef _SKQUEUE_H_
-#define _SKQUEUE_H_
-
-
-/*
- * define the event classes to be served
- */
-#define SKGE_DRV 1 /* Driver Event Class */
-#define SKGE_RLMT 2 /* RLMT Event Class */
-#define SKGE_I2C 3 /* I2C Event Class */
-#define SKGE_PNMI 4 /* PNMI Event Class */
-#define SKGE_CSUM 5 /* Checksum Event Class */
-#define SKGE_HWAC 6 /* Hardware Access Event Class */
-
-#define SKGE_SWT 9 /* Software Timer Event Class */
-#define SKGE_LACP 10 /* LACP Aggregation Event Class */
-#define SKGE_RSF 11 /* RSF Aggregation Event Class */
-#define SKGE_MARKER 12 /* MARKER Aggregation Event Class */
-#define SKGE_FD 13 /* FD Distributor Event Class */
-
-/*
- * define event queue as circular buffer
- */
-#define SK_MAX_EVENT 64
-
-/*
- * Parameter union for the Para stuff
- */
-typedef union u_EvPara {
- void *pParaPtr; /* Parameter Pointer */
- SK_U64 Para64; /* Parameter 64bit version */
- SK_U32 Para32[2]; /* Parameter Array of 32bit parameters */
-} SK_EVPARA;
-
-/*
- * Event Queue
- * skqueue.c
- * events are class/value pairs
- * class is addressee, e.g. RLMT, PNMI etc.
- * value is command, e.g. line state change, ring op change etc.
- */
-typedef struct s_EventElem {
- SK_U32 Class; /* Event class */
- SK_U32 Event; /* Event value */
- SK_EVPARA Para; /* Event parameter */
-} SK_EVENTELEM;
-
-typedef struct s_Queue {
- SK_EVENTELEM EvQueue[SK_MAX_EVENT];
- SK_EVENTELEM *EvPut;
- SK_EVENTELEM *EvGet;
-} SK_QUEUE;
-
-extern void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event,
- SK_EVPARA Para);
-extern int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc);
-
-
-/* Define Error Numbers and messages */
-#define SKERR_Q_E001 (SK_ERRBASE_QUEUE+0)
-#define SKERR_Q_E001MSG "Event queue overflow"
-#define SKERR_Q_E002 (SKERR_Q_E001+1)
-#define SKERR_Q_E002MSG "Undefined event class"
-#endif /* _SKQUEUE_H_ */
-
diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h
deleted file mode 100644
index ca75dfdcf2d..00000000000
--- a/drivers/net/sk98lin/h/skrlmt.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/******************************************************************************
- *
- * Name: skrlmt.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.37 $
- * Date: $Date: 2003/04/15 09:43:43 $
- * Purpose: Header file for Redundant Link ManagemenT.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the header file for Redundant Link ManagemenT.
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * ...
- * "sktypes.h"
- * "skqueue.h"
- * "skaddr.h"
- * "skrlmt.h"
- * ...
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKRLMT_H
-#define __INC_SKRLMT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_RLMT_NET_DOWN_TEMP 1 /* NET_DOWN due to last port down. */
-#define SK_RLMT_NET_DOWN_FINAL 2 /* NET_DOWN due to RLMT_STOP. */
-
-/* ----- Default queue sizes - must be multiples of 8 KB ----- */
-
-/* Less than 8 KB free in RX queue => pause frames. */
-#define SK_RLMT_STANDBY_QRXSIZE 128 /* Size of rx standby queue in KB. */
-#define SK_RLMT_STANDBY_QXASIZE 32 /* Size of async standby queue in KB. */
-#define SK_RLMT_STANDBY_QXSSIZE 0 /* Size of sync standby queue in KB. */
-
-#define SK_RLMT_MAX_TX_BUF_SIZE 60 /* Maximum RLMT transmit size. */
-
-/* ----- PORT states ----- */
-
-#define SK_RLMT_PS_INIT 0 /* Port state: Init. */
-#define SK_RLMT_PS_LINK_DOWN 1 /* Port state: Link down. */
-#define SK_RLMT_PS_DOWN 2 /* Port state: Port down. */
-#define SK_RLMT_PS_GOING_UP 3 /* Port state: Going up. */
-#define SK_RLMT_PS_UP 4 /* Port state: Up. */
-
-/* ----- RLMT states ----- */
-
-#define SK_RLMT_RS_INIT 0 /* RLMT state: Init. */
-#define SK_RLMT_RS_NET_DOWN 1 /* RLMT state: Net down. */
-#define SK_RLMT_RS_NET_UP 2 /* RLMT state: Net up. */
-
-/* ----- PORT events ----- */
-
-#define SK_RLMT_LINK_UP 1001 /* Link came up. */
-#define SK_RLMT_LINK_DOWN 1002 /* Link went down. */
-#define SK_RLMT_PORT_ADDR 1003 /* Port address changed. */
-
-/* ----- RLMT events ----- */
-
-#define SK_RLMT_START 2001 /* Start RLMT. */
-#define SK_RLMT_STOP 2002 /* Stop RLMT. */
-#define SK_RLMT_PACKET_RECEIVED 2003 /* Packet was received for RLMT. */
-#define SK_RLMT_STATS_CLEAR 2004 /* Clear statistics. */
-#define SK_RLMT_STATS_UPDATE 2005 /* Update statistics. */
-#define SK_RLMT_PREFPORT_CHANGE 2006 /* Change preferred port. */
-#define SK_RLMT_MODE_CHANGE 2007 /* New RlmtMode. */
-#define SK_RLMT_SET_NETS 2008 /* Number of Nets (1 or 2). */
-
-/* ----- RLMT mode bits ----- */
-
-/*
- * CAUTION: These defines are private to RLMT.
- * Please use the RLMT mode defines below.
- */
-
-#define SK_RLMT_CHECK_LINK 1 /* Check Link. */
-#define SK_RLMT_CHECK_LOC_LINK 2 /* Check other link on same adapter. */
-#define SK_RLMT_CHECK_SEG 4 /* Check segmentation. */
-
-#ifndef RLMT_CHECK_REMOTE
-#define SK_RLMT_CHECK_OTHERS SK_RLMT_CHECK_LOC_LINK
-#else /* RLMT_CHECK_REMOTE */
-#define SK_RLMT_CHECK_REM_LINK 8 /* Check link(s) on other adapter(s). */
-#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED 3
-#define SK_RLMT_CHECK_OTHERS \
- (SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-#endif /* RLMT_CHECK_REMOTE */
-
-#ifndef SK_RLMT_ENABLE_TRANSPARENT
-#define SK_RLMT_TRANSPARENT 0 /* RLMT transparent - inactive. */
-#else /* SK_RLMT_ENABLE_TRANSPARENT */
-#define SK_RLMT_TRANSPARENT 128 /* RLMT transparent. */
-#endif /* SK_RLMT_ENABLE_TRANSPARENT */
-
-/* ----- RLMT modes ----- */
-
-/* Check Link State. */
-#define SK_RLMT_MODE_CLS (SK_RLMT_CHECK_LINK)
-
-/* Check Local Ports: check other links on the same adapter. */
-#define SK_RLMT_MODE_CLP (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK)
-
-/* Check Local Ports and Segmentation Status. */
-#define SK_RLMT_MODE_CLPSS \
- (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG)
-
-#ifdef RLMT_CHECK_REMOTE
-/* Check Local and Remote Ports: check links (local or remote). */
- Name of define TBD!
-#define SK_RLMT_MODE_CRP \
- (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-
-/* Check Local and Remote Ports and Segmentation Status. */
- Name of define TBD!
-#define SK_RLMT_MODE_CRPSS \
- (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \
- SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG)
-#endif /* RLMT_CHECK_REMOTE */
-
-/* ----- RLMT lookahead result bits ----- */
-
-#define SK_RLMT_RX_RLMT 1 /* Give packet to RLMT. */
-#define SK_RLMT_RX_PROTOCOL 2 /* Give packet to protocol. */
-
-/* Macros */
-
-#if 0
-SK_AC *pAC /* adapter context */
-SK_U32 PortNum /* receiving port */
-unsigned PktLen /* received packet's length */
-SK_BOOL IsBc /* Flag: packet is broadcast */
-unsigned *pOffset /* offs. of bytes to present to SK_RLMT_LOOKAHEAD */
-unsigned *pNumBytes /* #Bytes to present to SK_RLMT_LOOKAHEAD */
-#endif /* 0 */
-
-#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \
- SK_AC *_pAC; \
- SK_U32 _PortNum; \
- _pAC = (pAC); \
- _PortNum = (SK_U32)(PortNum); \
- /* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \
- _pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \
- if (_pAC->Rlmt.RlmtOff) { \
- *(pNumBytes) = 0; \
- } \
- else {\
- if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \
- *(pNumBytes) = 0; \
- } \
- else if (IsBc) { \
- if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \
- *(pNumBytes) = 6; \
- *(pOffset) = 6; \
- } \
- else { \
- *(pNumBytes) = 0; \
- } \
- } \
- else { \
- if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \
- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
- *(pNumBytes) = 0; \
- } \
- else { \
- *(pNumBytes) = 6; \
- *(pOffset) = 0; \
- } \
- } \
- } \
-}
-
-#if 0
-SK_AC *pAC /* adapter context */
-SK_U32 PortNum /* receiving port */
-SK_U8 *pLaPacket, /* received packet's data (points to pOffset) */
-SK_BOOL IsBc /* Flag: packet is broadcast */
-SK_BOOL IsMc /* Flag: packet is multicast */
-unsigned *pForRlmt /* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */
-SK_RLMT_LOOKAHEAD() expects *pNumBytes from
-packet offset *pOffset (s.a.) at *pLaPacket.
-
-If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is
-BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler
-can trash unneeded parts of the if construction.
-#endif /* 0 */
-
-#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \
- SK_AC *_pAC; \
- SK_U32 _PortNum; \
- SK_U8 *_pLaPacket; \
- _pAC = (pAC); \
- _PortNum = (SK_U32)(PortNum); \
- _pLaPacket = (SK_U8 *)(pLaPacket); \
- if (IsBc) {\
- if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \
- _PortNum].Net->NetNumber].CurrentMacAddress.a)) { \
- _pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \
- _pAC->Rlmt.CheckSwitch = SK_TRUE; \
- } \
- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
- } \
- else if (IsMc) { \
- if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \
- _pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \
- if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \
- *(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \
- } \
- else { \
- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
- } \
- } \
- else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \
- *(pForRlmt) = SK_RLMT_RX_RLMT; \
- } \
- else { \
- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
- } \
- } \
- else { \
- if (SK_ADDR_EQUAL( \
- _pLaPacket, \
- _pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \
- *(pForRlmt) = SK_RLMT_RX_RLMT; \
- } \
- else { \
- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
- } \
- } \
-}
-
-#ifdef SK_RLMT_FAST_LOOKAHEAD
-Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif /* SK_RLMT_FAST_LOOKAHEAD */
-#ifdef SK_RLMT_SLOW_LOOKAHEAD
-Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif /* SK_RLMT_SLOW_LOOKAHEAD */
-
-/* typedefs *******************************************************************/
-
-#ifdef SK_RLMT_MBUF_PRIVATE
-typedef struct s_RlmtMbuf {
- some content
-} SK_RLMT_MBUF;
-#endif /* SK_RLMT_MBUF_PRIVATE */
-
-
-#ifdef SK_LA_INFO
-typedef struct s_Rlmt_PacketInfo {
- unsigned PacketLength; /* Length of packet. */
- unsigned PacketType; /* Directed/Multicast/Broadcast. */
-} SK_RLMT_PINFO;
-#endif /* SK_LA_INFO */
-
-
-typedef struct s_RootId {
- SK_U8 Id[8]; /* Root Bridge Id. */
-} SK_RLMT_ROOT_ID;
-
-
-typedef struct s_port {
- SK_MAC_ADDR CheckAddr;
- SK_BOOL SuspectTx;
-} SK_PORT_CHECK;
-
-
-typedef struct s_RlmtNet SK_RLMT_NET;
-
-
-typedef struct s_RlmtPort {
-
-/* ----- Public part (read-only) ----- */
-
- SK_U8 PortState; /* Current state of this port. */
-
- /* For PNMI */
- SK_BOOL LinkDown;
- SK_BOOL PortDown;
- SK_U8 Align01;
-
- SK_U32 PortNumber; /* Number of port on adapter. */
- SK_RLMT_NET * Net; /* Net port belongs to. */
-
- SK_U64 TxHelloCts;
- SK_U64 RxHelloCts;
- SK_U64 TxSpHelloReqCts;
- SK_U64 RxSpHelloCts;
-
-/* ----- Private part ----- */
-
-/* SK_U64 PacketsRx; */ /* Total packets received. */
- SK_U32 PacketsPerTimeSlot; /* Packets rxed between TOs. */
-/* SK_U32 DataPacketsPerTimeSlot; */ /* Data packets ... */
- SK_U32 BpduPacketsPerTimeSlot; /* BPDU packets rxed in TS. */
- SK_U64 BcTimeStamp; /* Time of last BC receive. */
- SK_U64 GuTimeStamp; /* Time of entering GOING_UP. */
-
- SK_TIMER UpTimer; /* Timer struct Link/Port up. */
- SK_TIMER DownRxTimer; /* Timer struct down rx. */
- SK_TIMER DownTxTimer; /* Timer struct down tx. */
-
- SK_U32 CheckingState; /* Checking State. */
-
- SK_ADDR_PORT * AddrPort;
-
- SK_U8 Random[4]; /* Random value. */
- unsigned PortsChecked; /* #ports checked. */
- unsigned PortsSuspect; /* #ports checked that are s. */
- SK_PORT_CHECK PortCheck[1];
-/* SK_PORT_CHECK PortCheck[SK_MAX_MACS - 1]; */
-
- SK_BOOL PortStarted; /* Port is started. */
- SK_BOOL PortNoRx; /* NoRx for >= 1 time slot. */
- SK_BOOL RootIdSet;
- SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */
-} SK_RLMT_PORT;
-
-
-struct s_RlmtNet {
-
-/* ----- Public part (read-only) ----- */
-
- SK_U32 NetNumber; /* Number of net. */
-
- SK_RLMT_PORT * Port[SK_MAX_MACS]; /* Ports that belong to this net. */
- SK_U32 NumPorts; /* Number of ports. */
- SK_U32 PrefPort; /* Preferred port. */
-
- /* For PNMI */
-
- SK_U32 ChgBcPrio; /* Change Priority of last broadcast received */
- SK_U32 RlmtMode; /* Check ... */
- SK_U32 ActivePort; /* Active port. */
- SK_U32 Preference; /* 0xFFFFFFFF: Automatic. */
-
- SK_U8 RlmtState; /* Current RLMT state. */
-
-/* ----- Private part ----- */
- SK_BOOL RootIdSet;
- SK_U16 Align01;
-
- int LinksUp; /* #Links up. */
- int PortsUp; /* #Ports up. */
- SK_U32 TimeoutValue; /* RLMT timeout value. */
-
- SK_U32 CheckingState; /* Checking State. */
- SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */
-
- SK_TIMER LocTimer; /* Timer struct. */
- SK_TIMER SegTimer; /* Timer struct. */
-};
-
-
-typedef struct s_Rlmt {
-
-/* ----- Public part (read-only) ----- */
-
- SK_U32 NumNets; /* Number of nets. */
- SK_U32 NetsStarted; /* Number of nets started. */
- SK_RLMT_NET Net[SK_MAX_NETS]; /* Array of available nets. */
- SK_RLMT_PORT Port[SK_MAX_MACS]; /* Array of available ports. */
-
-/* ----- Private part ----- */
- SK_BOOL CheckSwitch;
- SK_BOOL RlmtOff; /* set to zero if the Mac addresses
- are equal or the second one
- is zero */
- SK_U16 Align01;
-
-} SK_RLMT;
-
-
-extern SK_MAC_ADDR BridgeMcAddr;
-extern SK_MAC_ADDR SkRlmtMcAddr;
-
-/* function prototypes ********************************************************/
-
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkRlmt */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern void SkRlmtInit(
- SK_AC *pAC,
- SK_IOC IoC,
- int Level);
-
-extern int SkRlmtEvent(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 Event,
- SK_EVPARA Para);
-
-#else /* defined(SK_KR_PROTO) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style function prototypes are not yet provided.
-
-#endif /* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_SKRLMT_H */
diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h
deleted file mode 100644
index 04e6d7c1ec3..00000000000
--- a/drivers/net/sk98lin/h/sktimer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************
- *
- * Name: sktimer.h
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.11 $
- * Date: $Date: 2003/09/16 12:58:18 $
- * Purpose: Defines for the timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKTIMER.H contains all defines and types for the timer functions
- */
-
-#ifndef _SKTIMER_H_
-#define _SKTIMER_H_
-
-#include "h/skqueue.h"
-
-/*
- * SK timer
- * - needed wherever a timer is used. Put this in your data structure
- * wherever you want.
- */
-typedef struct s_Timer SK_TIMER;
-
-struct s_Timer {
- SK_TIMER *TmNext; /* linked list */
- SK_U32 TmClass; /* Timer Event class */
- SK_U32 TmEvent; /* Timer Event value */
- SK_EVPARA TmPara; /* Timer Event parameter */
- SK_U32 TmDelta; /* delta time */
- int TmActive; /* flag: active/inactive */
-};
-
-/*
- * Timer control struct.
- * - use in Adapters context name pAC->Tim
- */
-typedef struct s_TimCtrl {
- SK_TIMER *StQueue; /* Head of Timer queue */
-} SK_TIMCTRL;
-
-extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer);
-extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer,
- SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para);
-extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc);
-#endif /* _SKTIMER_H_ */
diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h
deleted file mode 100644
index 40edc96e105..00000000000
--- a/drivers/net/sk98lin/h/sktypes.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/******************************************************************************
- *
- * Name: sktypes.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.2 $
- * Date: $Date: 2003/10/07 08:16:51 $
- * Purpose: Define data types for Linux
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * In this file, all data types that are needed by the common modules
- * are mapped to Linux data types.
- *
- *
- * Include File Hierarchy:
- *
- *
- ******************************************************************************/
-
-#ifndef __INC_SKTYPES_H
-#define __INC_SKTYPES_H
-
-
-/* defines *******************************************************************/
-
-/*
- * Data types with a specific size. 'I' = signed, 'U' = unsigned.
- */
-#define SK_I8 s8
-#define SK_U8 u8
-#define SK_I16 s16
-#define SK_U16 u16
-#define SK_I32 s32
-#define SK_U32 u32
-#define SK_I64 s64
-#define SK_U64 u64
-
-#define SK_UPTR ulong /* casting pointer <-> integral */
-
-/*
-* Boolean type.
-*/
-#define SK_BOOL SK_U8
-#define SK_FALSE 0
-#define SK_TRUE (!SK_FALSE)
-
-/* typedefs *******************************************************************/
-
-/* function prototypes ********************************************************/
-
-#endif /* __INC_SKTYPES_H */
diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h
deleted file mode 100644
index a1a7294828e..00000000000
--- a/drivers/net/sk98lin/h/skversion.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/******************************************************************************
- *
- * Name: version.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.5 $
- * Date: $Date: 2003/10/07 08:16:51 $
- * Purpose: SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifdef lint
-static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
-static const char SysKonnectBuildNumber[] =
- "@(#)SK-BUILD: 6.23 PL: 01";
-#endif /* !defined(lint) */
-
-#define BOOT_STRING "sk98lin: Network Device Driver v6.23\n" \
- "(C)Copyright 1999-2004 Marvell(R)."
-
-#define VER_STRING "6.23"
-#define DRIVER_FILE_NAME "sk98lin"
-#define DRIVER_REL_DATE "Feb-13-2004"
-
-
diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
deleted file mode 100644
index fdd9e48e804..00000000000
--- a/drivers/net/sk98lin/h/skvpd.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/******************************************************************************
- *
- * Name: skvpd.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.15 $
- * Date: $Date: 2003/01/13 10:39:38 $
- * Purpose: Defines and Macros for VPD handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2003 SysKonnect GmbH.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * skvpd.h contains Diagnostic specific defines for VPD handling
- */
-
-#ifndef __INC_SKVPD_H_
-#define __INC_SKVPD_H_
-
-/*
- * Define Resource Type Identifiers and VPD keywords
- */
-#define RES_ID 0x82 /* Resource Type ID String (Product Name) */
-#define RES_VPD_R 0x90 /* start of VPD read only area */
-#define RES_VPD_W 0x91 /* start of VPD read/write area */
-#define RES_END 0x78 /* Resource Type End Tag */
-
-#ifndef VPD_NAME
-#define VPD_NAME "Name" /* Product Name, VPD name of RES_ID */
-#endif /* VPD_NAME */
-#define VPD_PN "PN" /* Adapter Part Number */
-#define VPD_EC "EC" /* Adapter Engineering Level */
-#define VPD_MN "MN" /* Manufacture ID */
-#define VPD_SN "SN" /* Serial Number */
-#define VPD_CP "CP" /* Extended Capability */
-#define VPD_RV "RV" /* Checksum and Reserved */
-#define VPD_YA "YA" /* Asset Tag Identifier */
-#define VPD_VL "VL" /* First Error Log Message (SK specific) */
-#define VPD_VF "VF" /* Second Error Log Message (SK specific) */
-#define VPD_RW "RW" /* Remaining Read / Write Area */
-
-/* 'type' values for vpd_setup_para() */
-#define VPD_RO_KEY 1 /* RO keys are "PN", "EC", "MN", "SN", "RV" */
-#define VPD_RW_KEY 2 /* RW keys are "Yx", "Vx", and "RW" */
-
-/* 'op' values for vpd_setup_para() */
-#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */
-#define OWR_KEY 2 /* overwrite key if already exists */
-
-/*
- * Define READ and WRITE Constants.
- */
-
-#define VPD_DEV_ID_GENESIS 0x4300
-
-#define VPD_SIZE_YUKON 256
-#define VPD_SIZE_GENESIS 512
-#define VPD_SIZE 512
-#define VPD_READ 0x0000
-#define VPD_WRITE 0x8000
-
-#define VPD_STOP(pAC,IoC) VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE)
-
-#define VPD_GET_RES_LEN(p) ((unsigned int) \
- (* (SK_U8 *)&(p)[1]) |\
- ((* (SK_U8 *)&(p)[2]) << 8))
-#define VPD_GET_VPD_LEN(p) ((unsigned int)(* (SK_U8 *)&(p)[2]))
-#define VPD_GET_VAL(p) ((char *)&(p)[3])
-
-#define VPD_MAX_LEN 50
-
-/* VPD status */
- /* bit 7..1 reserved */
-#define VPD_VALID (1<<0) /* VPD data buffer, vpd_free_ro, */
- /* and vpd_free_rw valid */
-
-/*
- * VPD structs
- */
-typedef struct s_vpd_status {
- unsigned short Align01; /* Alignment */
- unsigned short vpd_status; /* VPD status, description see above */
- int vpd_free_ro; /* unused bytes in read only area */
- int vpd_free_rw; /* bytes available in read/write area */
-} SK_VPD_STATUS;
-
-typedef struct s_vpd {
- SK_VPD_STATUS v; /* VPD status structure */
- char vpd_buf[VPD_SIZE]; /* VPD buffer */
- int rom_size; /* VPD ROM Size from PCI_OUR_REG_2 */
- int vpd_size; /* saved VPD-size */
-} SK_VPD;
-
-typedef struct s_vpd_para {
- unsigned int p_len; /* parameter length */
- char *p_val; /* points to the value */
-} SK_VPD_PARA;
-
-/*
- * structure of Large Resource Type Identifiers
- */
-
-/* was removed because of alignment problems */
-
-/*
- * structure of VPD keywords
- */
-typedef struct s_vpd_key {
- char p_key[2]; /* 2 bytes ID string */
- unsigned char p_len; /* 1 byte length */
- char p_val; /* start of the value string */
-} SK_VPD_KEY;
-
-
-/*
- * System specific VPD macros
- */
-#ifndef SKDIAG
-#ifndef VPD_DO_IO
-#define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal) (void)SkPciReadCfgByte(pAC,Addr,pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal)
-#else /* VPD_DO_IO */
-#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal)
-#endif /* VPD_DO_IO */
-#else /* SKDIAG */
-#define VPD_OUT8(pAC,Ioc,Addr,Val) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciWriteCfgByte(pAC,Addr,Val); \
- else \
- SK_OUT8(pAC,PCI_C(Addr),Val); \
- }
-#define VPD_OUT16(pAC,Ioc,Addr,Val) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciWriteCfgWord(pAC,Addr,Val); \
- else \
- SK_OUT16(pAC,PCI_C(Addr),Val); \
- }
-#define VPD_IN8(pAC,Ioc,Addr,pVal) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciReadCfgByte(pAC,Addr,pVal); \
- else \
- SK_IN8(pAC,PCI_C(Addr),pVal); \
- }
-#define VPD_IN16(pAC,Ioc,Addr,pVal) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciReadCfgWord(pAC,Addr,pVal); \
- else \
- SK_IN16(pAC,PCI_C(Addr),pVal); \
- }
-#define VPD_IN32(pAC,Ioc,Addr,pVal) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciReadCfgDWord(pAC,Addr,pVal); \
- else \
- SK_IN32(pAC,PCI_C(Addr),pVal); \
- }
-#endif /* nSKDIAG */
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_KR_PROTO
-#ifdef SKDIAG
-extern SK_U32 VpdReadDWord(
- SK_AC *pAC,
- SK_IOC IoC,
- int addr);
-#endif /* SKDIAG */
-
-extern SK_VPD_STATUS *VpdStat(
- SK_AC *pAC,
- SK_IOC IoC);
-
-extern int VpdKeys(
- SK_AC *pAC,
- SK_IOC IoC,
- char *buf,
- int *len,
- int *elements);
-
-extern int VpdRead(
- SK_AC *pAC,
- SK_IOC IoC,
- const char *key,
- char *buf,
- int *len);
-
-extern SK_BOOL VpdMayWrite(
- char *key);
-
-extern int VpdWrite(
- SK_AC *pAC,
- SK_IOC IoC,
- const char *key,
- const char *buf);
-
-extern int VpdDelete(
- SK_AC *pAC,
- SK_IOC IoC,
- char *key);
-
-extern int VpdUpdate(
- SK_AC *pAC,
- SK_IOC IoC);
-
-#ifdef SKDIAG
-extern int VpdReadBlock(
- SK_AC *pAC,
- SK_IOC IoC,
- char *buf,
- int addr,
- int len);
-
-extern int VpdWriteBlock(
- SK_AC *pAC,
- SK_IOC IoC,
- char *buf,
- int addr,
- int len);
-#endif /* SKDIAG */
-#else /* SK_KR_PROTO */
-extern SK_U32 VpdReadDWord();
-extern SK_VPD_STATUS *VpdStat();
-extern int VpdKeys();
-extern int VpdRead();
-extern SK_BOOL VpdMayWrite();
-extern int VpdWrite();
-extern int VpdDelete();
-extern int VpdUpdate();
-#endif /* SK_KR_PROTO */
-
-#endif /* __INC_SKVPD_H_ */
diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
deleted file mode 100644
index 7f8e6d0084c..00000000000
--- a/drivers/net/sk98lin/h/xmac_ii.h
+++ /dev/null
@@ -1,1579 +0,0 @@
-/******************************************************************************
- *
- * Name: xmac_ii.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.52 $
- * Date: $Date: 2003/10/02 16:35:50 $
- * Purpose: Defines and Macros for Gigabit Ethernet Controller
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_XMAC_H
-#define __INC_XMAC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * XMAC II registers
- *
- * The XMAC registers are 16 or 32 bits wide.
- * The XMACs host processor interface is set to 16 bit mode,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the XMAC registers
- * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(),
- * XM_INHASH(), and XM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note: NA reg = Network Address e.g DA, SA etc.
- *
- */
-#define XM_MMU_CMD 0x0000 /* 16 bit r/w MMU Command Register */
- /* 0x0004: reserved */
-#define XM_POFF 0x0008 /* 32 bit r/w Packet Offset Register */
-#define XM_BURST 0x000c /* 32 bit r/w Burst Register for half duplex*/
-#define XM_1L_VLAN_TAG 0x0010 /* 16 bit r/w One Level VLAN Tag ID */
-#define XM_2L_VLAN_TAG 0x0014 /* 16 bit r/w Two Level VLAN Tag ID */
- /* 0x0018 - 0x001e: reserved */
-#define XM_TX_CMD 0x0020 /* 16 bit r/w Transmit Command Register */
-#define XM_TX_RT_LIM 0x0024 /* 16 bit r/w Transmit Retry Limit Register */
-#define XM_TX_STIME 0x0028 /* 16 bit r/w Transmit Slottime Register */
-#define XM_TX_IPG 0x002c /* 16 bit r/w Transmit Inter Packet Gap */
-#define XM_RX_CMD 0x0030 /* 16 bit r/w Receive Command Register */
-#define XM_PHY_ADDR 0x0034 /* 16 bit r/w PHY Address Register */
-#define XM_PHY_DATA 0x0038 /* 16 bit r/w PHY Data Register */
- /* 0x003c: reserved */
-#define XM_GP_PORT 0x0040 /* 32 bit r/w General Purpose Port Register */
-#define XM_IMSK 0x0044 /* 16 bit r/w Interrupt Mask Register */
-#define XM_ISRC 0x0048 /* 16 bit r/o Interrupt Status Register */
-#define XM_HW_CFG 0x004c /* 16 bit r/w Hardware Config Register */
- /* 0x0050 - 0x005e: reserved */
-#define XM_TX_LO_WM 0x0060 /* 16 bit r/w Tx FIFO Low Water Mark */
-#define XM_TX_HI_WM 0x0062 /* 16 bit r/w Tx FIFO High Water Mark */
-#define XM_TX_THR 0x0064 /* 16 bit r/w Tx Request Threshold */
-#define XM_HT_THR 0x0066 /* 16 bit r/w Host Request Threshold */
-#define XM_PAUSE_DA 0x0068 /* NA reg r/w Pause Destination Address */
- /* 0x006e: reserved */
-#define XM_CTL_PARA 0x0070 /* 32 bit r/w Control Parameter Register */
-#define XM_MAC_OPCODE 0x0074 /* 16 bit r/w Opcode for MAC control frames */
-#define XM_MAC_PTIME 0x0076 /* 16 bit r/w Pause time for MAC ctrl frames*/
-#define XM_TX_STAT 0x0078 /* 32 bit r/o Tx Status LIFO Register */
-
- /* 0x0080 - 0x00fc: 16 NA reg r/w Exact Match Address Registers */
- /* use the XM_EXM() macro to address */
-#define XM_EXM_START 0x0080 /* r/w Start Address of the EXM Regs */
-
- /*
- * XM_EXM(Reg)
- *
- * returns the XMAC address offset of specified Exact Match Addr Reg
- *
- * para: Reg EXM register to addr (0 .. 15)
- *
- * usage: XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]);
- */
-#define XM_EXM(Reg) (XM_EXM_START + ((Reg) << 3))
-
-#define XM_SRC_CHK 0x0100 /* NA reg r/w Source Check Address Register */
-#define XM_SA 0x0108 /* NA reg r/w Station Address Register */
-#define XM_HSM 0x0110 /* 64 bit r/w Hash Match Address Registers */
-#define XM_RX_LO_WM 0x0118 /* 16 bit r/w Receive Low Water Mark */
-#define XM_RX_HI_WM 0x011a /* 16 bit r/w Receive High Water Mark */
-#define XM_RX_THR 0x011c /* 32 bit r/w Receive Request Threshold */
-#define XM_DEV_ID 0x0120 /* 32 bit r/o Device ID Register */
-#define XM_MODE 0x0124 /* 32 bit r/w Mode Register */
-#define XM_LSA 0x0128 /* NA reg r/o Last Source Register */
- /* 0x012e: reserved */
-#define XM_TS_READ 0x0130 /* 32 bit r/o Time Stamp Read Register */
-#define XM_TS_LOAD 0x0134 /* 32 bit r/o Time Stamp Load Value */
- /* 0x0138 - 0x01fe: reserved */
-#define XM_STAT_CMD 0x0200 /* 16 bit r/w Statistics Command Register */
-#define XM_RX_CNT_EV 0x0204 /* 32 bit r/o Rx Counter Event Register */
-#define XM_TX_CNT_EV 0x0208 /* 32 bit r/o Tx Counter Event Register */
-#define XM_RX_EV_MSK 0x020c /* 32 bit r/w Rx Counter Event Mask */
-#define XM_TX_EV_MSK 0x0210 /* 32 bit r/w Tx Counter Event Mask */
- /* 0x0204 - 0x027e: reserved */
-#define XM_TXF_OK 0x0280 /* 32 bit r/o Frames Transmitted OK Conuter */
-#define XM_TXO_OK_HI 0x0284 /* 32 bit r/o Octets Transmitted OK High Cnt*/
-#define XM_TXO_OK_LO 0x0288 /* 32 bit r/o Octets Transmitted OK Low Cnt */
-#define XM_TXF_BC_OK 0x028c /* 32 bit r/o Broadcast Frames Xmitted OK */
-#define XM_TXF_MC_OK 0x0290 /* 32 bit r/o Multicast Frames Xmitted OK */
-#define XM_TXF_UC_OK 0x0294 /* 32 bit r/o Unicast Frames Xmitted OK */
-#define XM_TXF_LONG 0x0298 /* 32 bit r/o Tx Long Frame Counter */
-#define XM_TXE_BURST 0x029c /* 32 bit r/o Tx Burst Event Counter */
-#define XM_TXF_MPAUSE 0x02a0 /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */
-#define XM_TXF_MCTRL 0x02a4 /* 32 bit r/o Tx MAC Ctrl Frame Counter */
-#define XM_TXF_SNG_COL 0x02a8 /* 32 bit r/o Tx Single Collision Counter */
-#define XM_TXF_MUL_COL 0x02ac /* 32 bit r/o Tx Multiple Collision Counter */
-#define XM_TXF_ABO_COL 0x02b0 /* 32 bit r/o Tx aborted due to Exces. Col. */
-#define XM_TXF_LAT_COL 0x02b4 /* 32 bit r/o Tx Late Collision Counter */
-#define XM_TXF_DEF 0x02b8 /* 32 bit r/o Tx Deferred Frame Counter */
-#define XM_TXF_EX_DEF 0x02bc /* 32 bit r/o Tx Excessive Deferall Counter */
-#define XM_TXE_FIFO_UR 0x02c0 /* 32 bit r/o Tx FIFO Underrun Event Cnt */
-#define XM_TXE_CS_ERR 0x02c4 /* 32 bit r/o Tx Carrier Sense Error Cnt */
-#define XM_TXP_UTIL 0x02c8 /* 32 bit r/o Tx Utilization in % */
- /* 0x02cc - 0x02ce: reserved */
-#define XM_TXF_64B 0x02d0 /* 32 bit r/o 64 Byte Tx Frame Counter */
-#define XM_TXF_127B 0x02d4 /* 32 bit r/o 65-127 Byte Tx Frame Counter */
-#define XM_TXF_255B 0x02d8 /* 32 bit r/o 128-255 Byte Tx Frame Counter */
-#define XM_TXF_511B 0x02dc /* 32 bit r/o 256-511 Byte Tx Frame Counter */
-#define XM_TXF_1023B 0x02e0 /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/
-#define XM_TXF_MAX_SZ 0x02e4 /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/
- /* 0x02e8 - 0x02fe: reserved */
-#define XM_RXF_OK 0x0300 /* 32 bit r/o Frames Received OK */
-#define XM_RXO_OK_HI 0x0304 /* 32 bit r/o Octets Received OK High Cnt */
-#define XM_RXO_OK_LO 0x0308 /* 32 bit r/o Octets Received OK Low Counter*/
-#define XM_RXF_BC_OK 0x030c /* 32 bit r/o Broadcast Frames Received OK */
-#define XM_RXF_MC_OK 0x0310 /* 32 bit r/o Multicast Frames Received OK */
-#define XM_RXF_UC_OK 0x0314 /* 32 bit r/o Unicast Frames Received OK */
-#define XM_RXF_MPAUSE 0x0318 /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */
-#define XM_RXF_MCTRL 0x031c /* 32 bit r/o Rx MAC Ctrl Frame Counter */
-#define XM_RXF_INV_MP 0x0320 /* 32 bit r/o Rx invalid Pause Frame Cnt */
-#define XM_RXF_INV_MOC 0x0324 /* 32 bit r/o Rx Frames with inv. MAC Opcode*/
-#define XM_RXE_BURST 0x0328 /* 32 bit r/o Rx Burst Event Counter */
-#define XM_RXE_FMISS 0x032c /* 32 bit r/o Rx Missed Frames Event Cnt */
-#define XM_RXF_FRA_ERR 0x0330 /* 32 bit r/o Rx Framing Error Counter */
-#define XM_RXE_FIFO_OV 0x0334 /* 32 bit r/o Rx FIFO overflow Event Cnt */
-#define XM_RXF_JAB_PKT 0x0338 /* 32 bit r/o Rx Jabber Packet Frame Cnt */
-#define XM_RXE_CAR_ERR 0x033c /* 32 bit r/o Rx Carrier Event Error Cnt */
-#define XM_RXF_LEN_ERR 0x0340 /* 32 bit r/o Rx in Range Length Error */
-#define XM_RXE_SYM_ERR 0x0344 /* 32 bit r/o Rx Symbol Error Counter */
-#define XM_RXE_SHT_ERR 0x0348 /* 32 bit r/o Rx Short Event Error Cnt */
-#define XM_RXE_RUNT 0x034c /* 32 bit r/o Rx Runt Event Counter */
-#define XM_RXF_LNG_ERR 0x0350 /* 32 bit r/o Rx Frame too Long Error Cnt */
-#define XM_RXF_FCS_ERR 0x0354 /* 32 bit r/o Rx Frame Check Seq. Error Cnt */
- /* 0x0358 - 0x035a: reserved */
-#define XM_RXF_CEX_ERR 0x035c /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/
-#define XM_RXP_UTIL 0x0360 /* 32 bit r/o Rx Utilization in % */
- /* 0x0364 - 0x0366: reserved */
-#define XM_RXF_64B 0x0368 /* 32 bit r/o 64 Byte Rx Frame Counter */
-#define XM_RXF_127B 0x036c /* 32 bit r/o 65-127 Byte Rx Frame Counter */
-#define XM_RXF_255B 0x0370 /* 32 bit r/o 128-255 Byte Rx Frame Counter */
-#define XM_RXF_511B 0x0374 /* 32 bit r/o 256-511 Byte Rx Frame Counter */
-#define XM_RXF_1023B 0x0378 /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/
-#define XM_RXF_MAX_SZ 0x037c /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/
- /* 0x02e8 - 0x02fe: reserved */
-
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- * (sc) self clearing
- * (ro) read only
- */
-
-/* XM_MMU_CMD 16 bit r/w MMU Command Register */
- /* Bit 15..13: reserved */
-#define XM_MMU_PHY_RDY (1<<12) /* Bit 12: PHY Read Ready */
-#define XM_MMU_PHY_BUSY (1<<11) /* Bit 11: PHY Busy */
-#define XM_MMU_IGN_PF (1<<10) /* Bit 10: Ignore Pause Frame */
-#define XM_MMU_MAC_LB (1<<9) /* Bit 9: Enable MAC Loopback */
- /* Bit 8: reserved */
-#define XM_MMU_FRC_COL (1<<7) /* Bit 7: Force Collision */
-#define XM_MMU_SIM_COL (1<<6) /* Bit 6: Simulate Collision */
-#define XM_MMU_NO_PRE (1<<5) /* Bit 5: No MDIO Preamble */
-#define XM_MMU_GMII_FD (1<<4) /* Bit 4: GMII uses Full Duplex */
-#define XM_MMU_RAT_CTRL (1<<3) /* Bit 3: Enable Rate Control */
-#define XM_MMU_GMII_LOOP (1<<2) /* Bit 2: PHY is in Loopback Mode */
-#define XM_MMU_ENA_RX (1<<1) /* Bit 1: Enable Receiver */
-#define XM_MMU_ENA_TX (1<<0) /* Bit 0: Enable Transmitter */
-
-
-/* XM_TX_CMD 16 bit r/w Transmit Command Register */
- /* Bit 15..7: reserved */
-#define XM_TX_BK2BK (1<<6) /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/
-#define XM_TX_ENC_BYP (1<<5) /* Bit 5: Set Encoder in Bypass Mode */
-#define XM_TX_SAM_LINE (1<<4) /* Bit 4: (sc) Start utilization calculation */
-#define XM_TX_NO_GIG_MD (1<<3) /* Bit 3: Disable Carrier Extension */
-#define XM_TX_NO_PRE (1<<2) /* Bit 2: Disable Preamble Generation */
-#define XM_TX_NO_CRC (1<<1) /* Bit 1: Disable CRC Generation */
-#define XM_TX_AUTO_PAD (1<<0) /* Bit 0: Enable Automatic Padding */
-
-
-/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */
- /* Bit 15..5: reserved */
-#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */
-
-
-/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */
- /* Bit 15..7: reserved */
-#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */
-
-
-/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */
- /* Bit 15..8: reserved */
-#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */
-
-
-/* XM_RX_CMD 16 bit r/w Receive Command Register */
- /* Bit 15..9: reserved */
-#define XM_RX_LENERR_OK (1<<8) /* Bit 8 don't set Rx Err bit for */
- /* inrange error packets */
-#define XM_RX_BIG_PK_OK (1<<7) /* Bit 7 don't set Rx Err bit for */
- /* jumbo packets */
-#define XM_RX_IPG_CAP (1<<6) /* Bit 6 repl. type field with IPG */
-#define XM_RX_TP_MD (1<<5) /* Bit 5: Enable transparent Mode */
-#define XM_RX_STRIP_FCS (1<<4) /* Bit 4: Enable FCS Stripping */
-#define XM_RX_SELF_RX (1<<3) /* Bit 3: Enable Rx of own packets */
-#define XM_RX_SAM_LINE (1<<2) /* Bit 2: (sc) Start utilization calculation */
-#define XM_RX_STRIP_PAD (1<<1) /* Bit 1: Strip pad bytes of Rx frames */
-#define XM_RX_DIS_CEXT (1<<0) /* Bit 0: Disable carrier ext. check */
-
-
-/* XM_PHY_ADDR 16 bit r/w PHY Address Register */
- /* Bit 15..5: reserved */
-#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */
-
-
-/* XM_GP_PORT 32 bit r/w General Purpose Port Register */
- /* Bit 31..7: reserved */
-#define XM_GP_ANIP (1L<<6) /* Bit 6: (ro) Auto-Neg. in progress */
-#define XM_GP_FRC_INT (1L<<5) /* Bit 5: (sc) Force Interrupt */
- /* Bit 4: reserved */
-#define XM_GP_RES_MAC (1L<<3) /* Bit 3: (sc) Reset MAC and FIFOs */
-#define XM_GP_RES_STAT (1L<<2) /* Bit 2: (sc) Reset the statistics module */
- /* Bit 1: reserved */
-#define XM_GP_INP_ASS (1L<<0) /* Bit 0: (ro) GP Input Pin asserted */
-
-
-/* XM_IMSK 16 bit r/w Interrupt Mask Register */
-/* XM_ISRC 16 bit r/o Interrupt Status Register */
- /* Bit 15: reserved */
-#define XM_IS_LNK_AE (1<<14) /* Bit 14: Link Asynchronous Event */
-#define XM_IS_TX_ABORT (1<<13) /* Bit 13: Transmit Abort, late Col. etc */
-#define XM_IS_FRC_INT (1<<12) /* Bit 12: Force INT bit set in GP */
-#define XM_IS_INP_ASS (1<<11) /* Bit 11: Input Asserted, GP bit 0 set */
-#define XM_IS_LIPA_RC (1<<10) /* Bit 10: Link Partner requests config */
-#define XM_IS_RX_PAGE (1<<9) /* Bit 9: Page Received */
-#define XM_IS_TX_PAGE (1<<8) /* Bit 8: Next Page Loaded for Transmit */
-#define XM_IS_AND (1<<7) /* Bit 7: Auto-Negotiation Done */
-#define XM_IS_TSC_OV (1<<6) /* Bit 6: Time Stamp Counter Overflow */
-#define XM_IS_RXC_OV (1<<5) /* Bit 5: Rx Counter Event Overflow */
-#define XM_IS_TXC_OV (1<<4) /* Bit 4: Tx Counter Event Overflow */
-#define XM_IS_RXF_OV (1<<3) /* Bit 3: Receive FIFO Overflow */
-#define XM_IS_TXF_UR (1<<2) /* Bit 2: Transmit FIFO Underrun */
-#define XM_IS_TX_COMP (1<<1) /* Bit 1: Frame Tx Complete */
-#define XM_IS_RX_COMP (1<<0) /* Bit 0: Frame Rx Complete */
-
-#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\
- XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR))
-
-
-/* XM_HW_CFG 16 bit r/w Hardware Config Register */
- /* Bit 15.. 4: reserved */
-#define XM_HW_GEN_EOP (1<<3) /* Bit 3: generate End of Packet pulse */
-#define XM_HW_COM4SIG (1<<2) /* Bit 2: use Comma Detect for Sig. Det.*/
- /* Bit 1: reserved */
-#define XM_HW_GMII_MD (1<<0) /* Bit 0: GMII Interface selected */
-
-
-/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */
-/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */
- /* Bit 15..10 reserved */
-#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */
-
-/* XM_TX_THR 16 bit r/w Tx Request Threshold */
-/* XM_HT_THR 16 bit r/w Host Request Threshold */
-/* XM_RX_THR 16 bit r/w Rx Request Threshold */
- /* Bit 15..11 reserved */
-#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */
-
-
-/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */
-#define XM_ST_VALID (1UL<<31) /* Bit 31: Status Valid */
-#define XM_ST_BYTE_CNT (0x3fffL<<17) /* Bit 30..17: Tx frame Length */
-#define XM_ST_RETRY_CNT (0x1fL<<12) /* Bit 16..12: Retry Count */
-#define XM_ST_EX_COL (1L<<11) /* Bit 11: Excessive Collisions */
-#define XM_ST_EX_DEF (1L<<10) /* Bit 10: Excessive Deferral */
-#define XM_ST_BURST (1L<<9) /* Bit 9: p. xmitted in burst md*/
-#define XM_ST_DEFER (1L<<8) /* Bit 8: packet was defered */
-#define XM_ST_BC (1L<<7) /* Bit 7: Broadcast packet */
-#define XM_ST_MC (1L<<6) /* Bit 6: Multicast packet */
-#define XM_ST_UC (1L<<5) /* Bit 5: Unicast packet */
-#define XM_ST_TX_UR (1L<<4) /* Bit 4: FIFO Underrun occured */
-#define XM_ST_CS_ERR (1L<<3) /* Bit 3: Carrier Sense Error */
-#define XM_ST_LAT_COL (1L<<2) /* Bit 2: Late Collision Error */
-#define XM_ST_MUL_COL (1L<<1) /* Bit 1: Multiple Collisions */
-#define XM_ST_SGN_COL (1L<<0) /* Bit 0: Single Collision */
-
-/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */
-/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */
- /* Bit 15..11: reserved */
-#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */
-
-
-/* XM_DEV_ID 32 bit r/o Device ID Register */
-#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */
-#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */
-
-
-/* XM_MODE 32 bit r/w Mode Register */
- /* Bit 31..27: reserved */
-#define XM_MD_ENA_REJ (1L<<26) /* Bit 26: Enable Frame Reject */
-#define XM_MD_SPOE_E (1L<<25) /* Bit 25: Send Pause on Edge */
- /* extern generated */
-#define XM_MD_TX_REP (1L<<24) /* Bit 24: Transmit Repeater Mode */
-#define XM_MD_SPOFF_I (1L<<23) /* Bit 23: Send Pause on FIFO full */
- /* intern generated */
-#define XM_MD_LE_STW (1L<<22) /* Bit 22: Rx Stat Word in Little Endian */
-#define XM_MD_TX_CONT (1L<<21) /* Bit 21: Send Continuous */
-#define XM_MD_TX_PAUSE (1L<<20) /* Bit 20: (sc) Send Pause Frame */
-#define XM_MD_ATS (1L<<19) /* Bit 19: Append Time Stamp */
-#define XM_MD_SPOL_I (1L<<18) /* Bit 18: Send Pause on Low */
- /* intern generated */
-#define XM_MD_SPOH_I (1L<<17) /* Bit 17: Send Pause on High */
- /* intern generated */
-#define XM_MD_CAP (1L<<16) /* Bit 16: Check Address Pair */
-#define XM_MD_ENA_HASH (1L<<15) /* Bit 15: Enable Hashing */
-#define XM_MD_CSA (1L<<14) /* Bit 14: Check Station Address */
-#define XM_MD_CAA (1L<<13) /* Bit 13: Check Address Array */
-#define XM_MD_RX_MCTRL (1L<<12) /* Bit 12: Rx MAC Control Frame */
-#define XM_MD_RX_RUNT (1L<<11) /* Bit 11: Rx Runt Frames */
-#define XM_MD_RX_IRLE (1L<<10) /* Bit 10: Rx in Range Len Err Frame */
-#define XM_MD_RX_LONG (1L<<9) /* Bit 9: Rx Long Frame */
-#define XM_MD_RX_CRCE (1L<<8) /* Bit 8: Rx CRC Error Frame */
-#define XM_MD_RX_ERR (1L<<7) /* Bit 7: Rx Error Frame */
-#define XM_MD_DIS_UC (1L<<6) /* Bit 6: Disable Rx Unicast */
-#define XM_MD_DIS_MC (1L<<5) /* Bit 5: Disable Rx Multicast */
-#define XM_MD_DIS_BC (1L<<4) /* Bit 4: Disable Rx Broadcast */
-#define XM_MD_ENA_PROM (1L<<3) /* Bit 3: Enable Promiscuous */
-#define XM_MD_ENA_BE (1L<<2) /* Bit 2: Enable Big Endian */
-#define XM_MD_FTF (1L<<1) /* Bit 1: (sc) Flush Tx FIFO */
-#define XM_MD_FRF (1L<<0) /* Bit 0: (sc) Flush Rx FIFO */
-
-#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
-#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
- XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
-
-/* XM_STAT_CMD 16 bit r/w Statistics Command Register */
- /* Bit 16..6: reserved */
-#define XM_SC_SNP_RXC (1<<5) /* Bit 5: (sc) Snap Rx Counters */
-#define XM_SC_SNP_TXC (1<<4) /* Bit 4: (sc) Snap Tx Counters */
-#define XM_SC_CP_RXC (1<<3) /* Bit 3: Copy Rx Counters Continuously */
-#define XM_SC_CP_TXC (1<<2) /* Bit 2: Copy Tx Counters Continuously */
-#define XM_SC_CLR_RXC (1<<1) /* Bit 1: (sc) Clear Rx Counters */
-#define XM_SC_CLR_TXC (1<<0) /* Bit 0: (sc) Clear Tx Counters */
-
-
-/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */
-/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */
-#define XMR_MAX_SZ_OV (1UL<<31) /* Bit 31: 1024-MaxSize Rx Cnt Ov*/
-#define XMR_1023B_OV (1L<<30) /* Bit 30: 512-1023Byte Rx Cnt Ov*/
-#define XMR_511B_OV (1L<<29) /* Bit 29: 256-511 Byte Rx Cnt Ov*/
-#define XMR_255B_OV (1L<<28) /* Bit 28: 128-255 Byte Rx Cnt Ov*/
-#define XMR_127B_OV (1L<<27) /* Bit 27: 65-127 Byte Rx Cnt Ov */
-#define XMR_64B_OV (1L<<26) /* Bit 26: 64 Byte Rx Cnt Ov */
-#define XMR_UTIL_OV (1L<<25) /* Bit 25: Rx Util Cnt Overflow */
-#define XMR_UTIL_UR (1L<<24) /* Bit 24: Rx Util Cnt Underrun */
-#define XMR_CEX_ERR_OV (1L<<23) /* Bit 23: CEXT Err Cnt Ov */
- /* Bit 22: reserved */
-#define XMR_FCS_ERR_OV (1L<<21) /* Bit 21: Rx FCS Error Cnt Ov */
-#define XMR_LNG_ERR_OV (1L<<20) /* Bit 20: Rx too Long Err Cnt Ov*/
-#define XMR_RUNT_OV (1L<<19) /* Bit 19: Runt Event Cnt Ov */
-#define XMR_SHT_ERR_OV (1L<<18) /* Bit 18: Rx Short Ev Err Cnt Ov*/
-#define XMR_SYM_ERR_OV (1L<<17) /* Bit 17: Rx Sym Err Cnt Ov */
- /* Bit 16: reserved */
-#define XMR_CAR_ERR_OV (1L<<15) /* Bit 15: Rx Carr Ev Err Cnt Ov */
-#define XMR_JAB_PKT_OV (1L<<14) /* Bit 14: Rx Jabb Packet Cnt Ov */
-#define XMR_FIFO_OV (1L<<13) /* Bit 13: Rx FIFO Ov Ev Cnt Ov */
-#define XMR_FRA_ERR_OV (1L<<12) /* Bit 12: Rx Framing Err Cnt Ov */
-#define XMR_FMISS_OV (1L<<11) /* Bit 11: Rx Missed Ev Cnt Ov */
-#define XMR_BURST (1L<<10) /* Bit 10: Rx Burst Event Cnt Ov */
-#define XMR_INV_MOC (1L<<9) /* Bit 9: Rx with inv. MAC OC Ov*/
-#define XMR_INV_MP (1L<<8) /* Bit 8: Rx inv Pause Frame Ov */
-#define XMR_MCTRL_OV (1L<<7) /* Bit 7: Rx MAC Ctrl-F Cnt Ov */
-#define XMR_MPAUSE_OV (1L<<6) /* Bit 6: Rx Pause MAC Ctrl-F Ov*/
-#define XMR_UC_OK_OV (1L<<5) /* Bit 5: Rx Unicast Frame CntOv*/
-#define XMR_MC_OK_OV (1L<<4) /* Bit 4: Rx Multicast Cnt Ov */
-#define XMR_BC_OK_OV (1L<<3) /* Bit 3: Rx Broadcast Cnt Ov */
-#define XMR_OK_LO_OV (1L<<2) /* Bit 2: Octets Rx OK Low CntOv*/
-#define XMR_OK_HI_OV (1L<<1) /* Bit 1: Octets Rx OK Hi Cnt Ov*/
-#define XMR_OK_OV (1L<<0) /* Bit 0: Frames Received Ok Ov */
-
-#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV)
-
-/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */
-/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */
- /* Bit 31..26: reserved */
-#define XMT_MAX_SZ_OV (1L<<25) /* Bit 25: 1024-MaxSize Tx Cnt Ov*/
-#define XMT_1023B_OV (1L<<24) /* Bit 24: 512-1023Byte Tx Cnt Ov*/
-#define XMT_511B_OV (1L<<23) /* Bit 23: 256-511 Byte Tx Cnt Ov*/
-#define XMT_255B_OV (1L<<22) /* Bit 22: 128-255 Byte Tx Cnt Ov*/
-#define XMT_127B_OV (1L<<21) /* Bit 21: 65-127 Byte Tx Cnt Ov */
-#define XMT_64B_OV (1L<<20) /* Bit 20: 64 Byte Tx Cnt Ov */
-#define XMT_UTIL_OV (1L<<19) /* Bit 19: Tx Util Cnt Overflow */
-#define XMT_UTIL_UR (1L<<18) /* Bit 18: Tx Util Cnt Underrun */
-#define XMT_CS_ERR_OV (1L<<17) /* Bit 17: Tx Carr Sen Err Cnt Ov*/
-#define XMT_FIFO_UR_OV (1L<<16) /* Bit 16: Tx FIFO Ur Ev Cnt Ov */
-#define XMT_EX_DEF_OV (1L<<15) /* Bit 15: Tx Ex Deferall Cnt Ov */
-#define XMT_DEF (1L<<14) /* Bit 14: Tx Deferred Cnt Ov */
-#define XMT_LAT_COL_OV (1L<<13) /* Bit 13: Tx Late Col Cnt Ov */
-#define XMT_ABO_COL_OV (1L<<12) /* Bit 12: Tx abo dueto Ex Col Ov*/
-#define XMT_MUL_COL_OV (1L<<11) /* Bit 11: Tx Mult Col Cnt Ov */
-#define XMT_SNG_COL (1L<<10) /* Bit 10: Tx Single Col Cnt Ov */
-#define XMT_MCTRL_OV (1L<<9) /* Bit 9: Tx MAC Ctrl Counter Ov*/
-#define XMT_MPAUSE (1L<<8) /* Bit 8: Tx Pause MAC Ctrl-F Ov*/
-#define XMT_BURST (1L<<7) /* Bit 7: Tx Burst Event Cnt Ov */
-#define XMT_LONG (1L<<6) /* Bit 6: Tx Long Frame Cnt Ov */
-#define XMT_UC_OK_OV (1L<<5) /* Bit 5: Tx Unicast Cnt Ov */
-#define XMT_MC_OK_OV (1L<<4) /* Bit 4: Tx Multicast Cnt Ov */
-#define XMT_BC_OK_OV (1L<<3) /* Bit 3: Tx Broadcast Cnt Ov */
-#define XMT_OK_LO_OV (1L<<2) /* Bit 2: Octets Tx OK Low CntOv*/
-#define XMT_OK_HI_OV (1L<<1) /* Bit 1: Octets Tx OK Hi Cnt Ov*/
-#define XMT_OK_OV (1L<<0) /* Bit 0: Frames Tx Ok Ov */
-
-#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV)
-
-/*
- * Receive Frame Status Encoding
- */
-#define XMR_FS_LEN (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */
-#define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: tagged wh 2Lev VLAN ID*/
-#define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: tagged wh 1Lev VLAN ID*/
-#define XMR_FS_BC (1L<<15) /* Bit 15: Broadcast Frame */
-#define XMR_FS_MC (1L<<14) /* Bit 14: Multicast Frame */
-#define XMR_FS_UC (1L<<13) /* Bit 13: Unicast Frame */
- /* Bit 12: reserved */
-#define XMR_FS_BURST (1L<<11) /* Bit 11: Burst Mode */
-#define XMR_FS_CEX_ERR (1L<<10) /* Bit 10: Carrier Ext. Error */
-#define XMR_FS_802_3 (1L<<9) /* Bit 9: 802.3 Frame */
-#define XMR_FS_COL_ERR (1L<<8) /* Bit 8: Collision Error */
-#define XMR_FS_CAR_ERR (1L<<7) /* Bit 7: Carrier Event Error */
-#define XMR_FS_LEN_ERR (1L<<6) /* Bit 6: In-Range Length Error */
-#define XMR_FS_FRA_ERR (1L<<5) /* Bit 5: Framing Error */
-#define XMR_FS_RUNT (1L<<4) /* Bit 4: Runt Frame */
-#define XMR_FS_LNG_ERR (1L<<3) /* Bit 3: Giant (Jumbo) Frame */
-#define XMR_FS_FCS_ERR (1L<<2) /* Bit 2: Frame Check Sequ Err */
-#define XMR_FS_ERR (1L<<1) /* Bit 1: Frame Error */
-#define XMR_FS_MCTRL (1L<<0) /* Bit 0: MAC Control Packet */
-
-/*
- * XMR_FS_ERR will be set if
- * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
- * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
- * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
- * XMR_FS_ERR unless the corresponding bit in the Receive Command
- * Register is set.
- */
-#define XMR_FS_ANY_ERR XMR_FS_ERR
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC-PHY Registers, indirect addressed over the XMAC
- */
-#define PHY_XMAC_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_XMAC_STAT 0x01 /* 16 bit r/w PHY Status Register */
-#define PHY_XMAC_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_XMAC_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_XMAC_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Abi Reg */
-#define PHY_XMAC_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_XMAC_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
- /* 0x09 - 0x0e: reserved */
-#define PHY_XMAC_EXT_STAT 0x0f /* 16 bit r/o Ext Status Register */
-#define PHY_XMAC_RES_ABI 0x10 /* 16 bit r/o PHY Resolved Ability */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Broadcom-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_BCOM_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_BCOM_STAT 0x01 /* 16 bit r/o PHY Status Register */
-#define PHY_BCOM_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_BCOM_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_BCOM_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */
-#define PHY_BCOM_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
- /* Broadcom-specific registers */
-#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */
-#define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
- /* 0x0b - 0x0e: reserved */
-#define PHY_BCOM_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
-#define PHY_BCOM_P_EXT_CTRL 0x10 /* 16 bit r/w PHY Extended Ctrl Reg */
-#define PHY_BCOM_P_EXT_STAT 0x11 /* 16 bit r/o PHY Extended Stat Reg */
-#define PHY_BCOM_RE_CTR 0x12 /* 16 bit r/w Receive Error Counter */
-#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carrier Sense Cnt */
-#define PHY_BCOM_RNO_CTR 0x14 /* 16 bit r/w Receiver NOT_OK Cnt */
- /* 0x15 - 0x17: reserved */
-#define PHY_BCOM_AUX_CTRL 0x18 /* 16 bit r/w Auxiliary Control Reg */
-#define PHY_BCOM_AUX_STAT 0x19 /* 16 bit r/o Auxiliary Stat Summary */
-#define PHY_BCOM_INT_STAT 0x1a /* 16 bit r/o Interrupt Status Reg */
-#define PHY_BCOM_INT_MASK 0x1b /* 16 bit r/w Interrupt Mask Reg */
- /* 0x1c: reserved */
- /* 0x1d - 0x1f: test registers */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Marvel-PHY Registers, indirect addressed over GMAC
- */
-#define PHY_MARV_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_MARV_STAT 0x01 /* 16 bit r/o PHY Status Register */
-#define PHY_MARV_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_MARV_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_MARV_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */
-#define PHY_MARV_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
- /* Marvel-specific registers */
-#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */
-#define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
- /* 0x0b - 0x0e: reserved */
-#define PHY_MARV_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
-#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Ctrl Reg */
-#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Stat Reg */
-#define PHY_MARV_INT_MASK 0x12 /* 16 bit r/w Interrupt Mask Reg */
-#define PHY_MARV_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */
-#define PHY_MARV_EXT_CTRL 0x14 /* 16 bit r/w Ext. PHY Specific Ctrl */
-#define PHY_MARV_RXE_CNT 0x15 /* 16 bit r/w Receive Error Counter */
-#define PHY_MARV_EXT_ADR 0x16 /* 16 bit r/w Ext. Ad. for Cable Diag. */
- /* 0x17: reserved */
-#define PHY_MARV_LED_CTRL 0x18 /* 16 bit r/w LED Control Reg */
-#define PHY_MARV_LED_OVER 0x19 /* 16 bit r/w Manual LED Override Reg */
-#define PHY_MARV_EXT_CTRL_2 0x1a /* 16 bit r/w Ext. PHY Specific Ctrl 2 */
-#define PHY_MARV_EXT_P_STAT 0x1b /* 16 bit r/w Ext. PHY Spec. Stat Reg */
-#define PHY_MARV_CABLE_DIAG 0x1c /* 16 bit r/o Cable Diagnostic Reg */
- /* 0x1d - 0x1f: reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Level One-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_LONE_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_LONE_STAT 0x01 /* 16 bit r/o PHY Status Register */
-#define PHY_LONE_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_LONE_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_LONE_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */
-#define PHY_LONE_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
- /* Level One-specific registers */
-#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/
-#define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
- /* 0x0b -0x0e: reserved */
-#define PHY_LONE_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
-#define PHY_LONE_PORT_CFG 0x10 /* 16 bit r/w Port Configuration Reg*/
-#define PHY_LONE_Q_STAT 0x11 /* 16 bit r/o Quick Status Reg */
-#define PHY_LONE_INT_ENAB 0x12 /* 16 bit r/w Interrupt Enable Reg */
-#define PHY_LONE_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */
-#define PHY_LONE_LED_CFG 0x14 /* 16 bit r/w LED Configuration Reg */
-#define PHY_LONE_PORT_CTRL 0x15 /* 16 bit r/w Port Control Reg */
-#define PHY_LONE_CIM 0x16 /* 16 bit r/o CIM Reg */
- /* 0x17 -0x1c: reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * National-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_NAT_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_NAT_STAT 0x01 /* 16 bit r/w PHY Status Register */
-#define PHY_NAT_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_NAT_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_NAT_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_NAT_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */
-#define PHY_NAT_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_NAT_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_NAT_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner Reg */
- /* National-specific registers */
-#define PHY_NAT_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */
-#define PHY_NAT_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
- /* 0x0b -0x0e: reserved */
-#define PHY_NAT_EXT_STAT 0x0f /* 16 bit r/o Extended Status Register */
-#define PHY_NAT_EXT_CTRL1 0x10 /* 16 bit r/o Extended Control Reg1 */
-#define PHY_NAT_Q_STAT1 0x11 /* 16 bit r/o Quick Status Reg1 */
-#define PHY_NAT_10B_OP 0x12 /* 16 bit r/o 10Base-T Operations Reg */
-#define PHY_NAT_EXT_CTRL2 0x13 /* 16 bit r/o Extended Control Reg1 */
-#define PHY_NAT_Q_STAT2 0x14 /* 16 bit r/o Quick Status Reg2 */
- /* 0x15 -0x18: reserved */
-#define PHY_NAT_PHY_ADDR 0x19 /* 16 bit r/o PHY Address Register */
-
-
-/*----------------------------------------------------------------------------*/
-
-/*
- * PHY bit definitions
- * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are
- * XMAC/Broadcom/LevelOne/National/Marvell-specific.
- * All other are general.
- */
-
-/***** PHY_XMAC_CTRL 16 bit r/w PHY Control Register *****/
-/***** PHY_BCOM_CTRL 16 bit r/w PHY Control Register *****/
-/***** PHY_MARV_CTRL 16 bit r/w PHY Status Register *****/
-/***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/
-#define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */
-#define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */
-#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */
-#define PHY_CT_ANE (1<<12) /* Bit 12: Auto-Negotiation Enabled */
-#define PHY_CT_PDOWN (1<<11) /* Bit 11: (BC,L1) Power Down Mode */
-#define PHY_CT_ISOL (1<<10) /* Bit 10: (BC,L1) Isolate Mode */
-#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */
-#define PHY_CT_DUP_MD (1<<8) /* Bit 8: Duplex Mode */
-#define PHY_CT_COL_TST (1<<7) /* Bit 7: (BC,L1) Collision Test enabled */
-#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: (BC,L1) Speed select, upper bit */
- /* Bit 5..0: reserved */
-
-#define PHY_CT_SP1000 PHY_CT_SPS_MSB /* enable speed of 1000 Mbps */
-#define PHY_CT_SP100 PHY_CT_SPS_LSB /* enable speed of 100 Mbps */
-#define PHY_CT_SP10 (0) /* enable speed of 10 Mbps */
-
-
-/***** PHY_XMAC_STAT 16 bit r/w PHY Status Register *****/
-/***** PHY_BCOM_STAT 16 bit r/w PHY Status Register *****/
-/***** PHY_MARV_STAT 16 bit r/w PHY Status Register *****/
-/***** PHY_LONE_STAT 16 bit r/w PHY Status Register *****/
- /* Bit 15..9: reserved */
- /* (BC/L1) 100/10 Mbps cap bits ignored*/
-#define PHY_ST_EXT_ST (1<<8) /* Bit 8: Extended Status Present */
- /* Bit 7: reserved */
-#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: (BC/L1) preamble suppression */
-#define PHY_ST_AN_OVER (1<<5) /* Bit 5: Auto-Negotiation Over */
-#define PHY_ST_REM_FLT (1<<4) /* Bit 4: Remote Fault Condition Occured */
-#define PHY_ST_AN_CAP (1<<3) /* Bit 3: Auto-Negotiation Capability */
-#define PHY_ST_LSYNC (1<<2) /* Bit 2: Link Synchronized */
-#define PHY_ST_JAB_DET (1<<1) /* Bit 1: (BC/L1) Jabber Detected */
-#define PHY_ST_EXT_REG (1<<0) /* Bit 0: Extended Register available */
-
-
-/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */
-/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */
-/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */
-/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */
-#define PHY_I1_OUI_MSK (0x3f<<10) /* Bit 15..10: Organization Unique ID */
-#define PHY_I1_MOD_NUM (0x3f<<4) /* Bit 9.. 4: Model Number */
-#define PHY_I1_REV_MSK 0x0f /* Bit 3.. 0: Revision Number */
-
-/* different Broadcom PHY Ids */
-#define PHY_BCOM_ID1_A1 0x6041
-#define PHY_BCOM_ID1_B2 0x6043
-#define PHY_BCOM_ID1_C0 0x6044
-#define PHY_BCOM_ID1_C5 0x6047
-
-
-/***** PHY_XMAC_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_XMAC_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
-#define PHY_AN_NXT_PG (1<<15) /* Bit 15: Request Next Page */
-#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */
-#define PHY_X_AN_RFB (3<<12) /* Bit 13..12: Remote Fault Bits */
- /* Bit 11.. 9: reserved */
-#define PHY_X_AN_PAUSE (3<<7) /* Bit 8.. 7: Pause Bits */
-#define PHY_X_AN_HD (1<<6) /* Bit 6: Half Duplex */
-#define PHY_X_AN_FD (1<<5) /* Bit 5: Full Duplex */
- /* Bit 4.. 0: reserved */
-
-/***** PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
- /* Bit 14: reserved */
-#define PHY_B_AN_RF (1<<13) /* Bit 13: Remote Fault */
- /* Bit 12: reserved */
-#define PHY_B_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */
-#define PHY_B_AN_PC (1<<10) /* Bit 10: Pause Capable */
- /* Bit 9..5: 100/10 BT cap bits ingnored */
-#define PHY_B_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/
-
-/***** PHY_LONE_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_LONE_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
- /* Bit 14: reserved */
-#define PHY_L_AN_RF (1<<13) /* Bit 13: Remote Fault */
- /* Bit 12: reserved */
-#define PHY_L_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */
-#define PHY_L_AN_PC (1<<10) /* Bit 10: Pause Capable */
- /* Bit 9..5: 100/10 BT cap bits ingnored */
-#define PHY_L_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/
-
-/***** PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
- /* Bit 14: reserved */
-#define PHY_N_AN_RF (1<<13) /* Bit 13: Remote Fault */
- /* Bit 12: reserved */
-#define PHY_N_AN_100F (1<<11) /* Bit 11: 100Base-T2 FD Support */
-#define PHY_N_AN_100H (1<<10) /* Bit 10: 100Base-T2 HD Support */
- /* Bit 9..5: 100/10 BT cap bits ingnored */
-#define PHY_N_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/
-
-/* field type definition for PHY_x_AN_SEL */
-#define PHY_SEL_TYPE 0x01 /* 00001 = Ethernet */
-
-/***** PHY_XMAC_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
- /* Bit 15..4: reserved */
-#define PHY_ANE_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */
-#define PHY_ANE_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */
-#define PHY_ANE_RX_PG (1<<1) /* Bit 1: Page Received */
- /* Bit 0: reserved */
-
-/***** PHY_BCOM_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
-/***** PHY_LONE_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
-/***** PHY_MARV_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
- /* Bit 15..5: reserved */
-#define PHY_ANE_PAR_DF (1<<4) /* Bit 4: Parallel Detection Fault */
-/* PHY_ANE_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */
-/* PHY_ANE_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */
-/* PHY_ANE_RX_PG (see XMAC) Bit 1: Page Received */
-#define PHY_ANE_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */
-
-/***** PHY_XMAC_NEPG 16 bit r/w Next Page Register *****/
-/***** PHY_BCOM_NEPG 16 bit r/w Next Page Register *****/
-/***** PHY_LONE_NEPG 16 bit r/w Next Page Register *****/
-/***** PHY_XMAC_NEPG_LP 16 bit r/o Next Page Link Partner *****/
-/***** PHY_BCOM_NEPG_LP 16 bit r/o Next Page Link Partner *****/
-/***** PHY_LONE_NEPG_LP 16 bit r/o Next Page Link Partner *****/
-#define PHY_NP_MORE (1<<15) /* Bit 15: More, Next Pages to follow */
-#define PHY_NP_ACK1 (1<<14) /* Bit 14: (ro) Ack1, for receiving a message */
-#define PHY_NP_MSG_VAL (1<<13) /* Bit 13: Message Page valid */
-#define PHY_NP_ACK2 (1<<12) /* Bit 12: Ack2, comply with msg content */
-#define PHY_NP_TOG (1<<11) /* Bit 11: Toggle Bit, ensure sync */
-#define PHY_NP_MSG 0x07ff /* Bit 10..0: Message from/to Link Partner */
-
-/*
- * XMAC-Specific
- */
-/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/
-#define PHY_X_EX_FD (1<<15) /* Bit 15: Device Supports Full Duplex */
-#define PHY_X_EX_HD (1<<14) /* Bit 14: Device Supports Half Duplex */
- /* Bit 13..0: reserved */
-
-/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/
- /* Bit 15..9: reserved */
-#define PHY_X_RS_PAUSE (3<<7) /* Bit 8..7: selected Pause Mode */
-#define PHY_X_RS_HD (1<<6) /* Bit 6: Half Duplex Mode selected */
-#define PHY_X_RS_FD (1<<5) /* Bit 5: Full Duplex Mode selected */
-#define PHY_X_RS_ABLMIS (1<<4) /* Bit 4: duplex or pause cap mismatch */
-#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability mismatch */
- /* Bit 2..0: reserved */
-/*
- * Remote Fault Bits (PHY_X_AN_RFB) encoding
- */
-#define X_RFB_OK (0<<12) /* Bit 13..12 No errors, Link OK */
-#define X_RFB_LF (1<<12) /* Bit 13..12 Link Failure */
-#define X_RFB_OFF (2<<12) /* Bit 13..12 Offline */
-#define X_RFB_AN_ERR (3<<12) /* Bit 13..12 Auto-Negotiation Error */
-
-/*
- * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding
- */
-#define PHY_X_P_NO_PAUSE (0<<7) /* Bit 8..7: no Pause Mode */
-#define PHY_X_P_SYM_MD (1<<7) /* Bit 8..7: symmetric Pause Mode */
-#define PHY_X_P_ASYM_MD (2<<7) /* Bit 8..7: asymmetric Pause Mode */
-#define PHY_X_P_BOTH_MD (3<<7) /* Bit 8..7: both Pause Mode */
-
-
-/*
- * Broadcom-Specific
- */
-/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-#define PHY_B_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
-#define PHY_B_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */
-#define PHY_B_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */
-#define PHY_B_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */
-#define PHY_B_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
-#define PHY_B_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
- /* Bit 7..0: reserved */
-
-/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-#define PHY_B_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */
-#define PHY_B_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */
-#define PHY_B_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */
-#define PHY_B_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */
-#define PHY_B_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */
-#define PHY_B_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */
- /* Bit 9..8: reserved */
-#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */
-
-/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/
-#define PHY_B_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */
-#define PHY_B_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */
-#define PHY_B_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */
-#define PHY_B_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */
- /* Bit 11..0: reserved */
-
-/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/
-#define PHY_B_PEC_MAC_PHY (1<<15) /* Bit 15: 10BIT/GMI-Interface */
-#define PHY_B_PEC_DIS_CROSS (1<<14) /* Bit 14: Disable MDI Crossover */
-#define PHY_B_PEC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */
-#define PHY_B_PEC_INT_DIS (1<<12) /* Bit 12: Interrupts Disabled */
-#define PHY_B_PEC_F_INT (1<<11) /* Bit 11: Force Interrupt */
-#define PHY_B_PEC_BY_45 (1<<10) /* Bit 10: Bypass 4B5B-Decoder */
-#define PHY_B_PEC_BY_SCR (1<<9) /* Bit 9: Bypass Scrambler */
-#define PHY_B_PEC_BY_MLT3 (1<<8) /* Bit 8: Bypass MLT3 Encoder */
-#define PHY_B_PEC_BY_RXA (1<<7) /* Bit 7: Bypass Rx Alignm. */
-#define PHY_B_PEC_RES_SCR (1<<6) /* Bit 6: Reset Scrambler */
-#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Ena LED Traffic Mode */
-#define PHY_B_PEC_LED_ON (1<<4) /* Bit 4: Force LED's on */
-#define PHY_B_PEC_LED_OFF (1<<3) /* Bit 3: Force LED's off */
-#define PHY_B_PEC_EX_IPG (1<<2) /* Bit 2: Extend Tx IPG Mode */
-#define PHY_B_PEC_3_LED (1<<1) /* Bit 1: Three Link LED mode */
-#define PHY_B_PEC_HIGH_LA (1<<0) /* Bit 0: GMII FIFO Elasticy */
-
-/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/
- /* Bit 15..14: reserved */
-#define PHY_B_PES_CROSS_STAT (1<<13) /* Bit 13: MDI Crossover Status */
-#define PHY_B_PES_INT_STAT (1<<12) /* Bit 12: Interrupt Status */
-#define PHY_B_PES_RRS (1<<11) /* Bit 11: Remote Receiver Stat. */
-#define PHY_B_PES_LRS (1<<10) /* Bit 10: Local Receiver Stat. */
-#define PHY_B_PES_LOCKED (1<<9) /* Bit 9: Locked */
-#define PHY_B_PES_LS (1<<8) /* Bit 8: Link Status */
-#define PHY_B_PES_RF (1<<7) /* Bit 7: Remote Fault */
-#define PHY_B_PES_CE_ER (1<<6) /* Bit 6: Carrier Ext Error */
-#define PHY_B_PES_BAD_SSD (1<<5) /* Bit 5: Bad SSD */
-#define PHY_B_PES_BAD_ESD (1<<4) /* Bit 4: Bad ESD */
-#define PHY_B_PES_RX_ER (1<<3) /* Bit 3: Receive Error */
-#define PHY_B_PES_TX_ER (1<<2) /* Bit 2: Transmit Error */
-#define PHY_B_PES_LOCK_ER (1<<1) /* Bit 1: Lock Error */
-#define PHY_B_PES_MLT3_ER (1<<0) /* Bit 0: MLT3 code Error */
-
-/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/
- /* Bit 15..8: reserved */
-#define PHY_B_FC_CTR 0xff /* Bit 7..0: False Carrier Counter */
-
-/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/
-#define PHY_B_RC_LOC_MSK 0xff00 /* Bit 15..8: Local Rx NOT_OK cnt */
-#define PHY_B_RC_REM_MSK 0x00ff /* Bit 7..0: Remote Rx NOT_OK cnt */
-
-/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/
-#define PHY_B_AC_L_SQE (1<<15) /* Bit 15: Low Squelch */
-#define PHY_B_AC_LONG_PACK (1<<14) /* Bit 14: Rx Long Packets */
-#define PHY_B_AC_ER_CTRL (3<<12) /* Bit 13..12: Edgerate Control */
- /* Bit 11: reserved */
-#define PHY_B_AC_TX_TST (1<<10) /* Bit 10: Tx test bit, always 1 */
- /* Bit 9.. 8: reserved */
-#define PHY_B_AC_DIS_PRF (1<<7) /* Bit 7: dis part resp filter */
- /* Bit 6: reserved */
-#define PHY_B_AC_DIS_PM (1<<5) /* Bit 5: dis power management */
- /* Bit 4: reserved */
-#define PHY_B_AC_DIAG (1<<3) /* Bit 3: Diagnostic Mode */
- /* Bit 2.. 0: reserved */
-
-/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/
-#define PHY_B_AS_AN_C (1<<15) /* Bit 15: AutoNeg complete */
-#define PHY_B_AS_AN_CA (1<<14) /* Bit 14: AN Complete Ack */
-#define PHY_B_AS_ANACK_D (1<<13) /* Bit 13: AN Ack Detect */
-#define PHY_B_AS_ANAB_D (1<<12) /* Bit 12: AN Ability Detect */
-#define PHY_B_AS_NPW (1<<11) /* Bit 11: AN Next Page Wait */
-#define PHY_B_AS_AN_RES_MSK (7<<8) /* Bit 10..8: AN HDC */
-#define PHY_B_AS_PDF (1<<7) /* Bit 7: Parallel Detect. Fault */
-#define PHY_B_AS_RF (1<<6) /* Bit 6: Remote Fault */
-#define PHY_B_AS_ANP_R (1<<5) /* Bit 5: AN Page Received */
-#define PHY_B_AS_LP_ANAB (1<<4) /* Bit 4: LP AN Ability */
-#define PHY_B_AS_LP_NPAB (1<<3) /* Bit 3: LP Next Page Ability */
-#define PHY_B_AS_LS (1<<2) /* Bit 2: Link Status */
-#define PHY_B_AS_PRR (1<<1) /* Bit 1: Pause Resolution-Rx */
-#define PHY_B_AS_PRT (1<<0) /* Bit 0: Pause Resolution-Tx */
-
-#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT)
-
-/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/
-/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/
- /* Bit 15: reserved */
-#define PHY_B_IS_PSE (1<<14) /* Bit 14: Pair Swap Error */
-#define PHY_B_IS_MDXI_SC (1<<13) /* Bit 13: MDIX Status Change */
-#define PHY_B_IS_HCT (1<<12) /* Bit 12: counter above 32k */
-#define PHY_B_IS_LCT (1<<11) /* Bit 11: counter above 128 */
-#define PHY_B_IS_AN_PR (1<<10) /* Bit 10: Page Received */
-#define PHY_B_IS_NO_HDCL (1<<9) /* Bit 9: No HCD Link */
-#define PHY_B_IS_NO_HDC (1<<8) /* Bit 8: No HCD */
-#define PHY_B_IS_NEG_USHDC (1<<7) /* Bit 7: Negotiated Unsup. HCD */
-#define PHY_B_IS_SCR_S_ER (1<<6) /* Bit 6: Scrambler Sync Error */
-#define PHY_B_IS_RRS_CHANGE (1<<5) /* Bit 5: Remote Rx Stat Change */
-#define PHY_B_IS_LRS_CHANGE (1<<4) /* Bit 4: Local Rx Stat Change */
-#define PHY_B_IS_DUP_CHANGE (1<<3) /* Bit 3: Duplex Mode Change */
-#define PHY_B_IS_LSP_CHANGE (1<<2) /* Bit 2: Link Speed Change */
-#define PHY_B_IS_LST_CHANGE (1<<1) /* Bit 1: Link Status Changed */
-#define PHY_B_IS_CRC_ER (1<<0) /* Bit 0: CRC Error */
-
-#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
-
-/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
-#define PHY_B_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */
-#define PHY_B_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */
-#define PHY_B_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */
-#define PHY_B_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */
-
-/*
- * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
- */
-#define PHY_B_RES_1000FD (7<<8) /* Bit 10..8: 1000Base-T Full Dup. */
-#define PHY_B_RES_1000HD (6<<8) /* Bit 10..8: 1000Base-T Half Dup. */
-/* others: 100/10: invalid for us */
-
-/*
- * Level One-Specific
- */
-/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-#define PHY_L_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
-#define PHY_L_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */
-#define PHY_L_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */
-#define PHY_L_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */
-#define PHY_L_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
-#define PHY_L_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
- /* Bit 7..0: reserved */
-
-/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-#define PHY_L_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */
-#define PHY_L_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */
-#define PHY_L_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */
-#define PHY_L_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */
-#define PHY_L_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */
-#define PHY_L_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */
- /* Bit 9..8: reserved */
-#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */
-
-/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/
-#define PHY_L_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */
-#define PHY_L_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */
-#define PHY_L_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */
-#define PHY_L_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */
- /* Bit 11..0: reserved */
-
-/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/
-#define PHY_L_PC_REP_MODE (1<<15) /* Bit 15: Repeater Mode */
- /* Bit 14: reserved */
-#define PHY_L_PC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */
-#define PHY_L_PC_BY_SCR (1<<12) /* Bit 12: Bypass Scrambler */
-#define PHY_L_PC_BY_45 (1<<11) /* Bit 11: Bypass 4B5B-Decoder */
-#define PHY_L_PC_JAB_DIS (1<<10) /* Bit 10: Jabber Disabled */
-#define PHY_L_PC_SQE (1<<9) /* Bit 9: Enable Heartbeat */
-#define PHY_L_PC_TP_LOOP (1<<8) /* Bit 8: TP Loopback */
-#define PHY_L_PC_SSS (1<<7) /* Bit 7: Smart Speed Selection */
-#define PHY_L_PC_FIFO_SIZE (1<<6) /* Bit 6: FIFO Size */
-#define PHY_L_PC_PRE_EN (1<<5) /* Bit 5: Preamble Enable */
-#define PHY_L_PC_CIM (1<<4) /* Bit 4: Carrier Integrity Mon */
-#define PHY_L_PC_10_SER (1<<3) /* Bit 3: Use Serial Output */
-#define PHY_L_PC_ANISOL (1<<2) /* Bit 2: Unisolate Port */
-#define PHY_L_PC_TEN_BIT (1<<1) /* Bit 1: 10bit iface mode on */
-#define PHY_L_PC_ALTCLOCK (1<<0) /* Bit 0: (ro) ALTCLOCK Mode on */
-
-/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/
-#define PHY_L_QS_D_RATE (3<<14) /* Bit 15..14: Data Rate */
-#define PHY_L_QS_TX_STAT (1<<13) /* Bit 13: Transmitting */
-#define PHY_L_QS_RX_STAT (1<<12) /* Bit 12: Receiving */
-#define PHY_L_QS_COL_STAT (1<<11) /* Bit 11: Collision */
-#define PHY_L_QS_L_STAT (1<<10) /* Bit 10: Link is up */
-#define PHY_L_QS_DUP_MOD (1<<9) /* Bit 9: Full/Half Duplex */
-#define PHY_L_QS_AN (1<<8) /* Bit 8: AutoNeg is On */
-#define PHY_L_QS_AN_C (1<<7) /* Bit 7: AN is Complete */
-#define PHY_L_QS_LLE (7<<4) /* Bit 6: Line Length Estim. */
-#define PHY_L_QS_PAUSE (1<<3) /* Bit 3: LP advertised Pause */
-#define PHY_L_QS_AS_PAUSE (1<<2) /* Bit 2: LP adv. asym. Pause */
-#define PHY_L_QS_ISOLATE (1<<1) /* Bit 1: CIM Isolated */
-#define PHY_L_QS_EVENT (1<<0) /* Bit 0: Event has occurred */
-
-/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/
-/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/
- /* Bit 15..14: reserved */
-#define PHY_L_IS_AN_F (1<<13) /* Bit 13: Auto-Negotiation fault */
- /* Bit 12: not described */
-#define PHY_L_IS_CROSS (1<<11) /* Bit 11: Crossover used */
-#define PHY_L_IS_POL (1<<10) /* Bit 10: Polarity correct. used */
-#define PHY_L_IS_SS (1<<9) /* Bit 9: Smart Speed Downgrade */
-#define PHY_L_IS_CFULL (1<<8) /* Bit 8: Counter Full */
-#define PHY_L_IS_AN_C (1<<7) /* Bit 7: AutoNeg Complete */
-#define PHY_L_IS_SPEED (1<<6) /* Bit 6: Speed Changed */
-#define PHY_L_IS_DUP (1<<5) /* Bit 5: Duplex Changed */
-#define PHY_L_IS_LS (1<<4) /* Bit 4: Link Status Changed */
-#define PHY_L_IS_ISOL (1<<3) /* Bit 3: Isolate Occured */
-#define PHY_L_IS_MDINT (1<<2) /* Bit 2: (ro) STAT: MII Int Pending */
-#define PHY_L_IS_INTEN (1<<1) /* Bit 1: ENAB: Enable IRQs */
-#define PHY_L_IS_FORCE (1<<0) /* Bit 0: ENAB: Force Interrupt */
-
-/* int. mask */
-#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
-
-/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/
-#define PHY_L_LC_LEDC (3<<14) /* Bit 15..14: Col/Blink/On/Off */
-#define PHY_L_LC_LEDR (3<<12) /* Bit 13..12: Rx/Blink/On/Off */
-#define PHY_L_LC_LEDT (3<<10) /* Bit 11..10: Tx/Blink/On/Off */
-#define PHY_L_LC_LEDG (3<<8) /* Bit 9..8: Giga/Blink/On/Off */
-#define PHY_L_LC_LEDS (3<<6) /* Bit 7..6: 10-100/Blink/On/Off */
-#define PHY_L_LC_LEDL (3<<4) /* Bit 5..4: Link/Blink/On/Off */
-#define PHY_L_LC_LEDF (3<<2) /* Bit 3..2: Duplex/Blink/On/Off */
-#define PHY_L_LC_PSTRECH (1<<1) /* Bit 1: Strech LED Pulses */
-#define PHY_L_LC_FREQ (1<<0) /* Bit 0: 30/100 ms */
-
-/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/
-#define PHY_L_PC_TX_TCLK (1<<15) /* Bit 15: Enable TX_TCLK */
- /* Bit 14: reserved */
-#define PHY_L_PC_ALT_NP (1<<13) /* Bit 14: Alternate Next Page */
-#define PHY_L_PC_GMII_ALT (1<<12) /* Bit 13: Alternate GMII driver */
- /* Bit 11: reserved */
-#define PHY_L_PC_TEN_CRS (1<<10) /* Bit 10: Extend CRS*/
- /* Bit 9..0: not described */
-
-/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/
-#define PHY_L_CIM_ISOL (255<<8)/* Bit 15..8: Isolate Count */
-#define PHY_L_CIM_FALSE_CAR (255<<0)/* Bit 7..0: False Carrier Count */
-
-
-/*
- * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
- */
-#define PHY_L_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */
-#define PHY_L_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */
-#define PHY_L_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */
-#define PHY_L_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */
-
-
-/*
- * National-Specific
- */
-/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-#define PHY_N_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
-#define PHY_N_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */
-#define PHY_N_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */
-#define PHY_N_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */
-#define PHY_N_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
-#define PHY_N_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
-#define PHY_N_1000C_APC (1<<7) /* Bit 7: Asymmetric Pause Cap. */
- /* Bit 6..0: reserved */
-
-/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-#define PHY_N_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */
-#define PHY_N_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */
-#define PHY_N_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */
-#define PHY_N_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/
-#define PHY_N_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */
-#define PHY_N_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */
-#define PHY_N_1000C_LP_APC (1<<9) /* Bit 9: LP Asym. Pause Cap. */
- /* Bit 8: reserved */
-#define PHY_N_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */
-
-/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/
-#define PHY_N_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */
-#define PHY_N_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */
-#define PHY_N_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */
-#define PHY_N_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */
- /* Bit 11..0: reserved */
-
-/* todo: those are still missing */
-/***** PHY_NAT_EXT_CTRL1 16 bit r/o Extended Control Reg1 *****/
-/***** PHY_NAT_Q_STAT1 16 bit r/o Quick Status Reg1 *****/
-/***** PHY_NAT_10B_OP 16 bit r/o 10Base-T Operations Reg *****/
-/***** PHY_NAT_EXT_CTRL2 16 bit r/o Extended Control Reg1 *****/
-/***** PHY_NAT_Q_STAT2 16 bit r/o Quick Status Reg2 *****/
-/***** PHY_NAT_PHY_ADDR 16 bit r/o PHY Address Register *****/
-
-/*
- * Marvell-Specific
- */
-/***** PHY_MARV_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_MARV_AUNE_LP 16 bit r/w Link Part Ability Reg *****/
-#define PHY_M_AN_NXT_PG BIT_15 /* Request Next Page */
-#define PHY_M_AN_ACK BIT_14 /* (ro) Acknowledge Received */
-#define PHY_M_AN_RF BIT_13 /* Remote Fault */
- /* Bit 12: reserved */
-#define PHY_M_AN_ASP BIT_11 /* Asymmetric Pause */
-#define PHY_M_AN_PC BIT_10 /* MAC Pause implemented */
-#define PHY_M_AN_100_FD BIT_8 /* Advertise 100Base-TX Full Duplex */
-#define PHY_M_AN_100_HD BIT_7 /* Advertise 100Base-TX Half Duplex */
-#define PHY_M_AN_10_FD BIT_6 /* Advertise 10Base-TX Full Duplex */
-#define PHY_M_AN_10_HD BIT_5 /* Advertise 10Base-TX Half Duplex */
-
-/* special defines for FIBER (88E1011S only) */
-#define PHY_M_AN_ASP_X BIT_8 /* Asymmetric Pause */
-#define PHY_M_AN_PC_X BIT_7 /* MAC Pause implemented */
-#define PHY_M_AN_1000X_AHD BIT_6 /* Advertise 10000Base-X Half Duplex */
-#define PHY_M_AN_1000X_AFD BIT_5 /* Advertise 10000Base-X Full Duplex */
-
-/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
-#define PHY_M_P_NO_PAUSE_X (0<<7) /* Bit 8.. 7: no Pause Mode */
-#define PHY_M_P_SYM_MD_X (1<<7) /* Bit 8.. 7: symmetric Pause Mode */
-#define PHY_M_P_ASYM_MD_X (2<<7) /* Bit 8.. 7: asymmetric Pause Mode */
-#define PHY_M_P_BOTH_MD_X (3<<7) /* Bit 8.. 7: both Pause Mode */
-
-/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-#define PHY_M_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
-#define PHY_M_1000C_MSE (1<<12) /* Bit 12: Manual Master/Slave Enable */
-#define PHY_M_1000C_MSC (1<<11) /* Bit 11: M/S Configuration (1=Master) */
-#define PHY_M_1000C_MPD (1<<10) /* Bit 10: Multi-Port Device */
-#define PHY_M_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
-#define PHY_M_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
- /* Bit 7..0: reserved */
-
-/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/
-#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */
-#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */
-#define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */
-#define PHY_M_PC_FL_GOOD (1<<10) /* Bit 10: Force Link Good */
-#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */
-#define PHY_M_PC_ENA_EXT_D (1<<7) /* Bit 7: Enable Ext. Distance (10BT) */
-#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */
-#define PHY_M_PC_DIS_125CLK (1<<4) /* Bit 4: Disable 125 CLK */
-#define PHY_M_PC_MAC_POW_UP (1<<3) /* Bit 3: MAC Power up */
-#define PHY_M_PC_SQE_T_ENA (1<<2) /* Bit 2: SQE Test Enabled */
-#define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */
-#define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */
-
-#define PHY_M_PC_EN_DET SHIFT8(2) /* Energy Detect (Mode 1) */
-#define PHY_M_PC_EN_DET_PLUS SHIFT8(3) /* Energy Detect Plus (Mode 2) */
-
-#define PHY_M_PC_MDI_XMODE(x) SHIFT5(x)
-#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */
-#define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */
-#define PHY_M_PC_ENA_AUTO 3 /* 11 = Enable Automatic Crossover */
-
-/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/
-#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */
-#define PHY_M_PS_SPEED_1000 (1<<15) /* 10 = 1000 Mbps */
-#define PHY_M_PS_SPEED_100 (1<<14) /* 01 = 100 Mbps */
-#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */
-#define PHY_M_PS_FULL_DUP (1<<13) /* Bit 13: Full Duplex */
-#define PHY_M_PS_PAGE_REC (1<<12) /* Bit 12: Page Received */
-#define PHY_M_PS_SPDUP_RES (1<<11) /* Bit 11: Speed & Duplex Resolved */
-#define PHY_M_PS_LINK_UP (1<<10) /* Bit 10: Link Up */
-#define PHY_M_PS_CABLE_MSK (3<<7) /* Bit 9.. 7: Cable Length Mask */
-#define PHY_M_PS_MDI_X_STAT (1<<6) /* Bit 6: MDI Crossover Stat (1=MDIX) */
-#define PHY_M_PS_DOWNS_STAT (1<<5) /* Bit 5: Downshift Status (1=downsh.) */
-#define PHY_M_PS_ENDET_STAT (1<<4) /* Bit 4: Energy Detect Status (1=act) */
-#define PHY_M_PS_TX_P_EN (1<<3) /* Bit 3: Tx Pause Enabled */
-#define PHY_M_PS_RX_P_EN (1<<2) /* Bit 2: Rx Pause Enabled */
-#define PHY_M_PS_POL_REV (1<<1) /* Bit 1: Polarity Reversed */
-#define PHY_M_PC_JABBER (1<<0) /* Bit 0: Jabber */
-
-#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
-
-/***** PHY_MARV_INT_MASK 16 bit r/w Interrupt Mask Reg *****/
-/***** PHY_MARV_INT_STAT 16 bit r/o Interrupt Status Reg *****/
-#define PHY_M_IS_AN_ERROR (1<<15) /* Bit 15: Auto-Negotiation Error */
-#define PHY_M_IS_LSP_CHANGE (1<<14) /* Bit 14: Link Speed Changed */
-#define PHY_M_IS_DUP_CHANGE (1<<13) /* Bit 13: Duplex Mode Changed */
-#define PHY_M_IS_AN_PR (1<<12) /* Bit 12: Page Received */
-#define PHY_M_IS_AN_COMPL (1<<11) /* Bit 11: Auto-Negotiation Completed */
-#define PHY_M_IS_LST_CHANGE (1<<10) /* Bit 10: Link Status Changed */
-#define PHY_M_IS_SYMB_ERROR (1<<9) /* Bit 9: Symbol Error */
-#define PHY_M_IS_FALSE_CARR (1<<8) /* Bit 8: False Carrier */
-#define PHY_M_IS_FIFO_ERROR (1<<7) /* Bit 7: FIFO Overflow/Underrun Error */
-#define PHY_M_IS_MDI_CHANGE (1<<6) /* Bit 6: MDI Crossover Changed */
-#define PHY_M_IS_DOWNSH_DET (1<<5) /* Bit 5: Downshift Detected */
-#define PHY_M_IS_END_CHANGE (1<<4) /* Bit 4: Energy Detect Changed */
- /* Bit 3..2: reserved */
-#define PHY_M_IS_POL_CHANGE (1<<1) /* Bit 1: Polarity Changed */
-#define PHY_M_IS_JABBER (1<<0) /* Bit 0: Jabber */
-
-#define PHY_M_DEF_MSK (PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \
- PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
-
-/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/
-#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */
-#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */
-#define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */
-#define PHY_M_EC_FIB_AN_ENA (1<<3) /* Bit 3: Fiber Auto-Neg. Enable */
-
-#define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */
-#define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */
-#define PHY_M_EC_MAC_S(x) SHIFT4(x) /* 01X=0; 110=2.5; 111=25 (MHz) */
-
-#define MAC_TX_CLK_0_MHZ 2
-#define MAC_TX_CLK_2_5_MHZ 6
-#define MAC_TX_CLK_25_MHZ 7
-
-/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/
-#define PHY_M_LEDC_DIS_LED (1<<15) /* Bit 15: Disable LED */
-#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */
-#define PHY_M_LEDC_F_INT (1<<11) /* Bit 11: Force Interrupt */
-#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */
- /* Bit 7.. 5: reserved */
-#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */
-#define PHY_M_LEDC_DP_CTRL (1<<2) /* Bit 2: Duplex Control */
-#define PHY_M_LEDC_RX_CTRL (1<<1) /* Bit 1: Rx activity / Link */
-#define PHY_M_LEDC_TX_CTRL (1<<0) /* Bit 0: Tx activity / Link */
-
-#define PHY_M_LED_PULS_DUR(x) SHIFT12(x) /* Pulse Stretch Duration */
-
-#define PULS_NO_STR 0 /* no pulse stretching */
-#define PULS_21MS 1 /* 21 ms to 42 ms */
-#define PULS_42MS 2 /* 42 ms to 84 ms */
-#define PULS_84MS 3 /* 84 ms to 170 ms */
-#define PULS_170MS 4 /* 170 ms to 340 ms */
-#define PULS_340MS 5 /* 340 ms to 670 ms */
-#define PULS_670MS 6 /* 670 ms to 1.3 s */
-#define PULS_1300MS 7 /* 1.3 s to 2.7 s */
-
-#define PHY_M_LED_BLINK_RT(x) SHIFT8(x) /* Blink Rate */
-
-#define BLINK_42MS 0 /* 42 ms */
-#define BLINK_84MS 1 /* 84 ms */
-#define BLINK_170MS 2 /* 170 ms */
-#define BLINK_340MS 3 /* 340 ms */
-#define BLINK_670MS 4 /* 670 ms */
- /* values 5 - 7: reserved */
-
-/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/
-#define PHY_M_LED_MO_DUP(x) SHIFT10(x) /* Bit 11..10: Duplex */
-#define PHY_M_LED_MO_10(x) SHIFT8(x) /* Bit 9.. 8: Link 10 */
-#define PHY_M_LED_MO_100(x) SHIFT6(x) /* Bit 7.. 6: Link 100 */
-#define PHY_M_LED_MO_1000(x) SHIFT4(x) /* Bit 5.. 4: Link 1000 */
-#define PHY_M_LED_MO_RX(x) SHIFT2(x) /* Bit 3.. 2: Rx */
-#define PHY_M_LED_MO_TX(x) SHIFT0(x) /* Bit 1.. 0: Tx */
-
-#define MO_LED_NORM 0
-#define MO_LED_BLINK 1
-#define MO_LED_OFF 2
-#define MO_LED_ON 3
-
-/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/
- /* Bit 15.. 7: reserved */
-#define PHY_M_EC2_FI_IMPED (1<<6) /* Bit 6: Fiber Input Impedance */
-#define PHY_M_EC2_FO_IMPED (1<<5) /* Bit 5: Fiber Output Impedance */
-#define PHY_M_EC2_FO_M_CLK (1<<4) /* Bit 4: Fiber Mode Clock Enable */
-#define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */
-#define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */
-
-/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
-#define PHY_M_FC_AUTO_SEL (1<<15) /* Bit 15: Fiber/Copper Auto Sel. dis. */
-#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14: Fiber/Copper Autoneg. reg acc */
-#define PHY_M_FC_RESULUTION (1<<13) /* Bit 13: Fiber/Copper Resulution */
-#define PHY_M_SER_IF_AN_BP (1<<12) /* Bit 12: Ser IF autoneg. bypass enable */
-#define PHY_M_SER_IF_BP_ST (1<<11) /* Bit 11: Ser IF autoneg. bypass status */
-#define PHY_M_IRQ_POLARITY (1<<10) /* Bit 10: IRQ polarity */
- /* Bit 9..4: reserved */
-#define PHY_M_UNDOC1 (1<< 7) /* undocumented bit !! */
-#define PHY_M_MODE_MASK (0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */
-
-
-/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/
-#define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */
-#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */
- /* Bit 12.. 8: reserved */
-#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance */
-
-/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
-#define CABD_STAT_NORMAL 0
-#define CABD_STAT_SHORT 1
-#define CABD_STAT_OPEN 2
-#define CABD_STAT_FAIL 3
-
-
-/*
- * GMAC registers
- *
- * The GMAC registers are 16 or 32 bits wide.
- * The GMACs host processor interface is 16 bits wide,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the GMAC registers
- * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(),
- * GM_INHASH(), and GM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note: NA reg = Network Address e.g DA, SA etc.
- *
- */
-
-/* Port Registers */
-#define GM_GP_STAT 0x0000 /* 16 bit r/o General Purpose Status */
-#define GM_GP_CTRL 0x0004 /* 16 bit r/w General Purpose Control */
-#define GM_TX_CTRL 0x0008 /* 16 bit r/w Transmit Control Reg. */
-#define GM_RX_CTRL 0x000c /* 16 bit r/w Receive Control Reg. */
-#define GM_TX_FLOW_CTRL 0x0010 /* 16 bit r/w Transmit Flow-Control */
-#define GM_TX_PARAM 0x0014 /* 16 bit r/w Transmit Parameter Reg. */
-#define GM_SERIAL_MODE 0x0018 /* 16 bit r/w Serial Mode Register */
-
-/* Source Address Registers */
-#define GM_SRC_ADDR_1L 0x001c /* 16 bit r/w Source Address 1 (low) */
-#define GM_SRC_ADDR_1M 0x0020 /* 16 bit r/w Source Address 1 (middle) */
-#define GM_SRC_ADDR_1H 0x0024 /* 16 bit r/w Source Address 1 (high) */
-#define GM_SRC_ADDR_2L 0x0028 /* 16 bit r/w Source Address 2 (low) */
-#define GM_SRC_ADDR_2M 0x002c /* 16 bit r/w Source Address 2 (middle) */
-#define GM_SRC_ADDR_2H 0x0030 /* 16 bit r/w Source Address 2 (high) */
-
-/* Multicast Address Hash Registers */
-#define GM_MC_ADDR_H1 0x0034 /* 16 bit r/w Multicast Address Hash 1 */
-#define GM_MC_ADDR_H2 0x0038 /* 16 bit r/w Multicast Address Hash 2 */
-#define GM_MC_ADDR_H3 0x003c /* 16 bit r/w Multicast Address Hash 3 */
-#define GM_MC_ADDR_H4 0x0040 /* 16 bit r/w Multicast Address Hash 4 */
-
-/* Interrupt Source Registers */
-#define GM_TX_IRQ_SRC 0x0044 /* 16 bit r/o Tx Overflow IRQ Source */
-#define GM_RX_IRQ_SRC 0x0048 /* 16 bit r/o Rx Overflow IRQ Source */
-#define GM_TR_IRQ_SRC 0x004c /* 16 bit r/o Tx/Rx Over. IRQ Source */
-
-/* Interrupt Mask Registers */
-#define GM_TX_IRQ_MSK 0x0050 /* 16 bit r/w Tx Overflow IRQ Mask */
-#define GM_RX_IRQ_MSK 0x0054 /* 16 bit r/w Rx Overflow IRQ Mask */
-#define GM_TR_IRQ_MSK 0x0058 /* 16 bit r/w Tx/Rx Over. IRQ Mask */
-
-/* Serial Management Interface (SMI) Registers */
-#define GM_SMI_CTRL 0x0080 /* 16 bit r/w SMI Control Register */
-#define GM_SMI_DATA 0x0084 /* 16 bit r/w SMI Data Register */
-#define GM_PHY_ADDR 0x0088 /* 16 bit r/w GPHY Address Register */
-
-/* MIB Counters */
-#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */
-#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */
-
-/*
- * MIB Counters base address definitions (low word) -
- * use offset 4 for access to high word (32 bit r/o)
- */
-#define GM_RXF_UC_OK \
- (GM_MIB_CNT_BASE + 0) /* Unicast Frames Received OK */
-#define GM_RXF_BC_OK \
- (GM_MIB_CNT_BASE + 8) /* Broadcast Frames Received OK */
-#define GM_RXF_MPAUSE \
- (GM_MIB_CNT_BASE + 16) /* Pause MAC Ctrl Frames Received */
-#define GM_RXF_MC_OK \
- (GM_MIB_CNT_BASE + 24) /* Multicast Frames Received OK */
-#define GM_RXF_FCS_ERR \
- (GM_MIB_CNT_BASE + 32) /* Rx Frame Check Seq. Error */
- /* GM_MIB_CNT_BASE + 40: reserved */
-#define GM_RXO_OK_LO \
- (GM_MIB_CNT_BASE + 48) /* Octets Received OK Low */
-#define GM_RXO_OK_HI \
- (GM_MIB_CNT_BASE + 56) /* Octets Received OK High */
-#define GM_RXO_ERR_LO \
- (GM_MIB_CNT_BASE + 64) /* Octets Received Invalid Low */
-#define GM_RXO_ERR_HI \
- (GM_MIB_CNT_BASE + 72) /* Octets Received Invalid High */
-#define GM_RXF_SHT \
- (GM_MIB_CNT_BASE + 80) /* Frames <64 Byte Received OK */
-#define GM_RXE_FRAG \
- (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Received with FCS Err */
-#define GM_RXF_64B \
- (GM_MIB_CNT_BASE + 96) /* 64 Byte Rx Frame */
-#define GM_RXF_127B \
- (GM_MIB_CNT_BASE + 104) /* 65-127 Byte Rx Frame */
-#define GM_RXF_255B \
- (GM_MIB_CNT_BASE + 112) /* 128-255 Byte Rx Frame */
-#define GM_RXF_511B \
- (GM_MIB_CNT_BASE + 120) /* 256-511 Byte Rx Frame */
-#define GM_RXF_1023B \
- (GM_MIB_CNT_BASE + 128) /* 512-1023 Byte Rx Frame */
-#define GM_RXF_1518B \
- (GM_MIB_CNT_BASE + 136) /* 1024-1518 Byte Rx Frame */
-#define GM_RXF_MAX_SZ \
- (GM_MIB_CNT_BASE + 144) /* 1519-MaxSize Byte Rx Frame */
-#define GM_RXF_LNG_ERR \
- (GM_MIB_CNT_BASE + 152) /* Rx Frame too Long Error */
-#define GM_RXF_JAB_PKT \
- (GM_MIB_CNT_BASE + 160) /* Rx Jabber Packet Frame */
- /* GM_MIB_CNT_BASE + 168: reserved */
-#define GM_RXE_FIFO_OV \
- (GM_MIB_CNT_BASE + 176) /* Rx FIFO overflow Event */
- /* GM_MIB_CNT_BASE + 184: reserved */
-#define GM_TXF_UC_OK \
- (GM_MIB_CNT_BASE + 192) /* Unicast Frames Xmitted OK */
-#define GM_TXF_BC_OK \
- (GM_MIB_CNT_BASE + 200) /* Broadcast Frames Xmitted OK */
-#define GM_TXF_MPAUSE \
- (GM_MIB_CNT_BASE + 208) /* Pause MAC Ctrl Frames Xmitted */
-#define GM_TXF_MC_OK \
- (GM_MIB_CNT_BASE + 216) /* Multicast Frames Xmitted OK */
-#define GM_TXO_OK_LO \
- (GM_MIB_CNT_BASE + 224) /* Octets Transmitted OK Low */
-#define GM_TXO_OK_HI \
- (GM_MIB_CNT_BASE + 232) /* Octets Transmitted OK High */
-#define GM_TXF_64B \
- (GM_MIB_CNT_BASE + 240) /* 64 Byte Tx Frame */
-#define GM_TXF_127B \
- (GM_MIB_CNT_BASE + 248) /* 65-127 Byte Tx Frame */
-#define GM_TXF_255B \
- (GM_MIB_CNT_BASE + 256) /* 128-255 Byte Tx Frame */
-#define GM_TXF_511B \
- (GM_MIB_CNT_BASE + 264) /* 256-511 Byte Tx Frame */
-#define GM_TXF_1023B \
- (GM_MIB_CNT_BASE + 272) /* 512-1023 Byte Tx Frame */
-#define GM_TXF_1518B \
- (GM_MIB_CNT_BASE + 280) /* 1024-1518 Byte Tx Frame */
-#define GM_TXF_MAX_SZ \
- (GM_MIB_CNT_BASE + 288) /* 1519-MaxSize Byte Tx Frame */
- /* GM_MIB_CNT_BASE + 296: reserved */
-#define GM_TXF_COL \
- (GM_MIB_CNT_BASE + 304) /* Tx Collision */
-#define GM_TXF_LAT_COL \
- (GM_MIB_CNT_BASE + 312) /* Tx Late Collision */
-#define GM_TXF_ABO_COL \
- (GM_MIB_CNT_BASE + 320) /* Tx aborted due to Exces. Col. */
-#define GM_TXF_MUL_COL \
- (GM_MIB_CNT_BASE + 328) /* Tx Multiple Collision */
-#define GM_TXF_SNG_COL \
- (GM_MIB_CNT_BASE + 336) /* Tx Single Collision */
-#define GM_TXE_FIFO_UR \
- (GM_MIB_CNT_BASE + 344) /* Tx FIFO Underrun Event */
-
-/*----------------------------------------------------------------------------*/
-/*
- * GMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- * (sc) self clearing
- * (r/o) read only
- */
-
-/* GM_GP_STAT 16 bit r/o General Purpose Status Register */
-#define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */
-#define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */
-#define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow-Control Mode Disabled */
-#define GM_GPSR_LINK_UP (1<<12) /* Bit 12: Link Up Status */
-#define GM_GPSR_PAUSE (1<<11) /* Bit 11: Pause State */
-#define GM_GPSR_TX_ACTIVE (1<<10) /* Bit 10: Tx in Progress */
-#define GM_GPSR_EXC_COL (1<<9) /* Bit 9: Excessive Collisions Occured */
-#define GM_GPSR_LAT_COL (1<<8) /* Bit 8: Late Collisions Occured */
- /* Bit 7..6: reserved */
-#define GM_GPSR_PHY_ST_CH (1<<5) /* Bit 5: PHY Status Change */
-#define GM_GPSR_GIG_SPEED (1<<4) /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */
-#define GM_GPSR_PART_MODE (1<<3) /* Bit 3: Partition mode */
-#define GM_GPSR_FC_RX_DIS (1<<2) /* Bit 2: Rx Flow-Control Mode Disabled */
-#define GM_GPSR_PROM_EN (1<<1) /* Bit 1: Promiscuous Mode Enabled */
- /* Bit 0: reserved */
-
-/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */
- /* Bit 15: reserved */
-#define GM_GPCR_PROM_ENA (1<<14) /* Bit 14: Enable Promiscuous Mode */
-#define GM_GPCR_FC_TX_DIS (1<<13) /* Bit 13: Disable Tx Flow-Control Mode */
-#define GM_GPCR_TX_ENA (1<<12) /* Bit 12: Enable Transmit */
-#define GM_GPCR_RX_ENA (1<<11) /* Bit 11: Enable Receive */
-#define GM_GPCR_BURST_ENA (1<<10) /* Bit 10: Enable Burst Mode */
-#define GM_GPCR_LOOP_ENA (1<<9) /* Bit 9: Enable MAC Loopback Mode */
-#define GM_GPCR_PART_ENA (1<<8) /* Bit 8: Enable Partition Mode */
-#define GM_GPCR_GIGS_ENA (1<<7) /* Bit 7: Gigabit Speed (1000 Mbps) */
-#define GM_GPCR_FL_PASS (1<<6) /* Bit 6: Force Link Pass */
-#define GM_GPCR_DUP_FULL (1<<5) /* Bit 5: Full Duplex Mode */
-#define GM_GPCR_FC_RX_DIS (1<<4) /* Bit 4: Disable Rx Flow-Control Mode */
-#define GM_GPCR_SPEED_100 (1<<3) /* Bit 3: Port Speed 100 Mbps */
-#define GM_GPCR_AU_DUP_DIS (1<<2) /* Bit 2: Disable Auto-Update Duplex */
-#define GM_GPCR_AU_FCT_DIS (1<<1) /* Bit 1: Disable Auto-Update Flow-C. */
-#define GM_GPCR_AU_SPD_DIS (1<<0) /* Bit 0: Disable Auto-Update Speed */
-
-#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
-#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\
- GM_GPCR_AU_SPD_DIS)
-
-/* GM_TX_CTRL 16 bit r/w Transmit Control Register */
-#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */
-#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */
-#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */
-#define GM_TXCR_COL_THR_MSK (7<<10) /* Bit 12..10: Collision Threshold */
-
-#define TX_COL_THR(x) (SHIFT10(x) & GM_TXCR_COL_THR_MSK)
-
-#define TX_COL_DEF 0x04
-
-/* GM_RX_CTRL 16 bit r/w Receive Control Register */
-#define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */
-#define GM_RXCR_MCF_ENA (1<<14) /* Bit 14: Enable Multicast filtering */
-#define GM_RXCR_CRC_DIS (1<<13) /* Bit 13: Remove 4-byte CRC */
-#define GM_RXCR_PASS_FC (1<<12) /* Bit 12: Pass FC packets to FIFO */
-
-/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */
-#define GM_TXPA_JAMLEN_MSK (0x03<<14) /* Bit 15..14: Jam Length */
-#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */
-#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */
- /* Bit 3..0: reserved */
-
-#define TX_JAM_LEN_VAL(x) (SHIFT14(x) & GM_TXPA_JAMLEN_MSK)
-#define TX_JAM_IPG_VAL(x) (SHIFT9(x) & GM_TXPA_JAMIPG_MSK)
-#define TX_IPG_JAM_DATA(x) (SHIFT4(x) & GM_TXPA_JAMDAT_MSK)
-
-#define TX_JAM_LEN_DEF 0x03
-#define TX_JAM_IPG_DEF 0x0b
-#define TX_IPG_JAM_DEF 0x1c
-
-/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */
-#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder (r/o) */
-#define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive Tx trials */
-#define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Len) */
-#define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Len) */
- /* Bit 7..5: reserved */
-#define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */
-
-#define DATA_BLIND_VAL(x) (SHIFT11(x) & GM_SMOD_DATABL_MSK)
-#define DATA_BLIND_DEF 0x04
-
-#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK)
-#define IPG_DATA_DEF 0x1e
-
-/* GM_SMI_CTRL 16 bit r/w SMI Control Register */
-#define GM_SMI_CT_PHY_A_MSK (0x1f<<11) /* Bit 15..11: PHY Device Address */
-#define GM_SMI_CT_REG_A_MSK (0x1f<<6) /* Bit 10.. 6: PHY Register Address */
-#define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/
-#define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */
-#define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */
- /* Bit 2..0: reserved */
-
-#define GM_SMI_CT_PHY_AD(x) (SHIFT11(x) & GM_SMI_CT_PHY_A_MSK)
-#define GM_SMI_CT_REG_AD(x) (SHIFT6(x) & GM_SMI_CT_REG_A_MSK)
-
- /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */
- /* Bit 15..6: reserved */
-#define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */
-#define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */
- /* Bit 3..0: reserved */
-
-/* Receive Frame Status Encoding */
-#define GMR_FS_LEN (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */
- /* Bit 15..14: reserved */
-#define GMR_FS_VLAN (1L<<13) /* Bit 13: VLAN Packet */
-#define GMR_FS_JABBER (1L<<12) /* Bit 12: Jabber Packet */
-#define GMR_FS_UN_SIZE (1L<<11) /* Bit 11: Undersize Packet */
-#define GMR_FS_MC (1L<<10) /* Bit 10: Multicast Packet */
-#define GMR_FS_BC (1L<<9) /* Bit 9: Broadcast Packet */
-#define GMR_FS_RX_OK (1L<<8) /* Bit 8: Receive OK (Good Packet) */
-#define GMR_FS_GOOD_FC (1L<<7) /* Bit 7: Good Flow-Control Packet */
-#define GMR_FS_BAD_FC (1L<<6) /* Bit 6: Bad Flow-Control Packet */
-#define GMR_FS_MII_ERR (1L<<5) /* Bit 5: MII Error */
-#define GMR_FS_LONG_ERR (1L<<4) /* Bit 4: Too Long Packet */
-#define GMR_FS_FRAGMENT (1L<<3) /* Bit 3: Fragment */
- /* Bit 2: reserved */
-#define GMR_FS_CRC_ERR (1L<<1) /* Bit 1: CRC Error */
-#define GMR_FS_RX_FF_OV (1L<<0) /* Bit 0: Rx FIFO Overflow */
-
-/*
- * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
- */
-#define GMR_FS_ANY_ERR (GMR_FS_CRC_ERR | \
- GMR_FS_LONG_ERR | \
- GMR_FS_MII_ERR | \
- GMR_FS_BAD_FC | \
- GMR_FS_GOOD_FC | \
- GMR_FS_JABBER)
-
-/* Rx GMAC FIFO Flush Mask (default) */
-#define RX_FF_FL_DEF_MSK (GMR_FS_CRC_ERR | \
- GMR_FS_RX_FF_OV | \
- GMR_FS_MII_ERR | \
- GMR_FS_BAD_FC | \
- GMR_FS_GOOD_FC | \
- GMR_FS_UN_SIZE | \
- GMR_FS_JABBER)
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_XMAC_H */
diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
deleted file mode 100644
index 6e6c56aa6d6..00000000000
--- a/drivers/net/sk98lin/skaddr.c
+++ /dev/null
@@ -1,1788 +0,0 @@
-/******************************************************************************
- *
- * Name: skaddr.c
- * Project: Gigabit Ethernet Adapters, ADDR-Module
- * Version: $Revision: 1.52 $
- * Date: $Date: 2003/06/02 13:46:15 $
- * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses, address override,
- * and promiscuous mode on GEnesis and Yukon adapters.
- *
- * Address Layout:
- * port address: physical MAC address
- * 1st exact match: logical MAC address (GEnesis only)
- * 2nd exact match: RLMT multicast (GEnesis only)
- * exact match 3-13: OS-specific multicasts (GEnesis only)
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
-#endif /* DEBUG ||!LINT || !SK_SLIM */
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-
-#define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
-#define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
-#define HASH_BITS 6 /* #bits in hash */
-#define SK_MC_BIT 0x01
-
-/* Error numbers and messages. */
-
-#define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
-#define SKERR_ADDR_E001MSG "Bad Flags."
-#define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
-#define SKERR_ADDR_E002MSG "New Error."
-
-/* typedefs *******************************************************************/
-
-/* None. */
-
-/* global variables ***********************************************************/
-
-/* 64-bit hash values with all bits set. */
-
-static const SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
-
-/* local variables ************************************************************/
-
-#ifdef DEBUG
-static int Next0[SK_MAX_MACS] = {0};
-#endif /* DEBUG */
-
-static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
- SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
- int Flags);
-static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
- SK_U32 PortNumber, int NewPromMode);
-static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
- SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
- int Flags);
-static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
- SK_U32 PortNumber, int NewPromMode);
-
-/* functions ******************************************************************/
-
-/******************************************************************************
- *
- * SkAddrInit - initialize data, set state to init
- *
- * Description:
- *
- * SK_INIT_DATA
- * ============
- *
- * This routine clears the multicast tables and resets promiscuous mode.
- * Some entries are reserved for the "logical MAC address", the
- * SK-RLMT multicast address, and the BPDU multicast address.
- *
- *
- * SK_INIT_IO
- * ==========
- *
- * All permanent MAC addresses are read from EPROM.
- * If the current MAC addresses are not already set in software,
- * they are set to the values of the permanent addresses.
- * The current addresses are written to the corresponding MAC.
- *
- *
- * SK_INIT_RUN
- * ===========
- *
- * Nothing.
- *
- * Context:
- * init, pageable
- *
- * Returns:
- * SK_ADDR_SUCCESS
- */
-int SkAddrInit(
-SK_AC *pAC, /* the adapter context */
-SK_IOC IoC, /* I/O context */
-int Level) /* initialization level */
-{
- int j;
- SK_U32 i;
- SK_U8 *InAddr;
- SK_U16 *OutAddr;
- SK_ADDR_PORT *pAPort;
-
- switch (Level) {
- case SK_INIT_DATA:
- SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0,
- (SK_U16) sizeof(SK_ADDR));
-
- for (i = 0; i < SK_MAX_MACS; i++) {
- pAPort = &pAC->Addr.Port[i];
- pAPort->PromMode = SK_PROM_MODE_NONE;
-
- pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
- pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
- pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
- pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
- }
-#ifdef xDEBUG
- for (i = 0; i < SK_MAX_MACS; i++) {
- if (pAC->Addr.Port[i].NextExactMatchRlmt <
- SK_ADDR_FIRST_MATCH_RLMT) {
- Next0[i] |= 4;
- }
- }
-#endif /* DEBUG */
- /* pAC->Addr.InitDone = SK_INIT_DATA; */
- break;
-
- case SK_INIT_IO:
-#ifndef SK_NO_RLMT
- for (i = 0; i < SK_MAX_NETS; i++) {
- pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
- }
-#endif /* !SK_NO_RLMT */
-#ifdef xDEBUG
- for (i = 0; i < SK_MAX_MACS; i++) {
- if (pAC->Addr.Port[i].NextExactMatchRlmt <
- SK_ADDR_FIRST_MATCH_RLMT) {
- Next0[i] |= 8;
- }
- }
-#endif /* DEBUG */
-
- /* Read permanent logical MAC address from Control Register File. */
- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
- InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
- SK_IN8(IoC, B2_MAC_1 + j, InAddr);
- }
-
- if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
- /* Set the current logical MAC address to the permanent one. */
- pAC->Addr.Net[0].CurrentMacAddress =
- pAC->Addr.Net[0].PermanentMacAddress;
- pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
- }
-
- /* Set the current logical MAC address. */
- pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
- pAC->Addr.Net[0].CurrentMacAddress;
-#if SK_MAX_NETS > 1
- /* Set logical MAC address for net 2 to (log | 3). */
- if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
- pAC->Addr.Net[1].PermanentMacAddress =
- pAC->Addr.Net[0].PermanentMacAddress;
- pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
- /* Set the current logical MAC address to the permanent one. */
- pAC->Addr.Net[1].CurrentMacAddress =
- pAC->Addr.Net[1].PermanentMacAddress;
- pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
- }
-#endif /* SK_MAX_NETS > 1 */
-
-#ifdef DEBUG
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
- ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
- i,
- pAC->Addr.Net[i].PermanentMacAddress.a[0],
- pAC->Addr.Net[i].PermanentMacAddress.a[1],
- pAC->Addr.Net[i].PermanentMacAddress.a[2],
- pAC->Addr.Net[i].PermanentMacAddress.a[3],
- pAC->Addr.Net[i].PermanentMacAddress.a[4],
- pAC->Addr.Net[i].PermanentMacAddress.a[5]))
-
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
- ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
- i,
- pAC->Addr.Net[i].CurrentMacAddress.a[0],
- pAC->Addr.Net[i].CurrentMacAddress.a[1],
- pAC->Addr.Net[i].CurrentMacAddress.a[2],
- pAC->Addr.Net[i].CurrentMacAddress.a[3],
- pAC->Addr.Net[i].CurrentMacAddress.a[4],
- pAC->Addr.Net[i].CurrentMacAddress.a[5]))
- }
-#endif /* DEBUG */
-
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- pAPort = &pAC->Addr.Port[i];
-
- /* Read permanent port addresses from Control Register File. */
- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
- InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
- SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
- }
-
- if (!pAPort->CurrentMacAddressSet) {
- /*
- * Set the current and previous physical MAC address
- * of this port to its permanent MAC address.
- */
- pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
- pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
- pAPort->CurrentMacAddressSet = SK_TRUE;
- }
-
- /* Set port's current physical MAC address. */
- OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- XM_OUTADDR(IoC, i, XM_SA, OutAddr);
- }
-#endif /* GENESIS */
-#ifdef YUKON
- if (!pAC->GIni.GIGenesis) {
- GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
- }
-#endif /* YUKON */
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
- ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAPort->PermanentMacAddress.a[0],
- pAPort->PermanentMacAddress.a[1],
- pAPort->PermanentMacAddress.a[2],
- pAPort->PermanentMacAddress.a[3],
- pAPort->PermanentMacAddress.a[4],
- pAPort->PermanentMacAddress.a[5]))
-
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
- ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAPort->CurrentMacAddress.a[0],
- pAPort->CurrentMacAddress.a[1],
- pAPort->CurrentMacAddress.a[2],
- pAPort->CurrentMacAddress.a[3],
- pAPort->CurrentMacAddress.a[4],
- pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
- }
- /* pAC->Addr.InitDone = SK_INIT_IO; */
- break;
-
- case SK_INIT_RUN:
-#ifdef xDEBUG
- for (i = 0; i < SK_MAX_MACS; i++) {
- if (pAC->Addr.Port[i].NextExactMatchRlmt <
- SK_ADDR_FIRST_MATCH_RLMT) {
- Next0[i] |= 16;
- }
- }
-#endif /* DEBUG */
-
- /* pAC->Addr.InitDone = SK_INIT_RUN; */
- break;
-
- default: /* error */
- break;
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrInit */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- * SkAddrMcClear - clear the multicast table
- *
- * Description:
- * This routine clears the multicast table.
- *
- * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- * immediately.
- *
- * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
- * to the adapter in use. The real work is done there.
- *
- * Context:
- * runtime, pageable
- * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- * may be called after SK_INIT_IO without limitation
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-int SkAddrMcClear(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Index of affected port */
-int Flags) /* permanent/non-perm, sw-only */
-{
- int ReturnCode;
-
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- if (pAC->GIni.GIGenesis) {
- ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
- }
- else {
- ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
- }
-
- return (ReturnCode);
-
-} /* SkAddrMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- * SkAddrXmacMcClear - clear the multicast table
- *
- * Description:
- * This routine clears the multicast table
- * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
- * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- * immediately.
- *
- * Context:
- * runtime, pageable
- * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- * may be called after SK_INIT_IO without limitation
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrXmacMcClear(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Index of affected port */
-int Flags) /* permanent/non-perm, sw-only */
-{
- int i;
-
- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
-
- /* Clear RLMT multicast addresses. */
- pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
- }
- else { /* not permanent => DRV */
-
- /* Clear InexactFilter */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
- }
-
- /* Clear DRV multicast addresses. */
-
- pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
- }
-
- if (!(Flags & SK_MC_SW_ONLY)) {
- (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrXmacMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- * SkAddrGmacMcClear - clear the multicast table
- *
- * Description:
- * This routine clears the multicast hashing table (InexactFilter)
- * (either the RLMT or the driver bits) of the given port.
- *
- * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- * immediately.
- *
- * Context:
- * runtime, pageable
- * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- * may be called after SK_INIT_IO without limitation
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrGmacMcClear(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Index of affected port */
-int Flags) /* permanent/non-perm, sw-only */
-{
- int i;
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif /* DEBUG */
-
- /* Clear InexactFilter */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
- }
-
- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
-
- /* Copy DRV bits to InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
-
- /* Clear InexactRlmtFilter. */
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
-
- }
- }
- else { /* not permanent => DRV */
-
- /* Copy RLMT bits to InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
-
- /* Clear InexactDrvFilter. */
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
- }
- }
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif /* DEBUG */
-
- if (!(Flags & SK_MC_SW_ONLY)) {
- (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrGmacMcClear */
-
-#ifndef SK_ADDR_CHEAT
-
-/******************************************************************************
- *
- * SkXmacMcHash - hash multicast address
- *
- * Description:
- * This routine computes the hash value for a multicast address.
- * A CRC32 algorithm is used.
- *
- * Notes:
- * The code was adapted from the XaQti data sheet.
- *
- * Context:
- * runtime, pageable
- *
- * Returns:
- * Hash value of multicast address.
- */
-static SK_U32 SkXmacMcHash(
-unsigned char *pMc) /* Multicast address */
-{
- SK_U32 Idx;
- SK_U32 Bit;
- SK_U32 Data;
- SK_U32 Crc;
-
- Crc = 0xFFFFFFFFUL;
- for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
- Data = *pMc++;
- for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
- Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
- }
- }
-
- return (Crc & ((1 << HASH_BITS) - 1));
-
-} /* SkXmacMcHash */
-
-
-/******************************************************************************
- *
- * SkGmacMcHash - hash multicast address
- *
- * Description:
- * This routine computes the hash value for a multicast address.
- * A CRC16 algorithm is used.
- *
- * Notes:
- *
- *
- * Context:
- * runtime, pageable
- *
- * Returns:
- * Hash value of multicast address.
- */
-static SK_U32 SkGmacMcHash(
-unsigned char *pMc) /* Multicast address */
-{
- SK_U32 Data;
- SK_U32 TmpData;
- SK_U32 Crc;
- int Byte;
- int Bit;
-
- Crc = 0xFFFFFFFFUL;
- for (Byte = 0; Byte < 6; Byte++) {
- /* Get next byte. */
- Data = (SK_U32) pMc[Byte];
-
- /* Change bit order in byte. */
- TmpData = Data;
- for (Bit = 0; Bit < 8; Bit++) {
- if (TmpData & 1L) {
- Data |= 1L << (7 - Bit);
- }
- else {
- Data &= ~(1L << (7 - Bit));
- }
- TmpData >>= 1;
- }
-
- Crc ^= (Data << 24);
- for (Bit = 0; Bit < 8; Bit++) {
- if (Crc & 0x80000000) {
- Crc = (Crc << 1) ^ GMAC_POLY;
- }
- else {
- Crc <<= 1;
- }
- }
- }
-
- return (Crc & ((1 << HASH_BITS) - 1));
-
-} /* SkGmacMcHash */
-
-#endif /* !SK_ADDR_CHEAT */
-
-/******************************************************************************
- *
- * SkAddrMcAdd - add a multicast address to a port
- *
- * Description:
- * This routine enables reception for a given address on the given port.
- *
- * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
- * adapter in use. The real work is done there.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_DATA
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_MC_ILLEGAL_ADDRESS
- * SK_MC_ILLEGAL_PORT
- * SK_MC_RLMT_OVERFLOW
- */
-int SkAddrMcAdd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Port Number */
-SK_MAC_ADDR *pMc, /* multicast address to be added */
-int Flags) /* permanent/non-permanent */
-{
- int ReturnCode;
-
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- if (pAC->GIni.GIGenesis) {
- ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
- }
- else {
- ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
- }
-
- return (ReturnCode);
-
-} /* SkAddrMcAdd */
-
-
-/******************************************************************************
- *
- * SkAddrXmacMcAdd - add a multicast address to a port
- *
- * Description:
- * This routine enables reception for a given address on the given port.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * The multicast bit is only checked if there are no free exact match
- * entries.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_DATA
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_MC_ILLEGAL_ADDRESS
- * SK_MC_RLMT_OVERFLOW
- */
-static int SkAddrXmacMcAdd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Port Number */
-SK_MAC_ADDR *pMc, /* multicast address to be added */
-int Flags) /* permanent/non-permanent */
-{
- int i;
- SK_U8 Inexact;
-#ifndef SK_ADDR_CHEAT
- SK_U32 HashBit;
-#endif /* !defined(SK_ADDR_CHEAT) */
-
- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
-#ifdef xDEBUG
- if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
- SK_ADDR_FIRST_MATCH_RLMT) {
- Next0[PortNumber] |= 1;
- return (SK_MC_RLMT_OVERFLOW);
- }
-#endif /* DEBUG */
-
- if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
- SK_ADDR_LAST_MATCH_RLMT) {
- return (SK_MC_RLMT_OVERFLOW);
- }
-
- /* Set a RLMT multicast address. */
-
- pAC->Addr.Port[PortNumber].Exact[
- pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
-
- return (SK_MC_FILTERING_EXACT);
- }
-
-#ifdef xDEBUG
- if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
- SK_ADDR_FIRST_MATCH_DRV) {
- Next0[PortNumber] |= 2;
- return (SK_MC_RLMT_OVERFLOW);
- }
-#endif /* DEBUG */
-
- if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-
- /* Set exact match entry. */
- pAC->Addr.Port[PortNumber].Exact[
- pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
-
- /* Clear InexactFilter */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
- }
- }
- else {
- if (!(pMc->a[0] & SK_MC_BIT)) {
- /* Hashing only possible with multicast addresses */
- return (SK_MC_ILLEGAL_ADDRESS);
- }
-#ifndef SK_ADDR_CHEAT
- /* Compute hash value of address. */
- HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
-
- /* Add bit to InexactFilter. */
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
- 1 << (HashBit % 8);
-#else /* SK_ADDR_CHEAT */
- /* Set all bits in InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
- }
-#endif /* SK_ADDR_CHEAT */
- }
-
- for (Inexact = 0, i = 0; i < 8; i++) {
- Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
- }
-
- if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
- return (SK_MC_FILTERING_EXACT);
- }
- else {
- return (SK_MC_FILTERING_INEXACT);
- }
-
-} /* SkAddrXmacMcAdd */
-
-
-/******************************************************************************
- *
- * SkAddrGmacMcAdd - add a multicast address to a port
- *
- * Description:
- * This routine enables reception for a given address on the given port.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_DATA
- *
- * Returns:
- * SK_MC_FILTERING_INEXACT
- * SK_MC_ILLEGAL_ADDRESS
- */
-static int SkAddrGmacMcAdd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Port Number */
-SK_MAC_ADDR *pMc, /* multicast address to be added */
-int Flags) /* permanent/non-permanent */
-{
- int i;
-#ifndef SK_ADDR_CHEAT
- SK_U32 HashBit;
-#endif /* !defined(SK_ADDR_CHEAT) */
-
- if (!(pMc->a[0] & SK_MC_BIT)) {
- /* Hashing only possible with multicast addresses */
- return (SK_MC_ILLEGAL_ADDRESS);
- }
-
-#ifndef SK_ADDR_CHEAT
-
- /* Compute hash value of address. */
- HashBit = SkGmacMcHash(&pMc->a[0]);
-
- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
-
- /* Add bit to InexactRlmtFilter. */
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
- 1 << (HashBit % 8);
-
- /* Copy bit to InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
- }
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
-#endif /* DEBUG */
- }
- else { /* not permanent => DRV */
-
- /* Add bit to InexactDrvFilter. */
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
- 1 << (HashBit % 8);
-
- /* Copy bit to InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
- }
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
-#endif /* DEBUG */
- }
-
-#else /* SK_ADDR_CHEAT */
-
- /* Set all bits in InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
- }
-#endif /* SK_ADDR_CHEAT */
-
- return (SK_MC_FILTERING_INEXACT);
-
-} /* SkAddrGmacMcAdd */
-
-#endif /* !SK_SLIM */
-
-/******************************************************************************
- *
- * SkAddrMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- * This routine enables reception of the addresses contained in a local
- * table for a given port.
- * It also programs the port's current physical MAC address.
- *
- * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
- * to the adapter in use. The real work is done there.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_ADDR_ILLEGAL_PORT
- */
-int SkAddrMcUpdate(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber) /* Port Number */
-{
- int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
- }
-#endif /* GENESIS */
-#ifdef YUKON
- if (!pAC->GIni.GIGenesis) {
- ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
- }
-#endif /* YUKON */
- return (ReturnCode);
-
-} /* SkAddrMcUpdate */
-
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- * This routine enables reception of the addresses contained in a local
- * table for a given port.
- * It also programs the port's current physical MAC address.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrXmacMcUpdate(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber) /* Port Number */
-{
- SK_U32 i;
- SK_U8 Inexact;
- SK_U16 *OutAddr;
- SK_ADDR_PORT *pAPort;
-
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
-
- pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-
- /* Start with 0 to also program the logical MAC address. */
- for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
- /* Set exact match address i on XMAC */
- OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
- XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
- }
-
- /* Clear other permanent exact match addresses on XMAC */
- if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
-
- SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
- SK_ADDR_LAST_MATCH_RLMT);
- }
-
- for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
- OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
- XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
- }
-
- /* Clear other non-permanent exact match addresses on XMAC */
- if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-
- SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
- SK_ADDR_LAST_MATCH_DRV);
- }
-
- for (Inexact = 0, i = 0; i < 8; i++) {
- Inexact |= pAPort->InexactFilter.Bytes[i];
- }
-
- if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
-
- /* Set all bits in 64-bit hash register. */
- XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else if (Inexact != 0) {
-
- /* Set 64-bit hash register to InexactFilter. */
- XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else {
- /* Disable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
- }
-
- if (pAPort->PromMode != SK_PROM_MODE_NONE) {
- (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
- }
-
- /* Set port's current physical MAC address. */
- OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-
- XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
-
-#ifdef xDEBUG
- for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
- SK_U8 InAddr8[6];
- SK_U16 *InAddr;
-
- /* Get exact match address i from port PortNumber. */
- InAddr = (SK_U16 *) &InAddr8[0];
-
- XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
-
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
- "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
- i,
- PortNumber,
- InAddr8[0],
- InAddr8[1],
- InAddr8[2],
- InAddr8[3],
- InAddr8[4],
- InAddr8[5],
- pAPort->Exact[i].a[0],
- pAPort->Exact[i].a[1],
- pAPort->Exact[i].a[2],
- pAPort->Exact[i].a[3],
- pAPort->Exact[i].a[4],
- pAPort->Exact[i].a[5]))
- }
-#endif /* DEBUG */
-
- /* Determine return value. */
- if (Inexact == 0 && pAPort->PromMode == 0) {
- return (SK_MC_FILTERING_EXACT);
- }
- else {
- return (SK_MC_FILTERING_INEXACT);
- }
-
-} /* SkAddrXmacMcUpdate */
-
-#endif /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- * This routine enables reception of the addresses contained in a local
- * table for a given port.
- * It also programs the port's current physical MAC address.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrGmacMcUpdate(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber) /* Port Number */
-{
-#ifndef SK_SLIM
- SK_U32 i;
- SK_U8 Inexact;
-#endif /* not SK_SLIM */
- SK_U16 *OutAddr;
- SK_ADDR_PORT *pAPort;
-
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
-
- pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-
-#ifndef SK_SLIM
- for (Inexact = 0, i = 0; i < 8; i++) {
- Inexact |= pAPort->InexactFilter.Bytes[i];
- }
-
- /* Set 64-bit hash register to InexactFilter. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
- &pAPort->InexactFilter.Bytes[0]);
-
- if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
-
- /* Set all bits in 64-bit hash register. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else {
- /* Enable Hashing. */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
-
- if (pAPort->PromMode != SK_PROM_MODE_NONE) {
- (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
- }
-#else /* SK_SLIM */
-
- /* Set all bits in 64-bit hash register. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-
- (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-
-#endif /* SK_SLIM */
-
- /* Set port's current physical MAC address. */
- OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
- GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
-
- /* Set port's current logical MAC address. */
- OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
- GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAPort->Exact[0].a[0],
- pAPort->Exact[0].a[1],
- pAPort->Exact[0].a[2],
- pAPort->Exact[0].a[3],
- pAPort->Exact[0].a[4],
- pAPort->Exact[0].a[5]))
-
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAPort->CurrentMacAddress.a[0],
- pAPort->CurrentMacAddress.a[1],
- pAPort->CurrentMacAddress.a[2],
- pAPort->CurrentMacAddress.a[3],
- pAPort->CurrentMacAddress.a[4],
- pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-
-#ifndef SK_SLIM
- /* Determine return value. */
- if (Inexact == 0 && pAPort->PromMode == 0) {
- return (SK_MC_FILTERING_EXACT);
- }
- else {
- return (SK_MC_FILTERING_INEXACT);
- }
-#else /* SK_SLIM */
- return (SK_MC_FILTERING_INEXACT);
-#endif /* SK_SLIM */
-
-} /* SkAddrGmacMcUpdate */
-
-#endif /* YUKON */
-
-#ifndef SK_NO_MAO
-
-/******************************************************************************
- *
- * SkAddrOverride - override a port's MAC address
- *
- * Description:
- * This routine overrides the MAC address of one port.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS if successful.
- * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
- * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
- * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
- */
-int SkAddrOverride(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Port Number */
-SK_MAC_ADDR SK_FAR *pNewAddr, /* new MAC address */
-int Flags) /* logical/physical MAC address */
-{
-#ifndef SK_NO_RLMT
- SK_EVPARA Para;
-#endif /* !SK_NO_RLMT */
- SK_U32 NetNumber;
- SK_U32 i;
- SK_U16 SK_FAR *OutAddr;
-
-#ifndef SK_NO_RLMT
- NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
-#else
- NetNumber = 0;
-#endif /* SK_NO_RLMT */
-#if (!defined(SK_SLIM) || defined(DEBUG))
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-#endif /* !SK_SLIM || DEBUG */
- if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
- return (SK_ADDR_MULTICAST_ADDRESS);
- }
-
- if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
-
- if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
- /* Parameter *pNewAddr is ignored. */
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
- }
-#ifndef SK_NO_RLMT
- /* Set PortNumber to number of net's active port. */
- PortNumber = pAC->Rlmt.Net[NetNumber].
- Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
- pAC->Addr.Port[PortNumber].Exact[0] =
- pAC->Addr.Net[NetNumber].CurrentMacAddress;
-
- /* Write address to first exact match entry of active port. */
- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
- }
- else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
- /* Deactivate logical MAC address. */
- /* Parameter *pNewAddr is ignored. */
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
- }
-#ifndef SK_NO_RLMT
- /* Set PortNumber to number of net's active port. */
- PortNumber = pAC->Rlmt.Net[NetNumber].
- Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
- for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
- pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
- }
-
- /* Write address to first exact match entry of active port. */
- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
- }
- else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
- if (SK_ADDR_EQUAL(pNewAddr->a,
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
- return (SK_ADDR_DUPLICATE_ADDRESS);
- }
-
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
-
- if (SK_ADDR_EQUAL(pNewAddr->a,
- pAC->Addr.Port[i].CurrentMacAddress.a)) {
- if (i == PortNumber) {
- return (SK_ADDR_SUCCESS);
- }
- else {
- return (SK_ADDR_DUPLICATE_ADDRESS);
- }
- }
- }
-
- pAC->Addr.Port[PortNumber].PreviousMacAddress =
- pAC->Addr.Port[PortNumber].CurrentMacAddress;
- pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-
- /* Change port's physical MAC address. */
- OutAddr = (SK_U16 SK_FAR *) pNewAddr;
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
- }
-#endif /* GENESIS */
-#ifdef YUKON
- if (!pAC->GIni.GIGenesis) {
- GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
- }
-#endif /* YUKON */
-
-#ifndef SK_NO_RLMT
- /* Report address change to RLMT. */
- Para.Para32[0] = PortNumber;
- Para.Para32[0] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
- }
- else { /* Logical MAC address. */
- if (SK_ADDR_EQUAL(pNewAddr->a,
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
- return (SK_ADDR_SUCCESS);
- }
-
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
-
- if (SK_ADDR_EQUAL(pNewAddr->a,
- pAC->Addr.Port[i].CurrentMacAddress.a)) {
- return (SK_ADDR_DUPLICATE_ADDRESS);
- }
- }
-
- /*
- * In case that the physical and the logical MAC addresses are equal
- * we must also change the physical MAC address here.
- * In this case we have an adapter which initially was programmed with
- * two identical MAC addresses.
- */
- if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
- pAC->Addr.Port[PortNumber].Exact[0].a)) {
-
- pAC->Addr.Port[PortNumber].PreviousMacAddress =
- pAC->Addr.Port[PortNumber].CurrentMacAddress;
- pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-
-#ifndef SK_NO_RLMT
- /* Report address change to RLMT. */
- Para.Para32[0] = PortNumber;
- Para.Para32[0] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
- }
-
-#ifndef SK_NO_RLMT
- /* Set PortNumber to number of net's active port. */
- PortNumber = pAC->Rlmt.Net[NetNumber].
- Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
- pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
- pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
-#ifdef DEBUG
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
-
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-
- /* Write address to first exact match entry of active port. */
- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrOverride */
-
-
-#endif /* SK_NO_MAO */
-
-/******************************************************************************
- *
- * SkAddrPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- * This routine manages promiscuous mode:
- * - none
- * - all LLC frames
- * - all MC frames
- *
- * It calls either SkAddrXmacPromiscuousChange or
- * SkAddrGmacPromiscuousChange, according to the adapter in use.
- * The real work is done there.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-int SkAddrPromiscuousChange(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* port whose promiscuous mode changes */
-int NewPromMode) /* new promiscuous mode */
-{
- int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- ReturnCode =
- SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
- }
-#endif /* GENESIS */
-#ifdef YUKON
- if (!pAC->GIni.GIGenesis) {
- ReturnCode =
- SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
- }
-#endif /* YUKON */
-
- return (ReturnCode);
-
-} /* SkAddrPromiscuousChange */
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- * This routine manages promiscuous mode:
- * - none
- * - all LLC frames
- * - all MC frames
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrXmacPromiscuousChange(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* port whose promiscuous mode changes */
-int NewPromMode) /* new promiscuous mode */
-{
- int i;
- SK_BOOL InexactModeBit;
- SK_U8 Inexact;
- SK_U8 HwInexact;
- SK_FILTER64 HwInexactFilter;
- SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
- int CurPromMode = SK_PROM_MODE_NONE;
-
- /* Read CurPromMode from Hardware. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-
- if ((LoMode & XM_MD_ENA_PROM) != 0) {
- /* Promiscuous mode! */
- CurPromMode |= SK_PROM_MODE_LLC;
- }
-
- for (Inexact = 0xFF, i = 0; i < 8; i++) {
- Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
- }
- if (Inexact == 0xFF) {
- CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
- }
- else {
- /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-
- InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
-
- /* Read 64-bit hash register from XMAC */
- XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
-
- for (HwInexact = 0xFF, i = 0; i < 8; i++) {
- HwInexact &= HwInexactFilter.Bytes[i];
- }
-
- if (InexactModeBit && (HwInexact == 0xFF)) {
- CurPromMode |= SK_PROM_MODE_ALL_MC;
- }
- }
-
- pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
- if (NewPromMode == CurPromMode) {
- return (SK_ADDR_SUCCESS);
- }
-
- if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
- !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
-
- /* Set all bits in 64-bit hash register. */
- XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
- !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
- for (Inexact = 0, i = 0; i < 8; i++) {
- Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
- }
- if (Inexact == 0) {
- /* Disable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
- }
- else {
- /* Set 64-bit hash register to InexactFilter. */
- XM_OUTHASH(IoC, PortNumber, XM_HSM,
- &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- }
-
- if ((NewPromMode & SK_PROM_MODE_LLC) &&
- !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
- /* Set the MAC in Promiscuous Mode */
- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else if ((CurPromMode & SK_PROM_MODE_LLC) &&
- !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
- /* Clear Promiscuous Mode */
- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrXmacPromiscuousChange */
-
-#endif /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- * This routine manages promiscuous mode:
- * - none
- * - all LLC frames
- * - all MC frames
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrGmacPromiscuousChange(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* port whose promiscuous mode changes */
-int NewPromMode) /* new promiscuous mode */
-{
- SK_U16 ReceiveControl; /* GMAC Receive Control Register */
- int CurPromMode = SK_PROM_MODE_NONE;
-
- /* Read CurPromMode from Hardware. */
- GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
-
- if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
- /* Promiscuous mode! */
- CurPromMode |= SK_PROM_MODE_LLC;
- }
-
- if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
- /* All Multicast mode! */
- CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
- }
-
- pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
- if (NewPromMode == CurPromMode) {
- return (SK_ADDR_SUCCESS);
- }
-
- if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
- !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */
-
- /* Set all bits in 64-bit hash register. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
-
- if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
- !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */
-
- /* Set 64-bit hash register to InexactFilter. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
- &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
- /* Enable Hashing. */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
-
- if ((NewPromMode & SK_PROM_MODE_LLC) &&
- !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
-
- /* Set the MAC to Promiscuous Mode. */
- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else if ((CurPromMode & SK_PROM_MODE_LLC) &&
- !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
-
- /* Clear Promiscuous Mode. */
- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrGmacPromiscuousChange */
-
-#endif /* YUKON */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- * SkAddrSwap - swap address info
- *
- * Description:
- * This routine swaps address info of two ports.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-int SkAddrSwap(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 FromPortNumber, /* Port1 Index */
-SK_U32 ToPortNumber) /* Port2 Index */
-{
- int i;
- SK_U8 Byte;
- SK_MAC_ADDR MacAddr;
- SK_U32 DWord;
-
- if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- /*
- * Swap:
- * - Exact Match Entries (GEnesis and Yukon)
- * Yukon uses first entry for the logical MAC
- * address (stored in the second GMAC register).
- * - FirstExactMatchRlmt (GEnesis only)
- * - NextExactMatchRlmt (GEnesis only)
- * - FirstExactMatchDrv (GEnesis only)
- * - NextExactMatchDrv (GEnesis only)
- * - 64-bit filter (InexactFilter)
- * - Promiscuous Mode
- * of ports.
- */
-
- for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
- MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
- pAC->Addr.Port[FromPortNumber].Exact[i] =
- pAC->Addr.Port[ToPortNumber].Exact[i];
- pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
- }
-
- for (i = 0; i < 8; i++) {
- Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
- pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
- pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
- pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
- }
-
- i = pAC->Addr.Port[FromPortNumber].PromMode;
- pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
- pAC->Addr.Port[ToPortNumber].PromMode = i;
-
- if (pAC->GIni.GIGenesis) {
- DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
- pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
- pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
- pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
-
- DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
- pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
- pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
- pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
-
- DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
- pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
- pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
- pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
-
- DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
- pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
- pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
- pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
- }
-
- /* CAUTION: Solution works if only ports of one adapter are in use. */
- for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
- Net->NetNumber].NumPorts; i++) {
- if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
- Port[i]->PortNumber == ToPortNumber) {
- pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
- ActivePort = i;
- /* 20001207 RA: Was "ToPortNumber;". */
- }
- }
-
- (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
- (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrSwap */
-
-#endif /* !SK_SLIM */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
deleted file mode 100644
index 37ce03fb8de..00000000000
--- a/drivers/net/sk98lin/skdim.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/******************************************************************************
- *
- * Name: skdim.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.5 $
- * Date: $Date: 2003/11/28 12:55:40 $
- * Purpose: All functions to maintain interrupt moderation
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage the dynamic interrupt moderation on both
- * GEnesis and Yukon adapters.
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef lint
-static const char SysKonnectFileId[] =
- "@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect.";
-#endif
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-#error C++ is not yet supported.
-extern "C" {
-#endif
-
-/*******************************************************************************
-**
-** Includes
-**
-*******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#include "h/skdrv1st.h"
-#endif
-
-#ifndef __INC_SKDRV2ND_H
-#include "h/skdrv2nd.h"
-#endif
-
-#include <linux/kernel_stat.h>
-
-/*******************************************************************************
-**
-** Defines
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Typedefs
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local function prototypes
-**
-*******************************************************************************/
-
-static unsigned int GetCurrentSystemLoad(SK_AC *pAC);
-static SK_U64 GetIsrCalls(SK_AC *pAC);
-static SK_BOOL IsIntModEnabled(SK_AC *pAC);
-static void SetCurrIntCtr(SK_AC *pAC);
-static void EnableIntMod(SK_AC *pAC);
-static void DisableIntMod(SK_AC *pAC);
-static void ResizeDimTimerDuration(SK_AC *pAC);
-static void DisplaySelectedModerationType(SK_AC *pAC);
-static void DisplaySelectedModerationMask(SK_AC *pAC);
-static void DisplayDescrRatio(SK_AC *pAC);
-
-/*******************************************************************************
-**
-** Global variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Global functions
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function : SkDimModerate
-** Description : Called in every ISR to check if moderation is to be applied
-** or not for the current number of interrupts
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : void (!)
-** Notes : -
-*******************************************************************************/
-
-void
-SkDimModerate(SK_AC *pAC) {
- unsigned int CurrSysLoad = 0; /* expressed in percent */
- unsigned int LoadIncrease = 0; /* expressed in percent */
- SK_U64 ThresholdInts = 0;
- SK_U64 IsrCallsPerSec = 0;
-
-#define M_DIMINFO pAC->DynIrqModInfo
-
- if (!IsIntModEnabled(pAC)) {
- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
- CurrSysLoad = GetCurrentSystemLoad(pAC);
- if (CurrSysLoad > 75) {
- /*
- ** More than 75% total system load! Enable the moderation
- ** to shield the system against too many interrupts.
- */
- EnableIntMod(pAC);
- } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) {
- LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad);
- if (LoadIncrease > ((M_DIMINFO.PrevSysLoad *
- C_INT_MOD_ENABLE_PERCENTAGE) / 100)) {
- if (CurrSysLoad > 10) {
- /*
- ** More than 50% increase with respect to the
- ** previous load of the system. Most likely this
- ** is due to our ISR-proc...
- */
- EnableIntMod(pAC);
- }
- }
- } else {
- /*
- ** Neither too much system load at all nor too much increase
- ** with respect to the previous system load. Hence, we can leave
- ** the ISR-handling like it is without enabling moderation.
- */
- }
- M_DIMINFO.PrevSysLoad = CurrSysLoad;
- }
- } else {
- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
- ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
- C_INT_MOD_DISABLE_PERCENTAGE) / 100);
- IsrCallsPerSec = GetIsrCalls(pAC);
- if (IsrCallsPerSec <= ThresholdInts) {
- /*
- ** The number of interrupts within the last second is
- ** lower than the disable_percentage of the desried
- ** maxrate. Therefore we can disable the moderation.
- */
- DisableIntMod(pAC);
- M_DIMINFO.MaxModIntsPerSec =
- (M_DIMINFO.MaxModIntsPerSecUpperLimit +
- M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2;
- } else {
- /*
- ** The number of interrupts per sec is the same as expected.
- ** Evalulate the descriptor-ratio. If it has changed, a resize
- ** in the moderation timer might be useful
- */
- if (M_DIMINFO.AutoSizing) {
- ResizeDimTimerDuration(pAC);
- }
- }
- }
- }
-
- /*
- ** Some information to the log...
- */
- if (M_DIMINFO.DisplayStats) {
- DisplaySelectedModerationType(pAC);
- DisplaySelectedModerationMask(pAC);
- DisplayDescrRatio(pAC);
- }
-
- M_DIMINFO.NbrProcessedDescr = 0;
- SetCurrIntCtr(pAC);
-}
-
-/*******************************************************************************
-** Function : SkDimStartModerationTimer
-** Description : Starts the audit-timer for the dynamic interrupt moderation
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : void (!)
-** Notes : -
-*******************************************************************************/
-
-void
-SkDimStartModerationTimer(SK_AC *pAC) {
- SK_EVPARA EventParam; /* Event struct for timer event */
-
- SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
- SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer,
- SK_DRV_MODERATION_TIMER_LENGTH,
- SKGE_DRV, SK_DRV_TIMER, EventParam);
-}
-
-/*******************************************************************************
-** Function : SkDimEnableModerationIfNeeded
-** Description : Either enables or disables moderation
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : void (!)
-** Notes : This function is called when a particular adapter is opened
-** There is no Disable function, because when all interrupts
-** might be disable, the moderation timer has no meaning at all
-******************************************************************************/
-
-void
-SkDimEnableModerationIfNeeded(SK_AC *pAC) {
-
- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
- EnableIntMod(pAC); /* notification print in this function */
- } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
- SkDimStartModerationTimer(pAC);
- if (M_DIMINFO.DisplayStats) {
- printk("Dynamic moderation has been enabled\n");
- }
- } else {
- if (M_DIMINFO.DisplayStats) {
- printk("No moderation has been enabled\n");
- }
- }
-}
-
-/*******************************************************************************
-** Function : SkDimDisplayModerationSettings
-** Description : Displays the current settings regarding interrupt moderation
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : void (!)
-** Notes : -
-*******************************************************************************/
-
-void
-SkDimDisplayModerationSettings(SK_AC *pAC) {
- DisplaySelectedModerationType(pAC);
- DisplaySelectedModerationMask(pAC);
-}
-
-/*******************************************************************************
-**
-** Local functions
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function : GetCurrentSystemLoad
-** Description : Retrieves the current system load of the system. This load
-** is evaluated for all processors within the system.
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : unsigned int: load expressed in percentage
-** Notes : The possible range being returned is from 0 up to 100.
-** Whereas 0 means 'no load at all' and 100 'system fully loaded'
-** It is impossible to determine what actually causes the system
-** to be in 100%, but maybe that is due to too much interrupts.
-*******************************************************************************/
-
-static unsigned int
-GetCurrentSystemLoad(SK_AC *pAC) {
- unsigned long jif = jiffies;
- unsigned int UserTime = 0;
- unsigned int SystemTime = 0;
- unsigned int NiceTime = 0;
- unsigned int IdleTime = 0;
- unsigned int TotalTime = 0;
- unsigned int UsedTime = 0;
- unsigned int SystemLoad = 0;
-
- /* unsigned int NbrCpu = 0; */
-
- /*
- ** The following lines have been commented out, because
- ** from kernel 2.5.44 onwards, the kernel-owned structure
- **
- ** struct kernel_stat kstat
- **
- ** is not marked as an exported symbol in the file
- **
- ** kernel/ksyms.c
- **
- ** As a consequence, using this driver as KLM is not possible
- ** and any access of the structure kernel_stat via the
- ** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided.
- **
- ** The kstat-information might be added again in future
- ** versions of the 2.5.xx kernel, but for the time being,
- ** number of interrupts will serve as indication how much
- ** load we currently have...
- **
- ** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) {
- ** UserTime = UserTime + kstat_cpu(NbrCpu).cpustat.user;
- ** NiceTime = NiceTime + kstat_cpu(NbrCpu).cpustat.nice;
- ** SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system;
- ** }
- */
- SK_U64 ThresholdInts = 0;
- SK_U64 IsrCallsPerSec = 0;
-
- ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
- C_INT_MOD_ENABLE_PERCENTAGE) + 100);
- IsrCallsPerSec = GetIsrCalls(pAC);
- if (IsrCallsPerSec >= ThresholdInts) {
- /*
- ** We do not know how much the real CPU-load is!
- ** Return 80% as a default in order to activate DIM
- */
- SystemLoad = 80;
- return (SystemLoad);
- }
-
- UsedTime = UserTime + NiceTime + SystemTime;
-
- IdleTime = jif * num_online_cpus() - UsedTime;
- TotalTime = UsedTime + IdleTime;
-
- SystemLoad = ( 100 * (UsedTime - M_DIMINFO.PrevUsedTime) ) /
- (TotalTime - M_DIMINFO.PrevTotalTime);
-
- if (M_DIMINFO.DisplayStats) {
- printk("Current system load is: %u\n", SystemLoad);
- }
-
- M_DIMINFO.PrevTotalTime = TotalTime;
- M_DIMINFO.PrevUsedTime = UsedTime;
-
- return (SystemLoad);
-}
-
-/*******************************************************************************
-** Function : GetIsrCalls
-** Description : Depending on the selected moderation mask, this function will
-** return the number of interrupts handled in the previous time-
-** frame. This evaluated number is based on the current number
-** of interrupts stored in PNMI-context and the previous stored
-** interrupts.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : int: the number of interrupts being executed in the last
-** timeframe
-** Notes : It makes only sense to call this function, when dynamic
-** interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetIsrCalls(SK_AC *pAC) {
- SK_U64 RxPort0IntDiff = 0;
- SK_U64 RxPort1IntDiff = 0;
- SK_U64 TxPort0IntDiff = 0;
- SK_U64 TxPort1IntDiff = 0;
-
- if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) {
- if (pAC->GIni.GIMacsFound == 2) {
- TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
- pAC->DynIrqModInfo.PrevPort1TxIntrCts;
- }
- TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
- pAC->DynIrqModInfo.PrevPort0TxIntrCts;
- } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) {
- if (pAC->GIni.GIMacsFound == 2) {
- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
- }
- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
- } else {
- if (pAC->GIni.GIMacsFound == 2) {
- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
- TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
- pAC->DynIrqModInfo.PrevPort1TxIntrCts;
- }
- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
- TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
- pAC->DynIrqModInfo.PrevPort0TxIntrCts;
- }
-
- return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function : GetRxCalls
-** Description : This function will return the number of times a receive inter-
-** rupt was processed. This is needed to evaluate any resizing
-** factor.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : SK_U64: the number of RX-ints being processed
-** Notes : It makes only sense to call this function, when dynamic
-** interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetRxCalls(SK_AC *pAC) {
- SK_U64 RxPort0IntDiff = 0;
- SK_U64 RxPort1IntDiff = 0;
-
- if (pAC->GIni.GIMacsFound == 2) {
- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
- }
- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-
- return (RxPort0IntDiff + RxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function : SetCurrIntCtr
-** Description : Will store the current number orf occured interrupts in the
-** adapter context. This is needed to evaluated the number of
-** interrupts within a current timeframe.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : void (!)
-** Notes : -
-*******************************************************************************/
-
-static void
-SetCurrIntCtr(SK_AC *pAC) {
- if (pAC->GIni.GIMacsFound == 2) {
- pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
- pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
- }
- pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
- pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
-}
-
-/*******************************************************************************
-** Function : IsIntModEnabled()
-** Description : Retrieves the current value of the interrupts moderation
-** command register. Its content determines whether any
-** moderation is running or not.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : SK_TRUE : if mod timer running
-** SK_FALSE : if no moderation is being performed
-** Notes : -
-*******************************************************************************/
-
-static SK_BOOL
-IsIntModEnabled(SK_AC *pAC) {
- unsigned long CtrCmd;
-
- SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
- if ((CtrCmd & TIM_START) == TIM_START) {
- return SK_TRUE;
- } else {
- return SK_FALSE;
- }
-}
-
-/*******************************************************************************
-** Function : EnableIntMod()
-** Description : Enables the interrupt moderation using the values stored in
-** in the pAC->DynIntMod data structure
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : -
-** Notes : -
-*******************************************************************************/
-
-static void
-EnableIntMod(SK_AC *pAC) {
- unsigned long ModBase;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
- ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
- } else {
- ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
- }
-
- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
- SK_OUT32(pAC->IoBase, B2_IRQM_MSK, pAC->DynIrqModInfo.MaskIrqModeration);
- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
- if (M_DIMINFO.DisplayStats) {
- printk("Enabled interrupt moderation (%i ints/sec)\n",
- M_DIMINFO.MaxModIntsPerSec);
- }
-}
-
-/*******************************************************************************
-** Function : DisableIntMod()
-** Description : Disables the interrupt moderation independent of what inter-
-** rupts are running or not
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : -
-** Notes : -
-*******************************************************************************/
-
-static void
-DisableIntMod(SK_AC *pAC) {
-
- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
- if (M_DIMINFO.DisplayStats) {
- printk("Disabled interrupt moderation\n");
- }
-}
-
-/*******************************************************************************
-** Function : ResizeDimTimerDuration();
-** Description : Checks the current used descriptor ratio and resizes the
-** duration timer (longer/smaller) if possible.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : -
-** Notes : There are both maximum and minimum timer duration value.
-** This function assumes that interrupt moderation is already
-** enabled!
-*******************************************************************************/
-
-static void
-ResizeDimTimerDuration(SK_AC *pAC) {
- SK_BOOL IncreaseTimerDuration;
- int TotalMaxNbrDescr;
- int UsedDescrRatio;
- int RatioDiffAbs;
- int RatioDiffRel;
- int NewMaxModIntsPerSec;
- int ModAdjValue;
- long ModBase;
-
- /*
- ** Check first if we are allowed to perform any modification
- */
- if (IsIntModEnabled(pAC)) {
- if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) {
- return;
- } else {
- if (M_DIMINFO.ModJustEnabled) {
- M_DIMINFO.ModJustEnabled = SK_FALSE;
- return;
- }
- }
- }
-
- /*
- ** If we got until here, we have to evaluate the amount of the
- ** descriptor ratio change...
- */
- TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
- UsedDescrRatio = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr;
-
- if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) {
- RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio);
- RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio;
- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
- IncreaseTimerDuration = SK_FALSE; /* in other words: DECREASE */
- } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) {
- RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
- RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
- IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
- } else {
- RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
- RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
- IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
- }
-
- /*
- ** Now we can determine the change in percent
- */
- if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) {
- ModAdjValue = 1; /* 1% change - maybe some other value in future */
- } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) {
- ModAdjValue = 1; /* 1% change - maybe some other value in future */
- } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) {
- ModAdjValue = 1; /* 1% change - maybe some other value in future */
- } else {
- ModAdjValue = 1; /* 1% change - maybe some other value in future */
- }
-
- if (IncreaseTimerDuration) {
- NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec +
- (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
- } else {
- NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec -
- (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
- }
-
- /*
- ** Check if we exceed boundaries...
- */
- if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) ||
- (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) {
- if (M_DIMINFO.DisplayStats) {
- printk("Cannot change ModTim from %i to %i ints/sec\n",
- M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
- }
- return;
- } else {
- if (M_DIMINFO.DisplayStats) {
- printk("Resized ModTim from %i to %i ints/sec\n",
- M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
- }
- }
-
- M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
- ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
- } else {
- ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
- }
-
- /*
- ** We do not need to touch any other registers
- */
- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
-}
-
-/*******************************************************************************
-** Function : DisplaySelectedModerationType()
-** Description : Displays what type of moderation we have
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : void!
-** Notes : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationType(SK_AC *pAC) {
-
- if (pAC->DynIrqModInfo.DisplayStats) {
- if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
- printk("Static int moderation runs with %i INTS/sec\n",
- pAC->DynIrqModInfo.MaxModIntsPerSec);
- } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
- if (IsIntModEnabled(pAC)) {
- printk("Dynamic int moderation runs with %i INTS/sec\n",
- pAC->DynIrqModInfo.MaxModIntsPerSec);
- } else {
- printk("Dynamic int moderation currently not applied\n");
- }
- } else {
- printk("No interrupt moderation selected!\n");
- }
- }
-}
-
-/*******************************************************************************
-** Function : DisplaySelectedModerationMask()
-** Description : Displays what interrupts are moderated
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : void!
-** Notes : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationMask(SK_AC *pAC) {
-
- if (pAC->DynIrqModInfo.DisplayStats) {
- if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) {
- switch (pAC->DynIrqModInfo.MaskIrqModeration) {
- case IRQ_MASK_TX_ONLY:
- printk("Only Tx-interrupts are moderated\n");
- break;
- case IRQ_MASK_RX_ONLY:
- printk("Only Rx-interrupts are moderated\n");
- break;
- case IRQ_MASK_SP_ONLY:
- printk("Only special-interrupts are moderated\n");
- break;
- case IRQ_MASK_TX_RX:
- printk("Tx- and Rx-interrupts are moderated\n");
- break;
- case IRQ_MASK_SP_RX:
- printk("Special- and Rx-interrupts are moderated\n");
- break;
- case IRQ_MASK_SP_TX:
- printk("Special- and Tx-interrupts are moderated\n");
- break;
- case IRQ_MASK_RX_TX_SP:
- printk("All Rx-, Tx and special-interrupts are moderated\n");
- break;
- default:
- printk("Don't know what is moderated\n");
- break;
- }
- } else {
- printk("No specific interrupts masked for moderation\n");
- }
- }
-}
-
-/*******************************************************************************
-** Function : DisplayDescrRatio
-** Description : Like the name states...
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : void!
-** Notes : -
-*******************************************************************************/
-
-static void
-DisplayDescrRatio(SK_AC *pAC) {
- int TotalMaxNbrDescr = 0;
-
- if (pAC->DynIrqModInfo.DisplayStats) {
- TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
- printk("Ratio descriptors: %i/%i\n",
- M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr);
- }
-}
-
-/*******************************************************************************
-**
-** End of file
-**
-*******************************************************************************/
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
deleted file mode 100644
index 36460694eb8..00000000000
--- a/drivers/net/sk98lin/skethtool.c
+++ /dev/null
@@ -1,628 +0,0 @@
-/******************************************************************************
- *
- * Name: skethtool.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.7 $
- * Date: $Date: 2004/09/29 13:32:07 $
- * Purpose: All functions regarding ethtool handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2004 Marvell.
- *
- * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet
- * Server Adapters.
- *
- * Author: Ralph Roesler (rroesler@syskonnect.de)
- * Mirko Lindner (mlindner@syskonnect.de)
- *
- * Address all question to: linux@syskonnect.de
- *
- * The technical manual for the adapters is available from SysKonnect's
- * web pages: www.syskonnect.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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- *****************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-#include "h/skversion.h"
-
-#include <linux/ethtool.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-
-/******************************************************************************
- *
- * Defines
- *
- *****************************************************************************/
-
-#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
- SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
- SUPPORTED_TP)
-
-#define ADV_COPPER_ALL (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
- ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
- ADVERTISED_TP)
-
-#define SUPP_FIBRE_ALL (SUPPORTED_1000baseT_Full | \
- SUPPORTED_FIBRE | \
- SUPPORTED_Autoneg)
-
-#define ADV_FIBRE_ALL (ADVERTISED_1000baseT_Full | \
- ADVERTISED_FIBRE | \
- ADVERTISED_Autoneg)
-
-
-/******************************************************************************
- *
- * Local Functions
- *
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * getSettings - retrieves the current settings of the selected adapter
- *
- * Description:
- * The current configuration of the selected adapter is returned.
- * This configuration involves a)speed, b)duplex and c)autoneg plus
- * a number of other variables.
- *
- * Returns: always 0
- *
- */
-static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
- const DEV_NET *pNet = netdev_priv(dev);
- int port = pNet->PortNr;
- const SK_AC *pAC = pNet->pAC;
- const SK_GEPORT *pPort = &pAC->GIni.GP[port];
-
- static int DuplexAutoNegConfMap[9][3]= {
- { -1 , -1 , -1 },
- { 0 , -1 , -1 },
- { SK_LMODE_HALF , DUPLEX_HALF, AUTONEG_DISABLE },
- { SK_LMODE_FULL , DUPLEX_FULL, AUTONEG_DISABLE },
- { SK_LMODE_AUTOHALF , DUPLEX_HALF, AUTONEG_ENABLE },
- { SK_LMODE_AUTOFULL , DUPLEX_FULL, AUTONEG_ENABLE },
- { SK_LMODE_AUTOBOTH , DUPLEX_FULL, AUTONEG_ENABLE },
- { SK_LMODE_AUTOSENSE , -1 , -1 },
- { SK_LMODE_INDETERMINATED, -1 , -1 }
- };
- static int SpeedConfMap[6][2] = {
- { 0 , -1 },
- { SK_LSPEED_AUTO , -1 },
- { SK_LSPEED_10MBPS , SPEED_10 },
- { SK_LSPEED_100MBPS , SPEED_100 },
- { SK_LSPEED_1000MBPS , SPEED_1000 },
- { SK_LSPEED_INDETERMINATED, -1 }
- };
- static int AdvSpeedMap[6][2] = {
- { 0 , -1 },
- { SK_LSPEED_AUTO , -1 },
- { SK_LSPEED_10MBPS , ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full },
- { SK_LSPEED_100MBPS , ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full },
- { SK_LSPEED_1000MBPS , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
- { SK_LSPEED_INDETERMINATED, -1 }
- };
-
- ecmd->phy_address = port;
- ecmd->speed = SpeedConfMap[pPort->PLinkSpeedUsed][1];
- ecmd->duplex = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
- ecmd->autoneg = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
- ecmd->transceiver = XCVR_INTERNAL;
-
- if (pAC->GIni.GICopperType) {
- ecmd->port = PORT_TP;
- ecmd->supported = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
- if (pAC->GIni.GIGenesis) {
- ecmd->supported &= ~(SUPPORTED_10baseT_Half);
- ecmd->supported &= ~(SUPPORTED_10baseT_Full);
- ecmd->supported &= ~(SUPPORTED_100baseT_Half);
- ecmd->supported &= ~(SUPPORTED_100baseT_Full);
- } else {
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
- ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
- }
-#ifdef CHIP_ID_YUKON_FE
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
- ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
- ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
- }
-#endif
- }
- if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
- ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
- ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
- }
- } else {
- ecmd->advertising = ecmd->supported;
- }
-
- if (ecmd->autoneg == AUTONEG_ENABLE)
- ecmd->advertising |= ADVERTISED_Autoneg;
- } else {
- ecmd->port = PORT_FIBRE;
- ecmd->supported = SUPP_FIBRE_ALL;
- ecmd->advertising = ADV_FIBRE_ALL;
- }
- return 0;
-}
-
-/*
- * MIB infrastructure uses instance value starting at 1
- * based on board and port.
- */
-static inline u32 pnmiInstance(const DEV_NET *pNet)
-{
- return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr;
-}
-
-/*****************************************************************************
- *
- * setSettings - configures the settings of a selected adapter
- *
- * Description:
- * Possible settings that may be altered are a)speed, b)duplex or
- * c)autonegotiation.
- *
- * Returns:
- * 0: everything fine, no error
- * <0: the return value is the error code of the failure
- */
-static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- u32 instance;
- char buf[4];
- int len = 1;
-
- if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100
- && ecmd->speed != SPEED_1000)
- return -EINVAL;
-
- if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
- return -EINVAL;
-
- if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
- return -EINVAL;
-
- if (ecmd->autoneg == AUTONEG_DISABLE)
- *buf = (ecmd->duplex == DUPLEX_FULL)
- ? SK_LMODE_FULL : SK_LMODE_HALF;
- else
- *buf = (ecmd->duplex == DUPLEX_FULL)
- ? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF;
-
- instance = pnmiInstance(pNet);
- if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE,
- &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
- return -EINVAL;
-
- switch(ecmd->speed) {
- case SPEED_1000:
- *buf = SK_LSPEED_1000MBPS;
- break;
- case SPEED_100:
- *buf = SK_LSPEED_100MBPS;
- break;
- case SPEED_10:
- *buf = SK_LSPEED_10MBPS;
- }
-
- if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
- &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
- return -EINVAL;
-
- return 0;
-}
-
-/*****************************************************************************
- *
- * getDriverInfo - returns generic driver and adapter information
- *
- * Description:
- * Generic driver information is returned via this function, such as
- * the name of the driver, its version and and firmware version.
- * In addition to this, the location of the selected adapter is
- * returned as a bus info string (e.g. '01:05.0').
- *
- * Returns: N/A
- *
- */
-static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- const DEV_NET *pNet = netdev_priv(dev);
- const SK_AC *pAC = pNet->pAC;
- char vers[32];
-
- snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)",
- (pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf);
-
- strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
- strcpy(info->version, vers);
- strcpy(info->fw_version, "N/A");
- strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
-}
-
-/*
- * Ethtool statistics support.
- */
-static const char StringsStats[][ETH_GSTRING_LEN] = {
- "rx_packets", "tx_packets",
- "rx_bytes", "tx_bytes",
- "rx_errors", "tx_errors",
- "rx_dropped", "tx_dropped",
- "multicasts", "collisions",
- "rx_length_errors", "rx_buffer_overflow_errors",
- "rx_crc_errors", "rx_frame_errors",
- "rx_too_short_errors", "rx_too_long_errors",
- "rx_carrier_extension_errors", "rx_symbol_errors",
- "rx_llc_mac_size_errors", "rx_carrier_errors",
- "rx_jabber_errors", "rx_missed_errors",
- "tx_abort_collision_errors", "tx_carrier_errors",
- "tx_buffer_underrun_errors", "tx_heartbeat_errors",
- "tx_window_errors",
-};
-
-static int getStatsCount(struct net_device *dev)
-{
- return ARRAY_SIZE(StringsStats);
-}
-
-static void getStrings(struct net_device *dev, u32 stringset, u8 *data)
-{
- switch(stringset) {
- case ETH_SS_STATS:
- memcpy(data, *StringsStats, sizeof(StringsStats));
- break;
- }
-}
-
-static void getEthtoolStats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
-{
- const DEV_NET *pNet = netdev_priv(dev);
- const SK_AC *pAC = pNet->pAC;
- const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
-
- *data++ = pPnmiStruct->Stat[0].StatRxOkCts;
- *data++ = pPnmiStruct->Stat[0].StatTxOkCts;
- *data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts;
- *data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts;
- *data++ = pPnmiStruct->InErrorsCts;
- *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
- *data++ = pPnmiStruct->RxNoBufCts;
- *data++ = pPnmiStruct->TxNoBufCts;
- *data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts;
- *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
- *data++ = pPnmiStruct->Stat[0].StatRxRuntCts;
- *data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts;
- *data++ = pPnmiStruct->Stat[0].StatRxFcsCts;
- *data++ = pPnmiStruct->Stat[0].StatRxFramingCts;
- *data++ = pPnmiStruct->Stat[0].StatRxShortsCts;
- *data++ = pPnmiStruct->Stat[0].StatRxTooLongCts;
- *data++ = pPnmiStruct->Stat[0].StatRxCextCts;
- *data++ = pPnmiStruct->Stat[0].StatRxSymbolCts;
- *data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts;
- *data++ = pPnmiStruct->Stat[0].StatRxCarrierCts;
- *data++ = pPnmiStruct->Stat[0].StatRxJabberCts;
- *data++ = pPnmiStruct->Stat[0].StatRxMissedCts;
- *data++ = pAC->stats.tx_aborted_errors;
- *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
- *data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts;
- *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
- *data++ = pAC->stats.tx_window_errors;
-}
-
-
-/*****************************************************************************
- *
- * toggleLeds - Changes the LED state of an adapter
- *
- * Description:
- * This function changes the current state of all LEDs of an adapter so
- * that it can be located by a user.
- *
- * Returns: N/A
- *
- */
-static void toggleLeds(DEV_NET *pNet, int on)
-{
- SK_AC *pAC = pNet->pAC;
- int port = pNet->PortNr;
- void __iomem *io = pAC->IoBase;
-
- if (pAC->GIni.GIGenesis) {
- SK_OUT8(io, MR_ADDR(port,LNK_LED_REG),
- on ? SK_LNK_ON : SK_LNK_OFF);
- SkGeYellowLED(pAC, io,
- on ? (LED_ON >> 1) : (LED_OFF >> 1));
- SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI),
- on ? SK_LED_TST : SK_LED_DIS);
-
- if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM)
- SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL,
- on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF);
- else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE)
- SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG,
- on ? 0x0800 : PHY_L_LC_LEDT);
- else
- SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI),
- on ? SK_LED_TST : SK_LED_DIS);
- } else {
- const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON) |
- PHY_M_LED_MO_10(MO_LED_ON) |
- PHY_M_LED_MO_100(MO_LED_ON) |
- PHY_M_LED_MO_1000(MO_LED_ON) |
- PHY_M_LED_MO_RX(MO_LED_ON));
- const u16 YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF) |
- PHY_M_LED_MO_10(MO_LED_OFF) |
- PHY_M_LED_MO_100(MO_LED_OFF) |
- PHY_M_LED_MO_1000(MO_LED_OFF) |
- PHY_M_LED_MO_RX(MO_LED_OFF));
-
-
- SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0);
- SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER,
- on ? YukLedOn : YukLedOff);
- }
-}
-
-/*****************************************************************************
- *
- * skGeBlinkTimer - Changes the LED state of an adapter
- *
- * Description:
- * This function changes the current state of all LEDs of an adapter so
- * that it can be located by a user. If the requested time interval for
- * this test has elapsed, this function cleans up everything that was
- * temporarily setup during the locate NIC test. This involves of course
- * also closing or opening any adapter so that the initial board state
- * is recovered.
- *
- * Returns: N/A
- *
- */
-void SkGeBlinkTimer(unsigned long data)
-{
- struct net_device *dev = (struct net_device *) data;
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- toggleLeds(pNet, pAC->LedsOn);
-
- pAC->LedsOn = !pAC->LedsOn;
- mod_timer(&pAC->BlinkTimer, jiffies + HZ/4);
-}
-
-/*****************************************************************************
- *
- * locateDevice - start the locate NIC feature of the elected adapter
- *
- * Description:
- * This function is used if the user want to locate a particular NIC.
- * All LEDs are regularly switched on and off, so the NIC can easily
- * be identified.
- *
- * Returns:
- * ==0: everything fine, no error, locateNIC test was started
- * !=0: one locateNIC test runs already
- *
- */
-static int locateDevice(struct net_device *dev, u32 data)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
- data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
-
- /* start blinking */
- pAC->LedsOn = 0;
- mod_timer(&pAC->BlinkTimer, jiffies);
- msleep_interruptible(data * 1000);
- del_timer_sync(&pAC->BlinkTimer);
- toggleLeds(pNet, 0);
-
- return 0;
-}
-
-/*****************************************************************************
- *
- * getPauseParams - retrieves the pause parameters
- *
- * Description:
- * All current pause parameters of a selected adapter are placed
- * in the passed ethtool_pauseparam structure and are returned.
- *
- * Returns: N/A
- *
- */
-static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
-
- epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
- (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM);
-
- epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND);
- epause->autoneg = epause->rx_pause || epause->tx_pause;
-}
-
-/*****************************************************************************
- *
- * setPauseParams - configures the pause parameters of an adapter
- *
- * Description:
- * This function sets the Rx or Tx pause parameters
- *
- * Returns:
- * ==0: everything fine, no error
- * !=0: the return value is the error code of the failure
- */
-static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
- u32 instance = pnmiInstance(pNet);
- struct ethtool_pauseparam old;
- u8 oldspeed = pPort->PLinkSpeedUsed;
- char buf[4];
- int len = 1;
- int ret;
-
- /*
- ** we have to determine the current settings to see if
- ** the operator requested any modification of the flow
- ** control parameters...
- */
- getPauseParams(dev, &old);
-
- /*
- ** perform modifications regarding the changes
- ** requested by the operator
- */
- if (epause->autoneg != old.autoneg)
- *buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC;
- else {
- if (epause->rx_pause && epause->tx_pause)
- *buf = SK_FLOW_MODE_SYMMETRIC;
- else if (epause->rx_pause && !epause->tx_pause)
- *buf = SK_FLOW_MODE_SYM_OR_REM;
- else if (!epause->rx_pause && epause->tx_pause)
- *buf = SK_FLOW_MODE_LOC_SEND;
- else
- *buf = SK_FLOW_MODE_NONE;
- }
-
- ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
- &buf, &len, instance, pNet->NetNr);
-
- if (ret != SK_PNMI_ERR_OK) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
- ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret));
- goto err;
- }
-
- /*
- ** It may be that autoneg has been disabled! Therefore
- ** set the speed to the previously used value...
- */
- if (!epause->autoneg) {
- len = 1;
- ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
- &oldspeed, &len, instance, pNet->NetNr);
- if (ret != SK_PNMI_ERR_OK)
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
- ("ethtool (sk98lin): error setting speed (%i)\n", ret));
- }
- err:
- return ret ? -EIO : 0;
-}
-
-/* Only Yukon supports checksum offload. */
-static int setScatterGather(struct net_device *dev, u32 data)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
- return -EOPNOTSUPP;
- return ethtool_op_set_sg(dev, data);
-}
-
-static int setTxCsum(struct net_device *dev, u32 data)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
- return -EOPNOTSUPP;
-
- return ethtool_op_set_tx_csum(dev, data);
-}
-
-static u32 getRxCsum(struct net_device *dev)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- return pAC->RxPort[pNet->PortNr].RxCsum;
-}
-
-static int setRxCsum(struct net_device *dev, u32 data)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
- return -EOPNOTSUPP;
-
- pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
- return 0;
-}
-
-static int getRegsLen(struct net_device *dev)
-{
- return 0x4000;
-}
-
-/*
- * Returns copy of whole control register region
- * Note: skip RAM address register because accessing it will
- * cause bus hangs!
- */
-static void getRegs(struct net_device *dev, struct ethtool_regs *regs,
- void *p)
-{
- DEV_NET *pNet = netdev_priv(dev);
- const void __iomem *io = pNet->pAC->IoBase;
-
- regs->version = 1;
- memset(p, 0, regs->len);
- memcpy_fromio(p, io, B3_RAM_ADDR);
-
- memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
- regs->len - B3_RI_WTO_R1);
-}
-
-const struct ethtool_ops SkGeEthtoolOps = {
- .get_settings = getSettings,
- .set_settings = setSettings,
- .get_drvinfo = getDriverInfo,
- .get_strings = getStrings,
- .get_stats_count = getStatsCount,
- .get_ethtool_stats = getEthtoolStats,
- .phys_id = locateDevice,
- .get_pauseparam = getPauseParams,
- .set_pauseparam = setPauseParams,
- .get_link = ethtool_op_get_link,
- .get_perm_addr = ethtool_op_get_perm_addr,
- .get_sg = ethtool_op_get_sg,
- .set_sg = setScatterGather,
- .get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = setTxCsum,
- .get_rx_csum = getRxCsum,
- .set_rx_csum = setRxCsum,
- .get_regs = getRegs,
- .get_regs_len = getRegsLen,
-};
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
deleted file mode 100644
index bf218621db1..00000000000
--- a/drivers/net/sk98lin/skge.c
+++ /dev/null
@@ -1,5211 +0,0 @@
-/******************************************************************************
- *
- * Name: skge.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.45 $
- * Date: $Date: 2004/02/12 14:41:02 $
- * Purpose: The main driver source module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet
- * Server Adapters.
- *
- * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
- * SysKonnects GEnesis Solaris driver
- * Author: Christoph Goos (cgoos@syskonnect.de)
- * Mirko Lindner (mlindner@syskonnect.de)
- *
- * Address all question to: linux@syskonnect.de
- *
- * The technical manual for the adapters is available from SysKonnect's
- * web pages: www.syskonnect.com
- * Goto "Support" and search Knowledge Base for "manual".
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Possible compiler options (#define xxx / -Dxxx):
- *
- * debugging can be enable by changing SK_DEBUG_CHKMOD and
- * SK_DEBUG_CHKCAT in makefile (described there).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the main module of the Linux GE driver.
- *
- * All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h
- * are part of SysKonnect's COMMON MODULES for the SK-98xx adapters.
- * Those are used for drivers on multiple OS', so some thing may seem
- * unnecessary complicated on Linux. Please do not try to 'clean up'
- * them without VERY good reasons, because this will make it more
- * difficult to keep the Linux driver in synchronisation with the
- * other versions.
- *
- * Include file hierarchy:
- *
- * <linux/module.h>
- *
- * "h/skdrv1st.h"
- * <linux/types.h>
- * <linux/kernel.h>
- * <linux/string.h>
- * <linux/errno.h>
- * <linux/ioport.h>
- * <linux/slab.h>
- * <linux/interrupt.h>
- * <linux/pci.h>
- * <linux/bitops.h>
- * <asm/byteorder.h>
- * <asm/io.h>
- * <linux/netdevice.h>
- * <linux/etherdevice.h>
- * <linux/skbuff.h>
- * those three depending on kernel version used:
- * <linux/bios32.h>
- * <linux/init.h>
- * <asm/uaccess.h>
- * <net/checksum.h>
- *
- * "h/skerror.h"
- * "h/skdebug.h"
- * "h/sktypes.h"
- * "h/lm80.h"
- * "h/xmac_ii.h"
- *
- * "h/skdrv2nd.h"
- * "h/skqueue.h"
- * "h/skgehwt.h"
- * "h/sktimer.h"
- * "h/ski2c.h"
- * "h/skgepnmi.h"
- * "h/skvpd.h"
- * "h/skgehw.h"
- * "h/skgeinit.h"
- * "h/skaddr.h"
- * "h/skgesirq.h"
- * "h/skrlmt.h"
- *
- ******************************************************************************/
-
-#include "h/skversion.h"
-
-#include <linux/in.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/ip.h>
-#include <linux/mii.h>
-#include <linux/mm.h>
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/*******************************************************************************
- *
- * Defines
- *
- ******************************************************************************/
-
-/* for debuging on x86 only */
-/* #define BREAKPOINT() asm(" int $3"); */
-
-/* use the transmit hw checksum driver functionality */
-#define USE_SK_TX_CHECKSUM
-
-/* use the receive hw checksum driver functionality */
-#define USE_SK_RX_CHECKSUM
-
-/* use the scatter-gather functionality with sendfile() */
-#define SK_ZEROCOPY
-
-/* use of a transmit complete interrupt */
-#define USE_TX_COMPLETE
-
-/*
- * threshold for copying small receive frames
- * set to 0 to avoid copying, set to 9001 to copy all frames
- */
-#define SK_COPY_THRESHOLD 50
-
-/* number of adapters that can be configured via command line params */
-#define SK_MAX_CARD_PARAM 16
-
-
-
-/*
- * use those defines for a compile-in version of the driver instead
- * of command line parameters
- */
-// #define LINK_SPEED_A {"Auto", }
-// #define LINK_SPEED_B {"Auto", }
-// #define AUTO_NEG_A {"Sense", }
-// #define AUTO_NEG_B {"Sense", }
-// #define DUP_CAP_A {"Both", }
-// #define DUP_CAP_B {"Both", }
-// #define FLOW_CTRL_A {"SymOrRem", }
-// #define FLOW_CTRL_B {"SymOrRem", }
-// #define ROLE_A {"Auto", }
-// #define ROLE_B {"Auto", }
-// #define PREF_PORT {"A", }
-// #define CON_TYPE {"Auto", }
-// #define RLMT_MODE {"CheckLinkState", }
-
-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
-#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
-#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
-
-
-/* Set blink mode*/
-#define OEM_CONFIG_VALUE ( SK_ACT_LED_BLINK | \
- SK_DUP_LED_NORMAL | \
- SK_LED_LINK100_ON)
-
-
-/* Isr return value */
-#define SkIsrRetVar irqreturn_t
-#define SkIsrRetNone IRQ_NONE
-#define SkIsrRetHandled IRQ_HANDLED
-
-
-/*******************************************************************************
- *
- * Local Function Prototypes
- *
- ******************************************************************************/
-
-static void FreeResources(struct SK_NET_DEVICE *dev);
-static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
-static SK_BOOL BoardAllocMem(SK_AC *pAC);
-static void BoardFreeMem(SK_AC *pAC);
-static void BoardInitMem(SK_AC *pAC);
-static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
-static SkIsrRetVar SkGeIsr(int irq, void *dev_id);
-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id);
-static int SkGeOpen(struct SK_NET_DEVICE *dev);
-static int SkGeClose(struct SK_NET_DEVICE *dev);
-static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev);
-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
-static void GetConfiguration(SK_AC*);
-static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
-static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
-static void FillRxRing(SK_AC*, RX_PORT*);
-static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*);
-static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
-static void ClearAndStartRx(SK_AC*, int);
-static void ClearTxIrq(SK_AC*, int, int);
-static void ClearRxRing(SK_AC*, RX_PORT*);
-static void ClearTxRing(SK_AC*, TX_PORT*);
-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
-static void PortReInitBmu(SK_AC*, int);
-static int SkGeIocMib(DEV_NET*, unsigned int, int);
-static int SkGeInitPCI(SK_AC *pAC);
-static void StartDrvCleanupTimer(SK_AC *pAC);
-static void StopDrvCleanupTimer(SK_AC *pAC);
-static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
-
-#ifdef SK_DIAG_SUPPORT
-static SK_U32 ParseDeviceNbrFromSlotName(const char *SlotName);
-static int SkDrvInitAdapter(SK_AC *pAC, int devNbr);
-static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
-#endif
-
-/*******************************************************************************
- *
- * Extern Function Prototypes
- *
- ******************************************************************************/
-extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);
-extern void SkDimDisplayModerationSettings(SK_AC *pAC);
-extern void SkDimStartModerationTimer(SK_AC *pAC);
-extern void SkDimModerate(SK_AC *pAC);
-extern void SkGeBlinkTimer(unsigned long data);
-
-#ifdef DEBUG
-static void DumpMsg(struct sk_buff*, char*);
-static void DumpData(char*, int);
-static void DumpLong(char*, int);
-#endif
-
-/* global variables *********************************************************/
-static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
-extern const struct ethtool_ops SkGeEthtoolOps;
-
-/* local variables **********************************************************/
-static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
-static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
-
-/*****************************************************************************
- *
- * SkPciWriteCfgDWord - write a 32 bit value to pci config space
- *
- * Description:
- * This routine writes a 32 bit value to the pci configuration
- * space.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-static inline int SkPciWriteCfgDWord(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U32 Val) /* pointer to store the read value */
-{
- pci_write_config_dword(pAC->PciDev, PciAddr, Val);
- return(0);
-} /* SkPciWriteCfgDWord */
-
-/*****************************************************************************
- *
- * SkGeInitPCI - Init the PCI resources
- *
- * Description:
- * This function initialize the PCI resources and IO
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-static __devinit int SkGeInitPCI(SK_AC *pAC)
-{
- struct SK_NET_DEVICE *dev = pAC->dev[0];
- struct pci_dev *pdev = pAC->PciDev;
- int retval;
-
- dev->mem_start = pci_resource_start (pdev, 0);
- pci_set_master(pdev);
-
- retval = pci_request_regions(pdev, "sk98lin");
- if (retval)
- goto out;
-
-#ifdef SK_BIG_ENDIAN
- /*
- * On big endian machines, we use the adapter's aibility of
- * reading the descriptors as big endian.
- */
- {
- SK_U32 our2;
- SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
- our2 |= PCI_REV_DESC;
- SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
- }
-#endif
-
- /*
- * Remap the regs into kernel space.
- */
- pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
- if (!pAC->IoBase) {
- retval = -EIO;
- goto out_release;
- }
-
- return 0;
-
- out_release:
- pci_release_regions(pdev);
- out:
- return retval;
-}
-
-
-/*****************************************************************************
- *
- * FreeResources - release resources allocated for adapter
- *
- * Description:
- * This function releases the IRQ, unmaps the IO and
- * frees the desriptor ring.
- *
- * Returns: N/A
- *
- */
-static void FreeResources(struct SK_NET_DEVICE *dev)
-{
-SK_U32 AllocFlag;
-DEV_NET *pNet;
-SK_AC *pAC;
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
- AllocFlag = pAC->AllocFlag;
- if (pAC->PciDev) {
- pci_release_regions(pAC->PciDev);
- }
- if (AllocFlag & SK_ALLOC_IRQ) {
- free_irq(dev->irq, dev);
- }
- if (pAC->IoBase) {
- iounmap(pAC->IoBase);
- }
- if (pAC->pDescrMem) {
- BoardFreeMem(pAC);
- }
-
-} /* FreeResources */
-
-MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
-MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
-MODULE_LICENSE("GPL");
-
-#ifdef LINK_SPEED_A
-static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
-#else
-static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef LINK_SPEED_B
-static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
-#else
-static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef AUTO_NEG_A
-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
-#else
-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_A
-static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A;
-#else
-static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_A
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A;
-#else
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_A
-static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A;
-#else
-static char *Role_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef AUTO_NEG_B
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B;
-#else
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_B
-static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B;
-#else
-static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_B
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B;
-#else
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_B
-static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;
-#else
-static char *Role_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef CON_TYPE
-static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE;
-#else
-static char *ConType[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef PREF_PORT
-static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;
-#else
-static char *PrefPort[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef RLMT_MODE
-static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
-#else
-static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-static int IntsPerSec[SK_MAX_CARD_PARAM];
-static char *Moderation[SK_MAX_CARD_PARAM];
-static char *ModerationMask[SK_MAX_CARD_PARAM];
-static char *AutoSizing[SK_MAX_CARD_PARAM];
-static char *Stats[SK_MAX_CARD_PARAM];
-
-module_param_array(Speed_A, charp, NULL, 0);
-module_param_array(Speed_B, charp, NULL, 0);
-module_param_array(AutoNeg_A, charp, NULL, 0);
-module_param_array(AutoNeg_B, charp, NULL, 0);
-module_param_array(DupCap_A, charp, NULL, 0);
-module_param_array(DupCap_B, charp, NULL, 0);
-module_param_array(FlowCtrl_A, charp, NULL, 0);
-module_param_array(FlowCtrl_B, charp, NULL, 0);
-module_param_array(Role_A, charp, NULL, 0);
-module_param_array(Role_B, charp, NULL, 0);
-module_param_array(ConType, charp, NULL, 0);
-module_param_array(PrefPort, charp, NULL, 0);
-module_param_array(RlmtMode, charp, NULL, 0);
-/* used for interrupt moderation */
-module_param_array(IntsPerSec, int, NULL, 0);
-module_param_array(Moderation, charp, NULL, 0);
-module_param_array(Stats, charp, NULL, 0);
-module_param_array(ModerationMask, charp, NULL, 0);
-module_param_array(AutoSizing, charp, NULL, 0);
-
-/*****************************************************************************
- *
- * SkGeBoardInit - do level 0 and 1 initialization
- *
- * Description:
- * This function prepares the board hardware for running. The desriptor
- * ring is set up, the IRQ is allocated and the configuration settings
- * are examined.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
-{
-short i;
-unsigned long Flags;
-char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
-char *VerStr = VER_STRING;
-int Ret; /* return code of request_irq */
-SK_BOOL DualNet;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
- for (i=0; i<SK_MAX_MACS; i++) {
- pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0];
- pAC->TxPort[i][0].PortIndex = i;
- pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i];
- pAC->RxPort[i].PortIndex = i;
- }
-
- /* Initialize the mutexes */
- for (i=0; i<SK_MAX_MACS; i++) {
- spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
- spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
- }
- spin_lock_init(&pAC->SlowPathLock);
-
- /* setup phy_id blink timer */
- pAC->BlinkTimer.function = SkGeBlinkTimer;
- pAC->BlinkTimer.data = (unsigned long) dev;
- init_timer(&pAC->BlinkTimer);
-
- /* level 0 init common modules here */
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- /* Does a RESET on board ...*/
- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
- printk("HWInit (0) failed.\n");
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return -EIO;
- }
- SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA);
- SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA);
- SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA);
- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA);
- SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
-
- pAC->BoardLevel = SK_INIT_DATA;
- pAC->RxBufSize = ETH_BUF_SIZE;
-
- SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
- SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
-
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- /* level 1 init common modules here (HW init) */
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
- printk("sk98lin: HWInit (1) failed.\n");
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return -EIO;
- }
- SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
-
- /* Set chipset type support */
- pAC->ChipsetType = 0;
- if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
- (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) {
- pAC->ChipsetType = 1;
- }
-
- GetConfiguration(pAC);
- if (pAC->RlmtNets == 2) {
- pAC->GIni.GIPortUsage = SK_MUL_LINK;
- }
-
- pAC->BoardLevel = SK_INIT_IO;
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- if (pAC->GIni.GIMacsFound == 2) {
- Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
- } else if (pAC->GIni.GIMacsFound == 1) {
- Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED,
- "sk98lin", dev);
- } else {
- printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
- pAC->GIni.GIMacsFound);
- return -EIO;
- }
-
- if (Ret) {
- printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
- dev->irq);
- return Ret;
- }
- pAC->AllocFlag |= SK_ALLOC_IRQ;
-
- /* Alloc memory for this board (Mem for RxD/TxD) : */
- if(!BoardAllocMem(pAC)) {
- printk("No memory for descriptor rings.\n");
- return -ENOMEM;
- }
-
- BoardInitMem(pAC);
- /* tschilling: New common function with minimum size check. */
- DualNet = SK_FALSE;
- if (pAC->RlmtNets == 2) {
- DualNet = SK_TRUE;
- }
-
- if (SkGeInitAssignRamToQueues(
- pAC,
- pAC->ActivePort,
- DualNet)) {
- BoardFreeMem(pAC);
- printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
- return -EIO;
- }
-
- return (0);
-} /* SkGeBoardInit */
-
-
-/*****************************************************************************
- *
- * BoardAllocMem - allocate the memory for the descriptor rings
- *
- * Description:
- * This function allocates the memory for all descriptor rings.
- * Each ring is aligned for the desriptor alignment and no ring
- * has a 4 GByte boundary in it (because the upper 32 bit must
- * be constant for all descriptiors in one rings).
- *
- * Returns:
- * SK_TRUE, if all memory could be allocated
- * SK_FALSE, if not
- */
-static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC)
-{
-caddr_t pDescrMem; /* pointer to descriptor memory area */
-size_t AllocLength; /* length of complete descriptor area */
-int i; /* loop counter */
-unsigned long BusAddr;
-
-
- /* rings plus one for alignment (do not cross 4 GB boundary) */
- /* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */
-#if (BITS_PER_LONG == 32)
- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
- + RX_RING_SIZE + 8;
-#endif
-
- pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
- &pAC->pDescrMemDMA);
-
- if (pDescrMem == NULL) {
- return (SK_FALSE);
- }
- pAC->pDescrMem = pDescrMem;
- BusAddr = (unsigned long) pAC->pDescrMemDMA;
-
- /* Descriptors need 8 byte alignment, and this is ensured
- * by pci_alloc_consistent.
- */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
- ("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n",
- i, (unsigned long) pDescrMem,
- BusAddr));
- pAC->TxPort[i][0].pTxDescrRing = pDescrMem;
- pAC->TxPort[i][0].VTxDescrRing = BusAddr;
- pDescrMem += TX_RING_SIZE;
- BusAddr += TX_RING_SIZE;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
- ("RX%d: pDescrMem: %lX, PhysDescrMem: %lX\n",
- i, (unsigned long) pDescrMem,
- (unsigned long)BusAddr));
- pAC->RxPort[i].pRxDescrRing = pDescrMem;
- pAC->RxPort[i].VRxDescrRing = BusAddr;
- pDescrMem += RX_RING_SIZE;
- BusAddr += RX_RING_SIZE;
- } /* for */
-
- return (SK_TRUE);
-} /* BoardAllocMem */
-
-
-/****************************************************************************
- *
- * BoardFreeMem - reverse of BoardAllocMem
- *
- * Description:
- * Free all memory allocated in BoardAllocMem: adapter context,
- * descriptor rings, locks.
- *
- * Returns: N/A
- */
-static void BoardFreeMem(
-SK_AC *pAC)
-{
-size_t AllocLength; /* length of complete descriptor area */
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("BoardFreeMem\n"));
-#if (BITS_PER_LONG == 32)
- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
- + RX_RING_SIZE + 8;
-#endif
-
- pci_free_consistent(pAC->PciDev, AllocLength,
- pAC->pDescrMem, pAC->pDescrMemDMA);
- pAC->pDescrMem = NULL;
-} /* BoardFreeMem */
-
-
-/*****************************************************************************
- *
- * BoardInitMem - initiate the descriptor rings
- *
- * Description:
- * This function sets the descriptor rings up in memory.
- * The adapter is initialized with the descriptor start addresses.
- *
- * Returns: N/A
- */
-static __devinit void BoardInitMem(SK_AC *pAC)
-{
-int i; /* loop counter */
-int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/
-int TxDescrSize; /* the size of a tx descriptor rounded up to alignment*/
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("BoardInitMem\n"));
-
- RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
- pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
- TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
- pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
-
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- SetupRing(
- pAC,
- pAC->TxPort[i][0].pTxDescrRing,
- pAC->TxPort[i][0].VTxDescrRing,
- (RXD**)&pAC->TxPort[i][0].pTxdRingHead,
- (RXD**)&pAC->TxPort[i][0].pTxdRingTail,
- (RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
- &pAC->TxPort[i][0].TxdRingFree,
- SK_TRUE);
- SetupRing(
- pAC,
- pAC->RxPort[i].pRxDescrRing,
- pAC->RxPort[i].VRxDescrRing,
- &pAC->RxPort[i].pRxdRingHead,
- &pAC->RxPort[i].pRxdRingTail,
- &pAC->RxPort[i].pRxdRingPrev,
- &pAC->RxPort[i].RxdRingFree,
- SK_FALSE);
- }
-} /* BoardInitMem */
-
-
-/*****************************************************************************
- *
- * SetupRing - create one descriptor ring
- *
- * Description:
- * This function creates one descriptor ring in the given memory area.
- * The head, tail and number of free descriptors in the ring are set.
- *
- * Returns:
- * none
- */
-static void SetupRing(
-SK_AC *pAC,
-void *pMemArea, /* a pointer to the memory area for the ring */
-uintptr_t VMemArea, /* the virtual bus address of the memory area */
-RXD **ppRingHead, /* address where the head should be written */
-RXD **ppRingTail, /* address where the tail should be written */
-RXD **ppRingPrev, /* address where the tail should be written */
-int *pRingFree, /* address where the # of free descr. goes */
-SK_BOOL IsTx) /* flag: is this a tx ring */
-{
-int i; /* loop counter */
-int DescrSize; /* the size of a descriptor rounded up to alignment*/
-int DescrNum; /* number of descriptors per ring */
-RXD *pDescr; /* pointer to a descriptor (receive or transmit) */
-RXD *pNextDescr; /* pointer to the next descriptor */
-RXD *pPrevDescr; /* pointer to the previous descriptor */
-uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */
-
- if (IsTx == SK_TRUE) {
- DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
- DESCR_ALIGN;
- DescrNum = TX_RING_SIZE / DescrSize;
- } else {
- DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
- DESCR_ALIGN;
- DescrNum = RX_RING_SIZE / DescrSize;
- }
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
- ("Descriptor size: %d Descriptor Number: %d\n",
- DescrSize,DescrNum));
-
- pDescr = (RXD*) pMemArea;
- pPrevDescr = NULL;
- pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
- VNextDescr = VMemArea + DescrSize;
- for(i=0; i<DescrNum; i++) {
- /* set the pointers right */
- pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
- pDescr->pNextRxd = pNextDescr;
- if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN;
-
- /* advance one step */
- pPrevDescr = pDescr;
- pDescr = pNextDescr;
- pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
- VNextDescr += DescrSize;
- }
- pPrevDescr->pNextRxd = (RXD*) pMemArea;
- pPrevDescr->VNextRxd = VMemArea;
- pDescr = (RXD*) pMemArea;
- *ppRingHead = (RXD*) pMemArea;
- *ppRingTail = *ppRingHead;
- *ppRingPrev = pPrevDescr;
- *pRingFree = DescrNum;
-} /* SetupRing */
-
-
-/*****************************************************************************
- *
- * PortReInitBmu - re-initiate the descriptor rings for one port
- *
- * Description:
- * This function reinitializes the descriptor rings of one port
- * in memory. The port must be stopped before.
- * The HW is initialized with the descriptor start addresses.
- *
- * Returns:
- * none
- */
-static void PortReInitBmu(
-SK_AC *pAC, /* pointer to adapter context */
-int PortIndex) /* index of the port for which to re-init */
-{
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("PortReInitBmu "));
-
- /* set address of first descriptor of ring in BMU */
- SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L,
- (uint32_t)(((caddr_t)
- (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
- pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
- pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &
- 0xFFFFFFFF));
- SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H,
- (uint32_t)(((caddr_t)
- (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
- pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
- pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));
- SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L,
- (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
- pAC->RxPort[PortIndex].pRxDescrRing +
- pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));
- SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H,
- (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
- pAC->RxPort[PortIndex].pRxDescrRing +
- pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
-} /* PortReInitBmu */
-
-
-/****************************************************************************
- *
- * SkGeIsr - handle adapter interrupts
- *
- * Description:
- * The interrupt routine is called when the network adapter
- * generates an interrupt. It may also be called if another device
- * shares this interrupt vector with the driver.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsr(int irq, void *dev_id)
-{
-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
-DEV_NET *pNet;
-SK_AC *pAC;
-SK_U32 IntSrc; /* interrupts source register contents */
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- /*
- * Check and process if its our interrupt
- */
- SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
- if (IntSrc == 0) {
- return SkIsrRetNone;
- }
-
- while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
- if (IntSrc & IS_IRQ_SW) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("Software IRQ\n"));
- }
-#endif
- if (IntSrc & IS_R1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF RX1 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
- SK_PNMI_CNT_RX_INTR(pAC, 0);
- }
- if (IntSrc & IS_R2_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF RX2 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
- SK_PNMI_CNT_RX_INTR(pAC, 1);
- }
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IS_XA1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF AS TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 0);
- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- }
- if (IntSrc & IS_XA2_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF AS TX2 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 1);
- spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
- }
-#if 0 /* only if sync. queues used */
- if (IntSrc & IS_XS1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF SY TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 1);
- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
- }
- if (IntSrc & IS_XS2_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF SY TX2 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 1);
- spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
- ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
- }
-#endif
-#endif
-
- /* do all IO at once */
- if (IntSrc & IS_R1_F)
- ClearAndStartRx(pAC, 0);
- if (IntSrc & IS_R2_F)
- ClearAndStartRx(pAC, 1);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IS_XA1_F)
- ClearTxIrq(pAC, 0, TX_PRIO_LOW);
- if (IntSrc & IS_XA2_F)
- ClearTxIrq(pAC, 1, TX_PRIO_LOW);
-#endif
- SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
- } /* while (IntSrc & IRQ_MASK != 0) */
-
- IntSrc &= pAC->GIni.GIValIrqMask;
- if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
- ("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
- pAC->CheckQueue = SK_FALSE;
- spin_lock(&pAC->SlowPathLock);
- if (IntSrc & SPECIAL_IRQS)
- SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
-
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock(&pAC->SlowPathLock);
- }
- /*
- * do it all again is case we cleared an interrupt that
- * came in after handling the ring (OUTs may be delayed
- * in hardware buffers, but are through after IN)
- *
- * rroesler: has been commented out and shifted to
- * SkGeDrvEvent(), because it is timer
- * guarded now
- *
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
- ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
- */
-
- if (pAC->CheckQueue) {
- pAC->CheckQueue = SK_FALSE;
- spin_lock(&pAC->SlowPathLock);
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock(&pAC->SlowPathLock);
- }
-
- /* IRQ is processed - Enable IRQs again*/
- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-
- return SkIsrRetHandled;
-} /* SkGeIsr */
-
-
-/****************************************************************************
- *
- * SkGeIsrOnePort - handle adapter interrupts for single port adapter
- *
- * Description:
- * The interrupt routine is called when the network adapter
- * generates an interrupt. It may also be called if another device
- * shares this interrupt vector with the driver.
- * This is the same as above, but handles only one port.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id)
-{
-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
-DEV_NET *pNet;
-SK_AC *pAC;
-SK_U32 IntSrc; /* interrupts source register contents */
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- /*
- * Check and process if its our interrupt
- */
- SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
- if (IntSrc == 0) {
- return SkIsrRetNone;
- }
-
- while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
- if (IntSrc & IS_IRQ_SW) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("Software IRQ\n"));
- }
-#endif
- if (IntSrc & IS_R1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF RX1 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
- SK_PNMI_CNT_RX_INTR(pAC, 0);
- }
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IS_XA1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF AS TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 0);
- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- }
-#if 0 /* only if sync. queues used */
- if (IntSrc & IS_XS1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF SY TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 0);
- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
- }
-#endif
-#endif
-
- /* do all IO at once */
- if (IntSrc & IS_R1_F)
- ClearAndStartRx(pAC, 0);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IS_XA1_F)
- ClearTxIrq(pAC, 0, TX_PRIO_LOW);
-#endif
- SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
- } /* while (IntSrc & IRQ_MASK != 0) */
-
- IntSrc &= pAC->GIni.GIValIrqMask;
- if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
- ("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
- pAC->CheckQueue = SK_FALSE;
- spin_lock(&pAC->SlowPathLock);
- if (IntSrc & SPECIAL_IRQS)
- SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
-
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock(&pAC->SlowPathLock);
- }
- /*
- * do it all again is case we cleared an interrupt that
- * came in after handling the ring (OUTs may be delayed
- * in hardware buffers, but are through after IN)
- *
- * rroesler: has been commented out and shifted to
- * SkGeDrvEvent(), because it is timer
- * guarded now
- *
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
- */
-
- /* IRQ is processed - Enable IRQs again*/
- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-
- return SkIsrRetHandled;
-} /* SkGeIsrOnePort */
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/****************************************************************************
- *
- * SkGePollController - polling receive, for netconsole
- *
- * Description:
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- *
- * Returns: N/A
- */
-static void SkGePollController(struct net_device *dev)
-{
- disable_irq(dev->irq);
- SkGeIsr(dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
-/****************************************************************************
- *
- * SkGeOpen - handle start of initialized adapter
- *
- * Description:
- * This function starts the initialized adapter.
- * The board level variable is set and the adapter is
- * brought to full functionality.
- * The device flags are set for operation.
- * Do all necessary level 2 initialization, enable interrupts and
- * give start command to RLMT.
- *
- * Returns:
- * 0 on success
- * != 0 on error
- */
-static int SkGeOpen(
-struct SK_NET_DEVICE *dev)
-{
- DEV_NET *pNet;
- SK_AC *pAC;
- unsigned long Flags; /* for spin lock */
- int i;
- SK_EVPARA EvPara; /* an event parameter union */
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
-
-#ifdef SK_DIAG_SUPPORT
- if (pAC->DiagModeActive == DIAG_ACTIVE) {
- if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
- return (-1); /* still in use by diag; deny actions */
- }
- }
-#endif
-
- /* Set blink mode */
- if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab ))
- pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
-
- if (pAC->BoardLevel == SK_INIT_DATA) {
- /* level 1 init common modules here */
- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
- printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
- return (-1);
- }
- SkI2cInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkEventInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkPnmiInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkAddrInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkRlmtInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkTimerInit (pAC, pAC->IoBase, SK_INIT_IO);
- pAC->BoardLevel = SK_INIT_IO;
- }
-
- if (pAC->BoardLevel != SK_INIT_RUN) {
- /* tschilling: Level 2 init modules here, check return value. */
- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
- printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
- return (-1);
- }
- SkI2cInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkEventInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkPnmiInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkAddrInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkRlmtInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkTimerInit (pAC, pAC->IoBase, SK_INIT_RUN);
- pAC->BoardLevel = SK_INIT_RUN;
- }
-
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- /* Enable transmit descriptor polling. */
- SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
- FillRxRing(pAC, &pAC->RxPort[i]);
- }
- SkGeYellowLED(pAC, pAC->IoBase, 1);
-
- StartDrvCleanupTimer(pAC);
- SkDimEnableModerationIfNeeded(pAC);
- SkDimDisplayModerationSettings(pAC);
-
- pAC->GIni.GIValIrqMask &= IRQ_MASK;
-
- /* enable Interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
- SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
- if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) {
- EvPara.Para32[0] = pAC->RlmtNets;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
- EvPara);
- EvPara.Para32[0] = pAC->RlmtMode;
- EvPara.Para32[1] = 0;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
- EvPara);
- }
-
- EvPara.Para32[0] = pNet->NetNr;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- pAC->MaxPorts++;
-
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeOpen suceeded\n"));
-
- return (0);
-} /* SkGeOpen */
-
-
-/****************************************************************************
- *
- * SkGeClose - Stop initialized adapter
- *
- * Description:
- * Close initialized adapter.
- *
- * Returns:
- * 0 - on success
- * error code - on error
- */
-static int SkGeClose(
-struct SK_NET_DEVICE *dev)
-{
- DEV_NET *pNet;
- DEV_NET *newPtrNet;
- SK_AC *pAC;
-
- unsigned long Flags; /* for spin lock */
- int i;
- int PortIdx;
- SK_EVPARA EvPara;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
-#ifdef SK_DIAG_SUPPORT
- if (pAC->DiagModeActive == DIAG_ACTIVE) {
- if (pAC->DiagFlowCtrl == SK_FALSE) {
- /*
- ** notify that the interface which has been closed
- ** by operator interaction must not be started up
- ** again when the DIAG has finished.
- */
- newPtrNet = netdev_priv(pAC->dev[0]);
- if (newPtrNet == pNet) {
- pAC->WasIfUp[0] = SK_FALSE;
- } else {
- pAC->WasIfUp[1] = SK_FALSE;
- }
- return 0; /* return to system everything is fine... */
- } else {
- pAC->DiagFlowCtrl = SK_FALSE;
- }
- }
-#endif
-
- netif_stop_queue(dev);
-
- if (pAC->RlmtNets == 1)
- PortIdx = pAC->ActivePort;
- else
- PortIdx = pNet->NetNr;
-
- StopDrvCleanupTimer(pAC);
-
- /*
- * Clear multicast table, promiscuous mode ....
- */
- SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
- SK_PROM_MODE_NONE);
-
- if (pAC->MaxPorts == 1) {
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- /* disable interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- EvPara.Para32[0] = pNet->NetNr;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- /* stop the hardware */
- SkGeDeInit(pAC, pAC->IoBase);
- pAC->BoardLevel = SK_INIT_DATA;
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- } else {
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- EvPara.Para32[0] = pNet->NetNr;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- /* Stop port */
- spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
- [TX_PRIO_LOW].TxDesRingLock, Flags);
- SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
- SK_STOP_ALL, SK_HARD_RST);
- spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
- [TX_PRIO_LOW].TxDesRingLock, Flags);
- }
-
- if (pAC->RlmtNets == 1) {
- /* clear all descriptor rings */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
- ClearRxRing(pAC, &pAC->RxPort[i]);
- ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
- }
- } else {
- /* clear port descriptor rings */
- ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
- ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
- ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
- }
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeClose: done "));
-
- SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
- SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct),
- sizeof(SK_PNMI_STRUCT_DATA));
-
- pAC->MaxPorts--;
-
- return (0);
-} /* SkGeClose */
-
-
-/*****************************************************************************
- *
- * SkGeXmit - Linux frame transmit function
- *
- * Description:
- * The system calls this function to send frames onto the wire.
- * It puts the frame in the tx descriptor ring. If the ring is
- * full then, the 'tbusy' flag is set.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- * WARNING: returning 1 in 'tbusy' case caused system crashes (double
- * allocated skb's) !!!
- */
-static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
-{
-DEV_NET *pNet;
-SK_AC *pAC;
-int Rc; /* return code of XmitFrame */
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- if ((!skb_shinfo(skb)->nr_frags) ||
- (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
- /* Don't activate scatter-gather and hardware checksum */
-
- if (pAC->RlmtNets == 2)
- Rc = XmitFrame(
- pAC,
- &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
- skb);
- else
- Rc = XmitFrame(
- pAC,
- &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
- skb);
- } else {
- /* scatter-gather and hardware TCP checksumming anabled*/
- if (pAC->RlmtNets == 2)
- Rc = XmitFrameSG(
- pAC,
- &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
- skb);
- else
- Rc = XmitFrameSG(
- pAC,
- &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
- skb);
- }
-
- /* Transmitter out of resources? */
- if (Rc <= 0) {
- netif_stop_queue(dev);
- }
-
- /* If not taken, give buffer ownership back to the
- * queueing layer.
- */
- if (Rc < 0)
- return (1);
-
- dev->trans_start = jiffies;
- return (0);
-} /* SkGeXmit */
-
-
-/*****************************************************************************
- *
- * XmitFrame - fill one socket buffer into the transmit ring
- *
- * Description:
- * This function puts a message into the transmit descriptor ring
- * if there is a descriptors left.
- * Linux skb's consist of only one continuous buffer.
- * The first step locks the ring. It is held locked
- * all time to avoid problems with SWITCH_../PORT_RESET.
- * Then the descriptoris allocated.
- * The second part is linking the buffer to the descriptor.
- * At the very last, the Control field of the descriptor
- * is made valid for the BMU and a start TX command is given
- * if necessary.
- *
- * Returns:
- * > 0 - on succes: the number of bytes in the message
- * = 0 - on resource shortage: this frame sent or dropped, now
- * the ring is full ( -> set tbusy)
- * < 0 - on failure: other problems ( -> return failure to upper layers)
- */
-static int XmitFrame(
-SK_AC *pAC, /* pointer to adapter context */
-TX_PORT *pTxPort, /* pointer to struct of port to send to */
-struct sk_buff *pMessage) /* pointer to send-message */
-{
- TXD *pTxd; /* the rxd to fill */
- TXD *pOldTxd;
- unsigned long Flags;
- SK_U64 PhysAddr;
- int BytesSend = pMessage->len;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
-
- spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-#ifndef USE_TX_COMPLETE
- FreeTxDescriptors(pAC, pTxPort);
-#endif
- if (pTxPort->TxdRingFree == 0) {
- /*
- ** no enough free descriptors in ring at the moment.
- ** Maybe free'ing some old one help?
- */
- FreeTxDescriptors(pAC, pTxPort);
- if (pTxPort->TxdRingFree == 0) {
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
- SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_TX_PROGRESS,
- ("XmitFrame failed\n"));
- /*
- ** the desired message can not be sent
- ** Because tbusy seems to be set, the message
- ** should not be freed here. It will be used
- ** by the scheduler of the ethernet handler
- */
- return (-1);
- }
- }
-
- /*
- ** If the passed socket buffer is of smaller MTU-size than 60,
- ** copy everything into new buffer and fill all bytes between
- ** the original packet end and the new packet end of 60 with 0x00.
- ** This is to resolve faulty padding by the HW with 0xaa bytes.
- */
- if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
- if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) {
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
- return 0;
- }
- pMessage->len = C_LEN_ETHERNET_MINSIZE;
- }
-
- /*
- ** advance head counter behind descriptor needed for this frame,
- ** so that needed descriptor is reserved from that on. The next
- ** action will be to add the passed buffer to the TX-descriptor
- */
- pTxd = pTxPort->pTxdRingHead;
- pTxPort->pTxdRingHead = pTxd->pNextTxd;
- pTxPort->TxdRingFree--;
-
-#ifdef SK_DUMP_TX
- DumpMsg(pMessage, "XmitFrame");
-#endif
-
- /*
- ** First step is to map the data to be sent via the adapter onto
- ** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4
- ** and 2.6 need to use pci_map_page() for that mapping.
- */
- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
- virt_to_page(pMessage->data),
- ((unsigned long) pMessage->data & ~PAGE_MASK),
- pMessage->len,
- PCI_DMA_TODEVICE);
- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
- pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
- pTxd->pMBuf = pMessage;
-
- if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
- u16 hdrlen = skb_transport_offset(pMessage);
- u16 offset = hdrlen + pMessage->csum_offset;
-
- if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
- (pAC->GIni.GIChipRev == 0) &&
- (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
- pTxd->TBControl = BMU_TCP_CHECK;
- } else {
- pTxd->TBControl = BMU_UDP_CHECK;
- }
-
- pTxd->TcpSumOfs = 0;
- pTxd->TcpSumSt = hdrlen;
- pTxd->TcpSumWr = offset;
-
- pTxd->TBControl |= BMU_OWN | BMU_STF |
- BMU_SW | BMU_EOF |
-#ifdef USE_TX_COMPLETE
- BMU_IRQ_EOF |
-#endif
- pMessage->len;
- } else {
- pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK |
- BMU_SW | BMU_EOF |
-#ifdef USE_TX_COMPLETE
- BMU_IRQ_EOF |
-#endif
- pMessage->len;
- }
-
- /*
- ** If previous descriptor already done, give TX start cmd
- */
- pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd);
- if ((pOldTxd->TBControl & BMU_OWN) == 0) {
- SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
- }
-
- /*
- ** after releasing the lock, the skb may immediately be free'd
- */
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
- if (pTxPort->TxdRingFree != 0) {
- return (BytesSend);
- } else {
- return (0);
- }
-
-} /* XmitFrame */
-
-/*****************************************************************************
- *
- * XmitFrameSG - fill one socket buffer into the transmit ring
- * (use SG and TCP/UDP hardware checksumming)
- *
- * Description:
- * This function puts a message into the transmit descriptor ring
- * if there is a descriptors left.
- *
- * Returns:
- * > 0 - on succes: the number of bytes in the message
- * = 0 - on resource shortage: this frame sent or dropped, now
- * the ring is full ( -> set tbusy)
- * < 0 - on failure: other problems ( -> return failure to upper layers)
- */
-static int XmitFrameSG(
-SK_AC *pAC, /* pointer to adapter context */
-TX_PORT *pTxPort, /* pointer to struct of port to send to */
-struct sk_buff *pMessage) /* pointer to send-message */
-{
-
- TXD *pTxd;
- TXD *pTxdFst;
- TXD *pTxdLst;
- int CurrFrag;
- int BytesSend;
- skb_frag_t *sk_frag;
- SK_U64 PhysAddr;
- unsigned long Flags;
- SK_U32 Control;
-
- spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-#ifndef USE_TX_COMPLETE
- FreeTxDescriptors(pAC, pTxPort);
-#endif
- if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
- FreeTxDescriptors(pAC, pTxPort);
- if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
- SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_TX_PROGRESS,
- ("XmitFrameSG failed - Ring full\n"));
- /* this message can not be sent now */
- return(-1);
- }
- }
-
- pTxd = pTxPort->pTxdRingHead;
- pTxdFst = pTxd;
- pTxdLst = pTxd;
- BytesSend = 0;
-
- /*
- ** Map the first fragment (header) into the DMA-space
- */
- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
- virt_to_page(pMessage->data),
- ((unsigned long) pMessage->data & ~PAGE_MASK),
- skb_headlen(pMessage),
- PCI_DMA_TODEVICE);
-
- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
- pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-
- /*
- ** Does the HW need to evaluate checksum for TCP or UDP packets?
- */
- if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
- u16 hdrlen = skb_transport_offset(pMessage);
- u16 offset = hdrlen + pMessage->csum_offset;
-
- Control = BMU_STFWD;
-
- /*
- ** We have to use the opcode for tcp here, because the
- ** opcode for udp is not working in the hardware yet
- ** (Revision 2.0)
- */
- if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
- (pAC->GIni.GIChipRev == 0) &&
- (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
- Control |= BMU_TCP_CHECK;
- } else {
- Control |= BMU_UDP_CHECK;
- }
-
- pTxd->TcpSumOfs = 0;
- pTxd->TcpSumSt = hdrlen;
- pTxd->TcpSumWr = offset;
- } else
- Control = BMU_CHECK | BMU_SW;
-
- pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
-
- pTxd = pTxd->pNextTxd;
- pTxPort->TxdRingFree--;
- BytesSend += skb_headlen(pMessage);
-
- /*
- ** Browse over all SG fragments and map each of them into the DMA space
- */
- for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) {
- sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag];
- /*
- ** we already have the proper value in entry
- */
- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
- sk_frag->page,
- sk_frag->page_offset,
- sk_frag->size,
- PCI_DMA_TODEVICE);
-
- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
- pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
- pTxd->pMBuf = pMessage;
-
- pTxd->TBControl = Control | BMU_OWN | sk_frag->size;
-
- /*
- ** Do we have the last fragment?
- */
- if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) {
-#ifdef USE_TX_COMPLETE
- pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
-#else
- pTxd->TBControl |= BMU_EOF;
-#endif
- pTxdFst->TBControl |= BMU_OWN | BMU_SW;
- }
- pTxdLst = pTxd;
- pTxd = pTxd->pNextTxd;
- pTxPort->TxdRingFree--;
- BytesSend += sk_frag->size;
- }
-
- /*
- ** If previous descriptor already done, give TX start cmd
- */
- if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) {
- SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
- }
-
- pTxPort->pTxdRingPrev = pTxdLst;
- pTxPort->pTxdRingHead = pTxd;
-
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-
- if (pTxPort->TxdRingFree > 0) {
- return (BytesSend);
- } else {
- return (0);
- }
-}
-
-/*****************************************************************************
- *
- * FreeTxDescriptors - release descriptors from the descriptor ring
- *
- * Description:
- * This function releases descriptors from a transmit ring if they
- * have been sent by the BMU.
- * If a descriptors is sent, it can be freed and the message can
- * be freed, too.
- * The SOFTWARE controllable bit is used to prevent running around a
- * completely free ring for ever. If this bit is no set in the
- * frame (by XmitFrame), this frame has never been sent or is
- * already freed.
- * The Tx descriptor ring lock must be held while calling this function !!!
- *
- * Returns:
- * none
- */
-static void FreeTxDescriptors(
-SK_AC *pAC, /* pointer to the adapter context */
-TX_PORT *pTxPort) /* pointer to destination port structure */
-{
-TXD *pTxd; /* pointer to the checked descriptor */
-TXD *pNewTail; /* pointer to 'end' of the ring */
-SK_U32 Control; /* TBControl field of descriptor */
-SK_U64 PhysAddr; /* address of DMA mapping */
-
- pNewTail = pTxPort->pTxdRingTail;
- pTxd = pNewTail;
- /*
- ** loop forever; exits if BMU_SW bit not set in start frame
- ** or BMU_OWN bit set in any frame
- */
- while (1) {
- Control = pTxd->TBControl;
- if ((Control & BMU_SW) == 0) {
- /*
- ** software controllable bit is set in first
- ** fragment when given to BMU. Not set means that
- ** this fragment was never sent or is already
- ** freed ( -> ring completely free now).
- */
- pTxPort->pTxdRingTail = pTxd;
- netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
- return;
- }
- if (Control & BMU_OWN) {
- pTxPort->pTxdRingTail = pTxd;
- if (pTxPort->TxdRingFree > 0) {
- netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
- }
- return;
- }
-
- /*
- ** release the DMA mapping, because until not unmapped
- ** this buffer is considered being under control of the
- ** adapter card!
- */
- PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
- PhysAddr |= (SK_U64) pTxd->VDataLow;
- pci_unmap_page(pAC->PciDev, PhysAddr,
- pTxd->pMBuf->len,
- PCI_DMA_TODEVICE);
-
- if (Control & BMU_EOF)
- DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */
-
- pTxPort->TxdRingFree++;
- pTxd->TBControl &= ~BMU_SW;
- pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
- } /* while(forever) */
-} /* FreeTxDescriptors */
-
-/*****************************************************************************
- *
- * FillRxRing - fill the receive ring with valid descriptors
- *
- * Description:
- * This function fills the receive ring descriptors with data
- * segments and makes them valid for the BMU.
- * The active ring is filled completely, if possible.
- * The non-active ring is filled only partial to save memory.
- *
- * Description of rx ring structure:
- * head - points to the descriptor which will be used next by the BMU
- * tail - points to the next descriptor to give to the BMU
- *
- * Returns: N/A
- */
-static void FillRxRing(
-SK_AC *pAC, /* pointer to the adapter context */
-RX_PORT *pRxPort) /* ptr to port struct for which the ring
- should be filled */
-{
-unsigned long Flags;
-
- spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
- while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {
- if(!FillRxDescriptor(pAC, pRxPort))
- break;
- }
- spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* FillRxRing */
-
-
-/*****************************************************************************
- *
- * FillRxDescriptor - fill one buffer into the receive ring
- *
- * Description:
- * The function allocates a new receive buffer and
- * puts it into the next descriptor.
- *
- * Returns:
- * SK_TRUE - a buffer was added to the ring
- * SK_FALSE - a buffer could not be added
- */
-static SK_BOOL FillRxDescriptor(
-SK_AC *pAC, /* pointer to the adapter context struct */
-RX_PORT *pRxPort) /* ptr to port struct of ring to fill */
-{
-struct sk_buff *pMsgBlock; /* pointer to a new message block */
-RXD *pRxd; /* the rxd to fill */
-SK_U16 Length; /* data fragment length */
-SK_U64 PhysAddr; /* physical address of a rx buffer */
-
- pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);
- if (pMsgBlock == NULL) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_ENTRY,
- ("%s: Allocation of rx buffer failed !\n",
- pAC->dev[pRxPort->PortIndex]->name));
- SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex);
- return(SK_FALSE);
- }
- skb_reserve(pMsgBlock, 2); /* to align IP frames */
- /* skb allocated ok, so add buffer */
- pRxd = pRxPort->pRxdRingTail;
- pRxPort->pRxdRingTail = pRxd->pNextRxd;
- pRxPort->RxdRingFree--;
- Length = pAC->RxBufSize;
- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
- virt_to_page(pMsgBlock->data),
- ((unsigned long) pMsgBlock->data &
- ~PAGE_MASK),
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
-
- pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
- pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
- pRxd->pMBuf = pMsgBlock;
- pRxd->RBControl = BMU_OWN |
- BMU_STF |
- BMU_IRQ_EOF |
- BMU_TCP_CHECK |
- Length;
- return (SK_TRUE);
-
-} /* FillRxDescriptor */
-
-
-/*****************************************************************************
- *
- * ReQueueRxBuffer - fill one buffer back into the receive ring
- *
- * Description:
- * Fill a given buffer back into the rx ring. The buffer
- * has been previously allocated and aligned, and its phys.
- * address calculated, so this is no more necessary.
- *
- * Returns: N/A
- */
-static void ReQueueRxBuffer(
-SK_AC *pAC, /* pointer to the adapter context struct */
-RX_PORT *pRxPort, /* ptr to port struct of ring to fill */
-struct sk_buff *pMsg, /* pointer to the buffer */
-SK_U32 PhysHigh, /* phys address high dword */
-SK_U32 PhysLow) /* phys address low dword */
-{
-RXD *pRxd; /* the rxd to fill */
-SK_U16 Length; /* data fragment length */
-
- pRxd = pRxPort->pRxdRingTail;
- pRxPort->pRxdRingTail = pRxd->pNextRxd;
- pRxPort->RxdRingFree--;
- Length = pAC->RxBufSize;
-
- pRxd->VDataLow = PhysLow;
- pRxd->VDataHigh = PhysHigh;
- pRxd->pMBuf = pMsg;
- pRxd->RBControl = BMU_OWN |
- BMU_STF |
- BMU_IRQ_EOF |
- BMU_TCP_CHECK |
- Length;
- return;
-} /* ReQueueRxBuffer */
-
-/*****************************************************************************
- *
- * ReceiveIrq - handle a receive IRQ
- *
- * Description:
- * This function is called when a receive IRQ is set.
- * It walks the receive descriptor ring and sends up all
- * frames that are complete.
- *
- * Returns: N/A
- */
-static void ReceiveIrq(
- SK_AC *pAC, /* pointer to adapter context */
- RX_PORT *pRxPort, /* pointer to receive port struct */
- SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */
-{
-RXD *pRxd; /* pointer to receive descriptors */
-SK_U32 Control; /* control field of descriptor */
-struct sk_buff *pMsg; /* pointer to message holding frame */
-struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
-int FrameLength; /* total length of received frame */
-SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
-SK_EVPARA EvPara; /* an event parameter union */
-unsigned long Flags; /* for spin lock */
-int PortIndex = pRxPort->PortIndex;
-unsigned int Offset;
-unsigned int NumBytes;
-unsigned int ForRlmt;
-SK_BOOL IsBc;
-SK_BOOL IsMc;
-SK_BOOL IsBadFrame; /* Bad frame */
-
-SK_U32 FrameStat;
-SK_U64 PhysAddr;
-
-rx_start:
- /* do forever; exit if BMU_OWN found */
- for ( pRxd = pRxPort->pRxdRingHead ;
- pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
- pRxd = pRxd->pNextRxd,
- pRxPort->pRxdRingHead = pRxd,
- pRxPort->RxdRingFree ++) {
-
- /*
- * For a better understanding of this loop
- * Go through every descriptor beginning at the head
- * Please note: the ring might be completely received so the OWN bit
- * set is not a good crirteria to leave that loop.
- * Therefore the RingFree counter is used.
- * On entry of this loop pRxd is a pointer to the Rxd that needs
- * to be checked next.
- */
-
- Control = pRxd->RBControl;
-
- /* check if this descriptor is ready */
- if ((Control & BMU_OWN) != 0) {
- /* this descriptor is not yet ready */
- /* This is the usual end of the loop */
- /* We don't need to start the ring again */
- FillRxRing(pAC, pRxPort);
- return;
- }
- pAC->DynIrqModInfo.NbrProcessedDescr++;
-
- /* get length of frame and check it */
- FrameLength = Control & BMU_BBC;
- if (FrameLength > pAC->RxBufSize) {
- goto rx_failed;
- }
-
- /* check for STF and EOF */
- if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {
- goto rx_failed;
- }
-
- /* here we have a complete frame in the ring */
- pMsg = pRxd->pMBuf;
-
- FrameStat = pRxd->FrameStat;
-
- /* check for frame length mismatch */
-#define XMR_FS_LEN_SHIFT 18
-#define GMR_FS_LEN_SHIFT 16
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
- if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("skge: Frame length mismatch (%u/%u).\n",
- FrameLength,
- (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
- goto rx_failed;
- }
- }
- else {
- if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("skge: Frame length mismatch (%u/%u).\n",
- FrameLength,
- (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
- goto rx_failed;
- }
- }
-
- /* Set Rx Status */
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
- IsBc = (FrameStat & XMR_FS_BC) != 0;
- IsMc = (FrameStat & XMR_FS_MC) != 0;
- IsBadFrame = (FrameStat &
- (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
- } else {
- IsBc = (FrameStat & GMR_FS_BC) != 0;
- IsMc = (FrameStat & GMR_FS_MC) != 0;
- IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
- ((FrameStat & GMR_FS_RX_OK) == 0));
- }
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
- ("Received frame of length %d on port %d\n",
- FrameLength, PortIndex));
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
- ("Number of free rx descriptors: %d\n",
- pRxPort->RxdRingFree));
-/* DumpMsg(pMsg, "Rx"); */
-
- if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
-#if 0
- (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
-#endif
- /* there is a receive error in this frame */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("skge: Error in received frame, dropped!\n"
- "Control: %x\nRxStat: %x\n",
- Control, FrameStat));
-
- ReQueueRxBuffer(pAC, pRxPort, pMsg,
- pRxd->VDataHigh, pRxd->VDataLow);
-
- continue;
- }
-
- /*
- * if short frame then copy data to reduce memory waste
- */
- if ((FrameLength < SK_COPY_THRESHOLD) &&
- ((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) {
- /*
- * Short frame detected and allocation successfull
- */
- /* use new skb and copy data */
- skb_reserve(pNewMsg, 2);
- skb_put(pNewMsg, FrameLength);
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
-
- pci_dma_sync_single_for_cpu(pAC->PciDev,
- (dma_addr_t) PhysAddr,
- FrameLength,
- PCI_DMA_FROMDEVICE);
- skb_copy_to_linear_data(pNewMsg, pMsg, FrameLength);
-
- pci_dma_sync_single_for_device(pAC->PciDev,
- (dma_addr_t) PhysAddr,
- FrameLength,
- PCI_DMA_FROMDEVICE);
- ReQueueRxBuffer(pAC, pRxPort, pMsg,
- pRxd->VDataHigh, pRxd->VDataLow);
-
- pMsg = pNewMsg;
-
- }
- else {
- /*
- * if large frame, or SKB allocation failed, pass
- * the SKB directly to the networking
- */
-
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
-
- /* release the DMA mapping */
- pci_unmap_single(pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
-
- /* set length in message */
- skb_put(pMsg, FrameLength);
- } /* frame > SK_COPY_TRESHOLD */
-
-#ifdef USE_SK_RX_CHECKSUM
- pMsg->csum = pRxd->TcpSums & 0xffff;
- pMsg->ip_summed = CHECKSUM_COMPLETE;
-#else
- pMsg->ip_summed = CHECKSUM_NONE;
-#endif
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
- ForRlmt = SK_RLMT_RX_PROTOCOL;
-#if 0
- IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
-#endif
- SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
- IsBc, &Offset, &NumBytes);
- if (NumBytes != 0) {
-#if 0
- IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
-#endif
- SK_RLMT_LOOKAHEAD(pAC, PortIndex,
- &pMsg->data[Offset],
- IsBc, IsMc, &ForRlmt);
- }
- if (ForRlmt == SK_RLMT_RX_PROTOCOL) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W"));
- /* send up only frames from active port */
- if ((PortIndex == pAC->ActivePort) ||
- (pAC->RlmtNets == 2)) {
- /* frame for upper layer */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));
-#ifdef xDEBUG
- DumpMsg(pMsg, "Rx");
-#endif
- SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
- FrameLength, pRxPort->PortIndex);
-
- pMsg->protocol = eth_type_trans(pMsg,
- pAC->dev[pRxPort->PortIndex]);
- netif_rx(pMsg);
- pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
- }
- else {
- /* drop frame */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("D"));
- DEV_KFREE_SKB(pMsg);
- }
-
- } /* if not for rlmt */
- else {
- /* packet for rlmt */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
- pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
- pAC->IoBase, FrameLength);
- if (pRlmtMbuf != NULL) {
- pRlmtMbuf->pNext = NULL;
- pRlmtMbuf->Length = FrameLength;
- pRlmtMbuf->PortIdx = PortIndex;
- EvPara.pParaPtr = pRlmtMbuf;
- memcpy((char*)(pRlmtMbuf->pData),
- (char*)(pMsg->data),
- FrameLength);
-
- /* SlowPathLock needed? */
- if (SlowPathLock == SK_TRUE) {
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- SkEventQueue(pAC, SKGE_RLMT,
- SK_RLMT_PACKET_RECEIVED,
- EvPara);
- pAC->CheckQueue = SK_TRUE;
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- } else {
- SkEventQueue(pAC, SKGE_RLMT,
- SK_RLMT_PACKET_RECEIVED,
- EvPara);
- pAC->CheckQueue = SK_TRUE;
- }
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("Q"));
- }
- if ((pAC->dev[pRxPort->PortIndex]->flags &
- (IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
- (ForRlmt & SK_RLMT_RX_PROTOCOL) ==
- SK_RLMT_RX_PROTOCOL) {
- pMsg->protocol = eth_type_trans(pMsg,
- pAC->dev[pRxPort->PortIndex]);
- netif_rx(pMsg);
- pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
- }
- else {
- DEV_KFREE_SKB(pMsg);
- }
-
- } /* if packet for rlmt */
- } /* for ... scanning the RXD ring */
-
- /* RXD ring is empty -> fill and restart */
- FillRxRing(pAC, pRxPort);
- /* do not start if called from Close */
- if (pAC->BoardLevel > SK_INIT_DATA) {
- ClearAndStartRx(pAC, PortIndex);
- }
- return;
-
-rx_failed:
- /* remove error frame */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
- ("Schrottdescriptor, length: 0x%x\n", FrameLength));
-
- /* release the DMA mapping */
-
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_unmap_page(pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
- DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
- pRxd->pMBuf = NULL;
- pRxPort->RxdRingFree++;
- pRxPort->pRxdRingHead = pRxd->pNextRxd;
- goto rx_start;
-
-} /* ReceiveIrq */
-
-
-/*****************************************************************************
- *
- * ClearAndStartRx - give a start receive command to BMU, clear IRQ
- *
- * Description:
- * This function sends a start command and a clear interrupt
- * command for one receive queue to the BMU.
- *
- * Returns: N/A
- * none
- */
-static void ClearAndStartRx(
-SK_AC *pAC, /* pointer to the adapter context */
-int PortIndex) /* index of the receive port (XMAC) */
-{
- SK_OUT8(pAC->IoBase,
- RxQueueAddr[PortIndex]+Q_CSR,
- CSR_START | CSR_IRQ_CL_F);
-} /* ClearAndStartRx */
-
-
-/*****************************************************************************
- *
- * ClearTxIrq - give a clear transmit IRQ command to BMU
- *
- * Description:
- * This function sends a clear tx IRQ command for one
- * transmit queue to the BMU.
- *
- * Returns: N/A
- */
-static void ClearTxIrq(
-SK_AC *pAC, /* pointer to the adapter context */
-int PortIndex, /* index of the transmit port (XMAC) */
-int Prio) /* priority or normal queue */
-{
- SK_OUT8(pAC->IoBase,
- TxQueueAddr[PortIndex][Prio]+Q_CSR,
- CSR_IRQ_CL_F);
-} /* ClearTxIrq */
-
-
-/*****************************************************************************
- *
- * ClearRxRing - remove all buffers from the receive ring
- *
- * Description:
- * This function removes all receive buffers from the ring.
- * The receive BMU must be stopped before calling this function.
- *
- * Returns: N/A
- */
-static void ClearRxRing(
-SK_AC *pAC, /* pointer to adapter context */
-RX_PORT *pRxPort) /* pointer to rx port struct */
-{
-RXD *pRxd; /* pointer to the current descriptor */
-unsigned long Flags;
-SK_U64 PhysAddr;
-
- if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
- return;
- }
- spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
- pRxd = pRxPort->pRxdRingHead;
- do {
- if (pRxd->pMBuf != NULL) {
-
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_unmap_page(pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
- DEV_KFREE_SKB(pRxd->pMBuf);
- pRxd->pMBuf = NULL;
- }
- pRxd->RBControl &= BMU_OWN;
- pRxd = pRxd->pNextRxd;
- pRxPort->RxdRingFree++;
- } while (pRxd != pRxPort->pRxdRingTail);
- pRxPort->pRxdRingTail = pRxPort->pRxdRingHead;
- spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* ClearRxRing */
-
-/*****************************************************************************
- *
- * ClearTxRing - remove all buffers from the transmit ring
- *
- * Description:
- * This function removes all transmit buffers from the ring.
- * The transmit BMU must be stopped before calling this function
- * and transmitting at the upper level must be disabled.
- * The BMU own bit of all descriptors is cleared, the rest is
- * done by calling FreeTxDescriptors.
- *
- * Returns: N/A
- */
-static void ClearTxRing(
-SK_AC *pAC, /* pointer to adapter context */
-TX_PORT *pTxPort) /* pointer to tx prt struct */
-{
-TXD *pTxd; /* pointer to the current descriptor */
-int i;
-unsigned long Flags;
-
- spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
- pTxd = pTxPort->pTxdRingHead;
- for (i=0; i<pAC->TxDescrPerRing; i++) {
- pTxd->TBControl &= ~BMU_OWN;
- pTxd = pTxd->pNextTxd;
- }
- FreeTxDescriptors(pAC, pTxPort);
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-} /* ClearTxRing */
-
-/*****************************************************************************
- *
- * SkGeSetMacAddr - Set the hardware MAC address
- *
- * Description:
- * This function sets the MAC address used by the adapter.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
-{
-
-DEV_NET *pNet = netdev_priv(dev);
-SK_AC *pAC = pNet->pAC;
-
-struct sockaddr *addr = p;
-unsigned long Flags;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeSetMacAddr starts now...\n"));
- if(netif_running(dev))
- return -EBUSY;
-
- memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
- if (pAC->RlmtNets == 2)
- SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
- (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
- else
- SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
- (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
-
-
-
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return 0;
-} /* SkGeSetMacAddr */
-
-
-/*****************************************************************************
- *
- * SkGeSetRxMode - set receive mode
- *
- * Description:
- * This function sets the receive mode of an adapter. The adapter
- * supports promiscuous mode, allmulticast mode and a number of
- * multicast addresses. If more multicast addresses the available
- * are selected, a hash function in the hardware is used.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
-{
-
-DEV_NET *pNet;
-SK_AC *pAC;
-
-struct dev_mc_list *pMcList;
-int i;
-int PortIdx;
-unsigned long Flags;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeSetRxMode starts now... "));
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
- if (pAC->RlmtNets == 1)
- PortIdx = pAC->ActivePort;
- else
- PortIdx = pNet->NetNr;
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- if (dev->flags & IFF_PROMISC) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("PROMISCUOUS mode\n"));
- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
- SK_PROM_MODE_LLC);
- } else if (dev->flags & IFF_ALLMULTI) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("ALLMULTI mode\n"));
- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
- SK_PROM_MODE_ALL_MC);
- } else {
- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
- SK_PROM_MODE_NONE);
- SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("Number of MC entries: %d ", dev->mc_count));
-
- pMcList = dev->mc_list;
- for (i=0; i<dev->mc_count; i++, pMcList = pMcList->next) {
- SkAddrMcAdd(pAC, pAC->IoBase, PortIdx,
- (SK_MAC_ADDR*)pMcList->dmi_addr, 0);
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA,
- ("%02x:%02x:%02x:%02x:%02x:%02x\n",
- pMcList->dmi_addr[0],
- pMcList->dmi_addr[1],
- pMcList->dmi_addr[2],
- pMcList->dmi_addr[3],
- pMcList->dmi_addr[4],
- pMcList->dmi_addr[5]));
- }
- SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
- }
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- return;
-} /* SkGeSetRxMode */
-
-
-/*****************************************************************************
- *
- * SkGeChangeMtu - set the MTU to another value
- *
- * Description:
- * This function sets is called whenever the MTU size is changed
- * (ifconfig mtu xxx dev ethX). If the MTU is bigger than standard
- * ethernet MTU size, long frame support is activated.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
-{
-DEV_NET *pNet;
-struct net_device *pOtherDev;
-SK_AC *pAC;
-unsigned long Flags;
-int i;
-SK_EVPARA EvPara;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeChangeMtu starts now...\n"));
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
- return -EINVAL;
- }
-
- if(pAC->BoardLevel != SK_INIT_RUN) {
- return -EINVAL;
- }
-
-#ifdef SK_DIAG_SUPPORT
- if (pAC->DiagModeActive == DIAG_ACTIVE) {
- if (pAC->DiagFlowCtrl == SK_FALSE) {
- return -1; /* still in use, deny any actions of MTU */
- } else {
- pAC->DiagFlowCtrl = SK_FALSE;
- }
- }
-#endif
-
- pOtherDev = pAC->dev[1 - pNet->NetNr];
-
- if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
- && (NewMtu <= 1500))
- return 0;
-
- pAC->RxBufSize = NewMtu + 32;
- dev->mtu = NewMtu;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("New MTU: %d\n", NewMtu));
-
- /*
- ** Prevent any reconfiguration while changing the MTU
- ** by disabling any interrupts
- */
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
- /*
- ** Notify RLMT that any ports are to be stopped
- */
- EvPara.Para32[0] = 0;
- EvPara.Para32[1] = -1;
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- EvPara.Para32[0] = 1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- } else {
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- }
-
- /*
- ** After calling the SkEventDispatcher(), RLMT is aware about
- ** the stopped ports -> configuration can take place!
- */
- SkEventDispatcher(pAC, pAC->IoBase);
-
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
- netif_stop_queue(pAC->dev[i]);
-
- }
-
- /*
- ** Depending on the desired MTU size change, a different number of
- ** RX buffers need to be allocated
- */
- if (NewMtu > 1500) {
- /*
- ** Use less rx buffers
- */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
- (pAC->RxDescrPerRing / 4);
- } else {
- if (i == pAC->ActivePort) {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
- (pAC->RxDescrPerRing / 4);
- } else {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
- (pAC->RxDescrPerRing / 10);
- }
- }
- }
- } else {
- /*
- ** Use the normal amount of rx buffers
- */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- pAC->RxPort[i].RxFillLimit = 1;
- } else {
- if (i == pAC->ActivePort) {
- pAC->RxPort[i].RxFillLimit = 1;
- } else {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
- (pAC->RxDescrPerRing / 4);
- }
- }
- }
- }
-
- SkGeDeInit(pAC, pAC->IoBase);
-
- /*
- ** enable/disable hardware support for long frames
- */
- if (NewMtu > 1500) {
-// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
- pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
- } else {
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- pAC->GIni.GIPortUsage = SK_MUL_LINK;
- } else {
- pAC->GIni.GIPortUsage = SK_RED_LINK;
- }
- }
-
- SkGeInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
-
- /*
- ** tschilling:
- ** Speed and others are set back to default in level 1 init!
- */
- GetConfiguration(pAC);
-
- SkGeInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkI2cInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN);
- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN);
-
- /*
- ** clear and reinit the rx rings here
- */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
- ClearRxRing(pAC, &pAC->RxPort[i]);
- FillRxRing(pAC, &pAC->RxPort[i]);
-
- /*
- ** Enable transmit descriptor polling
- */
- SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
- FillRxRing(pAC, &pAC->RxPort[i]);
- };
-
- SkGeYellowLED(pAC, pAC->IoBase, 1);
- SkDimEnableModerationIfNeeded(pAC);
- SkDimDisplayModerationSettings(pAC);
-
- netif_start_queue(pAC->dev[pNet->PortNr]);
- for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
- spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
- }
-
- /*
- ** Enable Interrupts again
- */
- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
- SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
-
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
-
- /*
- ** Notify RLMT about the changing and restarting one (or more) ports
- */
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- EvPara.Para32[0] = pAC->RlmtNets;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara);
- EvPara.Para32[0] = pNet->PortNr;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-
- if (netif_running(pOtherDev)) {
- DEV_NET *pOtherNet = netdev_priv(pOtherDev);
- EvPara.Para32[0] = pOtherNet->PortNr;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- }
- } else {
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- }
-
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- /*
- ** While testing this driver with latest kernel 2.5 (2.5.70), it
- ** seems as if upper layers have a problem to handle a successful
- ** return value of '0'. If such a zero is returned, the complete
- ** system hangs for several minutes (!), which is in acceptable.
- **
- ** Currently it is not clear, what the exact reason for this problem
- ** is. The implemented workaround for 2.5 is to return the desired
- ** new MTU size if all needed changes for the new MTU size where
- ** performed. In kernels 2.2 and 2.4, a zero value is returned,
- ** which indicates the successful change of the mtu-size.
- */
- return NewMtu;
-
-} /* SkGeChangeMtu */
-
-
-/*****************************************************************************
- *
- * SkGeStats - return ethernet device statistics
- *
- * Description:
- * This function return statistic data about the ethernet device
- * to the operating system.
- *
- * Returns:
- * pointer to the statistic structure.
- */
-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
-{
-DEV_NET *pNet = netdev_priv(dev);
-SK_AC *pAC = pNet->pAC;
-SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */
-SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */
-SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */
-unsigned int Size; /* size of pnmi struct */
-unsigned long Flags; /* for spin lock */
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeStats starts now...\n"));
- pPnmiStruct = &pAC->PnmiStruct;
-
-#ifdef SK_DIAG_SUPPORT
- if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
- (pAC->BoardLevel == SK_INIT_RUN)) {
-#endif
- SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA));
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- Size = SK_PNMI_STRUCT_SIZE;
- SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-#ifdef SK_DIAG_SUPPORT
- }
-#endif
-
- pPnmiStat = &pPnmiStruct->Stat[0];
- pPnmiConf = &pPnmiStruct->Conf[0];
-
- pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF;
- pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
- pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
- pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
-
- if (dev->mtu <= 1500) {
- pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
- } else {
- pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
- pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
- }
-
-
- if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12)
- pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts;
-
- pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
- pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
- pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
- pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF;
- pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
-
- /* detailed rx_errors: */
- pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF;
- pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
- pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF;
- pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF;
- pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
- pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF;
-
- /* detailed tx_errors */
- pAC->stats.tx_aborted_errors = (SK_U32) 0;
- pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
- pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF;
- pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
- pAC->stats.tx_window_errors = (SK_U32) 0;
-
- return(&pAC->stats);
-} /* SkGeStats */
-
-/*
- * Basic MII register access
- */
-static int SkGeMiiIoctl(struct net_device *dev,
- struct mii_ioctl_data *data, int cmd)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- SK_IOC IoC = pAC->IoBase;
- int Port = pNet->PortNr;
- SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
- unsigned long Flags;
- int err = 0;
- int reg = data->reg_num & 0x1f;
- SK_U16 val = data->val_in;
-
- if (!netif_running(dev))
- return -ENODEV; /* Phy still in reset */
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- switch(cmd) {
- case SIOCGMIIPHY:
- data->phy_id = pPrt->PhyAddr;
-
- /* fallthru */
- case SIOCGMIIREG:
- if (pAC->GIni.GIGenesis)
- SkXmPhyRead(pAC, IoC, Port, reg, &val);
- else
- SkGmPhyRead(pAC, IoC, Port, reg, &val);
-
- data->val_out = val;
- break;
-
- case SIOCSMIIREG:
- if (!capable(CAP_NET_ADMIN))
- err = -EPERM;
-
- else if (pAC->GIni.GIGenesis)
- SkXmPhyWrite(pAC, IoC, Port, reg, val);
- else
- SkGmPhyWrite(pAC, IoC, Port, reg, val);
- break;
- default:
- err = -EOPNOTSUPP;
- }
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return err;
-}
-
-
-/*****************************************************************************
- *
- * SkGeIoctl - IO-control function
- *
- * Description:
- * This function is called if an ioctl is issued on the device.
- * There are three subfunction for reading, writing and test-writing
- * the private MIB data structure (useful for SysKonnect-internal tools).
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
-{
-DEV_NET *pNet;
-SK_AC *pAC;
-void *pMemBuf;
-struct pci_dev *pdev = NULL;
-SK_GE_IOCTL Ioctl;
-unsigned int Err = 0;
-int Size = 0;
-int Ret = 0;
-unsigned int Length = 0;
-int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeIoctl starts now...\n"));
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG)
- return SkGeMiiIoctl(dev, if_mii(rq), cmd);
-
- if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
- return -EFAULT;
- }
-
- switch(cmd) {
- case SK_IOCTL_SETMIB:
- case SK_IOCTL_PRESETMIB:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- case SK_IOCTL_GETMIB:
- if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
- Ioctl.Len<sizeof(pAC->PnmiStruct)?
- Ioctl.Len : sizeof(pAC->PnmiStruct))) {
- return -EFAULT;
- }
- Size = SkGeIocMib(pNet, Ioctl.Len, cmd);
- if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct,
- Ioctl.Len<Size? Ioctl.Len : Size)) {
- return -EFAULT;
- }
- Ioctl.Len = Size;
- if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
- return -EFAULT;
- }
- break;
- case SK_IOCTL_GEN:
- if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
- Length = Ioctl.Len;
- } else {
- Length = sizeof(pAC->PnmiStruct) + HeaderLength;
- }
- if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
- return -ENOMEM;
- }
- if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
- Err = -EFAULT;
- goto fault_gen;
- }
- if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
- Err = -EFAULT;
- goto fault_gen;
- }
- if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
- Err = -EFAULT;
- goto fault_gen;
- }
- Ioctl.Len = Length;
- if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
- Err = -EFAULT;
- goto fault_gen;
- }
-fault_gen:
- kfree(pMemBuf); /* cleanup everything */
- break;
-#ifdef SK_DIAG_SUPPORT
- case SK_IOCTL_DIAG:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
- Length = Ioctl.Len;
- } else {
- Length = sizeof(pAC->PnmiStruct) + HeaderLength;
- }
- if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
- return -ENOMEM;
- }
- if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
- Err = -EFAULT;
- goto fault_diag;
- }
- pdev = pAC->PciDev;
- Length = 3 * sizeof(SK_U32); /* Error, Bus and Device */
- /*
- ** While coding this new IOCTL interface, only a few lines of code
- ** are to to be added. Therefore no dedicated function has been
- ** added. If more functionality is added, a separate function
- ** should be used...
- */
- * ((SK_U32 *)pMemBuf) = 0;
- * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
- * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
- if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
- Err = -EFAULT;
- goto fault_diag;
- }
- Ioctl.Len = Length;
- if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
- Err = -EFAULT;
- goto fault_diag;
- }
-fault_diag:
- kfree(pMemBuf); /* cleanup everything */
- break;
-#endif
- default:
- Err = -EOPNOTSUPP;
- }
-
- return(Err);
-
-} /* SkGeIoctl */
-
-
-/*****************************************************************************
- *
- * SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message
- *
- * Description:
- * This function reads/writes the MIB data using PNMI (Private Network
- * Management Interface).
- * The destination for the data must be provided with the
- * ioctl call and is given to the driver in the form of
- * a user space address.
- * Copying from the user-provided data area into kernel messages
- * and back is done by copy_from_user and copy_to_user calls in
- * SkGeIoctl.
- *
- * Returns:
- * returned size from PNMI call
- */
-static int SkGeIocMib(
-DEV_NET *pNet, /* pointer to the adapter context */
-unsigned int Size, /* length of ioctl data */
-int mode) /* flag for set/preset */
-{
-unsigned long Flags; /* for spin lock */
-SK_AC *pAC;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeIocMib starts now...\n"));
- pAC = pNet->pAC;
- /* access MIB */
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- switch(mode) {
- case SK_IOCTL_GETMIB:
- SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
- pNet->NetNr);
- break;
- case SK_IOCTL_PRESETMIB:
- SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
- pNet->NetNr);
- break;
- case SK_IOCTL_SETMIB:
- SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
- pNet->NetNr);
- break;
- default:
- break;
- }
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("MIB data access succeeded\n"));
- return (Size);
-} /* SkGeIocMib */
-
-
-/*****************************************************************************
- *
- * GetConfiguration - read configuration information
- *
- * Description:
- * This function reads per-adapter configuration information from
- * the options provided on the command line.
- *
- * Returns:
- * none
- */
-static void GetConfiguration(
-SK_AC *pAC) /* pointer to the adapter context structure */
-{
-SK_I32 Port; /* preferred port */
-SK_BOOL AutoSet;
-SK_BOOL DupSet;
-int LinkSpeed = SK_LSPEED_AUTO; /* Link speed */
-int AutoNeg = 1; /* autoneg off (0) or on (1) */
-int DuplexCap = 0; /* 0=both,1=full,2=half */
-int FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; /* FlowControl */
-int MSMode = SK_MS_MODE_AUTO; /* master/slave mode */
-
-SK_BOOL IsConTypeDefined = SK_TRUE;
-SK_BOOL IsLinkSpeedDefined = SK_TRUE;
-SK_BOOL IsFlowCtrlDefined = SK_TRUE;
-SK_BOOL IsRoleDefined = SK_TRUE;
-SK_BOOL IsModeDefined = SK_TRUE;
-/*
- * The two parameters AutoNeg. and DuplexCap. map to one configuration
- * parameter. The mapping is described by this table:
- * DuplexCap -> | both | full | half |
- * AutoNeg | | | |
- * -----------------------------------------------------------------
- * Off | illegal | Full | Half |
- * -----------------------------------------------------------------
- * On | AutoBoth | AutoFull | AutoHalf |
- * -----------------------------------------------------------------
- * Sense | AutoSense | AutoSense | AutoSense |
- */
-int Capabilities[3][3] =
- { { -1, SK_LMODE_FULL , SK_LMODE_HALF },
- {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
- {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
-
-#define DC_BOTH 0
-#define DC_FULL 1
-#define DC_HALF 2
-#define AN_OFF 0
-#define AN_ON 1
-#define AN_SENS 2
-#define M_CurrPort pAC->GIni.GP[Port]
-
-
- /*
- ** Set the default values first for both ports!
- */
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO;
- }
-
- /*
- ** Check merged parameter ConType. If it has not been used,
- ** verify any other parameter (e.g. AutoNeg) and use default values.
- **
- ** Stating both ConType and other lowlevel link parameters is also
- ** possible. If this is the case, the passed ConType-parameter is
- ** overwritten by the lowlevel link parameter.
- **
- ** The following settings are used for a merged ConType-parameter:
- **
- ** ConType DupCap AutoNeg FlowCtrl Role Speed
- ** ------- ------ ------- -------- ---------- -----
- ** Auto Both On SymOrRem Auto Auto
- ** 100FD Full Off None <ignored> 100
- ** 100HD Half Off None <ignored> 100
- ** 10FD Full Off None <ignored> 10
- ** 10HD Half Off None <ignored> 10
- **
- ** This ConType parameter is used for all ports of the adapter!
- */
- if ( (ConType != NULL) &&
- (pAC->Index < SK_MAX_CARD_PARAM) &&
- (ConType[pAC->Index] != NULL) ) {
-
- /* Check chipset family */
- if ((!pAC->ChipsetType) &&
- (strcmp(ConType[pAC->Index],"Auto")!=0) &&
- (strcmp(ConType[pAC->Index],"")!=0)) {
- /* Set the speed parameter back */
- printk("sk98lin: Illegal value \"%s\" "
- "for ConType."
- " Using Auto.\n",
- ConType[pAC->Index]);
-
- sprintf(ConType[pAC->Index], "Auto");
- }
-
- if (strcmp(ConType[pAC->Index],"")==0) {
- IsConTypeDefined = SK_FALSE; /* No ConType defined */
- } else if (strcmp(ConType[pAC->Index],"Auto")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO;
- }
- } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
- }
- } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
- }
- } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
- }
- } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
- }
- } else {
- printk("sk98lin: Illegal value \"%s\" for ConType\n",
- ConType[pAC->Index]);
- IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
- }
- } else {
- IsConTypeDefined = SK_FALSE; /* No ConType defined */
- }
-
- /*
- ** Parse any parameter settings for port A:
- ** a) any LinkSpeed stated?
- */
- if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- Speed_A[pAC->Index] != NULL) {
- if (strcmp(Speed_A[pAC->Index],"")==0) {
- IsLinkSpeedDefined = SK_FALSE;
- } else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
- LinkSpeed = SK_LSPEED_AUTO;
- } else if (strcmp(Speed_A[pAC->Index],"10")==0) {
- LinkSpeed = SK_LSPEED_10MBPS;
- } else if (strcmp(Speed_A[pAC->Index],"100")==0) {
- LinkSpeed = SK_LSPEED_100MBPS;
- } else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
- LinkSpeed = SK_LSPEED_1000MBPS;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Speed_A\n",
- Speed_A[pAC->Index]);
- IsLinkSpeedDefined = SK_FALSE;
- }
- } else {
- IsLinkSpeedDefined = SK_FALSE;
- }
-
- /*
- ** Check speed parameter:
- ** Only copper type adapter and GE V2 cards
- */
- if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
- ((LinkSpeed != SK_LSPEED_AUTO) &&
- (LinkSpeed != SK_LSPEED_1000MBPS))) {
- printk("sk98lin: Illegal value for Speed_A. "
- "Not a copper card or GE V2 card\n Using "
- "speed 1000\n");
- LinkSpeed = SK_LSPEED_1000MBPS;
- }
-
- /*
- ** Decide whether to set new config value if somethig valid has
- ** been received.
- */
- if (IsLinkSpeedDefined) {
- pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
- }
-
- /*
- ** b) Any Autonegotiation and DuplexCapabilities set?
- ** Please note that both belong together...
- */
- AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
- AutoSet = SK_FALSE;
- if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- AutoNeg_A[pAC->Index] != NULL) {
- AutoSet = SK_TRUE;
- if (strcmp(AutoNeg_A[pAC->Index],"")==0) {
- AutoSet = SK_FALSE;
- } else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
- AutoNeg = AN_ON;
- } else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
- AutoNeg = AN_OFF;
- } else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
- AutoNeg = AN_SENS;
- } else {
- printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n",
- AutoNeg_A[pAC->Index]);
- }
- }
-
- DuplexCap = DC_BOTH;
- DupSet = SK_FALSE;
- if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- DupCap_A[pAC->Index] != NULL) {
- DupSet = SK_TRUE;
- if (strcmp(DupCap_A[pAC->Index],"")==0) {
- DupSet = SK_FALSE;
- } else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
- DuplexCap = DC_BOTH;
- } else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
- DuplexCap = DC_FULL;
- } else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
- DuplexCap = DC_HALF;
- } else {
- printk("sk98lin: Illegal value \"%s\" for DupCap_A\n",
- DupCap_A[pAC->Index]);
- }
- }
-
- /*
- ** Check for illegal combinations
- */
- if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
- ((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
- (DuplexCap == SK_LMODE_STAT_HALF)) &&
- (pAC->ChipsetType)) {
- printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
- " Using Full Duplex.\n");
- DuplexCap = DC_FULL;
- }
-
- if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
- printk("sk98lin, Port A: DuplexCapabilities"
- " ignored using Sense mode\n");
- }
-
- if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
- printk("sk98lin: Port A: Illegal combination"
- " of values AutoNeg. and DuplexCap.\n Using "
- "Full Duplex\n");
- DuplexCap = DC_FULL;
- }
-
- if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
- DuplexCap = DC_FULL;
- }
-
- if (!AutoSet && DupSet) {
- printk("sk98lin: Port A: Duplex setting not"
- " possible in\n default AutoNegotiation mode"
- " (Sense).\n Using AutoNegotiation On\n");
- AutoNeg = AN_ON;
- }
-
- /*
- ** set the desired mode
- */
- if (AutoSet || DupSet) {
- pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
- }
-
- /*
- ** c) Any Flowcontrol-parameter set?
- */
- if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- FlowCtrl_A[pAC->Index] != NULL) {
- if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) {
- IsFlowCtrlDefined = SK_FALSE;
- } else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
- FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
- } else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
- FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
- } else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
- FlowCtrl = SK_FLOW_MODE_LOC_SEND;
- } else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
- FlowCtrl = SK_FLOW_MODE_NONE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n",
- FlowCtrl_A[pAC->Index]);
- IsFlowCtrlDefined = SK_FALSE;
- }
- } else {
- IsFlowCtrlDefined = SK_FALSE;
- }
-
- if (IsFlowCtrlDefined) {
- if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
- printk("sk98lin: Port A: FlowControl"
- " impossible without AutoNegotiation,"
- " disabled\n");
- FlowCtrl = SK_FLOW_MODE_NONE;
- }
- pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
- }
-
- /*
- ** d) What is with the RoleParameter?
- */
- if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- Role_A[pAC->Index] != NULL) {
- if (strcmp(Role_A[pAC->Index],"")==0) {
- IsRoleDefined = SK_FALSE;
- } else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
- MSMode = SK_MS_MODE_AUTO;
- } else if (strcmp(Role_A[pAC->Index],"Master")==0) {
- MSMode = SK_MS_MODE_MASTER;
- } else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
- MSMode = SK_MS_MODE_SLAVE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Role_A\n",
- Role_A[pAC->Index]);
- IsRoleDefined = SK_FALSE;
- }
- } else {
- IsRoleDefined = SK_FALSE;
- }
-
- if (IsRoleDefined == SK_TRUE) {
- pAC->GIni.GP[0].PMSMode = MSMode;
- }
-
-
-
- /*
- ** Parse any parameter settings for port B:
- ** a) any LinkSpeed stated?
- */
- IsConTypeDefined = SK_TRUE;
- IsLinkSpeedDefined = SK_TRUE;
- IsFlowCtrlDefined = SK_TRUE;
- IsModeDefined = SK_TRUE;
-
- if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- Speed_B[pAC->Index] != NULL) {
- if (strcmp(Speed_B[pAC->Index],"")==0) {
- IsLinkSpeedDefined = SK_FALSE;
- } else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
- LinkSpeed = SK_LSPEED_AUTO;
- } else if (strcmp(Speed_B[pAC->Index],"10")==0) {
- LinkSpeed = SK_LSPEED_10MBPS;
- } else if (strcmp(Speed_B[pAC->Index],"100")==0) {
- LinkSpeed = SK_LSPEED_100MBPS;
- } else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
- LinkSpeed = SK_LSPEED_1000MBPS;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Speed_B\n",
- Speed_B[pAC->Index]);
- IsLinkSpeedDefined = SK_FALSE;
- }
- } else {
- IsLinkSpeedDefined = SK_FALSE;
- }
-
- /*
- ** Check speed parameter:
- ** Only copper type adapter and GE V2 cards
- */
- if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
- ((LinkSpeed != SK_LSPEED_AUTO) &&
- (LinkSpeed != SK_LSPEED_1000MBPS))) {
- printk("sk98lin: Illegal value for Speed_B. "
- "Not a copper card or GE V2 card\n Using "
- "speed 1000\n");
- LinkSpeed = SK_LSPEED_1000MBPS;
- }
-
- /*
- ** Decide whether to set new config value if somethig valid has
- ** been received.
- */
- if (IsLinkSpeedDefined) {
- pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
- }
-
- /*
- ** b) Any Autonegotiation and DuplexCapabilities set?
- ** Please note that both belong together...
- */
- AutoNeg = AN_SENS; /* default: do auto Sense */
- AutoSet = SK_FALSE;
- if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- AutoNeg_B[pAC->Index] != NULL) {
- AutoSet = SK_TRUE;
- if (strcmp(AutoNeg_B[pAC->Index],"")==0) {
- AutoSet = SK_FALSE;
- } else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
- AutoNeg = AN_ON;
- } else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
- AutoNeg = AN_OFF;
- } else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
- AutoNeg = AN_SENS;
- } else {
- printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n",
- AutoNeg_B[pAC->Index]);
- }
- }
-
- DuplexCap = DC_BOTH;
- DupSet = SK_FALSE;
- if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- DupCap_B[pAC->Index] != NULL) {
- DupSet = SK_TRUE;
- if (strcmp(DupCap_B[pAC->Index],"")==0) {
- DupSet = SK_FALSE;
- } else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
- DuplexCap = DC_BOTH;
- } else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
- DuplexCap = DC_FULL;
- } else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
- DuplexCap = DC_HALF;
- } else {
- printk("sk98lin: Illegal value \"%s\" for DupCap_B\n",
- DupCap_B[pAC->Index]);
- }
- }
-
-
- /*
- ** Check for illegal combinations
- */
- if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
- ((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
- (DuplexCap == SK_LMODE_STAT_HALF)) &&
- (pAC->ChipsetType)) {
- printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
- " Using Full Duplex.\n");
- DuplexCap = DC_FULL;
- }
-
- if (AutoSet && AutoNeg==AN_SENS && DupSet) {
- printk("sk98lin, Port B: DuplexCapabilities"
- " ignored using Sense mode\n");
- }
-
- if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
- printk("sk98lin: Port B: Illegal combination"
- " of values AutoNeg. and DuplexCap.\n Using "
- "Full Duplex\n");
- DuplexCap = DC_FULL;
- }
-
- if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
- DuplexCap = DC_FULL;
- }
-
- if (!AutoSet && DupSet) {
- printk("sk98lin: Port B: Duplex setting not"
- " possible in\n default AutoNegotiation mode"
- " (Sense).\n Using AutoNegotiation On\n");
- AutoNeg = AN_ON;
- }
-
- /*
- ** set the desired mode
- */
- if (AutoSet || DupSet) {
- pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
- }
-
- /*
- ** c) Any FlowCtrl parameter set?
- */
- if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- FlowCtrl_B[pAC->Index] != NULL) {
- if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) {
- IsFlowCtrlDefined = SK_FALSE;
- } else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
- FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
- } else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
- FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
- } else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
- FlowCtrl = SK_FLOW_MODE_LOC_SEND;
- } else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
- FlowCtrl = SK_FLOW_MODE_NONE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n",
- FlowCtrl_B[pAC->Index]);
- IsFlowCtrlDefined = SK_FALSE;
- }
- } else {
- IsFlowCtrlDefined = SK_FALSE;
- }
-
- if (IsFlowCtrlDefined) {
- if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
- printk("sk98lin: Port B: FlowControl"
- " impossible without AutoNegotiation,"
- " disabled\n");
- FlowCtrl = SK_FLOW_MODE_NONE;
- }
- pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
- }
-
- /*
- ** d) What is the RoleParameter?
- */
- if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- Role_B[pAC->Index] != NULL) {
- if (strcmp(Role_B[pAC->Index],"")==0) {
- IsRoleDefined = SK_FALSE;
- } else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
- MSMode = SK_MS_MODE_AUTO;
- } else if (strcmp(Role_B[pAC->Index],"Master")==0) {
- MSMode = SK_MS_MODE_MASTER;
- } else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
- MSMode = SK_MS_MODE_SLAVE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Role_B\n",
- Role_B[pAC->Index]);
- IsRoleDefined = SK_FALSE;
- }
- } else {
- IsRoleDefined = SK_FALSE;
- }
-
- if (IsRoleDefined) {
- pAC->GIni.GP[1].PMSMode = MSMode;
- }
-
- /*
- ** Evaluate settings for both ports
- */
- pAC->ActivePort = 0;
- if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- PrefPort[pAC->Index] != NULL) {
- if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */
- pAC->ActivePort = 0;
- pAC->Rlmt.Net[0].Preference = -1; /* auto */
- pAC->Rlmt.Net[0].PrefPort = 0;
- } else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
- /*
- ** do not set ActivePort here, thus a port
- ** switch is issued after net up.
- */
- Port = 0;
- pAC->Rlmt.Net[0].Preference = Port;
- pAC->Rlmt.Net[0].PrefPort = Port;
- } else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
- /*
- ** do not set ActivePort here, thus a port
- ** switch is issued after net up.
- */
- if (pAC->GIni.GIMacsFound == 1) {
- printk("sk98lin: Illegal value \"B\" for PrefPort.\n"
- " Port B not available on single port adapters.\n");
-
- pAC->ActivePort = 0;
- pAC->Rlmt.Net[0].Preference = -1; /* auto */
- pAC->Rlmt.Net[0].PrefPort = 0;
- } else {
- Port = 1;
- pAC->Rlmt.Net[0].Preference = Port;
- pAC->Rlmt.Net[0].PrefPort = Port;
- }
- } else {
- printk("sk98lin: Illegal value \"%s\" for PrefPort\n",
- PrefPort[pAC->Index]);
- }
- }
-
- pAC->RlmtNets = 1;
-
- if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- RlmtMode[pAC->Index] != NULL) {
- if (strcmp(RlmtMode[pAC->Index], "") == 0) {
- pAC->RlmtMode = 0;
- } else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK;
- } else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK |
- SK_RLMT_CHECK_LOC_LINK;
- } else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK |
- SK_RLMT_CHECK_LOC_LINK |
- SK_RLMT_CHECK_SEG;
- } else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
- (pAC->GIni.GIMacsFound == 2)) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK;
- pAC->RlmtNets = 2;
- } else {
- printk("sk98lin: Illegal value \"%s\" for"
- " RlmtMode, using default\n",
- RlmtMode[pAC->Index]);
- pAC->RlmtMode = 0;
- }
- } else {
- pAC->RlmtMode = 0;
- }
-
- /*
- ** Check the interrupt moderation parameters
- */
- if (Moderation[pAC->Index] != NULL) {
- if (strcmp(Moderation[pAC->Index], "") == 0) {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
- } else if (strcmp(Moderation[pAC->Index], "Static") == 0) {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
- } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC;
- } else if (strcmp(Moderation[pAC->Index], "None") == 0) {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Moderation.\n"
- " Disable interrupt moderation.\n",
- Moderation[pAC->Index]);
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
- }
- } else {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
- }
-
- if (Stats[pAC->Index] != NULL) {
- if (strcmp(Stats[pAC->Index], "Yes") == 0) {
- pAC->DynIrqModInfo.DisplayStats = SK_TRUE;
- } else {
- pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
- }
- } else {
- pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
- }
-
- if (ModerationMask[pAC->Index] != NULL) {
- if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
- } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY;
- } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY;
- } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
- } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
- } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
- } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
- } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
- } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
- } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else { /* some rubbish */
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
- }
- } else { /* operator has stated nothing */
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
- }
-
- if (AutoSizing[pAC->Index] != NULL) {
- if (strcmp(AutoSizing[pAC->Index], "On") == 0) {
- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
- } else {
- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
- }
- } else { /* operator has stated nothing */
- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
- }
-
- if (IntsPerSec[pAC->Index] != 0) {
- if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) ||
- (IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) {
- printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n"
- " Using default value of %i.\n",
- IntsPerSec[pAC->Index],
- C_INT_MOD_IPS_LOWER_RANGE,
- C_INT_MOD_IPS_UPPER_RANGE,
- C_INTS_PER_SEC_DEFAULT);
- pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
- } else {
- pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
- }
- } else {
- pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
- }
-
- /*
- ** Evaluate upper and lower moderation threshold
- */
- pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
- pAC->DynIrqModInfo.MaxModIntsPerSec +
- (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
-
- pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
- pAC->DynIrqModInfo.MaxModIntsPerSec -
- (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
-
- pAC->DynIrqModInfo.PrevTimeVal = jiffies; /* initial value */
-
-
-} /* GetConfiguration */
-
-
-/*****************************************************************************
- *
- * ProductStr - return a adapter identification string from vpd
- *
- * Description:
- * This function reads the product name string from the vpd area
- * and puts it the field pAC->DeviceString.
- *
- * Returns: N/A
- */
-static inline int ProductStr(
- SK_AC *pAC, /* pointer to adapter context */
- char *DeviceStr, /* result string */
- int StrLen /* length of the string */
-)
-{
-char Keyword[] = VPD_NAME; /* vpd productname identifier */
-int ReturnCode; /* return code from vpd_read */
-unsigned long Flags;
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- return ReturnCode;
-} /* ProductStr */
-
-/*****************************************************************************
- *
- * StartDrvCleanupTimer - Start timer to check for descriptors which
- * might be placed in descriptor ring, but
- * havent been handled up to now
- *
- * Description:
- * This function requests a HW-timer fo the Yukon card. The actions to
- * perform when this timer expires, are located in the SkDrvEvent().
- *
- * Returns: N/A
- */
-static void
-StartDrvCleanupTimer(SK_AC *pAC) {
- SK_EVPARA EventParam; /* Event struct for timer event */
-
- SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER;
- SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer,
- SK_DRV_RX_CLEANUP_TIMER_LENGTH,
- SKGE_DRV, SK_DRV_TIMER, EventParam);
-}
-
-/*****************************************************************************
- *
- * StopDrvCleanupTimer - Stop timer to check for descriptors
- *
- * Description:
- * This function requests a HW-timer fo the Yukon card. The actions to
- * perform when this timer expires, are located in the SkDrvEvent().
- *
- * Returns: N/A
- */
-static void
-StopDrvCleanupTimer(SK_AC *pAC) {
- SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer);
- SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER));
-}
-
-/****************************************************************************/
-/* functions for common modules *********************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- * SkDrvAllocRlmtMbuf - allocate an RLMT mbuf
- *
- * Description:
- * This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure
- * is embedded into a socket buff data area.
- *
- * Context:
- * runtime
- *
- * Returns:
- * NULL or pointer to Mbuf.
- */
-SK_MBUF *SkDrvAllocRlmtMbuf(
-SK_AC *pAC, /* pointer to adapter context */
-SK_IOC IoC, /* the IO-context */
-unsigned BufferSize) /* size of the requested buffer */
-{
-SK_MBUF *pRlmtMbuf; /* pointer to a new rlmt-mbuf structure */
-struct sk_buff *pMsgBlock; /* pointer to a new message block */
-
- pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC);
- if (pMsgBlock == NULL) {
- return (NULL);
- }
- pRlmtMbuf = (SK_MBUF*) pMsgBlock->data;
- skb_reserve(pMsgBlock, sizeof(SK_MBUF));
- pRlmtMbuf->pNext = NULL;
- pRlmtMbuf->pOs = pMsgBlock;
- pRlmtMbuf->pData = pMsgBlock->data; /* Data buffer. */
- pRlmtMbuf->Size = BufferSize; /* Data buffer size. */
- pRlmtMbuf->Length = 0; /* Length of packet (<= Size). */
- return (pRlmtMbuf);
-
-} /* SkDrvAllocRlmtMbuf */
-
-
-/*****************************************************************************
- *
- * SkDrvFreeRlmtMbuf - free an RLMT mbuf
- *
- * Description:
- * This routine frees one or more RLMT mbuf(s).
- *
- * Context:
- * runtime
- *
- * Returns:
- * Nothing
- */
-void SkDrvFreeRlmtMbuf(
-SK_AC *pAC, /* pointer to adapter context */
-SK_IOC IoC, /* the IO-context */
-SK_MBUF *pMbuf) /* size of the requested buffer */
-{
-SK_MBUF *pFreeMbuf;
-SK_MBUF *pNextMbuf;
-
- pFreeMbuf = pMbuf;
- do {
- pNextMbuf = pFreeMbuf->pNext;
- DEV_KFREE_SKB_ANY(pFreeMbuf->pOs);
- pFreeMbuf = pNextMbuf;
- } while ( pFreeMbuf != NULL );
-} /* SkDrvFreeRlmtMbuf */
-
-
-/*****************************************************************************
- *
- * SkOsGetTime - provide a time value
- *
- * Description:
- * This routine provides a time value. The unit is 1/HZ (defined by Linux).
- * It is not used for absolute time, but only for time differences.
- *
- *
- * Returns:
- * Time value
- */
-SK_U64 SkOsGetTime(SK_AC *pAC)
-{
- SK_U64 PrivateJiffies;
- SkOsGetTimeCurrent(pAC, &PrivateJiffies);
- return PrivateJiffies;
-} /* SkOsGetTime */
-
-
-/*****************************************************************************
- *
- * SkPciReadCfgDWord - read a 32 bit value from pci config space
- *
- * Description:
- * This routine reads a 32 bit value from the pci configuration
- * space.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciReadCfgDWord(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U32 *pVal) /* pointer to store the read value */
-{
- pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
- return(0);
-} /* SkPciReadCfgDWord */
-
-
-/*****************************************************************************
- *
- * SkPciReadCfgWord - read a 16 bit value from pci config space
- *
- * Description:
- * This routine reads a 16 bit value from the pci configuration
- * space.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciReadCfgWord(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U16 *pVal) /* pointer to store the read value */
-{
- pci_read_config_word(pAC->PciDev, PciAddr, pVal);
- return(0);
-} /* SkPciReadCfgWord */
-
-
-/*****************************************************************************
- *
- * SkPciReadCfgByte - read a 8 bit value from pci config space
- *
- * Description:
- * This routine reads a 8 bit value from the pci configuration
- * space.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciReadCfgByte(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U8 *pVal) /* pointer to store the read value */
-{
- pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
- return(0);
-} /* SkPciReadCfgByte */
-
-
-/*****************************************************************************
- *
- * SkPciWriteCfgWord - write a 16 bit value to pci config space
- *
- * Description:
- * This routine writes a 16 bit value to the pci configuration
- * space. The flag PciConfigUp indicates whether the config space
- * is accesible or must be set up first.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciWriteCfgWord(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U16 Val) /* pointer to store the read value */
-{
- pci_write_config_word(pAC->PciDev, PciAddr, Val);
- return(0);
-} /* SkPciWriteCfgWord */
-
-
-/*****************************************************************************
- *
- * SkPciWriteCfgWord - write a 8 bit value to pci config space
- *
- * Description:
- * This routine writes a 8 bit value to the pci configuration
- * space. The flag PciConfigUp indicates whether the config space
- * is accesible or must be set up first.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciWriteCfgByte(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U8 Val) /* pointer to store the read value */
-{
- pci_write_config_byte(pAC->PciDev, PciAddr, Val);
- return(0);
-} /* SkPciWriteCfgByte */
-
-
-/*****************************************************************************
- *
- * SkDrvEvent - handle driver events
- *
- * Description:
- * This function handles events from all modules directed to the driver
- *
- * Context:
- * Is called under protection of slow path lock.
- *
- * Returns:
- * 0 if everything ok
- * < 0 on error
- *
- */
-int SkDrvEvent(
-SK_AC *pAC, /* pointer to adapter context */
-SK_IOC IoC, /* io-context */
-SK_U32 Event, /* event-id */
-SK_EVPARA Param) /* event-parameter */
-{
-SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */
-struct sk_buff *pMsg; /* pointer to a message block */
-int FromPort; /* the port from which we switch away */
-int ToPort; /* the port we switch to */
-SK_EVPARA NewPara; /* parameter for further events */
-int Stat;
-unsigned long Flags;
-SK_BOOL DualNet;
-
- switch (Event) {
- case SK_DRV_ADAP_FAIL:
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("ADAPTER FAIL EVENT\n"));
- printk("%s: Adapter failed.\n", pAC->dev[0]->name);
- /* disable interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- /* cgoos */
- break;
- case SK_DRV_PORT_FAIL:
- FromPort = Param.Para32[0];
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("PORT FAIL EVENT, Port: %d\n", FromPort));
- if (FromPort == 0) {
- printk("%s: Port A failed.\n", pAC->dev[0]->name);
- } else {
- printk("%s: Port B failed.\n", pAC->dev[1]->name);
- }
- /* cgoos */
- break;
- case SK_DRV_PORT_RESET: /* SK_U32 PortIdx */
- /* action list 4 */
- FromPort = Param.Para32[0];
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("PORT RESET EVENT, Port: %d ", FromPort));
- NewPara.Para64 = FromPort;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
- spin_lock_irqsave(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
-
- SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
- netif_carrier_off(pAC->dev[Param.Para32[0]]);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
-
- /* clear rx ring from received frames */
- ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
-
- ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
- spin_lock_irqsave(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
-
- /* tschilling: Handling of return value inserted. */
- if (SkGeInitPort(pAC, IoC, FromPort)) {
- if (FromPort == 0) {
- printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
- } else {
- printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
- }
- }
- SkAddrMcUpdate(pAC,IoC, FromPort);
- PortReInitBmu(pAC, FromPort);
- SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
- ClearAndStartRx(pAC, FromPort);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- break;
- case SK_DRV_NET_UP: /* SK_U32 PortIdx */
- { struct net_device *dev = pAC->dev[Param.Para32[0]];
- /* action list 5 */
- FromPort = Param.Para32[0];
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("NET UP EVENT, Port: %d ", Param.Para32[0]));
- /* Mac update */
- SkAddrMcUpdate(pAC,IoC, FromPort);
-
- if (DoPrintInterfaceChange) {
- printk("%s: network connection up using"
- " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
-
- /* tschilling: Values changed according to LinkSpeedUsed. */
- Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
- if (Stat == SK_LSPEED_STAT_10MBPS) {
- printk(" speed: 10\n");
- } else if (Stat == SK_LSPEED_STAT_100MBPS) {
- printk(" speed: 100\n");
- } else if (Stat == SK_LSPEED_STAT_1000MBPS) {
- printk(" speed: 1000\n");
- } else {
- printk(" speed: unknown\n");
- }
-
-
- Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
- if (Stat == SK_LMODE_STAT_AUTOHALF ||
- Stat == SK_LMODE_STAT_AUTOFULL) {
- printk(" autonegotiation: yes\n");
- }
- else {
- printk(" autonegotiation: no\n");
- }
- if (Stat == SK_LMODE_STAT_AUTOHALF ||
- Stat == SK_LMODE_STAT_HALF) {
- printk(" duplex mode: half\n");
- }
- else {
- printk(" duplex mode: full\n");
- }
- Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
- if (Stat == SK_FLOW_STAT_REM_SEND ) {
- printk(" flowctrl: remote send\n");
- }
- else if (Stat == SK_FLOW_STAT_LOC_SEND ){
- printk(" flowctrl: local send\n");
- }
- else if (Stat == SK_FLOW_STAT_SYMMETRIC ){
- printk(" flowctrl: symmetric\n");
- }
- else {
- printk(" flowctrl: none\n");
- }
-
- /* tschilling: Check against CopperType now. */
- if ((pAC->GIni.GICopperType == SK_TRUE) &&
- (pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
- SK_LSPEED_STAT_1000MBPS)) {
- Stat = pAC->GIni.GP[FromPort].PMSStatus;
- if (Stat == SK_MS_STAT_MASTER ) {
- printk(" role: master\n");
- }
- else if (Stat == SK_MS_STAT_SLAVE ) {
- printk(" role: slave\n");
- }
- else {
- printk(" role: ???\n");
- }
- }
-
- /*
- Display dim (dynamic interrupt moderation)
- informations
- */
- if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC)
- printk(" irq moderation: static (%d ints/sec)\n",
- pAC->DynIrqModInfo.MaxModIntsPerSec);
- else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC)
- printk(" irq moderation: dynamic (%d ints/sec)\n",
- pAC->DynIrqModInfo.MaxModIntsPerSec);
- else
- printk(" irq moderation: disabled\n");
-
-
- printk(" scatter-gather: %s\n",
- (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
- printk(" tx-checksum: %s\n",
- (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
- printk(" rx-checksum: %s\n",
- pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
-
- } else {
- DoPrintInterfaceChange = SK_TRUE;
- }
-
- if ((Param.Para32[0] != pAC->ActivePort) &&
- (pAC->RlmtNets == 1)) {
- NewPara.Para32[0] = pAC->ActivePort;
- NewPara.Para32[1] = Param.Para32[0];
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
- NewPara);
- }
-
- /* Inform the world that link protocol is up. */
- netif_carrier_on(dev);
- break;
- }
- case SK_DRV_NET_DOWN: /* SK_U32 Reason */
- /* action list 7 */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("NET DOWN EVENT "));
- if (DoPrintInterfaceChange) {
- printk("%s: network connection down\n",
- pAC->dev[Param.Para32[1]]->name);
- } else {
- DoPrintInterfaceChange = SK_TRUE;
- }
- netif_carrier_off(pAC->dev[Param.Para32[1]]);
- break;
- case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("PORT SWITCH HARD "));
- case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
- /* action list 6 */
- printk("%s: switching to port %c\n", pAC->dev[0]->name,
- 'A'+Param.Para32[1]);
- case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
- FromPort = Param.Para32[0];
- ToPort = Param.Para32[1];
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("PORT SWITCH EVENT, From: %d To: %d (Pref %d) ",
- FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort));
- NewPara.Para64 = FromPort;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
- NewPara.Para64 = ToPort;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
- spin_lock_irqsave(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
- SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
- spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
-
- ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
- ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
-
- ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
- ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
- spin_lock_irqsave(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- pAC->ActivePort = ToPort;
-#if 0
- SetQueueSizes(pAC);
-#else
- /* tschilling: New common function with minimum size check. */
- DualNet = SK_FALSE;
- if (pAC->RlmtNets == 2) {
- DualNet = SK_TRUE;
- }
-
- if (SkGeInitAssignRamToQueues(
- pAC,
- pAC->ActivePort,
- DualNet)) {
- spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- printk("SkGeInitAssignRamToQueues failed.\n");
- break;
- }
-#endif
- /* tschilling: Handling of return values inserted. */
- if (SkGeInitPort(pAC, IoC, FromPort) ||
- SkGeInitPort(pAC, IoC, ToPort)) {
- printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
- }
- if (Event == SK_DRV_SWITCH_SOFT) {
- SkMacRxTxEnable(pAC, IoC, FromPort);
- }
- SkMacRxTxEnable(pAC, IoC, ToPort);
- SkAddrSwap(pAC, IoC, FromPort, ToPort);
- SkAddrMcUpdate(pAC, IoC, FromPort);
- SkAddrMcUpdate(pAC, IoC, ToPort);
- PortReInitBmu(pAC, FromPort);
- PortReInitBmu(pAC, ToPort);
- SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
- SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
- ClearAndStartRx(pAC, FromPort);
- ClearAndStartRx(pAC, ToPort);
- spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- break;
- case SK_DRV_RLMT_SEND: /* SK_MBUF *pMb */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("RLS "));
- pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
- pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
- skb_put(pMsg, pRlmtMbuf->Length);
- if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
- pMsg) < 0)
-
- DEV_KFREE_SKB_ANY(pMsg);
- break;
- case SK_DRV_TIMER:
- if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
- /*
- ** expiration of the moderation timer implies that
- ** dynamic moderation is to be applied
- */
- SkDimStartModerationTimer(pAC);
- SkDimModerate(pAC);
- if (pAC->DynIrqModInfo.DisplayStats) {
- SkDimDisplayModerationSettings(pAC);
- }
- } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) {
- /*
- ** check if we need to check for descriptors which
- ** haven't been handled the last millisecs
- */
- StartDrvCleanupTimer(pAC);
- if (pAC->GIni.GIMacsFound == 2) {
- ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE);
- }
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE);
- } else {
- printk("Expiration of unknown timer\n");
- }
- break;
- default:
- break;
- }
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("END EVENT "));
-
- return (0);
-} /* SkDrvEvent */
-
-
-/*****************************************************************************
- *
- * SkErrorLog - log errors
- *
- * Description:
- * This function logs errors to the system buffer and to the console
- *
- * Returns:
- * 0 if everything ok
- * < 0 on error
- *
- */
-void SkErrorLog(
-SK_AC *pAC,
-int ErrClass,
-int ErrNum,
-char *pErrorMsg)
-{
-char ClassStr[80];
-
- switch (ErrClass) {
- case SK_ERRCL_OTHER:
- strcpy(ClassStr, "Other error");
- break;
- case SK_ERRCL_CONFIG:
- strcpy(ClassStr, "Configuration error");
- break;
- case SK_ERRCL_INIT:
- strcpy(ClassStr, "Initialization error");
- break;
- case SK_ERRCL_NORES:
- strcpy(ClassStr, "Out of resources error");
- break;
- case SK_ERRCL_SW:
- strcpy(ClassStr, "internal Software error");
- break;
- case SK_ERRCL_HW:
- strcpy(ClassStr, "Hardware failure");
- break;
- case SK_ERRCL_COMM:
- strcpy(ClassStr, "Communication error");
- break;
- }
- printk(KERN_INFO "%s: -- ERROR --\n Class: %s\n"
- " Nr: 0x%x\n Msg: %s\n", pAC->dev[0]->name,
- ClassStr, ErrNum, pErrorMsg);
-
-} /* SkErrorLog */
-
-#ifdef SK_DIAG_SUPPORT
-
-/*****************************************************************************
- *
- * SkDrvEnterDiagMode - handles DIAG attach request
- *
- * Description:
- * Notify the kernel to NOT access the card any longer due to DIAG
- * Deinitialize the Card
- *
- * Returns:
- * int
- */
-int SkDrvEnterDiagMode(
-SK_AC *pAc) /* pointer to adapter context */
-{
- DEV_NET *pNet = netdev_priv(pAc->dev[0]);
- SK_AC *pAC = pNet->pAC;
-
- SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct),
- sizeof(SK_PNMI_STRUCT_DATA));
-
- pAC->DiagModeActive = DIAG_ACTIVE;
- if (pAC->BoardLevel > SK_INIT_DATA) {
- if (netif_running(pAC->dev[0])) {
- pAC->WasIfUp[0] = SK_TRUE;
- pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */
- } else {
- pAC->WasIfUp[0] = SK_FALSE;
- }
- if (pNet != netdev_priv(pAC->dev[1])) {
- pNet = netdev_priv(pAC->dev[1]);
- if (netif_running(pAC->dev[1])) {
- pAC->WasIfUp[1] = SK_TRUE;
- pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvDeInitAdapter(pAC, 1); /* do SkGeClose */
- } else {
- pAC->WasIfUp[1] = SK_FALSE;
- }
- }
- pAC->BoardLevel = SK_INIT_DATA;
- }
- return(0);
-}
-
-/*****************************************************************************
- *
- * SkDrvLeaveDiagMode - handles DIAG detach request
- *
- * Description:
- * Notify the kernel to may access the card again after use by DIAG
- * Initialize the Card
- *
- * Returns:
- * int
- */
-int SkDrvLeaveDiagMode(
-SK_AC *pAc) /* pointer to adapter control context */
-{
- SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup),
- sizeof(SK_PNMI_STRUCT_DATA));
- pAc->DiagModeActive = DIAG_NOTACTIVE;
- pAc->Pnmi.DiagAttached = SK_DIAG_IDLE;
- if (pAc->WasIfUp[0] == SK_TRUE) {
- pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvInitAdapter(pAc, 0); /* first device */
- }
- if (pAc->WasIfUp[1] == SK_TRUE) {
- pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvInitAdapter(pAc, 1); /* second device */
- }
- return(0);
-}
-
-/*****************************************************************************
- *
- * ParseDeviceNbrFromSlotName - Evaluate PCI device number
- *
- * Description:
- * This function parses the PCI slot name information string and will
- * retrieve the devcie number out of it. The slot_name maintianed by
- * linux is in the form of '02:0a.0', whereas the first two characters
- * represent the bus number in hex (in the sample above this is
- * pci bus 0x02) and the next two characters the device number (0x0a).
- *
- * Returns:
- * SK_U32: The device number from the PCI slot name
- */
-
-static SK_U32 ParseDeviceNbrFromSlotName(
-const char *SlotName) /* pointer to pci slot name eg. '02:0a.0' */
-{
- char *CurrCharPos = (char *) SlotName;
- int FirstNibble = -1;
- int SecondNibble = -1;
- SK_U32 Result = 0;
-
- while (*CurrCharPos != '\0') {
- if (*CurrCharPos == ':') {
- while (*CurrCharPos != '.') {
- CurrCharPos++;
- if ( (*CurrCharPos >= '0') &&
- (*CurrCharPos <= '9')) {
- if (FirstNibble == -1) {
- /* dec. value for '0' */
- FirstNibble = *CurrCharPos - 48;
- } else {
- SecondNibble = *CurrCharPos - 48;
- }
- } else if ( (*CurrCharPos >= 'a') &&
- (*CurrCharPos <= 'f') ) {
- if (FirstNibble == -1) {
- FirstNibble = *CurrCharPos - 87;
- } else {
- SecondNibble = *CurrCharPos - 87;
- }
- } else {
- Result = 0;
- }
- }
-
- Result = FirstNibble;
- Result = Result << 4; /* first nibble is higher one */
- Result = Result | SecondNibble;
- }
- CurrCharPos++; /* next character */
- }
- return (Result);
-}
-
-/****************************************************************************
- *
- * SkDrvDeInitAdapter - deinitialize adapter (this function is only
- * called if Diag attaches to that card)
- *
- * Description:
- * Close initialized adapter.
- *
- * Returns:
- * 0 - on success
- * error code - on error
- */
-static int SkDrvDeInitAdapter(
-SK_AC *pAC, /* pointer to adapter context */
-int devNbr) /* what device is to be handled */
-{
- struct SK_NET_DEVICE *dev;
-
- dev = pAC->dev[devNbr];
-
- /* On Linux 2.6 the network driver does NOT mess with reference
- ** counts. The driver MUST be able to be unloaded at any time
- ** due to the possibility of hotplug.
- */
- if (SkGeClose(dev) != 0) {
- return (-1);
- }
- return (0);
-
-} /* SkDrvDeInitAdapter() */
-
-/****************************************************************************
- *
- * SkDrvInitAdapter - Initialize adapter (this function is only
- * called if Diag deattaches from that card)
- *
- * Description:
- * Close initialized adapter.
- *
- * Returns:
- * 0 - on success
- * error code - on error
- */
-static int SkDrvInitAdapter(
-SK_AC *pAC, /* pointer to adapter context */
-int devNbr) /* what device is to be handled */
-{
- struct SK_NET_DEVICE *dev;
-
- dev = pAC->dev[devNbr];
-
- if (SkGeOpen(dev) != 0) {
- return (-1);
- }
-
- /*
- ** Use correct MTU size and indicate to kernel TX queue can be started
- */
- if (SkGeChangeMtu(dev, dev->mtu) != 0) {
- return (-1);
- }
- return (0);
-
-} /* SkDrvInitAdapter */
-
-#endif
-
-#ifdef DEBUG
-/****************************************************************************/
-/* "debug only" section *****************************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- * DumpMsg - print a frame
- *
- * Description:
- * This function prints frames to the system logfile/to the console.
- *
- * Returns: N/A
- *
- */
-static void DumpMsg(struct sk_buff *skb, char *str)
-{
- int msglen;
-
- if (skb == NULL) {
- printk("DumpMsg(): NULL-Message\n");
- return;
- }
-
- if (skb->data == NULL) {
- printk("DumpMsg(): Message empty\n");
- return;
- }
-
- msglen = skb->len;
- if (msglen > 64)
- msglen = 64;
-
- printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len);
-
- DumpData((char *)skb->data, msglen);
-
- printk("------- End of message ---------\n");
-} /* DumpMsg */
-
-
-
-/*****************************************************************************
- *
- * DumpData - print a data area
- *
- * Description:
- * This function prints a area of data to the system logfile/to the
- * console.
- *
- * Returns: N/A
- *
- */
-static void DumpData(char *p, int size)
-{
-register int i;
-int haddr, addr;
-char hex_buffer[180];
-char asc_buffer[180];
-char HEXCHAR[] = "0123456789ABCDEF";
-
- addr = 0;
- haddr = 0;
- hex_buffer[0] = 0;
- asc_buffer[0] = 0;
- for (i=0; i < size; ) {
- if (*p >= '0' && *p <='z')
- asc_buffer[addr] = *p;
- else
- asc_buffer[addr] = '.';
- addr++;
- asc_buffer[addr] = 0;
- hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[*p & 0x0f];
- haddr++;
- hex_buffer[haddr] = ' ';
- haddr++;
- hex_buffer[haddr] = 0;
- p++;
- i++;
- if (i%16 == 0) {
- printk("%s %s\n", hex_buffer, asc_buffer);
- addr = 0;
- haddr = 0;
- }
- }
-} /* DumpData */
-
-
-/*****************************************************************************
- *
- * DumpLong - print a data area as long values
- *
- * Description:
- * This function prints a area of data to the system logfile/to the
- * console.
- *
- * Returns: N/A
- *
- */
-static void DumpLong(char *pc, int size)
-{
-register int i;
-int haddr, addr;
-char hex_buffer[180];
-char asc_buffer[180];
-char HEXCHAR[] = "0123456789ABCDEF";
-long *p;
-int l;
-
- addr = 0;
- haddr = 0;
- hex_buffer[0] = 0;
- asc_buffer[0] = 0;
- p = (long*) pc;
- for (i=0; i < size; ) {
- l = (long) *p;
- hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[l & 0x0f];
- haddr++;
- hex_buffer[haddr] = ' ';
- haddr++;
- hex_buffer[haddr] = 0;
- p++;
- i++;
- if (i%8 == 0) {
- printk("%4x %s\n", (i-8)*4, hex_buffer);
- haddr = 0;
- }
- }
- printk("------------------------\n");
-} /* DumpLong */
-
-#endif
-
-static int __devinit skge_probe_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- SK_AC *pAC;
- DEV_NET *pNet = NULL;
- struct net_device *dev = NULL;
- static int boards_found = 0;
- int error = -ENODEV;
- int using_dac = 0;
- char DeviceStr[80];
-
- if (pci_enable_device(pdev))
- goto out;
-
- /* Configure DMA attributes. */
- if (sizeof(dma_addr_t) > sizeof(u32) &&
- !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
- using_dac = 1;
- error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
- if (error < 0) {
- printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
- "for consistent allocations\n", pci_name(pdev));
- goto out_disable_device;
- }
- } else {
- error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- if (error) {
- printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
- pci_name(pdev));
- goto out_disable_device;
- }
- }
-
- error = -ENOMEM;
- dev = alloc_etherdev(sizeof(DEV_NET));
- if (!dev) {
- printk(KERN_ERR "sk98lin: unable to allocate etherdev "
- "structure!\n");
- goto out_disable_device;
- }
-
- pNet = netdev_priv(dev);
- pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
- if (!pNet->pAC) {
- printk(KERN_ERR "sk98lin: unable to allocate adapter "
- "structure!\n");
- goto out_free_netdev;
- }
-
- pAC = pNet->pAC;
- pAC->PciDev = pdev;
-
- pAC->dev[0] = dev;
- pAC->dev[1] = dev;
- pAC->CheckQueue = SK_FALSE;
-
- dev->irq = pdev->irq;
-
- error = SkGeInitPCI(pAC);
- if (error) {
- printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
- goto out_free_netdev;
- }
-
- SET_MODULE_OWNER(dev);
- dev->open = &SkGeOpen;
- dev->stop = &SkGeClose;
- dev->hard_start_xmit = &SkGeXmit;
- dev->get_stats = &SkGeStats;
- dev->set_multicast_list = &SkGeSetRxMode;
- dev->set_mac_address = &SkGeSetMacAddr;
- dev->do_ioctl = &SkGeIoctl;
- dev->change_mtu = &SkGeChangeMtu;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = &SkGePollController;
-#endif
- SET_NETDEV_DEV(dev, &pdev->dev);
- SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
- /* Use only if yukon hardware */
- if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
- dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
- dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
- pAC->RxPort[0].RxCsum = 1;
-#endif
- }
-
- if (using_dac)
- dev->features |= NETIF_F_HIGHDMA;
-
- pAC->Index = boards_found++;
-
- error = SkGeBoardInit(dev, pAC);
- if (error)
- goto out_free_netdev;
-
- /* Read Adapter name from VPD */
- if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
- error = -EIO;
- printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
- goto out_free_resources;
- }
-
- /* Register net device */
- error = register_netdev(dev);
- if (error) {
- printk(KERN_ERR "sk98lin: Could not register device.\n");
- goto out_free_resources;
- }
-
- /* Print adapter specific string from vpd */
- printk("%s: %s\n", dev->name, DeviceStr);
-
- /* Print configuration settings */
- printk(" PrefPort:%c RlmtMode:%s\n",
- 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
- (pAC->RlmtMode==0) ? "Check Link State" :
- ((pAC->RlmtMode==1) ? "Check Link State" :
- ((pAC->RlmtMode==3) ? "Check Local Port" :
- ((pAC->RlmtMode==7) ? "Check Segmentation" :
- ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
- SkGeYellowLED(pAC, pAC->IoBase, 1);
-
- memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
- pNet->PortNr = 0;
- pNet->NetNr = 0;
-
- boards_found++;
-
- pci_set_drvdata(pdev, dev);
-
- /* More then one port found */
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- dev = alloc_etherdev(sizeof(DEV_NET));
- if (!dev) {
- printk(KERN_ERR "sk98lin: unable to allocate etherdev "
- "structure!\n");
- goto single_port;
- }
-
- pNet = netdev_priv(dev);
- pNet->PortNr = 1;
- pNet->NetNr = 1;
- pNet->pAC = pAC;
-
- dev->open = &SkGeOpen;
- dev->stop = &SkGeClose;
- dev->hard_start_xmit = &SkGeXmit;
- dev->get_stats = &SkGeStats;
- dev->set_multicast_list = &SkGeSetRxMode;
- dev->set_mac_address = &SkGeSetMacAddr;
- dev->do_ioctl = &SkGeIoctl;
- dev->change_mtu = &SkGeChangeMtu;
- SET_NETDEV_DEV(dev, &pdev->dev);
- SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
- if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
- dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
- dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
- pAC->RxPort[1].RxCsum = 1;
-#endif
- }
-
- if (using_dac)
- dev->features |= NETIF_F_HIGHDMA;
-
- error = register_netdev(dev);
- if (error) {
- printk(KERN_ERR "sk98lin: Could not register device"
- " for second port. (%d)\n", error);
- free_netdev(dev);
- goto single_port;
- }
-
- pAC->dev[1] = dev;
- memcpy(&dev->dev_addr,
- &pAC->Addr.Net[1].CurrentMacAddress, 6);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
- printk("%s: %s\n", dev->name, DeviceStr);
- printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
- }
-
-single_port:
-
- /* Save the hardware revision */
- pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
- (pAC->GIni.GIPciHwRev & 0x0F);
-
- /* Set driver globals */
- pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME;
- pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
-
- memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
- memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
-
- return 0;
-
- out_free_resources:
- FreeResources(dev);
- out_free_netdev:
- free_netdev(dev);
- out_disable_device:
- pci_disable_device(pdev);
- out:
- return error;
-}
-
-static void __devexit skge_remove_one(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- struct net_device *otherdev = pAC->dev[1];
-
- unregister_netdev(dev);
-
- SkGeYellowLED(pAC, pAC->IoBase, 0);
-
- if (pAC->BoardLevel == SK_INIT_RUN) {
- SK_EVPARA EvPara;
- unsigned long Flags;
-
- /* board is still alive */
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- EvPara.Para32[0] = 0;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- EvPara.Para32[0] = 1;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
- /* disable interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- SkGeDeInit(pAC, pAC->IoBase);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- pAC->BoardLevel = SK_INIT_DATA;
- /* We do NOT check here, if IRQ was pending, of course*/
- }
-
- if (pAC->BoardLevel == SK_INIT_IO) {
- /* board is still alive */
- SkGeDeInit(pAC, pAC->IoBase);
- pAC->BoardLevel = SK_INIT_DATA;
- }
-
- FreeResources(dev);
- free_netdev(dev);
- if (otherdev != dev)
- free_netdev(otherdev);
- kfree(pAC);
-}
-
-#ifdef CONFIG_PM
-static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- struct net_device *otherdev = pAC->dev[1];
-
- if (netif_running(dev)) {
- netif_carrier_off(dev);
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */
- netif_device_detach(dev);
- }
- if (otherdev != dev) {
- if (netif_running(otherdev)) {
- netif_carrier_off(otherdev);
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */
- netif_device_detach(otherdev);
- }
- }
-
- pci_save_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
- if (pAC->AllocFlag & SK_ALLOC_IRQ) {
- free_irq(dev->irq, dev);
- }
- pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
- return 0;
-}
-
-static int skge_resume(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- struct net_device *otherdev = pAC->dev[1];
- int ret;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- ret = pci_enable_device(pdev);
- if (ret) {
- printk(KERN_WARNING "sk98lin: unable to enable device %s "
- "in resume\n", dev->name);
- goto err_out;
- }
- pci_set_master(pdev);
- if (pAC->GIni.GIMacsFound == 2)
- ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
- else
- ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "sk98lin", dev);
- if (ret) {
- printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
- ret = -EBUSY;
- goto err_out_disable_pdev;
- }
-
- netif_device_attach(dev);
- if (netif_running(dev)) {
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvInitAdapter(pAC, 0); /* first device */
- }
- if (otherdev != dev) {
- netif_device_attach(otherdev);
- if (netif_running(otherdev)) {
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvInitAdapter(pAC, 1); /* second device */
- }
- }
-
- return 0;
-
-err_out_disable_pdev:
- pci_disable_device(pdev);
-err_out:
- pAC->AllocFlag &= ~SK_ALLOC_IRQ;
- dev->irq = 0;
- return ret;
-}
-#else
-#define skge_suspend NULL
-#define skge_resume NULL
-#endif
-
-static struct pci_device_id skge_pci_tbl[] = {
- { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-/* DLink card does not have valid VPD so this driver gags
- * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- */
- { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
- { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
-
-static struct pci_driver skge_driver = {
- .name = "sk98lin",
- .id_table = skge_pci_tbl,
- .probe = skge_probe_one,
- .remove = __devexit_p(skge_remove_one),
- .suspend = skge_suspend,
- .resume = skge_resume,
-};
-
-static int __init skge_init(void)
-{
- printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
- " and is scheduled for removal\n");
-
- return pci_register_driver(&skge_driver);
-}
-
-static void __exit skge_exit(void)
-{
- pci_unregister_driver(&skge_driver);
-}
-
-module_init(skge_init);
-module_exit(skge_exit);
diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c
deleted file mode 100644
index db670993c2d..00000000000
--- a/drivers/net/sk98lin/skgehwt.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/******************************************************************************
- *
- * Name: skgehwt.c
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.15 $
- * Date: $Date: 2003/09/16 13:41:23 $
- * Purpose: Hardware Timer
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- * Hardware Timer function queue management.
- */
-intro()
-{}
-#endif
-
-/*
- * Prototypes of local functions.
- */
-#define SK_HWT_MAX (65000)
-
-/* correction factor */
-#define SK_HWT_FAC (1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100)
-
-/*
- * Initialize hardware timer.
- *
- * Must be called during init level 1.
- */
-void SkHwtInit(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- pAC->Hwt.TStart = 0 ;
- pAC->Hwt.TStop = 0 ;
- pAC->Hwt.TActive = SK_FALSE;
-
- SkHwtStop(pAC, Ioc);
-}
-
-/*
- *
- * Start hardware timer (clock ticks are 16us).
- *
- */
-void SkHwtStart(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-SK_U32 Time) /* Time in units of 16us to load the timer with. */
-{
- SK_U32 Cnt;
-
- if (Time > SK_HWT_MAX)
- Time = SK_HWT_MAX;
-
- pAC->Hwt.TStart = Time;
- pAC->Hwt.TStop = 0L;
-
- Cnt = Time;
-
- /*
- * if time < 16 us
- * time = 16 us
- */
- if (!Cnt) {
- Cnt++;
- }
-
- SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC);
-
- SK_OUT16(Ioc, B2_TI_CTRL, TIM_START); /* Start timer. */
-
- pAC->Hwt.TActive = SK_TRUE;
-}
-
-/*
- * Stop hardware timer.
- * and clear the timer IRQ
- */
-void SkHwtStop(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP);
-
- SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ);
-
- pAC->Hwt.TActive = SK_FALSE;
-}
-
-
-/*
- * Stop hardware timer and read time elapsed since last start.
- *
- * returns
- * The elapsed time since last start in units of 16us.
- *
- */
-SK_U32 SkHwtRead(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- SK_U32 TRead;
- SK_U32 IStatus;
-
- if (pAC->Hwt.TActive) {
-
- SkHwtStop(pAC, Ioc);
-
- SK_IN32(Ioc, B2_TI_VAL, &TRead);
- TRead /= SK_HWT_FAC;
-
- SK_IN32(Ioc, B0_ISRC, &IStatus);
-
- /* Check if timer expired (or wraped around) */
- if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) {
-
- SkHwtStop(pAC, Ioc);
-
- pAC->Hwt.TStop = pAC->Hwt.TStart;
- }
- else {
-
- pAC->Hwt.TStop = pAC->Hwt.TStart - TRead;
- }
- }
- return(pAC->Hwt.TStop);
-}
-
-/*
- * interrupt source= timer
- */
-void SkHwtIsr(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- SkHwtStop(pAC, Ioc);
-
- pAC->Hwt.TStop = pAC->Hwt.TStart;
-
- SkTimerDone(pAC, Ioc);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
deleted file mode 100644
index 67f1d6a5c15..00000000000
--- a/drivers/net/sk98lin/skgeinit.c
+++ /dev/null
@@ -1,2005 +0,0 @@
-/******************************************************************************
- *
- * Name: skgeinit.c
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.97 $
- * Date: $Date: 2003/10/02 16:45:31 $
- * Purpose: Contains functions to initialize the adapter
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* global variables ***********************************************************/
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell.";
-#endif
-
-struct s_QOffTab {
- int RxQOff; /* Receive Queue Address Offset */
- int XsQOff; /* Sync Tx Queue Address Offset */
- int XaQOff; /* Async Tx Queue Address Offset */
-};
-static struct s_QOffTab QOffTab[] = {
- {Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2}
-};
-
-struct s_Config {
- char ScanString[8];
- SK_U32 Value;
-};
-
-static struct s_Config OemConfig = {
- {'O','E','M','_','C','o','n','f'},
-#ifdef SK_OEM_CONFIG
- OEM_CONFIG_VALUE,
-#else
- 0,
-#endif
-};
-
-/******************************************************************************
- *
- * SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings
- *
- * Description:
- * Enable or disable the descriptor polling of the transmit descriptor
- * ring(s) (TxD) for port 'Port'.
- * The new configuration is *not* saved over any SkGeStopPort() and
- * SkGeInitPort() calls.
- *
- * Returns:
- * nothing
- */
-void SkGePollTxD(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
-{
- SK_GEPORT *pPrt;
- SK_U32 DWord;
-
- pPrt = &pAC->GIni.GP[Port];
-
- DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL);
-
- if (pPrt->PXSQSize != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord);
- }
-
- if (pPrt->PXAQSize != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord);
- }
-} /* SkGePollTxD */
-
-
-/******************************************************************************
- *
- * SkGeYellowLED() - Switch the yellow LED on or off.
- *
- * Description:
- * Switch the yellow LED on or off.
- *
- * Note:
- * This function may be called any time after SkGeInit(Level 1).
- *
- * Returns:
- * nothing
- */
-void SkGeYellowLED(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int State) /* yellow LED state, 0 = OFF, 0 != ON */
-{
- if (State == 0) {
- /* Switch yellow LED OFF */
- SK_OUT8(IoC, B0_LED, LED_STAT_OFF);
- }
- else {
- /* Switch yellow LED ON */
- SK_OUT8(IoC, B0_LED, LED_STAT_ON);
- }
-} /* SkGeYellowLED */
-
-
-#if (!defined(SK_SLIM) || defined(GENESIS))
-/******************************************************************************
- *
- * SkGeXmitLED() - Modify the Operational Mode of a transmission LED.
- *
- * Description:
- * The Rx or Tx LED which is specified by 'Led' will be
- * enabled, disabled or switched on in test mode.
- *
- * Note:
- * 'Led' must contain the address offset of the LEDs INI register.
- *
- * Usage:
- * SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
- *
- * Returns:
- * nothing
- */
-void SkGeXmitLED(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Led, /* offset to the LED Init Value register */
-int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */
-{
- SK_U32 LedIni;
-
- switch (Mode) {
- case SK_LED_ENA:
- LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
- SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni);
- SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
- break;
- case SK_LED_TST:
- SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON);
- SK_OUT32(IoC, Led + XMIT_LED_CNT, 100);
- SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
- break;
- case SK_LED_DIS:
- default:
- /*
- * Do NOT stop the LED Timer here. The LED might be
- * in on state. But it needs to go off.
- */
- SK_OUT32(IoC, Led + XMIT_LED_CNT, 0);
- SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF);
- break;
- }
-
- /*
- * 1000BT: The Transmit LED is driven by the PHY.
- * But the default LED configuration is used for
- * Level One and Broadcom PHYs.
- * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.)
- * (In this case it has to be added here. But we will see. XXX)
- */
-} /* SkGeXmitLED */
-#endif /* !SK_SLIM || GENESIS */
-
-
-/******************************************************************************
- *
- * DoCalcAddr() - Calculates the start and the end address of a queue.
- *
- * Description:
- * This function calculates the start and the end address of a queue.
- * Afterwards the 'StartVal' is incremented to the next start position.
- * If the port is already initialized the calculated values
- * will be checked against the configured values and an
- * error will be returned, if they are not equal.
- * If the port is not initialized the values will be written to
- * *StartAdr and *EndAddr.
- *
- * Returns:
- * 0: success
- * 1: configuration error
- */
-static int DoCalcAddr(
-SK_AC *pAC, /* adapter context */
-SK_GEPORT SK_FAR *pPrt, /* port index */
-int QuSize, /* size of the queue to configure in kB */
-SK_U32 SK_FAR *StartVal, /* start value for address calculation */
-SK_U32 SK_FAR *QuStartAddr,/* start addr to calculate */
-SK_U32 SK_FAR *QuEndAddr) /* end address to calculate */
-{
- SK_U32 EndVal;
- SK_U32 NextStart;
- int Rtv;
-
- Rtv = 0;
- if (QuSize == 0) {
- EndVal = *StartVal;
- NextStart = EndVal;
- }
- else {
- EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1;
- NextStart = EndVal + 1;
- }
-
- if (pPrt->PState >= SK_PRT_INIT) {
- if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) {
- Rtv = 1;
- }
- }
- else {
- *QuStartAddr = *StartVal;
- *QuEndAddr = EndVal;
- }
-
- *StartVal = NextStart;
- return(Rtv);
-} /* DoCalcAddr */
-
-/******************************************************************************
- *
- * SkGeInitAssignRamToQueues() - allocate default queue sizes
- *
- * Description:
- * This function assigns the memory to the different queues and ports.
- * When DualNet is set to SK_TRUE all ports get the same amount of memory.
- * Otherwise the first port gets most of the memory and all the
- * other ports just the required minimum.
- * This function can only be called when pAC->GIni.GIRamSize and
- * pAC->GIni.GIMacsFound have been initialized, usually this happens
- * at init level 1
- *
- * Returns:
- * 0 - ok
- * 1 - invalid input values
- * 2 - not enough memory
- */
-
-int SkGeInitAssignRamToQueues(
-SK_AC *pAC, /* Adapter context */
-int ActivePort, /* Active Port in RLMT mode */
-SK_BOOL DualNet) /* adapter context */
-{
- int i;
- int UsedKilobytes; /* memory already assigned */
- int ActivePortKilobytes; /* memory available for active port */
- SK_GEPORT *pGePort;
-
- UsedKilobytes = 0;
-
- if (ActivePort >= pAC->GIni.GIMacsFound) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
- ("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n",
- ActivePort));
- return(1);
- }
- if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) +
- ((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
- ("SkGeInitAssignRamToQueues: Not enough memory (%d)\n",
- pAC->GIni.GIRamSize));
- return(2);
- }
-
- if (DualNet) {
- /* every port gets the same amount of memory */
- ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound;
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
- pGePort = &pAC->GIni.GP[i];
-
- /* take away the minimum memory for active queues */
- ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
-
- /* receive queue gets the minimum + 80% of the rest */
- pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((
- ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100))
- + SK_MIN_RXQ_SIZE;
-
- ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
- /* synchronous transmit queue */
- pGePort->PXSQSize = 0;
-
- /* asynchronous transmit queue */
- pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes +
- SK_MIN_TXQ_SIZE);
- }
- }
- else {
- /* Rlmt Mode or single link adapter */
-
- /* Set standby queue size defaults for all standby ports */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
- if (i != ActivePort) {
- pGePort = &pAC->GIni.GP[i];
-
- pGePort->PRxQSize = SK_MIN_RXQ_SIZE;
- pGePort->PXAQSize = SK_MIN_TXQ_SIZE;
- pGePort->PXSQSize = 0;
-
- /* Count used RAM */
- UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize;
- }
- }
- /* what's left? */
- ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes;
-
- /* assign it to the active port */
- /* first take away the minimum memory */
- ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
- pGePort = &pAC->GIni.GP[ActivePort];
-
- /* receive queue get's the minimum + 80% of the rest */
- pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes *
- (unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE;
-
- ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
- /* synchronous transmit queue */
- pGePort->PXSQSize = 0;
-
- /* asynchronous transmit queue */
- pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) +
- SK_MIN_TXQ_SIZE;
- }
-#ifdef VCPU
- VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n",
- pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize);
-#endif /* VCPU */
-
- return(0);
-} /* SkGeInitAssignRamToQueues */
-
-/******************************************************************************
- *
- * SkGeCheckQSize() - Checks the Adapters Queue Size Configuration
- *
- * Description:
- * This function verifies the Queue Size Configuration specified
- * in the variables PRxQSize, PXSQSize, and PXAQSize of all
- * used ports.
- * This requirements must be fullfilled to have a valid configuration:
- * - The size of all queues must not exceed GIRamSize.
- * - The queue sizes must be specified in units of 8 kB.
- * - The size of Rx queues of available ports must not be
- * smaller than 16 kB.
- * - The size of at least one Tx queue (synch. or asynch.)
- * of available ports must not be smaller than 16 kB
- * when Jumbo Frames are used.
- * - The RAM start and end addresses must not be changed
- * for ports which are already initialized.
- * Furthermore SkGeCheckQSize() defines the Start and End Addresses
- * of all ports and stores them into the HWAC port structure.
- *
- * Returns:
- * 0: Queue Size Configuration valid
- * 1: Queue Size Configuration invalid
- */
-static int SkGeCheckQSize(
-SK_AC *pAC, /* adapter context */
-int Port) /* port index */
-{
- SK_GEPORT *pPrt;
- int i;
- int Rtv;
- int Rtv2;
- SK_U32 StartAddr;
-#ifndef SK_SLIM
- int UsedMem; /* total memory used (max. found ports) */
-#endif
-
- Rtv = 0;
-
-#ifndef SK_SLIM
-
- UsedMem = 0;
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- pPrt = &pAC->GIni.GP[i];
-
- if ((pPrt->PRxQSize & QZ_UNITS) != 0 ||
- (pPrt->PXSQSize & QZ_UNITS) != 0 ||
- (pPrt->PXAQSize & QZ_UNITS) != 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
- return(1);
- }
-
- if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG);
- return(1);
- }
-
- /*
- * the size of at least one Tx queue (synch. or asynch.) has to be > 0.
- * if Jumbo Frames are used, this size has to be >= 16 kB.
- */
- if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) ||
- (pAC->GIni.GIPortUsage == SK_JUMBO_LINK &&
- ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
- (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG);
- return(1);
- }
-
- UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize;
- }
-
- if (UsedMem > pAC->GIni.GIRamSize) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
- return(1);
- }
-#endif /* !SK_SLIM */
-
- /* Now start address calculation */
- StartAddr = pAC->GIni.GIRamOffs;
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- pPrt = &pAC->GIni.GP[i];
-
- /* Calculate/Check values for the receive queue */
- Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr,
- &pPrt->PRxQRamStart, &pPrt->PRxQRamEnd);
- Rtv |= Rtv2;
-
- /* Calculate/Check values for the synchronous Tx queue */
- Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr,
- &pPrt->PXsQRamStart, &pPrt->PXsQRamEnd);
- Rtv |= Rtv2;
-
- /* Calculate/Check values for the asynchronous Tx queue */
- Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr,
- &pPrt->PXaQRamStart, &pPrt->PXaQRamEnd);
- Rtv |= Rtv2;
-
- if (Rtv) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG);
- return(1);
- }
- }
-
- return(0);
-} /* SkGeCheckQSize */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGeInitMacArb() - Initialize the MAC Arbiter
- *
- * Description:
- * This function initializes the MAC Arbiter.
- * It must not be called if there is still an
- * initialized or active port.
- *
- * Returns:
- * nothing
- */
-static void SkGeInitMacArb(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- /* release local reset */
- SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR);
-
- /* configure timeout values */
- SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53);
- SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53);
- SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53);
- SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53);
-
- SK_OUT8(IoC, B3_MA_RCINI_RX1, 0);
- SK_OUT8(IoC, B3_MA_RCINI_RX2, 0);
- SK_OUT8(IoC, B3_MA_RCINI_TX1, 0);
- SK_OUT8(IoC, B3_MA_RCINI_TX2, 0);
-
- /* recovery values are needed for XMAC II Rev. B2 only */
- /* Fast Output Enable Mode was intended to use with Rev. B2, but now? */
-
- /*
- * There is no start or enable button to push, therefore
- * the MAC arbiter is configured and enabled now.
- */
-} /* SkGeInitMacArb */
-
-
-/******************************************************************************
- *
- * SkGeInitPktArb() - Initialize the Packet Arbiter
- *
- * Description:
- * This function initializes the Packet Arbiter.
- * It must not be called if there is still an
- * initialized or active port.
- *
- * Returns:
- * nothing
- */
-static void SkGeInitPktArb(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- /* release local reset */
- SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR);
-
- /* configure timeout values */
- SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
- SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
- SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
- SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
-
- /*
- * enable timeout timers if jumbo frames not used
- * NOTE: the packet arbiter timeout interrupt is needed for
- * half duplex hangup workaround
- */
- if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) {
- if (pAC->GIni.GIMacsFound == 1) {
- SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1);
- }
- else {
- SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2);
- }
- }
-} /* SkGeInitPktArb */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkGeInitMacFifo() - Initialize the MAC FIFOs
- *
- * Description:
- * Initialize all MAC FIFOs of the specified port
- *
- * Returns:
- * nothing
- */
-static void SkGeInitMacFifo(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 Word;
-#ifdef VCPU
- SK_U32 DWord;
-#endif /* VCPU */
- /*
- * For each FIFO:
- * - release local reset
- * - use default value for MAC FIFO size
- * - setup defaults for the control register
- * - enable the FIFO
- */
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* Configure Rx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR);
- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF);
- SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
-
- /* Configure Tx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR);
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
- SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
-
- /* Enable frame flushing if jumbo frames used */
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH);
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* set Rx GMAC FIFO Flush Mask */
- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK);
-
- Word = (SK_U16)GMF_RX_CTRL_DEF;
-
- /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
- if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-
- Word &= ~GMF_RX_F_FL_ON;
- }
-
- /* Configure Rx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word);
-
- /* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */
- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
-
- /* Configure Tx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
- SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
-
-#ifdef VCPU
- SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord);
- SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord);
-#endif /* VCPU */
-
- /* set Tx GMAC FIFO Almost Empty Threshold */
-/* SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */
- }
-#endif /* YUKON */
-
-} /* SkGeInitMacFifo */
-
-#ifdef SK_LNK_SYNC_CNT
-/******************************************************************************
- *
- * SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting
- *
- * Description:
- * This function starts the Link Sync Counter of the specified
- * port and enables the generation of an Link Sync IRQ.
- * The Link Sync Counter may be used to detect an active link,
- * if autonegotiation is not used.
- *
- * Note:
- * o To ensure receiving the Link Sync Event the LinkSyncCounter
- * should be initialized BEFORE clearing the XMAC's reset!
- * o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this
- * function.
- *
- * Returns:
- * nothing
- */
-void SkGeLoadLnkSyncCnt(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U32 CntVal) /* Counter value */
-{
- SK_U32 OrgIMsk;
- SK_U32 NewIMsk;
- SK_U32 ISrc;
- SK_BOOL IrqPend;
-
- /* stop counter */
- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP);
-
- /*
- * ASIC problem:
- * Each time starting the Link Sync Counter an IRQ is generated
- * by the adapter. See problem report entry from 21.07.98
- *
- * Workaround: Disable Link Sync IRQ and clear the unexpeced IRQ
- * if no IRQ is already pending.
- */
- IrqPend = SK_FALSE;
- SK_IN32(IoC, B0_ISRC, &ISrc);
- SK_IN32(IoC, B0_IMSK, &OrgIMsk);
- if (Port == MAC_1) {
- NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1;
- if ((ISrc & IS_LNK_SYNC_M1) != 0) {
- IrqPend = SK_TRUE;
- }
- }
- else {
- NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2;
- if ((ISrc & IS_LNK_SYNC_M2) != 0) {
- IrqPend = SK_TRUE;
- }
- }
- if (!IrqPend) {
- SK_OUT32(IoC, B0_IMSK, NewIMsk);
- }
-
- /* load counter */
- SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal);
-
- /* start counter */
- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START);
-
- if (!IrqPend) {
- /* clear the unexpected IRQ, and restore the interrupt mask */
- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ);
- SK_OUT32(IoC, B0_IMSK, OrgIMsk);
- }
-} /* SkGeLoadLnkSyncCnt*/
-#endif /* SK_LNK_SYNC_CNT */
-
-#if defined(SK_DIAG) || defined(SK_CFG_SYNC)
-/******************************************************************************
- *
- * SkGeCfgSync() - Configure synchronous bandwidth for this port.
- *
- * Description:
- * This function may be used to configure synchronous bandwidth
- * to the specified port. This may be done any time after
- * initializing the port. The configuration values are NOT saved
- * in the HWAC port structure and will be overwritten any
- * time when stopping and starting the port.
- * Any values for the synchronous configuration will be ignored
- * if the size of the synchronous queue is zero!
- *
- * The default configuration for the synchronous service is
- * TXA_ENA_FSYNC. This means if the size of
- * the synchronous queue is unequal zero but no specific
- * synchronous bandwidth is configured, the synchronous queue
- * will always have the 'unlimited' transmit priority!
- *
- * This mode will be restored if the synchronous bandwidth is
- * deallocated ('IntTime' = 0 and 'LimCount' = 0).
- *
- * Returns:
- * 0: success
- * 1: parameter configuration error
- * 2: try to configure quality of service although no
- * synchronous queue is configured
- */
-int SkGeCfgSync(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U32 IntTime, /* Interval Timer Value in units of 8ns */
-SK_U32 LimCount, /* Number of bytes to transfer during IntTime */
-int SyncMode) /* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */
-{
- int Rtv;
-
- Rtv = 0;
-
- /* check the parameters */
- if (LimCount > IntTime ||
- (LimCount == 0 && IntTime != 0) ||
- (LimCount != 0 && IntTime == 0)) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
- return(1);
- }
-
- if (pAC->GIni.GP[Port].PXSQSize == 0) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG);
- return(2);
- }
-
- /* calculate register values */
- IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100;
- LimCount = LimCount / 8;
-
- if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
- return(1);
- }
-
- /*
- * - Enable 'Force Sync' to ensure the synchronous queue
- * has the priority while configuring the new values.
- * - Also 'disable alloc' to ensure the settings complies
- * to the SyncMode parameter.
- * - Disable 'Rate Control' to configure the new values.
- * - write IntTime and LimCount
- * - start 'Rate Control' and disable 'Force Sync'
- * if Interval Timer or Limit Counter not zero.
- */
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
- TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-
- SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime);
- SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount);
-
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
- (SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC)));
-
- if (IntTime != 0 || LimCount != 0) {
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC);
- }
-
- return(0);
-} /* SkGeCfgSync */
-#endif /* SK_DIAG || SK_CFG_SYNC*/
-
-
-/******************************************************************************
- *
- * DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue
- *
- * Desccription:
- * If the queue is used, enable and initialize it.
- * Make sure the queue is still reset, if it is not used.
- *
- * Returns:
- * nothing
- */
-static void DoInitRamQueue(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int QuIoOffs, /* Queue IO Address Offset */
-SK_U32 QuStartAddr, /* Queue Start Address */
-SK_U32 QuEndAddr, /* Queue End Address */
-int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */
-{
- SK_U32 RxUpThresVal;
- SK_U32 RxLoThresVal;
-
- if (QuStartAddr != QuEndAddr) {
- /* calculate thresholds, assume we have a big Rx queue */
- RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8;
- RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8;
-
- /* build HW address format */
- QuStartAddr = QuStartAddr / 8;
- QuEndAddr = QuEndAddr / 8;
-
- /* release local reset */
- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR);
-
- /* configure addresses */
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr);
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr);
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr);
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr);
-
- switch (QuType) {
- case SK_RX_SRAM_Q:
- /* configure threshold for small Rx Queue */
- RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8;
-
- /* continue with SK_RX_BRAM_Q */
- case SK_RX_BRAM_Q:
- /* write threshold for Rx Queue */
-
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal);
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal);
-
- /* the high priority threshold not used */
- break;
- case SK_TX_RAM_Q:
- /*
- * Do NOT use Store & Forward under normal operation due to
- * performance optimization (GENESIS only).
- * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB)
- * or YUKON is used ((GMAC Tx FIFO is only 1 kB)
- * we NEED Store & Forward of the RAM buffer.
- */
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK ||
- pAC->GIni.GIYukon) {
- /* enable Store & Forward Mode for the Tx Side */
- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD);
- }
- break;
- }
-
- /* set queue operational */
- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD);
- }
- else {
- /* ensure the queue is still disabled */
- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET);
- }
-} /* DoInitRamQueue */
-
-
-/******************************************************************************
- *
- * SkGeInitRamBufs() - Initialize the RAM Buffer Queues
- *
- * Description:
- * Initialize all RAM Buffer Queues of the specified port
- *
- * Returns:
- * nothing
- */
-static void SkGeInitRamBufs(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- int RxQType;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) {
- RxQType = SK_RX_SRAM_Q; /* small Rx Queue */
- }
- else {
- RxQType = SK_RX_BRAM_Q; /* big Rx Queue */
- }
-
- DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart,
- pPrt->PRxQRamEnd, RxQType);
-
- DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart,
- pPrt->PXsQRamEnd, SK_TX_RAM_Q);
-
- DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
- pPrt->PXaQRamEnd, SK_TX_RAM_Q);
-
-} /* SkGeInitRamBufs */
-
-
-/******************************************************************************
- *
- * SkGeInitRamIface() - Initialize the RAM Interface
- *
- * Description:
- * This function initializes the Adapters RAM Interface.
- *
- * Note:
- * This function is used in the diagnostics.
- *
- * Returns:
- * nothing
- */
-static void SkGeInitRamIface(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- /* release local reset */
- SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR);
-
- /* configure timeout values */
- SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53);
-
-} /* SkGeInitRamIface */
-
-
-/******************************************************************************
- *
- * SkGeInitBmu() - Initialize the BMU state machines
- *
- * Description:
- * Initialize all BMU state machines of the specified port
- *
- * Returns:
- * nothing
- */
-static void SkGeInitBmu(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U32 RxWm;
- SK_U32 TxWm;
-
- pPrt = &pAC->GIni.GP[Port];
-
- RxWm = SK_BMU_RX_WM;
- TxWm = SK_BMU_TX_WM;
-
- if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
- /* for better performance */
- RxWm /= 2;
- TxWm /= 2;
- }
-
- /* Rx Queue: Release all local resets and set the watermark */
- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
-
- /*
- * Tx Queue: Release all local resets if the queue is used !
- * set watermark
- */
- if (pPrt->PXSQSize != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
- }
-
- if (pPrt->PXAQSize != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
- }
- /*
- * Do NOT enable the descriptor poll timers here, because
- * the descriptor addresses are not specified yet.
- */
-} /* SkGeInitBmu */
-
-
-/******************************************************************************
- *
- * TestStopBit() - Test the stop bit of the queue
- *
- * Description:
- * Stopping a queue is not as simple as it seems to be.
- * If descriptor polling is enabled, it may happen
- * that RX/TX stop is done and SV idle is NOT set.
- * In this case we have to issue another stop command.
- *
- * Returns:
- * The queues control status register
- */
-static SK_U32 TestStopBit(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int QuIoOffs) /* Queue IO Address Offset */
-{
- SK_U32 QuCsr; /* CSR contents */
-
- SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
-
- if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
- /* Stop Descriptor overridden by start command */
- SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
-
- SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
- }
-
- return(QuCsr);
-} /* TestStopBit */
-
-
-/******************************************************************************
- *
- * SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'.
- *
- * Description:
- * After calling this function the descriptor rings and Rx and Tx
- * queues of this port may be reconfigured.
- *
- * It is possible to stop the receive and transmit path separate or
- * both together.
- *
- * Dir = SK_STOP_TX Stops the transmit path only and resets the MAC.
- * The receive queue is still active and
- * the pending Rx frames may be still transferred
- * into the RxD.
- * SK_STOP_RX Stop the receive path. The tansmit path
- * has to be stopped once before.
- * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX
- *
- * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive.
- * SK_HARD_RST Resets the MAC and the PHY.
- *
- * Example:
- * 1) A Link Down event was signaled for a port. Therefore the activity
- * of this port should be stopped and a hardware reset should be issued
- * to enable the workaround of XMAC Errata #2. But the received frames
- * should not be discarded.
- * ...
- * SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST);
- * (transfer all pending Rx frames)
- * SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST);
- * ...
- *
- * 2) An event was issued which request the driver to switch
- * the 'virtual active' link to an other already active port
- * as soon as possible. The frames in the receive queue of this
- * port may be lost. But the PHY must not be reset during this
- * event.
- * ...
- * SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST);
- * ...
- *
- * Extended Description:
- * If SK_STOP_TX is set,
- * o disable the MAC's receive and transmitter to prevent
- * from sending incomplete frames
- * o stop the port's transmit queues before terminating the
- * BMUs to prevent from performing incomplete PCI cycles
- * on the PCI bus
- * - The network Rx and Tx activity and PCI Tx transfer is
- * disabled now.
- * o reset the MAC depending on the RstMode
- * o Stop Interval Timer and Limit Counter of Tx Arbiter,
- * also disable Force Sync bit and Enable Alloc bit.
- * o perform a local reset of the port's Tx path
- * - reset the PCI FIFO of the async Tx queue
- * - reset the PCI FIFO of the sync Tx queue
- * - reset the RAM Buffer async Tx queue
- * - reset the RAM Buffer sync Tx queue
- * - reset the MAC Tx FIFO
- * o switch Link and Tx LED off, stop the LED counters
- *
- * If SK_STOP_RX is set,
- * o stop the port's receive queue
- * - The path data transfer activity is fully stopped now.
- * o perform a local reset of the port's Rx path
- * - reset the PCI FIFO of the Rx queue
- * - reset the RAM Buffer receive queue
- * - reset the MAC Rx FIFO
- * o switch Rx LED off, stop the LED counter
- *
- * If all ports are stopped,
- * o reset the RAM Interface.
- *
- * Notes:
- * o This function may be called during the driver states RESET_PORT and
- * SWITCH_PORT.
- */
-void SkGeStopPort(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-int Port, /* port to stop (MAC_1 + n) */
-int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
-int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
-{
-#ifndef SK_DIAG
- SK_EVPARA Para;
-#endif /* !SK_DIAG */
- SK_GEPORT *pPrt;
- SK_U32 DWord;
- SK_U32 XsCsr;
- SK_U32 XaCsr;
- SK_U64 ToutStart;
- int i;
- int ToutCnt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if ((Dir & SK_STOP_TX) != 0) {
- /* disable receiver and transmitter */
- SkMacRxTxDisable(pAC, IoC, Port);
-
- /* stop both transmit queues */
- /*
- * If the BMU is in the reset state CSR_STOP will terminate
- * immediately.
- */
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP);
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP);
-
- ToutStart = SkOsGetTime(pAC);
- ToutCnt = 0;
- do {
- /*
- * Clear packet arbiter timeout to make sure
- * this loop will terminate.
- */
- SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
- PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
-
- /*
- * If the transfer stucks at the MAC the STOP command will not
- * terminate if we don't flush the XMAC's transmit FIFO !
- */
- SkMacFlushTxFifo(pAC, IoC, Port);
-
- XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
- XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
-
- if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
- /*
- * Timeout of 1/18 second reached.
- * This needs to be checked at 1/18 sec only.
- */
- ToutCnt++;
- if (ToutCnt > 1) {
- /* Might be a problem when the driver event handler
- * calls StopPort again. XXX.
- */
-
- /* Fatal Error, Loop aborted */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018,
- SKERR_HWI_E018MSG);
-#ifndef SK_DIAG
- Para.Para64 = Port;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-#endif /* !SK_DIAG */
- return;
- }
- /*
- * Cache incoherency workaround: Assume a start command
- * has been lost while sending the frame.
- */
- ToutStart = SkOsGetTime(pAC);
-
- if ((XsCsr & CSR_STOP) != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START);
- }
- if ((XaCsr & CSR_STOP) != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START);
- }
- }
-
- /*
- * Because of the ASIC problem report entry from 21.08.1998 it is
- * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
- */
- } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE ||
- (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
- /* Reset the MAC depending on the RstMode */
- if (RstMode == SK_SOFT_RST) {
- SkMacSoftRst(pAC, IoC, Port);
- }
- else {
- SkMacHardRst(pAC, IoC, Port);
- }
-
- /* Disable Force Sync bit and Enable Alloc bit */
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
- TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-
- /* Stop Interval Timer and Limit Counter of Tx Arbiter */
- SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L);
- SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L);
-
- /* Perform a local reset of the port's Tx path */
-
- /* Reset the PCI FIFO of the async Tx queue */
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
- /* Reset the PCI FIFO of the sync Tx queue */
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
- /* Reset the RAM Buffer async Tx queue */
- SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
- /* Reset the RAM Buffer sync Tx queue */
- SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET);
-
- /* Reset Tx MAC FIFO */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* Note: MFF_RST_SET does NOT reset the XMAC ! */
- SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET);
-
- /* switch Link and Tx LED off, stop the LED counters */
- /* Link LED is switched off by the RLMT and the Diag itself */
- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* Reset TX MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
- }
-#endif /* YUKON */
- }
-
- if ((Dir & SK_STOP_RX) != 0) {
- /*
- * The RX Stop Command will not terminate if no buffers
- * are queued in the RxD ring. But it will always reach
- * the Idle state. Therefore we can use this feature to
- * stop the transfer of received packets.
- */
- /* stop the port's receive queue */
- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP);
-
- i = 100;
- do {
- /*
- * Clear packet arbiter timeout to make sure
- * this loop will terminate
- */
- SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
- PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
-
- DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff);
-
- /* timeout if i==0 (bug fix for #10748) */
- if (--i == 0) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
- SKERR_HWI_E024MSG);
- break;
- }
- /*
- * because of the ASIC problem report entry from 21.08.98
- * it is required to wait until CSR_STOP is reset and
- * CSR_SV_IDLE is set.
- */
- } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
- /* The path data transfer activity is fully stopped now */
-
- /* Perform a local reset of the port's Rx path */
-
- /* Reset the PCI FIFO of the Rx queue */
- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
- /* Reset the RAM Buffer receive queue */
- SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET);
-
- /* Reset Rx MAC FIFO */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET);
-
- /* switch Rx LED off, stop the LED counter */
- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* Reset Rx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
- }
-#endif /* YUKON */
- }
-} /* SkGeStopPort */
-
-
-/******************************************************************************
- *
- * SkGeInit0() - Level 0 Initialization
- *
- * Description:
- * - Initialize the BMU address offsets
- *
- * Returns:
- * nothing
- */
-static void SkGeInit0(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- int i;
- SK_GEPORT *pPrt;
-
- for (i = 0; i < SK_MAX_MACS; i++) {
- pPrt = &pAC->GIni.GP[i];
-
- pPrt->PState = SK_PRT_RESET;
- pPrt->PRxQOff = QOffTab[i].RxQOff;
- pPrt->PXsQOff = QOffTab[i].XsQOff;
- pPrt->PXaQOff = QOffTab[i].XaQOff;
- pPrt->PCheckPar = SK_FALSE;
- pPrt->PIsave = 0;
- pPrt->PPrevShorts = 0;
- pPrt->PLinkResCt = 0;
- pPrt->PAutoNegTOCt = 0;
- pPrt->PPrevRx = 0;
- pPrt->PPrevFcs = 0;
- pPrt->PRxLim = SK_DEF_RX_WA_LIM;
- pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
- pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS;
- pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS;
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN;
- pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE;
- pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
- pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL |
- SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL);
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
- pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
- pPrt->PMSCap = 0;
- pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO;
- pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET;
- pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
- pPrt->PAutoNegFail = SK_FALSE;
- pPrt->PHWLinkUp = SK_FALSE;
- pPrt->PLinkBroken = SK_TRUE; /* See WA code */
- pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
- pPrt->PMacColThres = TX_COL_DEF;
- pPrt->PMacJamLen = TX_JAM_LEN_DEF;
- pPrt->PMacJamIpgVal = TX_JAM_IPG_DEF;
- pPrt->PMacJamIpgData = TX_IPG_JAM_DEF;
- pPrt->PMacIpgData = IPG_DATA_DEF;
- pPrt->PMacLimit4 = SK_FALSE;
- }
-
- pAC->GIni.GIPortUsage = SK_RED_LINK;
- pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value;
- pAC->GIni.GIValIrqMask = IS_ALL_MSK;
-
-} /* SkGeInit0*/
-
-
-/******************************************************************************
- *
- * SkGeInit1() - Level 1 Initialization
- *
- * Description:
- * o Do a software reset.
- * o Clear all reset bits.
- * o Verify that the detected hardware is present.
- * Return an error if not.
- * o Get the hardware configuration
- * + Read the number of MACs/Ports.
- * + Read the RAM size.
- * + Read the PCI Revision Id.
- * + Find out the adapters host clock speed
- * + Read and check the PHY type
- *
- * Returns:
- * 0: success
- * 5: Unexpected PHY type detected
- * 6: HW self test failed
- */
-static int SkGeInit1(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- SK_U8 Byte;
- SK_U16 Word;
- SK_U16 CtrlStat;
- SK_U32 DWord;
- int RetVal;
- int i;
-
- RetVal = 0;
-
- /* save CLK_RUN bits (YUKON-Lite) */
- SK_IN16(IoC, B0_CTST, &CtrlStat);
-
- /* do the SW-reset */
- SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-
- /* release the SW-reset */
- SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
-
- /* reset all error bits in the PCI STATUS register */
- /*
- * Note: PCI Cfg cycles cannot be used, because they are not
- * available on some platforms after 'boot time'.
- */
- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
- /* release Master Reset */
- SK_OUT8(IoC, B0_CTST, CS_MRST_CLR);
-
-#ifdef CLK_RUN
- CtrlStat |= CS_CLK_RUN_ENA;
-#endif /* CLK_RUN */
-
- /* restore CLK_RUN bits */
- SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat &
- (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)));
-
- /* read Chip Identification Number */
- SK_IN8(IoC, B2_CHIP_ID, &Byte);
- pAC->GIni.GIChipId = Byte;
-
- /* read number of MACs */
- SK_IN8(IoC, B2_MAC_CFG, &Byte);
- pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
-
- /* get Chip Revision Number */
- pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4);
-
- /* get diff. PCI parameters */
- SK_IN16(IoC, B0_CTST, &CtrlStat);
-
- /* read the adapters RAM size */
- SK_IN8(IoC, B2_E_0, &Byte);
-
- pAC->GIni.GIGenesis = SK_FALSE;
- pAC->GIni.GIYukon = SK_FALSE;
- pAC->GIni.GIYukonLite = SK_FALSE;
-
-#ifdef GENESIS
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-
- pAC->GIni.GIGenesis = SK_TRUE;
-
- if (Byte == (SK_U8)3) {
- /* special case: 4 x 64k x 36, offset = 0x80000 */
- pAC->GIni.GIRamSize = 1024;
- pAC->GIni.GIRamOffs = (SK_U32)512 * 1024;
- }
- else {
- pAC->GIni.GIRamSize = (int)Byte * 512;
- pAC->GIni.GIRamOffs = 0;
- }
- /* all GE adapters work with 53.125 MHz host clock */
- pAC->GIni.GIHstClkFact = SK_FACT_53;
-
- /* set Descr. Poll Timer Init Value to 250 ms */
- pAC->GIni.GIPollTimerVal =
- SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100;
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
-
- pAC->GIni.GIYukon = SK_TRUE;
-
- pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4;
-
- pAC->GIni.GIRamOffs = 0;
-
- /* WA for chip Rev. A */
- pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON &&
- pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0;
-
- /* get PM Capabilities of PCI config space */
- SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word);
-
- /* check if VAUX is available */
- if (((CtrlStat & CS_VAUX_AVAIL) != 0) &&
- /* check also if PME from D3cold is set */
- ((Word & PCI_PME_D3C_SUP) != 0)) {
- /* set entry in GE init struct */
- pAC->GIni.GIVauxAvail = SK_TRUE;
- }
-
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
- /* this is Rev. A1 */
- pAC->GIni.GIYukonLite = SK_TRUE;
- }
- else {
- /* save Flash-Address Register */
- SK_IN32(IoC, B2_FAR, &DWord);
-
- /* test Flash-Address Register */
- SK_OUT8(IoC, B2_FAR + 3, 0xff);
- SK_IN8(IoC, B2_FAR + 3, &Byte);
-
- if (Byte != 0) {
- /* this is Rev. A0 */
- pAC->GIni.GIYukonLite = SK_TRUE;
-
- /* restore Flash-Address Register */
- SK_OUT32(IoC, B2_FAR, DWord);
- }
- }
-
- /* switch power to VCC (WA for VAUX problem) */
- SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
- PC_VAUX_OFF | PC_VCC_ON));
-
- /* read the Interrupt source */
- SK_IN32(IoC, B0_ISRC, &DWord);
-
- if ((DWord & IS_HW_ERR) != 0) {
- /* read the HW Error Interrupt source */
- SK_IN32(IoC, B0_HWE_ISRC, &DWord);
-
- if ((DWord & IS_IRQ_SENSOR) != 0) {
- /* disable HW Error IRQ */
- pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
- }
- }
-
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- /* set GMAC Link Control reset */
- SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET);
-
- /* clear GMAC Link Control reset */
- SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
- }
- /* all YU chips work with 78.125 MHz host clock */
- pAC->GIni.GIHstClkFact = SK_FACT_78;
-
- pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */
- }
-#endif /* YUKON */
-
- /* check if 64-bit PCI Slot is present */
- pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
-
- /* check if 66 MHz PCI Clock is active */
- pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
-
- /* read PCI HW Revision Id. */
- SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte);
- pAC->GIni.GIPciHwRev = Byte;
-
- /* read the PMD type */
- SK_IN8(IoC, B2_PMD_TYP, &Byte);
- pAC->GIni.GICopperType = (SK_U8)(Byte == 'T');
-
- /* read the PHY type */
- SK_IN8(IoC, B2_E_1, &Byte);
-
- Byte &= 0x0f; /* the PHY type is stored in the lower nibble */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- switch (Byte) {
- case SK_PHY_XMAC:
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC;
- break;
- case SK_PHY_BCOM:
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM;
- pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
- SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE;
- break;
- case SK_PHY_NAT:
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT;
- break;
-#endif /* OTHER_PHY */
- default:
- /* ERROR: unexpected PHY type detected */
- RetVal = 5;
- break;
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- if (Byte < (SK_U8)SK_PHY_MARV_COPPER) {
- /* if this field is not initialized */
- Byte = (SK_U8)SK_PHY_MARV_COPPER;
-
- pAC->GIni.GICopperType = SK_TRUE;
- }
-
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV;
-
- if (pAC->GIni.GICopperType) {
-
- pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO |
- SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS |
- SK_LSPEED_CAP_1000MBPS);
-
- pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
-
- pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
- SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
- }
- else {
- Byte = (SK_U8)SK_PHY_MARV_FIBER;
- }
- }
-#endif /* YUKON */
-
- pAC->GIni.GP[i].PhyType = (int)Byte;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
- ("PHY type: %d PHY addr: %04x\n", Byte,
- pAC->GIni.GP[i].PhyAddr));
- }
-
- /* get MAC Type & set function pointers dependent on */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- pAC->GIni.GIMacType = SK_MAC_XMAC;
-
- pAC->GIni.GIFunc.pFnMacUpdateStats = SkXmUpdateStats;
- pAC->GIni.GIFunc.pFnMacStatistic = SkXmMacStatistic;
- pAC->GIni.GIFunc.pFnMacResetCounter = SkXmResetCounter;
- pAC->GIni.GIFunc.pFnMacOverflow = SkXmOverflowStatus;
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- pAC->GIni.GIMacType = SK_MAC_GMAC;
-
- pAC->GIni.GIFunc.pFnMacUpdateStats = SkGmUpdateStats;
- pAC->GIni.GIFunc.pFnMacStatistic = SkGmMacStatistic;
- pAC->GIni.GIFunc.pFnMacResetCounter = SkGmResetCounter;
- pAC->GIni.GIFunc.pFnMacOverflow = SkGmOverflowStatus;
-
-#ifdef SPECIAL_HANDLING
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
- /* check HW self test result */
- SK_IN8(IoC, B2_E_3, &Byte);
- if (Byte & B2_E3_RES_MASK) {
- RetVal = 6;
- }
- }
-#endif
- }
-#endif /* YUKON */
-
- return(RetVal);
-} /* SkGeInit1 */
-
-
-/******************************************************************************
- *
- * SkGeInit2() - Level 2 Initialization
- *
- * Description:
- * - start the Blink Source Counter
- * - start the Descriptor Poll Timer
- * - configure the MAC-Arbiter
- * - configure the Packet-Arbiter
- * - enable the Tx Arbiters
- * - enable the RAM Interface Arbiter
- *
- * Returns:
- * nothing
- */
-static void SkGeInit2(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
-#ifdef GENESIS
- SK_U32 DWord;
-#endif /* GENESIS */
- int i;
-
- /* start the Descriptor Poll Timer */
- if (pAC->GIni.GIPollTimerVal != 0) {
- if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) {
- pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG);
- }
- SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal);
- SK_OUT8(IoC, B28_DPT_CTRL, DPT_START);
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* start the Blink Source Counter */
- DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-
- SK_OUT32(IoC, B2_BSC_INI, DWord);
- SK_OUT8(IoC, B2_BSC_CTRL, BSC_START);
-
- /*
- * Configure the MAC Arbiter and the Packet Arbiter.
- * They will be started once and never be stopped.
- */
- SkGeInitMacArb(pAC, IoC);
-
- SkGeInitPktArb(pAC, IoC);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* start Time Stamp Timer */
- SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START);
- }
-#endif /* YUKON */
-
- /* enable the Tx Arbiters */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB);
- }
-
- /* enable the RAM Interface Arbiter */
- SkGeInitRamIface(pAC, IoC);
-
-} /* SkGeInit2 */
-
-/******************************************************************************
- *
- * SkGeInit() - Initialize the GE Adapter with the specified level.
- *
- * Description:
- * Level 0: Initialize the Module structures.
- * Level 1: Generic Hardware Initialization. The IOP/MemBase pointer has
- * to be set before calling this level.
- *
- * o Do a software reset.
- * o Clear all reset bits.
- * o Verify that the detected hardware is present.
- * Return an error if not.
- * o Get the hardware configuration
- * + Set GIMacsFound with the number of MACs.
- * + Store the RAM size in GIRamSize.
- * + Save the PCI Revision ID in GIPciHwRev.
- * o return an error
- * if Number of MACs > SK_MAX_MACS
- *
- * After returning from Level 0 the adapter
- * may be accessed with IO operations.
- *
- * Level 2: start the Blink Source Counter
- *
- * Returns:
- * 0: success
- * 1: Number of MACs exceeds SK_MAX_MACS (after level 1)
- * 2: Adapter not present or not accessible
- * 3: Illegal initialization level
- * 4: Initialization Level 1 Call missing
- * 5: Unexpected PHY type detected
- * 6: HW self test failed
- */
-int SkGeInit(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Level) /* initialization level */
-{
- int RetVal; /* return value */
- SK_U32 DWord;
-
- RetVal = 0;
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
- ("SkGeInit(Level %d)\n", Level));
-
- switch (Level) {
- case SK_INIT_DATA:
- /* Initialization Level 0 */
- SkGeInit0(pAC, IoC);
- pAC->GIni.GILevel = SK_INIT_DATA;
- break;
-
- case SK_INIT_IO:
- /* Initialization Level 1 */
- RetVal = SkGeInit1(pAC, IoC);
- if (RetVal != 0) {
- break;
- }
-
- /* check if the adapter seems to be accessible */
- SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL);
- SK_IN32(IoC, B2_IRQM_INI, &DWord);
- SK_OUT32(IoC, B2_IRQM_INI, 0L);
-
- if (DWord != SK_TEST_VAL) {
- RetVal = 2;
- break;
- }
-
- /* check if the number of GIMacsFound matches SK_MAX_MACS */
- if (pAC->GIni.GIMacsFound > SK_MAX_MACS) {
- RetVal = 1;
- break;
- }
-
- /* Level 1 successfully passed */
- pAC->GIni.GILevel = SK_INIT_IO;
- break;
-
- case SK_INIT_RUN:
- /* Initialization Level 2 */
- if (pAC->GIni.GILevel != SK_INIT_IO) {
-#ifndef SK_DIAG
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG);
-#endif /* !SK_DIAG */
- RetVal = 4;
- break;
- }
- SkGeInit2(pAC, IoC);
-
- /* Level 2 successfully passed */
- pAC->GIni.GILevel = SK_INIT_RUN;
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG);
- RetVal = 3;
- break;
- }
-
- return(RetVal);
-} /* SkGeInit */
-
-
-/******************************************************************************
- *
- * SkGeDeInit() - Deinitialize the adapter
- *
- * Description:
- * All ports of the adapter will be stopped if not already done.
- * Do a software reset and switch off all LEDs.
- *
- * Returns:
- * nothing
- */
-void SkGeDeInit(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- int i;
- SK_U16 Word;
-
-#if (!defined(SK_SLIM) && !defined(VCPU))
- /* ensure I2C is ready */
- SkI2cWaitIrq(pAC, IoC);
-#endif
-
- /* stop all current transfer activity */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
- pAC->GIni.GP[i].PState != SK_PRT_RESET) {
-
- SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
- }
- }
-
- /* Reset all bits in the PCI STATUS register */
- /*
- * Note: PCI Cfg cycles cannot be used, because they are not
- * available on some platforms after 'boot time'.
- */
- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
- /* do the reset, all LEDs are switched off now */
- SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-
- pAC->GIni.GILevel = SK_INIT_DATA;
-} /* SkGeDeInit */
-
-
-/******************************************************************************
- *
- * SkGeInitPort() Initialize the specified port.
- *
- * Description:
- * PRxQSize, PXSQSize, and PXAQSize has to be
- * configured for the specified port before calling this function.
- * The descriptor rings has to be initialized too.
- *
- * o (Re)configure queues of the specified port.
- * o configure the MAC of the specified port.
- * o put ASIC and MAC(s) in operational mode.
- * o initialize Rx/Tx and Sync LED
- * o initialize RAM Buffers and MAC FIFOs
- *
- * The port is ready to connect when returning.
- *
- * Note:
- * The MAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- * 0: success
- * 1: Queue size initialization error. The configured values
- * for PRxQSize, PXSQSize, or PXAQSize are invalid for one
- * or more queues. The specified port was NOT initialized.
- * An error log entry was generated.
- * 2: The port has to be stopped before it can be initialized again.
- */
-int SkGeInitPort(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port to configure */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (SkGeCheckQSize(pAC, Port) != 0) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG);
- return(1);
- }
-
- if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG);
- return(2);
- }
-
- /* configuration ok, initialize the Port now */
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* initialize Rx, Tx and Link LED */
- /*
- * If 1000BT Phy needs LED initialization than swap
- * LED and XMAC initialization order
- */
- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA);
- /* The Link LED is initialized by RLMT or Diagnostics itself */
-
- SkXmInitMac(pAC, IoC, Port);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- SkGmInitMac(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
- /* do NOT initialize the Link Sync Counter */
-
- SkGeInitMacFifo(pAC, IoC, Port);
-
- SkGeInitRamBufs(pAC, IoC, Port);
-
- if (pPrt->PXSQSize != 0) {
- /* enable Force Sync bit if synchronous queue available */
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC);
- }
-
- SkGeInitBmu(pAC, IoC, Port);
-
- /* mark port as initialized */
- pPrt->PState = SK_PRT_INIT;
-
- return(0);
-} /* SkGeInitPort */
diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c
deleted file mode 100644
index 0a6f67a7a39..00000000000
--- a/drivers/net/sk98lin/skgemib.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*****************************************************************************
- *
- * Name: skgemib.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.11 $
- * Date: $Date: 2003/09/15 13:38:12 $
- * Purpose: Private Network Management Interface Management Database
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * PRIVATE OID handler function prototypes
- */
-PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action,
- SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action,
- SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int* pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-
-#ifdef SK_POWER_MGMT
-PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_DIAG_SUPPORT */
-
-
-/* defines *******************************************************************/
-#define ID_TABLE_SIZE (sizeof(IdTable)/sizeof(IdTable[0]))
-
-
-/* global variables **********************************************************/
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = {
- {OID_GEN_XMIT_OK,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX},
- {OID_GEN_RCV_OK,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX},
- {OID_GEN_XMIT_ERROR,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_GEN_RCV_ERROR,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_GEN_RCV_NO_BUFFER,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_GEN_DIRECTED_FRAMES_XMIT,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST},
- {OID_GEN_MULTICAST_FRAMES_XMIT,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST},
- {OID_GEN_BROADCAST_FRAMES_XMIT,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST},
- {OID_GEN_DIRECTED_FRAMES_RCV,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST},
- {OID_GEN_MULTICAST_FRAMES_RCV,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST},
- {OID_GEN_BROADCAST_FRAMES_RCV,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST},
- {OID_GEN_RCV_CRC_ERROR,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS},
- {OID_GEN_TRANSMIT_QUEUE_LENGTH,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_802_3_PERMANENT_ADDRESS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, 0},
- {OID_802_3_CURRENT_ADDRESS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, 0},
- {OID_802_3_RCV_ERROR_ALIGNMENT,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING},
- {OID_802_3_XMIT_ONE_COLLISION,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL},
- {OID_802_3_XMIT_MORE_COLLISIONS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL},
- {OID_802_3_XMIT_DEFERRED,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL},
- {OID_802_3_XMIT_MAX_COLLISIONS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL},
- {OID_802_3_RCV_OVERRUN,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW},
- {OID_802_3_XMIT_UNDERRUN,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN},
- {OID_802_3_XMIT_TIMES_CRS_LOST,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER},
- {OID_802_3_XMIT_LATE_COLLISIONS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL},
-#ifdef SK_POWER_MGMT
- {OID_PNP_CAPABILITIES,
- 0,
- 0,
- 0,
- SK_PNMI_RO, PowerManagement, 0},
- {OID_PNP_SET_POWER,
- 0,
- 0,
- 0,
- SK_PNMI_WO, PowerManagement, 0},
- {OID_PNP_QUERY_POWER,
- 0,
- 0,
- 0,
- SK_PNMI_RO, PowerManagement, 0},
- {OID_PNP_ADD_WAKE_UP_PATTERN,
- 0,
- 0,
- 0,
- SK_PNMI_WO, PowerManagement, 0},
- {OID_PNP_REMOVE_WAKE_UP_PATTERN,
- 0,
- 0,
- 0,
- SK_PNMI_WO, PowerManagement, 0},
- {OID_PNP_ENABLE_WAKE_UP,
- 0,
- 0,
- 0,
- SK_PNMI_RW, PowerManagement, 0},
-#endif /* SK_POWER_MGMT */
-#ifdef SK_DIAG_SUPPORT
- {OID_SKGE_DIAG_MODE,
- 0,
- 0,
- 0,
- SK_PNMI_RW, DiagActions, 0},
-#endif /* SK_DIAG_SUPPORT */
- {OID_SKGE_MDB_VERSION,
- 1,
- 0,
- SK_PNMI_MAI_OFF(MgmtDBVersion),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_SUPPORTED_LIST,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_SKGE_ALL_DATA,
- 0,
- 0,
- 0,
- SK_PNMI_RW, OidStruct, 0},
- {OID_SKGE_VPD_FREE_BYTES,
- 1,
- 0,
- SK_PNMI_MAI_OFF(VpdFreeBytes),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_ENTRIES_LIST,
- 1,
- 0,
- SK_PNMI_MAI_OFF(VpdEntriesList),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_ENTRIES_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(VpdEntriesNumber),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_KEY,
- SK_PNMI_VPD_ENTRIES,
- sizeof(SK_PNMI_VPD),
- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_VALUE,
- SK_PNMI_VPD_ENTRIES,
- sizeof(SK_PNMI_VPD),
- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_ACCESS,
- SK_PNMI_VPD_ENTRIES,
- sizeof(SK_PNMI_VPD),
- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_ACTION,
- SK_PNMI_VPD_ENTRIES,
- sizeof(SK_PNMI_VPD),
- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction),
- SK_PNMI_RW, Vpd, 0},
- {OID_SKGE_PORT_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(PortNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DEVICE_TYPE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DeviceType),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DRIVER_DESCR,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DriverDescr),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DRIVER_VERSION,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DriverVersion),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DRIVER_RELDATE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DriverReleaseDate),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DRIVER_FILENAME,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DriverFileName),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_HW_DESCR,
- 1,
- 0,
- SK_PNMI_MAI_OFF(HwDescr),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_HW_VERSION,
- 1,
- 0,
- SK_PNMI_MAI_OFF(HwVersion),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_CHIPSET,
- 1,
- 0,
- SK_PNMI_MAI_OFF(Chipset),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_CHIPID,
- 1,
- 0,
- SK_PNMI_MAI_OFF(ChipId),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RAMSIZE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RamSize),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_VAUXAVAIL,
- 1,
- 0,
- SK_PNMI_MAI_OFF(VauxAvail),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_ACTION,
- 1,
- 0,
- SK_PNMI_MAI_OFF(Action),
- SK_PNMI_RW, Perform, 0},
- {OID_SKGE_RESULT,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TestResult),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_BUS_TYPE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(BusType),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_BUS_SPEED,
- 1,
- 0,
- SK_PNMI_MAI_OFF(BusSpeed),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_BUS_WIDTH,
- 1,
- 0,
- SK_PNMI_MAI_OFF(BusWidth),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_SW_QUEUE_LEN,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxSwQueueLen),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_SW_QUEUE_MAX,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxSwQueueMax),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_RETRY,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxRetryCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_INTR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxIntrCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_INTR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxIntrCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_NO_BUF_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxNoBufCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_NO_BUF_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxNoBufCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_USED_DESCR_NO,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxUsedDescrNo),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_DELIVERED_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxDeliveredCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_OCTETS_DELIV_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_HW_ERROR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxHwErrorsCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_HW_ERROR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxHwErrorsCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_IN_ERRORS_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(InErrorsCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_OUT_ERROR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(OutErrorsCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_ERR_RECOVERY_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(ErrRecoveryCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_SYSUPTIME,
- 1,
- 0,
- SK_PNMI_MAI_OFF(SysUpTime),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_SENSOR_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(SensorNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_SENSOR_INDEX,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_DESCR,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_TYPE,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_VALUE,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_WAR_THRES_LOW,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_WAR_THRES_UPP,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_ERR_THRES_LOW,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_ERR_THRES_UPP,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_STATUS,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_WAR_CTS,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_ERR_CTS,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_WAR_TIME,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_ERR_TIME,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_CHKSM_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(ChecksumNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_CHKSM_RX_OK_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_CHKSM_RX_UNABLE_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_CHKSM_RX_ERR_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_CHKSM_TX_OK_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_CHKSM_TX_UNABLE_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_STAT_TX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX},
- {OID_SKGE_STAT_TX_OCTETS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET},
- {OID_SKGE_STAT_TX_BROADCAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST},
- {OID_SKGE_STAT_TX_MULTICAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST},
- {OID_SKGE_STAT_TX_UNICAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST},
- {OID_SKGE_STAT_TX_LONGFRAMES,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES},
- {OID_SKGE_STAT_TX_BURST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST},
- {OID_SKGE_STAT_TX_PFLOWC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC},
- {OID_SKGE_STAT_TX_FLOWC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC},
- {OID_SKGE_STAT_TX_SINGLE_COL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL},
- {OID_SKGE_STAT_TX_MULTI_COL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL},
- {OID_SKGE_STAT_TX_EXCESS_COL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL},
- {OID_SKGE_STAT_TX_LATE_COL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL},
- {OID_SKGE_STAT_TX_DEFFERAL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL},
- {OID_SKGE_STAT_TX_EXCESS_DEF,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF},
- {OID_SKGE_STAT_TX_UNDERRUN,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN},
- {OID_SKGE_STAT_TX_CARRIER,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER},
-/* {OID_SKGE_STAT_TX_UTIL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization),
- SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
- {OID_SKGE_STAT_TX_64,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64},
- {OID_SKGE_STAT_TX_127,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127},
- {OID_SKGE_STAT_TX_255,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255},
- {OID_SKGE_STAT_TX_511,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511},
- {OID_SKGE_STAT_TX_1023,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023},
- {OID_SKGE_STAT_TX_MAX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX},
- {OID_SKGE_STAT_TX_SYNC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC},
- {OID_SKGE_STAT_TX_SYNC_OCTETS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET},
- {OID_SKGE_STAT_RX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX},
- {OID_SKGE_STAT_RX_OCTETS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET},
- {OID_SKGE_STAT_RX_BROADCAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST},
- {OID_SKGE_STAT_RX_MULTICAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST},
- {OID_SKGE_STAT_RX_UNICAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST},
- {OID_SKGE_STAT_RX_LONGFRAMES,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES},
- {OID_SKGE_STAT_RX_PFLOWC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC},
- {OID_SKGE_STAT_RX_FLOWC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC},
- {OID_SKGE_STAT_RX_PFLOWC_ERR,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR},
- {OID_SKGE_STAT_RX_FLOWC_UNKWN,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN},
- {OID_SKGE_STAT_RX_BURST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST},
- {OID_SKGE_STAT_RX_MISSED,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED},
- {OID_SKGE_STAT_RX_FRAMING,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING},
- {OID_SKGE_STAT_RX_OVERFLOW,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW},
- {OID_SKGE_STAT_RX_JABBER,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER},
- {OID_SKGE_STAT_RX_CARRIER,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER},
- {OID_SKGE_STAT_RX_IR_LENGTH,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH},
- {OID_SKGE_STAT_RX_SYMBOL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL},
- {OID_SKGE_STAT_RX_SHORTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS},
- {OID_SKGE_STAT_RX_RUNT,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT},
- {OID_SKGE_STAT_RX_CEXT,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT},
- {OID_SKGE_STAT_RX_TOO_LONG,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG},
- {OID_SKGE_STAT_RX_FCS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS},
-/* {OID_SKGE_STAT_RX_UTIL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization),
- SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
- {OID_SKGE_STAT_RX_64,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64},
- {OID_SKGE_STAT_RX_127,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127},
- {OID_SKGE_STAT_RX_255,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255},
- {OID_SKGE_STAT_RX_511,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511},
- {OID_SKGE_STAT_RX_1023,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023},
- {OID_SKGE_STAT_RX_MAX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX},
- {OID_SKGE_PHYS_CUR_ADDR,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr),
- SK_PNMI_RW, Addr, 0},
- {OID_SKGE_PHYS_FAC_ADDR,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr),
- SK_PNMI_RO, Addr, 0},
- {OID_SKGE_PMD,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_CONNECTOR,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_PHY_TYPE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_LINK_CAP,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_LINK_MODE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_LINK_MODE_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_LINK_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_FLOWCTRL_CAP,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_FLOWCTRL_MODE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_FLOWCTRL_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_PHY_OPERATION_CAP,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_PHY_OPERATION_MODE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_PHY_OPERATION_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_SPEED_CAP,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_SPEED_MODE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_SPEED_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_TRAP,
- 1,
- 0,
- SK_PNMI_MAI_OFF(Trap),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TRAP_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TrapNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RLMT_MODE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtMode),
- SK_PNMI_RW, Rlmt, 0},
- {OID_SKGE_RLMT_PORT_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtPortNumber),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_PORT_ACTIVE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtPortActive),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_PORT_PREFERRED,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtPortPreferred),
- SK_PNMI_RW, Rlmt, 0},
- {OID_SKGE_RLMT_CHANGE_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtChangeCts),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_CHANGE_TIME,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtChangeTime),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_CHANGE_ESTIM,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtChangeEstimate),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_CHANGE_THRES,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtChangeThreshold),
- SK_PNMI_RW, Rlmt, 0},
- {OID_SKGE_RLMT_PORT_INDEX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_TX_HELLO_CTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_RX_HELLO_CTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_TX_SP_REQ_CTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_RX_SP_CTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_MONITOR_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtMonitorNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RLMT_MONITOR_INDEX,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex),
- SK_PNMI_RO, Monitor, 0},
- {OID_SKGE_RLMT_MONITOR_ADDR,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr),
- SK_PNMI_RO, Monitor, 0},
- {OID_SKGE_RLMT_MONITOR_ERRS,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts),
- SK_PNMI_RO, Monitor, 0},
- {OID_SKGE_RLMT_MONITOR_TIMESTAMP,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp),
- SK_PNMI_RO, Monitor, 0},
- {OID_SKGE_RLMT_MONITOR_ADMIN,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin),
- SK_PNMI_RW, Monitor, 0},
- {OID_SKGE_MTU,
- 1,
- 0,
- SK_PNMI_MAI_OFF(MtuSize),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_VCT_GET,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Vct, 0},
- {OID_SKGE_VCT_SET,
- 0,
- 0,
- 0,
- SK_PNMI_WO, Vct, 0},
- {OID_SKGE_VCT_STATUS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Vct, 0},
- {OID_SKGE_BOARDLEVEL,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
-};
-
diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
deleted file mode 100644
index b36dd9ac6b2..00000000000
--- a/drivers/net/sk98lin/skgepnmi.c
+++ /dev/null
@@ -1,8210 +0,0 @@
-/*****************************************************************************
- *
- * Name: skgepnmi.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.111 $
- * Date: $Date: 2003/09/15 13:35:35 $
- * Purpose: Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-#ifndef _lint
-static const char SysKonnectFileId[] =
- "@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
-#endif /* !_lint */
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/xmac_ii.h"
-#include "h/skdebug.h"
-#include "h/skqueue.h"
-#include "h/skgepnmi.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skdrv2nd.h"
-#include "h/skgepnm2.h"
-#ifdef SK_POWER_MGMT
-#include "h/skgepmgt.h"
-#endif
-/* defines *******************************************************************/
-
-#ifndef DEBUG
-#define PNMI_STATIC static
-#else /* DEBUG */
-#define PNMI_STATIC
-#endif /* DEBUG */
-
-/*
- * Public Function prototypes
- */
-int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
-int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
- unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
-int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
- unsigned int * pLen, SK_U32 NetIndex);
-
-
-/*
- * Private Function prototypes
- */
-
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
- PhysPortIndex);
-PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
- PhysPortIndex);
-PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
-PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
-PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
- unsigned int PhysPortIndex, unsigned int StatIndex);
-PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
- unsigned int StatIndex, SK_U32 NetIndex);
-PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
-PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
- unsigned int *pEntries);
-PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
- unsigned int KeyArrLen, unsigned int *pKeyNo);
-PNMI_STATIC int LookupId(SK_U32 Id);
-PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
- unsigned int LastMac);
-PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
-PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
- unsigned int PortIndex);
-PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
- unsigned int SensorIndex);
-PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
-PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
-PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
- unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-#include "skgemib.c"
-
-/* global variables **********************************************************/
-
-/*
- * Overflow status register bit table and corresponding counter
- * dependent on MAC type - the number relates to the size of overflow
- * mask returned by the pFnMacOverflow function
- */
-PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
-/* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST},
-/* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST},
-/* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC},
-/* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST},
-/* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW},
-/* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH},
-/* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64},
-/* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127},
-/* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255},
-/* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511},
-/* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023},
-/* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX},
-/* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES},
-/* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED},
-/* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL},
-/* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL},
-/* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL},
-/* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL},
-/* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL},
-/* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN},
-/* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED},
-/* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED},
-/* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED},
-/* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED},
-/* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED},
-/* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED},
-/* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST},
-/* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST},
-/* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC},
-/* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST},
-/* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS},
-/* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED},
-/* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW},
-/* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH},
-/* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW},
-/* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH},
-/* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE},
-/* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT},
-/* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64},
-/* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127},
-/* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255},
-/* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511},
-/* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023},
-/* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX},
-/* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES},
-/* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG},
-/* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER},
-/* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED},
-/* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW},
-/* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED},
-/* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED},
-/* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED},
-/* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED},
-/* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED},
-/* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED},
-/* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED},
-/* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED},
-/* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED}
-};
-
-/*
- * Table for hardware register saving on resets and port switches
- */
-PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
- /* SK_PNMI_HTX */
- {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_OCTETHIGH */
- {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
- /* SK_PNMI_HTX_OCTETLOW */
- {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
- /* SK_PNMI_HTX_BROADCAST */
- {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
- /* SK_PNMI_HTX_MULTICAST */
- {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
- /* SK_PNMI_HTX_UNICAST */
- {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
- /* SK_PNMI_HTX_BURST */
- {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_PMACC */
- {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
- /* SK_PNMI_HTX_MACC */
- {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_COL */
- {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
- /* SK_PNMI_HTX_SINGLE_COL */
- {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
- /* SK_PNMI_HTX_MULTI_COL */
- {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
- /* SK_PNMI_HTX_EXCESS_COL */
- {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
- /* SK_PNMI_HTX_LATE_COL */
- {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
- /* SK_PNMI_HTX_DEFFERAL */
- {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_EXCESS_DEF */
- {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_UNDERRUN */
- {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
- /* SK_PNMI_HTX_CARRIER */
- {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_UTILUNDER */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_UTILOVER */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_64 */
- {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
- /* SK_PNMI_HTX_127 */
- {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
- /* SK_PNMI_HTX_255 */
- {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
- /* SK_PNMI_HTX_511 */
- {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
- /* SK_PNMI_HTX_1023 */
- {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
- /* SK_PNMI_HTX_MAX */
- {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
- /* SK_PNMI_HTX_LONGFRAMES */
- {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
- /* SK_PNMI_HTX_SYNC */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_SYNC_OCTET */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_RESERVED */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX */
- {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_OCTETHIGH */
- {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
- /* SK_PNMI_HRX_OCTETLOW */
- {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
- /* SK_PNMI_HRX_BADOCTETHIGH */
- {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
- /* SK_PNMI_HRX_BADOCTETLOW */
- {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
- /* SK_PNMI_HRX_BROADCAST */
- {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
- /* SK_PNMI_HRX_MULTICAST */
- {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
- /* SK_PNMI_HRX_UNICAST */
- {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
- /* SK_PNMI_HRX_PMACC */
- {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
- /* SK_PNMI_HRX_MACC */
- {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_PMACC_ERR */
- {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_MACC_UNKWN */
- {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_BURST */
- {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_MISSED */
- {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_FRAMING */
- {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_UNDERSIZE */
- {{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
- /* SK_PNMI_HRX_OVERFLOW */
- {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
- /* SK_PNMI_HRX_JABBER */
- {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
- /* SK_PNMI_HRX_CARRIER */
- {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_IRLENGTH */
- {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_SYMBOL */
- {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_SHORTS */
- {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_RUNT */
- {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
- /* SK_PNMI_HRX_TOO_LONG */
- {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
- /* SK_PNMI_HRX_FCS */
- {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
- /* SK_PNMI_HRX_CEXT */
- {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_UTILUNDER */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_UTILOVER */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_64 */
- {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
- /* SK_PNMI_HRX_127 */
- {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
- /* SK_PNMI_HRX_255 */
- {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
- /* SK_PNMI_HRX_511 */
- {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
- /* SK_PNMI_HRX_1023 */
- {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
- /* SK_PNMI_HRX_MAX */
- {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
- /* SK_PNMI_HRX_LONGFRAMES */
- {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
- /* SK_PNMI_HRX_RESERVED */
- {{0, SK_FALSE}, {0, SK_FALSE}}
-};
-
-
-/*****************************************************************************
- *
- * Public functions
- *
- */
-
-/*****************************************************************************
- *
- * SkPnmiInit - Init function of PNMI
- *
- * Description:
- * SK_INIT_DATA: Initialises the data structures
- * SK_INIT_IO: Resets the XMAC statistics, determines the device and
- * connector type.
- * SK_INIT_RUN: Starts a timer event for port switch per hour
- * calculation.
- *
- * Returns:
- * Always 0
- */
-int SkPnmiInit(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Level) /* Initialization level */
-{
- unsigned int PortMax; /* Number of ports */
- unsigned int PortIndex; /* Current port index in loop */
- SK_U16 Val16; /* Multiple purpose 16 bit variable */
- SK_U8 Val8; /* Mulitple purpose 8 bit variable */
- SK_EVPARA EventParam; /* Event struct for timer event */
- SK_PNMI_VCT *pVctBackupData;
-
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiInit: Called, level=%d\n", Level));
-
- switch (Level) {
-
- case SK_INIT_DATA:
- SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
- pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
- pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
- pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
- for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
-
- pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
- pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
- }
-
-#ifdef SK_PNMI_CHECK
- if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
- ("CounterOffset struct size (%d) differs from"
- "SK_PNMI_MAX_IDX (%d)\n",
- SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
- }
-
- if (SK_PNMI_MAX_IDX !=
- (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
- ("StatAddr table size (%d) differs from "
- "SK_PNMI_MAX_IDX (%d)\n",
- (sizeof(StatAddr) /
- (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)),
- SK_PNMI_MAX_IDX));
- }
-#endif /* SK_PNMI_CHECK */
- break;
-
- case SK_INIT_IO:
- /*
- * Reset MAC counters
- */
- PortMax = pAC->GIni.GIMacsFound;
-
- for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
-
- pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
- }
-
- /* Initialize DSP variables for Vct() to 0xff => Never written! */
- for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
- pAC->GIni.GP[PortIndex].PCableLen = 0xff;
- pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
- pVctBackupData->PCableLen = 0xff;
- }
-
- /*
- * Get pci bus speed
- */
- SK_IN16(IoC, B0_CTST, &Val16);
- if ((Val16 & CS_BUS_CLOCK) == 0) {
-
- pAC->Pnmi.PciBusSpeed = 33;
- }
- else {
- pAC->Pnmi.PciBusSpeed = 66;
- }
-
- /*
- * Get pci bus width
- */
- SK_IN16(IoC, B0_CTST, &Val16);
- if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
-
- pAC->Pnmi.PciBusWidth = 32;
- }
- else {
- pAC->Pnmi.PciBusWidth = 64;
- }
-
- /*
- * Get chipset
- */
- switch (pAC->GIni.GIChipId) {
- case CHIP_ID_GENESIS:
- pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
- break;
-
- case CHIP_ID_YUKON:
- pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
- break;
-
- default:
- break;
- }
-
- /*
- * Get PMD and DeviceType
- */
- SK_IN8(IoC, B2_PMD_TYP, &Val8);
- switch (Val8) {
- case 'S':
- pAC->Pnmi.PMD = 3;
- if (pAC->GIni.GIMacsFound > 1) {
-
- pAC->Pnmi.DeviceType = 0x00020002;
- }
- else {
- pAC->Pnmi.DeviceType = 0x00020001;
- }
- break;
-
- case 'L':
- pAC->Pnmi.PMD = 2;
- if (pAC->GIni.GIMacsFound > 1) {
-
- pAC->Pnmi.DeviceType = 0x00020004;
- }
- else {
- pAC->Pnmi.DeviceType = 0x00020003;
- }
- break;
-
- case 'C':
- pAC->Pnmi.PMD = 4;
- if (pAC->GIni.GIMacsFound > 1) {
-
- pAC->Pnmi.DeviceType = 0x00020006;
- }
- else {
- pAC->Pnmi.DeviceType = 0x00020005;
- }
- break;
-
- case 'T':
- pAC->Pnmi.PMD = 5;
- if (pAC->GIni.GIMacsFound > 1) {
-
- pAC->Pnmi.DeviceType = 0x00020008;
- }
- else {
- pAC->Pnmi.DeviceType = 0x00020007;
- }
- break;
-
- default :
- pAC->Pnmi.PMD = 1;
- pAC->Pnmi.DeviceType = 0;
- break;
- }
-
- /*
- * Get connector
- */
- SK_IN8(IoC, B2_CONN_TYP, &Val8);
- switch (Val8) {
- case 'C':
- pAC->Pnmi.Connector = 2;
- break;
-
- case 'D':
- pAC->Pnmi.Connector = 3;
- break;
-
- case 'F':
- pAC->Pnmi.Connector = 4;
- break;
-
- case 'J':
- pAC->Pnmi.Connector = 5;
- break;
-
- case 'V':
- pAC->Pnmi.Connector = 6;
- break;
-
- default:
- pAC->Pnmi.Connector = 1;
- break;
- }
- break;
-
- case SK_INIT_RUN:
- /*
- * Start timer for RLMT change counter
- */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
- 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
- EventParam);
- break;
-
- default:
- break; /* Nothing todo */
- }
-
- return (0);
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetVar - Retrieves the value of a single OID
- *
- * Description:
- * Calls a general sub-function for all this stuff. If the instance
- * -1 is passed, the values of all instances are returned in an
- * array of values.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed
- * SK_PNMI_ERR_GENERAL A general severe internal error occured
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
- * the data.
- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-static int SkPnmiGetVar(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Id, /* Object ID that is to be processed */
-void *pBuf, /* Buffer to which the management data will be copied */
-unsigned int *pLen, /* On call: buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
- Id, *pLen, Instance, NetIndex));
-
- return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
- Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetVar - Presets the value of a single OID
- *
- * Description:
- * Calls a general sub-function for all this stuff. The preset does
- * the same as a set, but returns just before finally setting the
- * new value. This is useful to check if a set might be successfull.
- * If the instance -1 is passed, an array of values is supposed and
- * all instances of the OID will be set.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-static int SkPnmiPreSetVar(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Id, /* Object ID that is to be processed */
-void *pBuf, /* Buffer to which the management data will be copied */
-unsigned int *pLen, /* Total length of management data */
-SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
- Id, *pLen, Instance, NetIndex));
-
-
- return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
- Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetVar - Sets the value of a single OID
- *
- * Description:
- * Calls a general sub-function for all this stuff. The preset does
- * the same as a set, but returns just before finally setting the
- * new value. This is useful to check if a set might be successfull.
- * If the instance -1 is passed, an array of values is supposed and
- * all instances of the OID will be set.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-int SkPnmiSetVar(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Id, /* Object ID that is to be processed */
-void *pBuf, /* Buffer to which the management data will be copied */
-unsigned int *pLen, /* Total length of management data */
-SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
- Id, *pLen, Instance, NetIndex));
-
- return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
- Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- * Runs through the IdTable, queries the single OIDs and stores the
- * returned data into the management database structure
- * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
- * is stored in the IdTable. The return value of the function will also
- * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- * minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed
- * SK_PNMI_ERR_GENERAL A general severe internal error occured
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
- * the data.
- * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
- */
-int SkPnmiGetStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-void *pBuf, /* Buffer to which the management data will be copied. */
-unsigned int *pLen, /* Length of buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int TableIndex;
- unsigned int DstOffset;
- unsigned int InstanceNo;
- unsigned int InstanceCnt;
- SK_U32 Instance;
- unsigned int TmpLen;
- char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
-
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
- *pLen, NetIndex));
-
- if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
- if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
- (SK_U32)(-1));
- }
-
- *pLen = SK_PNMI_STRUCT_SIZE;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Check NetIndex
- */
- if (NetIndex >= pAC->Rlmt.NumNets) {
- return (SK_PNMI_ERR_UNKNOWN_NET);
- }
-
- /* Update statistic */
- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
-
- if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
- SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- /*
- * Increment semaphores to indicate that an update was
- * already done
- */
- pAC->Pnmi.MacUpdatedFlag ++;
- pAC->Pnmi.RlmtUpdatedFlag ++;
- pAC->Pnmi.SirqUpdatedFlag ++;
-
- /* Get vpd keys for instance calculation */
- Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
- if (Ret != SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.MacUpdatedFlag --;
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Retrieve values */
- SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
- for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
- InstanceNo = IdTable[TableIndex].InstanceNo;
- for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
- InstanceCnt ++) {
-
- DstOffset = IdTable[TableIndex].Offset +
- (InstanceCnt - 1) *
- IdTable[TableIndex].StructSize;
-
- /*
- * For the VPD the instance is not an index number
- * but the key itself. Determin with the instance
- * counter the VPD key to be used.
- */
- if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
- IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
- IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
- IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
-
- SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
- }
- else {
- Instance = (SK_U32)InstanceCnt;
- }
-
- TmpLen = *pLen - DstOffset;
- Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
- IdTable[TableIndex].Id, (char *)pBuf +
- DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
-
- /*
- * An unknown instance error means that we reached
- * the last instance of that variable. Proceed with
- * the next OID in the table and ignore the return
- * code.
- */
- if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
- break;
- }
-
- if (Ret != SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.MacUpdatedFlag --;
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
- SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
- }
- }
-
- pAC->Pnmi.MacUpdatedFlag --;
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- *pLen = SK_PNMI_STRUCT_SIZE;
- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- * Calls a general sub-function for all this set stuff. The preset does
- * the same as a set, but returns just before finally setting the
- * new value. This is useful to check if a set might be successfull.
- * The sub-function runs through the IdTable, checks which OIDs are able
- * to set, and calls the handler function of the OID to perform the
- * preset. The return value of the function will also be stored in
- * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- * SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- */
-int SkPnmiPreSetStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-void *pBuf, /* Buffer which contains the data to be set */
-unsigned int *pLen, /* Length of buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
- *pLen, NetIndex));
-
- return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
- pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- * Calls a general sub-function for all this set stuff. The return value
- * of the function will also be stored in SK_PNMI_STRUCT_DATA if the
- * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- * The sub-function runs through the IdTable, checks which OIDs are able
- * to set, and calls the handler function of the OID to perform the
- * set. The return value of the function will also be stored in
- * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- * SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- */
-int SkPnmiSetStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-void *pBuf, /* Buffer which contains the data to be set */
-unsigned int *pLen, /* Length of buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
- *pLen, NetIndex));
-
- return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
- pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiEvent - Event handler
- *
- * Description:
- * Handles the following events:
- * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an
- * interrupt will be generated which is
- * first handled by SIRQ which generates a
- * this event. The event increments the
- * upper 32 bit of the 64 bit counter.
- * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module
- * when a sensor reports a warning or
- * error. The event will store a trap
- * message in the trap buffer.
- * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this
- * module and is used to calculate the
- * port switches per hour.
- * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and
- * timestamps.
- * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver
- * before a hard reset of the XMAC is
- * performed. All counters will be saved
- * and added to the hardware counter
- * values after reset to grant continuous
- * counter values.
- * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port
- * went logically up. A trap message will
- * be stored to the trap buffer.
- * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port
- * went logically down. A trap message will
- * be stored to the trap buffer.
- * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
- * spanning tree root bridges were
- * detected. A trap message will be stored
- * to the trap buffer.
- * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went
- * down. PNMI will not further add the
- * statistic values to the virtual port.
- * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and
- * is now an active port. PNMI will now
- * add the statistic data of this port to
- * the virtual port.
- * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first parameter
- * contains the number of nets. 1 means single net, 2 means
- * dual net. The second parameter is -1
- *
- * Returns:
- * Always 0
- */
-int SkPnmiEvent(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Event, /* Event-Id */
-SK_EVPARA Param) /* Event dependent parameter */
-{
- unsigned int PhysPortIndex;
- unsigned int MaxNetNumber;
- int CounterIndex;
- int Ret;
- SK_U16 MacStatus;
- SK_U64 OverflowStatus;
- SK_U64 Mask;
- int MacType;
- SK_U64 Value;
- SK_U32 Val32;
- SK_U16 Register;
- SK_EVPARA EventParam;
- SK_U64 NewestValue;
- SK_U64 OldestValue;
- SK_U64 Delta;
- SK_PNMI_ESTIMATE *pEst;
- SK_U32 NetIndex;
- SK_GEPORT *pPrt;
- SK_PNMI_VCT *pVctBackupData;
- SK_U32 RetCode;
- int i;
- SK_U32 CableLength;
-
-
-#ifdef DEBUG
- if (Event != SK_PNMI_EVT_XMAC_RESET) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
- (unsigned int)Event, (unsigned int)Param.Para64));
- }
-#endif /* DEBUG */
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
-
- MacType = pAC->GIni.GIMacType;
-
- switch (Event) {
-
- case SK_PNMI_EVT_SIRQ_OVERFLOW:
- PhysPortIndex = (int)Param.Para32[0];
- MacStatus = (SK_U16)Param.Para32[1];
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
- " wrong, PhysPortIndex=0x%x\n",
- PhysPortIndex));
- return (0);
- }
-#endif /* DEBUG */
- OverflowStatus = 0;
-
- /*
- * Check which source caused an overflow interrupt.
- */
- if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
- MacStatus, &OverflowStatus) != 0) ||
- (OverflowStatus == 0)) {
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
- }
-
- /*
- * Check the overflow status register and increment
- * the upper dword of corresponding counter.
- */
- for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
- CounterIndex ++) {
-
- Mask = (SK_U64)1 << CounterIndex;
- if ((OverflowStatus & Mask) == 0) {
-
- continue;
- }
-
- switch (StatOvrflwBit[CounterIndex][MacType]) {
-
- case SK_PNMI_HTX_UTILUNDER:
- case SK_PNMI_HTX_UTILOVER:
- if (MacType == SK_MAC_XMAC) {
- XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
- Register |= XM_TX_SAM_LINE;
- XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
- }
- break;
-
- case SK_PNMI_HRX_UTILUNDER:
- case SK_PNMI_HRX_UTILOVER:
- if (MacType == SK_MAC_XMAC) {
- XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
- Register |= XM_RX_SAM_LINE;
- XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
- }
- break;
-
- case SK_PNMI_HTX_OCTETHIGH:
- case SK_PNMI_HTX_OCTETLOW:
- case SK_PNMI_HTX_RESERVED:
- case SK_PNMI_HRX_OCTETHIGH:
- case SK_PNMI_HRX_OCTETLOW:
- case SK_PNMI_HRX_IRLENGTH:
- case SK_PNMI_HRX_RESERVED:
-
- /*
- * the following counters aren't be handled (id > 63)
- */
- case SK_PNMI_HTX_SYNC:
- case SK_PNMI_HTX_SYNC_OCTET:
- break;
-
- case SK_PNMI_HRX_LONGFRAMES:
- if (MacType == SK_MAC_GMAC) {
- pAC->Pnmi.Port[PhysPortIndex].
- CounterHigh[CounterIndex] ++;
- }
- break;
-
- default:
- pAC->Pnmi.Port[PhysPortIndex].
- CounterHigh[CounterIndex] ++;
- }
- }
- break;
-
- case SK_PNMI_EVT_SEN_WAR_LOW:
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate
- * an event for user space applications with the
- * SK_DRIVER_SENDEVENT macro.
- */
- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
- (unsigned int)Param.Para64);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_SEN_WAR_UPP:
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate
- * an event for user space applications with the
- * SK_DRIVER_SENDEVENT macro.
- */
- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
- (unsigned int)Param.Para64);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_SEN_ERR_LOW:
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate
- * an event for user space applications with the
- * SK_DRIVER_SENDEVENT macro.
- */
- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
- (unsigned int)Param.Para64);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_SEN_ERR_UPP:
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate
- * an event for user space applications with the
- * SK_DRIVER_SENDEVENT macro.
- */
- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
- (unsigned int)Param.Para64);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_CHG_EST_TIMER:
- /*
- * Calculate port switch average on a per hour basis
- * Time interval for check : 28125 ms
- * Number of values for average : 8
- *
- * Be careful in changing these values, on change check
- * - typedef of SK_PNMI_ESTIMATE (Size of EstValue
- * array one less than value number)
- * - Timer initialization SkTimerStart() in SkPnmiInit
- * - Delta value below must be multiplicated with
- * power of 2
- *
- */
- pEst = &pAC->Pnmi.RlmtChangeEstimate;
- CounterIndex = pEst->EstValueIndex + 1;
- if (CounterIndex == 7) {
-
- CounterIndex = 0;
- }
- pEst->EstValueIndex = CounterIndex;
-
- NewestValue = pAC->Pnmi.RlmtChangeCts;
- OldestValue = pEst->EstValue[CounterIndex];
- pEst->EstValue[CounterIndex] = NewestValue;
-
- /*
- * Calculate average. Delta stores the number of
- * port switches per 28125 * 8 = 225000 ms
- */
- if (NewestValue >= OldestValue) {
-
- Delta = NewestValue - OldestValue;
- }
- else {
- /* Overflow situation */
- Delta = (SK_U64)(0 - OldestValue) + NewestValue;
- }
-
- /*
- * Extrapolate delta to port switches per hour.
- * Estimate = Delta * (3600000 / 225000)
- * = Delta * 16
- * = Delta << 4
- */
- pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
-
- /*
- * Check if threshold is exceeded. If the threshold is
- * permanently exceeded every 28125 ms an event will be
- * generated to remind the user of this condition.
- */
- if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
- (pAC->Pnmi.RlmtChangeEstimate.Estimate >=
- pAC->Pnmi.RlmtChangeThreshold)) {
-
- QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- }
-
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
- 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
- EventParam);
- break;
-
- case SK_PNMI_EVT_CLEAR_COUNTER:
- /*
- * Param.Para32[0] contains the NetIndex (0 ..1).
- * Param.Para32[1] is reserved, contains -1.
- */
- NetIndex = (SK_U32)Param.Para32[0];
-
-#ifdef DEBUG
- if (NetIndex >= pAC->Rlmt.NumNets) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
- NetIndex));
-
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Set all counters and timestamps to zero.
- * The according NetIndex is required as a
- * parameter of the event.
- */
- ResetCounter(pAC, IoC, NetIndex);
- break;
-
- case SK_PNMI_EVT_XMAC_RESET:
- /*
- * To grant continuous counter values store the current
- * XMAC statistic values to the entries 1..n of the
- * CounterOffset array. XMAC Errata #2
- */
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif
- PhysPortIndex = (unsigned int)Param.Para64;
-
- /*
- * Update XMAC statistic to get fresh values
- */
- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
- if (Ret != SK_PNMI_ERR_OK) {
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
- }
- /*
- * Increment semaphore to indicate that an update was
- * already done
- */
- pAC->Pnmi.MacUpdatedFlag ++;
-
- for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
- CounterIndex ++) {
-
- if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
- continue;
- }
-
- pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
- GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
- pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
- }
-
- pAC->Pnmi.MacUpdatedFlag --;
- break;
-
- case SK_PNMI_EVT_RLMT_PORT_UP:
- PhysPortIndex = (unsigned int)Param.Para32[0];
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
- " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate an event for
- * user space applications with the SK_DRIVER_SENDEVENT macro.
- */
- QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
- /* Bugfix for XMAC errata (#10620)*/
- if (MacType == SK_MAC_XMAC) {
- /* Add incremental difference to offset (#10620)*/
- (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
- XM_RXE_SHT_ERR, &Val32);
-
- Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
- CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
- pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
- Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
- }
-
- /* Tell VctStatus() that a link was up meanwhile. */
- pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;
- break;
-
- case SK_PNMI_EVT_RLMT_PORT_DOWN:
- PhysPortIndex = (unsigned int)Param.Para32[0];
-
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
- " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate an event for
- * user space applications with the SK_DRIVER_SENDEVENT macro.
- */
- QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
- /* Bugfix #10620 - get zero level for incremental difference */
- if (MacType == SK_MAC_XMAC) {
-
- (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
- XM_RXE_SHT_ERR, &Val32);
-
- pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
- (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
- CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
- }
- break;
-
- case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
- PhysPortIndex = (unsigned int)Param.Para32[0];
- NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
- PhysPortIndex));
- }
-
- if (NetIndex >= pAC->Rlmt.NumNets) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
- NetIndex));
- }
-#endif /* DEBUG */
-
- /*
- * For now, ignore event if NetIndex != 0.
- */
- if (Param.Para32[1] != 0) {
-
- return (0);
- }
-
- /*
- * Nothing to do if port is already inactive
- */
- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- return (0);
- }
-
- /*
- * Update statistic counters to calculate new offset for the virtual
- * port and increment semaphore to indicate that an update was already
- * done.
- */
- if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
- SK_PNMI_ERR_OK) {
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /*
- * Calculate new counter offset for virtual port to grant continous
- * counting on port switches. The virtual port consists of all currently
- * active ports. The port down event indicates that a port is removed
- * from the virtual port. Therefore add the counter value of the removed
- * port to the CounterOffset for the virtual port to grant the same
- * counter value.
- */
- for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
- CounterIndex ++) {
-
- if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
- continue;
- }
-
- Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
- pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
- }
-
- /*
- * Set port to inactive
- */
- pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
-
- pAC->Pnmi.MacUpdatedFlag --;
- break;
-
- case SK_PNMI_EVT_RLMT_ACTIVE_UP:
- PhysPortIndex = (unsigned int)Param.Para32[0];
- NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
- PhysPortIndex));
- }
-
- if (NetIndex >= pAC->Rlmt.NumNets) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
- NetIndex));
- }
-#endif /* DEBUG */
-
- /*
- * For now, ignore event if NetIndex != 0.
- */
- if (Param.Para32[1] != 0) {
-
- return (0);
- }
-
- /*
- * Nothing to do if port is already active
- */
- if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- return (0);
- }
-
- /*
- * Statistic maintenance
- */
- pAC->Pnmi.RlmtChangeCts ++;
- pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-
- /*
- * Store a trap message in the trap buffer and generate an event for
- * user space applications with the SK_DRIVER_SENDEVENT macro.
- */
- QueueRlmtNewMacTrap(pAC, PhysPortIndex);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
- /*
- * Update statistic counters to calculate new offset for the virtual
- * port and increment semaphore to indicate that an update was
- * already done.
- */
- if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
- SK_PNMI_ERR_OK) {
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /*
- * Calculate new counter offset for virtual port to grant continous
- * counting on port switches. A new port is added to the virtual port.
- * Therefore substract the counter value of the new port from the
- * CounterOffset for the virtual port to grant the same value.
- */
- for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
- CounterIndex ++) {
-
- if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
- continue;
- }
-
- Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
- pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
- }
-
- /* Set port to active */
- pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
-
- pAC->Pnmi.MacUpdatedFlag --;
- break;
-
- case SK_PNMI_EVT_RLMT_SEGMENTATION:
- /*
- * Para.Para32[0] contains the NetIndex.
- */
-
- /*
- * Store a trap message in the trap buffer and generate an event for
- * user space applications with the SK_DRIVER_SENDEVENT macro.
- */
- QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_RLMT_SET_NETS:
- /*
- * Param.Para32[0] contains the number of Nets.
- * Param.Para32[1] is reserved, contains -1.
- */
- /*
- * Check number of nets
- */
- MaxNetNumber = pAC->GIni.GIMacsFound;
- if (((unsigned int)Param.Para32[0] < 1)
- || ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
- return (SK_PNMI_ERR_UNKNOWN_NET);
- }
-
- if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
- pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
- }
- else { /* dual net mode */
- pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
- }
- break;
-
- case SK_PNMI_EVT_VCT_RESET:
- PhysPortIndex = Param.Para32[0];
- pPrt = &pAC->GIni.GP[PhysPortIndex];
- pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-
- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
- RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
- if (RetCode == 2) {
- /*
- * VCT test is still running.
- * Start VCT timer counter again.
- */
- SK_MEMSET((char *) &Param, 0, sizeof(Param));
- Param.Para32[0] = PhysPortIndex;
- Param.Para32[1] = -1;
- SkTimerStart(pAC, IoC,
- &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
- 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
- break;
- }
- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
- pAC->Pnmi.VctStatus[PhysPortIndex] |=
- (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-
- /* Copy results for later use to PNMI struct. */
- for (i = 0; i < 4; i++) {
- if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
- if ((pPrt->PMdiPairLen[i] > 35) &&
- (pPrt->PMdiPairLen[i] < 0xff)) {
- pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
- }
- }
- if ((pPrt->PMdiPairLen[i] > 35) &&
- (pPrt->PMdiPairLen[i] != 0xff)) {
- CableLength = 1000 *
- (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
- }
- else {
- CableLength = 0;
- }
- pVctBackupData->PMdiPairLen[i] = CableLength;
- pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
- }
-
- Param.Para32[0] = PhysPortIndex;
- Param.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
- SkEventDispatcher(pAC, IoC);
- }
-
- break;
-
- default:
- break;
- }
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
-}
-
-
-/******************************************************************************
- *
- * Private functions
- *
- */
-
-/*****************************************************************************
- *
- * PnmiVar - Gets, presets, and sets single OIDs
- *
- * Description:
- * Looks up the requested OID, calls the corresponding handler
- * function, and passes the parameters with the get, preset, or
- * set command. The function is called by SkGePnmiGetVar,
- * SkGePnmiPreSetVar, or SkGePnmiSetVar.
- *
- * Returns:
- * SK_PNMI_ERR_XXX. For details have a look at the description of the
- * calling functions.
- * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiVar(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* Total length of pBuf management data */
-SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int TableIndex;
- int Ret;
-
-
- if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_OID);
- }
-
- /* Check NetIndex */
- if (NetIndex >= pAC->Rlmt.NumNets) {
- return (SK_PNMI_ERR_UNKNOWN_NET);
- }
-
- SK_PNMI_CHECKFLAGS("PnmiVar: On call");
-
- Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
- Instance, TableIndex, NetIndex);
-
- SK_PNMI_CHECKFLAGS("PnmiVar: On return");
-
- return (Ret);
-}
-
-/*****************************************************************************
- *
- * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
- *
- * Description:
- * The return value of the function will also be stored in
- * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
- * checks which OIDs are able to set, and calls the handler function of
- * the OID to perform the set. The return value of the function will
- * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
- * by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
- *
- * Returns:
- * SK_PNMI_ERR_XXX. The codes are described in the calling functions.
- * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* PRESET/SET action to be performed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* Length of pBuf management data buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int TableIndex;
- unsigned int DstOffset;
- unsigned int Len;
- unsigned int InstanceNo;
- unsigned int InstanceCnt;
- SK_U32 Instance;
- SK_U32 Id;
-
-
- /* Check if the passed buffer has the right size */
- if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
- /* Check if we can return the error within the buffer */
- if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
- (SK_U32)(-1));
- }
-
- *pLen = SK_PNMI_STRUCT_SIZE;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /* Check NetIndex */
- if (NetIndex >= pAC->Rlmt.NumNets) {
- return (SK_PNMI_ERR_UNKNOWN_NET);
- }
-
- SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
-
- /*
- * Update the values of RLMT and SIRQ and increment semaphores to
- * indicate that an update was already done.
- */
- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- pAC->Pnmi.RlmtUpdatedFlag ++;
- pAC->Pnmi.SirqUpdatedFlag ++;
-
- /* Preset/Set values */
- for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
- if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
- (IdTable[TableIndex].Access != SK_PNMI_WO)) {
-
- continue;
- }
-
- InstanceNo = IdTable[TableIndex].InstanceNo;
- Id = IdTable[TableIndex].Id;
-
- for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
- InstanceCnt ++) {
-
- DstOffset = IdTable[TableIndex].Offset +
- (InstanceCnt - 1) *
- IdTable[TableIndex].StructSize;
-
- /*
- * Because VPD multiple instance variables are
- * not setable we do not need to evaluate VPD
- * instances. Have a look to VPD instance
- * calculation in SkPnmiGetStruct().
- */
- Instance = (SK_U32)InstanceCnt;
-
- /*
- * Evaluate needed buffer length
- */
- Len = 0;
- Ret = IdTable[TableIndex].Func(pAC, IoC,
- SK_PNMI_GET, IdTable[TableIndex].Id,
- NULL, &Len, Instance, TableIndex, NetIndex);
-
- if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
- break;
- }
- if (Ret != SK_PNMI_ERR_TOO_SHORT) {
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
- SK_PNMI_SET_STAT(pBuf,
- SK_PNMI_ERR_GENERAL, DstOffset);
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (SK_PNMI_ERR_GENERAL);
- }
- if (Id == OID_SKGE_VPD_ACTION) {
-
- switch (*(pBuf + DstOffset)) {
-
- case SK_PNMI_VPD_CREATE:
- Len = 3 + *(pBuf + DstOffset + 3);
- break;
-
- case SK_PNMI_VPD_DELETE:
- Len = 3;
- break;
-
- default:
- Len = 1;
- break;
- }
- }
-
- /* Call the OID handler function */
- Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
- IdTable[TableIndex].Id, pBuf + DstOffset,
- &Len, Instance, TableIndex, NetIndex);
-
- if (Ret != SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
- DstOffset);
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- }
- }
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * LookupId - Lookup an OID in the IdTable
- *
- * Description:
- * Scans the IdTable to find the table entry of an OID.
- *
- * Returns:
- * The table index or -1 if not found.
- */
-PNMI_STATIC int LookupId(
-SK_U32 Id) /* Object identifier to be searched */
-{
- int i;
-
- for (i = 0; i < ID_TABLE_SIZE; i++) {
-
- if (IdTable[i].Id == Id) {
-
- return i;
- }
- }
-
- return (-1);
-}
-
-/*****************************************************************************
- *
- * OidStruct - Handler of OID_SKGE_ALL_DATA
- *
- * Description:
- * This OID performs a Get/Preset/SetStruct call and returns all data
- * in a SK_PNMI_STRUCT_DATA structure.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int OidStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- if (Id != OID_SKGE_ALL_DATA) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
- SK_PNMI_ERR003MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Check instance. We only handle single instance variables
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- switch (Action) {
-
- case SK_PNMI_GET:
- return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
- case SK_PNMI_PRESET:
- return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
- case SK_PNMI_SET:
- return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
- }
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
-}
-
-/*****************************************************************************
- *
- * Perform - OID handler of OID_SKGE_ACTION
- *
- * Description:
- * None.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Perform(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- SK_U32 ActionOp;
-
-
- /*
- * Check instance. We only handle single instance variables
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /* Check if a get should be performed */
- if (Action == SK_PNMI_GET) {
-
- /* A get is easy. We always return the same value */
- ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
- SK_PNMI_STORE_U32(pBuf, ActionOp);
- *pLen = sizeof(SK_U32);
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Continue with PRESET/SET action */
- if (*pLen > sizeof(SK_U32)) {
-
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* Check if the command is a known one */
- SK_PNMI_READ_U32(pBuf, ActionOp);
- if (*pLen > sizeof(SK_U32) ||
- (ActionOp != SK_PNMI_ACT_IDLE &&
- ActionOp != SK_PNMI_ACT_RESET &&
- ActionOp != SK_PNMI_ACT_SELFTEST &&
- ActionOp != SK_PNMI_ACT_RESETCNT)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* A preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- switch (ActionOp) {
-
- case SK_PNMI_ACT_IDLE:
- /* Nothing to do */
- break;
-
- case SK_PNMI_ACT_RESET:
- /*
- * Perform a driver reset or something that comes near
- * to this.
- */
- Ret = SK_DRIVER_RESET(pAC, IoC);
- if (Ret != 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
- SK_PNMI_ERR005MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- case SK_PNMI_ACT_SELFTEST:
- /*
- * Perform a driver selftest or something similar to this.
- * Currently this feature is not used and will probably
- * implemented in another way.
- */
- Ret = SK_DRIVER_SELFTEST(pAC, IoC);
- pAC->Pnmi.TestResult = Ret;
- break;
-
- case SK_PNMI_ACT_RESETCNT:
- /* Set all counters and timestamps to zero */
- ResetCounter(pAC, IoC, NetIndex);
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
- SK_PNMI_ERR006MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
- *
- * Description:
- * Retrieves the statistic values of the virtual port (logical
- * index 0). Only special OIDs of NDIS are handled which consist
- * of a 32 bit instead of a 64 bit value. The OIDs are public
- * because perhaps some other platform can use them too.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Mac8023Stat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- SK_U64 StatVal;
- SK_U32 StatVal32;
- SK_BOOL Is64BitReq = SK_FALSE;
-
- /*
- * Only the active Mac is returned
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /*
- * Check action type
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check length */
- switch (Id) {
-
- case OID_802_3_PERMANENT_ADDRESS:
- case OID_802_3_CURRENT_ADDRESS:
- if (*pLen < sizeof(SK_MAC_ADDR)) {
-
- *pLen = sizeof(SK_MAC_ADDR);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
-#ifndef SK_NDIS_64BIT_CTR
- if (*pLen < sizeof(SK_U32)) {
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
-#else /* SK_NDIS_64BIT_CTR */
-
- /* for compatibility, at least 32bit are required for OID */
- if (*pLen < sizeof(SK_U32)) {
- /*
- * but indicate handling for 64bit values,
- * if insufficient space is provided
- */
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
- break;
- }
-
- /*
- * Update all statistics, because we retrieve virtual MAC, which
- * consists of multiple physical statistics and increment semaphore
- * to indicate that an update was already done.
- */
- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
- if ( Ret != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /*
- * Get value (MAC Index 0 identifies the virtual MAC)
- */
- switch (Id) {
-
- case OID_802_3_PERMANENT_ADDRESS:
- CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
- *pLen = sizeof(SK_MAC_ADDR);
- break;
-
- case OID_802_3_CURRENT_ADDRESS:
- CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
- *pLen = sizeof(SK_MAC_ADDR);
- break;
-
- default:
- StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
-
- /* by default 32bit values are evaluated */
- if (!Is64BitReq) {
- StatVal32 = (SK_U32)StatVal;
- SK_PNMI_STORE_U32(pBuf, StatVal32);
- *pLen = sizeof(SK_U32);
- }
- else {
- SK_PNMI_STORE_U64(pBuf, StatVal);
- *pLen = sizeof(SK_U64);
- }
- break;
- }
-
- pAC->Pnmi.MacUpdatedFlag --;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
- *
- * Description:
- * Retrieves the MAC statistic data.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int MacPrivateStat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int LogPortMax;
- unsigned int LogPortIndex;
- unsigned int PhysPortMax;
- unsigned int Limit;
- unsigned int Offset;
- int MacType;
- int Ret;
- SK_U64 StatVal;
-
-
-
- /* Calculate instance if wished. MAC index 0 is the virtual MAC */
- PhysPortMax = pAC->GIni.GIMacsFound;
- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
- MacType = pAC->GIni.GIMacType;
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
- LogPortMax--;
- }
-
- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
- /* Check instance range */
- if ((Instance < 1) || (Instance > LogPortMax)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
- Limit = LogPortIndex + 1;
- }
-
- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
- LogPortIndex = 0;
- Limit = LogPortMax;
- }
-
- /* Check action */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check length */
- if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
-
- *pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Update MAC statistic and increment semaphore to indicate that
- * an update was already done.
- */
- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
- if (Ret != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /* Get value */
- Offset = 0;
- for (; LogPortIndex < Limit; LogPortIndex ++) {
-
- switch (Id) {
-
-/* XXX not yet implemented due to XMAC problems
- case OID_SKGE_STAT_TX_UTIL:
- return (SK_PNMI_ERR_GENERAL);
-*/
-/* XXX not yet implemented due to XMAC problems
- case OID_SKGE_STAT_RX_UTIL:
- return (SK_PNMI_ERR_GENERAL);
-*/
- case OID_SKGE_STAT_RX:
- if (MacType == SK_MAC_GMAC) {
- StatVal =
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HRX_BROADCAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HRX_MULTICAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HRX_UNICAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HRX_UNDERSIZE, NetIndex);
- }
- else {
- StatVal = GetStatVal(pAC, IoC, LogPortIndex,
- IdTable[TableIndex].Param, NetIndex);
- }
- break;
-
- case OID_SKGE_STAT_TX:
- if (MacType == SK_MAC_GMAC) {
- StatVal =
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HTX_BROADCAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HTX_MULTICAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HTX_UNICAST, NetIndex);
- }
- else {
- StatVal = GetStatVal(pAC, IoC, LogPortIndex,
- IdTable[TableIndex].Param, NetIndex);
- }
- break;
-
- default:
- StatVal = GetStatVal(pAC, IoC, LogPortIndex,
- IdTable[TableIndex].Param, NetIndex);
- }
- SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
-
- Offset += sizeof(SK_U64);
- }
- *pLen = Offset;
-
- pAC->Pnmi.MacUpdatedFlag --;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
- *
- * Description:
- * Get/Presets/Sets the current and factory MAC address. The MAC
- * address of the virtual port, which is reported to the OS, may
- * not be changed, but the physical ones. A set to the virtual port
- * will be ignored. No error should be reported because otherwise
- * a multiple instance set (-1) would always fail.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Addr(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int LogPortMax;
- unsigned int PhysPortMax;
- unsigned int LogPortIndex;
- unsigned int PhysPortIndex;
- unsigned int Limit;
- unsigned int Offset = 0;
-
- /*
- * Calculate instance if wished. MAC index 0 is the virtual
- * MAC.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
- LogPortMax--;
- }
-
- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
- /* Check instance range */
- if ((Instance < 1) || (Instance > LogPortMax)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
- Limit = LogPortIndex + 1;
- }
- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
- LogPortIndex = 0;
- Limit = LogPortMax;
- }
-
- /*
- * Perform Action
- */
- if (Action == SK_PNMI_GET) {
-
- /* Check length */
- if (*pLen < (Limit - LogPortIndex) * 6) {
-
- *pLen = (Limit - LogPortIndex) * 6;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Get value
- */
- for (; LogPortIndex < Limit; LogPortIndex ++) {
-
- switch (Id) {
-
- case OID_SKGE_PHYS_CUR_ADDR:
- if (LogPortIndex == 0) {
- CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
- }
- else {
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-
- CopyMac(pBuf + Offset,
- &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
- }
- Offset += 6;
- break;
-
- case OID_SKGE_PHYS_FAC_ADDR:
- if (LogPortIndex == 0) {
- CopyMac(pBuf + Offset,
- &pAC->Addr.Net[NetIndex].PermanentMacAddress);
- }
- else {
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- CopyMac(pBuf + Offset,
- &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
- }
- Offset += 6;
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
- SK_PNMI_ERR008MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- *pLen = Offset;
- }
- else {
- /*
- * The logical MAC address may not be changed only
- * the physical ones
- */
- if (Id == OID_SKGE_PHYS_FAC_ADDR) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /*
- * Only the current address may be changed
- */
- if (Id != OID_SKGE_PHYS_CUR_ADDR) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
- SK_PNMI_ERR009MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Check length */
- if (*pLen < (Limit - LogPortIndex) * 6) {
-
- *pLen = (Limit - LogPortIndex) * 6;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- if (*pLen > (Limit - LogPortIndex) * 6) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /*
- * Check Action
- */
- if (Action == SK_PNMI_PRESET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_OK);
- }
-
- /*
- * Set OID_SKGE_MAC_CUR_ADDR
- */
- for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
-
- /*
- * A set to virtual port and set of broadcast
- * address will be ignored
- */
- if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
- "\xff\xff\xff\xff\xff\xff", 6) == 0) {
-
- continue;
- }
-
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
- LogPortIndex);
-
- Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
- (SK_MAC_ADDR *)(pBuf + Offset),
- (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
- SK_ADDR_PHYSICAL_ADDRESS));
- if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
-
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- *pLen = Offset;
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
- *
- * Description:
- * Retrieves the statistic values of the CSUM module. The CSUM data
- * structure must be available in the SK_AC even if the CSUM module
- * is not included, because PNMI reads the statistic data from the
- * CSUM part of SK_AC directly.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int CsumStat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int Index;
- unsigned int Limit;
- unsigned int Offset = 0;
- SK_U64 StatVal;
-
-
- /*
- * Calculate instance if wished
- */
- if (Instance != (SK_U32)(-1)) {
-
- if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- Index = (unsigned int)Instance - 1;
- Limit = Index + 1;
- }
- else {
- Index = 0;
- Limit = SKCS_NUM_PROTOCOLS;
- }
-
- /*
- * Check action
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check length */
- if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
- *pLen = (Limit - Index) * sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Get value
- */
- for (; Index < Limit; Index ++) {
-
- switch (Id) {
-
- case OID_SKGE_CHKSM_RX_OK_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
- break;
-
- case OID_SKGE_CHKSM_RX_UNABLE_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
- break;
-
- case OID_SKGE_CHKSM_RX_ERR_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
- break;
-
- case OID_SKGE_CHKSM_TX_OK_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
- break;
-
- case OID_SKGE_CHKSM_TX_UNABLE_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
- SK_PNMI_ERR010MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
- Offset += sizeof(SK_U64);
- }
-
- /*
- * Store used buffer space
- */
- *pLen = Offset;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
- *
- * Description:
- * Retrieves the statistic values of the I2C module, which handles
- * the temperature and voltage sensors.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int SensorStat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int i;
- unsigned int Index;
- unsigned int Limit;
- unsigned int Offset;
- unsigned int Len;
- SK_U32 Val32;
- SK_U64 Val64;
-
-
- /*
- * Calculate instance if wished
- */
- if ((Instance != (SK_U32)(-1))) {
-
- if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- Index = (unsigned int)Instance -1;
- Limit = (unsigned int)Instance;
- }
- else {
- Index = 0;
- Limit = (unsigned int) pAC->I2c.MaxSens;
- }
-
- /*
- * Check action
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check length */
- switch (Id) {
-
- case OID_SKGE_SENSOR_VALUE:
- case OID_SKGE_SENSOR_WAR_THRES_LOW:
- case OID_SKGE_SENSOR_WAR_THRES_UPP:
- case OID_SKGE_SENSOR_ERR_THRES_LOW:
- case OID_SKGE_SENSOR_ERR_THRES_UPP:
- if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
-
- *pLen = (Limit - Index) * sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_SENSOR_DESCR:
- for (Offset = 0, i = Index; i < Limit; i ++) {
-
- Len = (unsigned int)
- SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
- if (Len >= SK_PNMI_STRINGLEN2) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
- SK_PNMI_ERR011MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- Offset += Len;
- }
- if (*pLen < Offset) {
-
- *pLen = Offset;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_SENSOR_INDEX:
- case OID_SKGE_SENSOR_TYPE:
- case OID_SKGE_SENSOR_STATUS:
- if (*pLen < Limit - Index) {
-
- *pLen = Limit - Index;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_SENSOR_WAR_CTS:
- case OID_SKGE_SENSOR_WAR_TIME:
- case OID_SKGE_SENSOR_ERR_CTS:
- case OID_SKGE_SENSOR_ERR_TIME:
- if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
- *pLen = (Limit - Index) * sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
- SK_PNMI_ERR012MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
-
- }
-
- /*
- * Get value
- */
- for (Offset = 0; Index < Limit; Index ++) {
-
- switch (Id) {
-
- case OID_SKGE_SENSOR_INDEX:
- *(pBuf + Offset) = (char)Index;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SENSOR_DESCR:
- Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
- SK_MEMCPY(pBuf + Offset + 1,
- pAC->I2c.SenTable[Index].SenDesc, Len);
- *(pBuf + Offset) = (char)Len;
- Offset += Len + 1;
- break;
-
- case OID_SKGE_SENSOR_TYPE:
- *(pBuf + Offset) =
- (char)pAC->I2c.SenTable[Index].SenType;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SENSOR_VALUE:
- Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_WAR_THRES_LOW:
- Val32 = (SK_U32)pAC->I2c.SenTable[Index].
- SenThreWarnLow;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_WAR_THRES_UPP:
- Val32 = (SK_U32)pAC->I2c.SenTable[Index].
- SenThreWarnHigh;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_ERR_THRES_LOW:
- Val32 = (SK_U32)pAC->I2c.SenTable[Index].
- SenThreErrLow;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_ERR_THRES_UPP:
- Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_STATUS:
- *(pBuf + Offset) =
- (char)pAC->I2c.SenTable[Index].SenErrFlag;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SENSOR_WAR_CTS:
- Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_SENSOR_ERR_CTS:
- Val64 = pAC->I2c.SenTable[Index].SenErrCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_SENSOR_WAR_TIME:
- Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
- SenBegWarnTS);
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_SENSOR_ERR_TIME:
- Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
- SenBegErrTS);
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("SensorStat: Unknown OID should be handled before"));
-
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- /*
- * Store used buffer space
- */
- *pLen = Offset;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Vpd - OID handler function of OID_SKGE_VPD_XXX
- *
- * Description:
- * Get/preset/set of VPD data. As instance the name of a VPD key
- * can be passed. The Instance parameter is a SK_U32 and can be
- * used as a string buffer for the VPD key, because their maximum
- * length is 4 byte.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Vpd(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_VPD_STATUS *pVpdStatus;
- unsigned int BufLen;
- char Buf[256];
- char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
- char KeyStr[SK_PNMI_VPD_KEY_SIZE];
- unsigned int KeyNo;
- unsigned int Offset;
- unsigned int Index;
- unsigned int FirstIndex;
- unsigned int LastIndex;
- unsigned int Len;
- int Ret;
- SK_U32 Val32;
-
- /*
- * Get array of all currently stored VPD keys
- */
- Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
- if (Ret != SK_PNMI_ERR_OK) {
- *pLen = 0;
- return (Ret);
- }
-
- /*
- * If instance is not -1, try to find the requested VPD key for
- * the multiple instance variables. The other OIDs as for example
- * OID VPD_ACTION are single instance variables and must be
- * handled separatly.
- */
- FirstIndex = 0;
- LastIndex = KeyNo;
-
- if ((Instance != (SK_U32)(-1))) {
-
- if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
- Id == OID_SKGE_VPD_ACCESS) {
-
- SK_STRNCPY(KeyStr, (char *)&Instance, 4);
- KeyStr[4] = 0;
-
- for (Index = 0; Index < KeyNo; Index ++) {
-
- if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
- FirstIndex = Index;
- LastIndex = Index+1;
- break;
- }
- }
- if (Index == KeyNo) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- }
- else if (Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- }
-
- /*
- * Get value, if a query should be performed
- */
- if (Action == SK_PNMI_GET) {
-
- switch (Id) {
-
- case OID_SKGE_VPD_FREE_BYTES:
- /* Check length of buffer */
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /* Get number of free bytes */
- pVpdStatus = VpdStat(pAC, IoC);
- if (pVpdStatus == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
- SK_PNMI_ERR017MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
- SK_PNMI_ERR018MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_VPD_ENTRIES_LIST:
- /* Check length */
- for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
-
- Len += SK_STRLEN(KeyArr[Index]) + 1;
- }
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /* Get value */
- *(pBuf) = (char)Len - 1;
- for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
-
- Len = SK_STRLEN(KeyArr[Index]);
- SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
-
- Offset += Len;
-
- if (Index < KeyNo - 1) {
-
- *(pBuf + Offset) = ' ';
- Offset ++;
- }
- }
- *pLen = Offset;
- break;
-
- case OID_SKGE_VPD_ENTRIES_NUMBER:
- /* Check length */
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- Val32 = (SK_U32)KeyNo;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_VPD_KEY:
- /* Check buffer length, if it is large enough */
- for (Len = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- Len += SK_STRLEN(KeyArr[Index]) + 1;
- }
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Get the key to an intermediate buffer, because
- * we have to prepend a length byte.
- */
- for (Offset = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- Len = SK_STRLEN(KeyArr[Index]);
-
- *(pBuf + Offset) = (char)Len;
- SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
- Len);
- Offset += Len + 1;
- }
- *pLen = Offset;
- break;
-
- case OID_SKGE_VPD_VALUE:
- /* Check the buffer length if it is large enough */
- for (Offset = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- BufLen = 256;
- if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
- (int *)&BufLen) > 0 ||
- BufLen >= SK_PNMI_VPD_DATALEN) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR021,
- SK_PNMI_ERR021MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
- Offset += BufLen + 1;
- }
- if (*pLen < Offset) {
-
- *pLen = Offset;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Get the value to an intermediate buffer, because
- * we have to prepend a length byte.
- */
- for (Offset = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- BufLen = 256;
- if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
- (int *)&BufLen) > 0 ||
- BufLen >= SK_PNMI_VPD_DATALEN) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR022,
- SK_PNMI_ERR022MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- *(pBuf + Offset) = (char)BufLen;
- SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
- Offset += BufLen + 1;
- }
- *pLen = Offset;
- break;
-
- case OID_SKGE_VPD_ACCESS:
- if (*pLen < LastIndex - FirstIndex) {
-
- *pLen = LastIndex - FirstIndex;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- for (Offset = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- if (VpdMayWrite(KeyArr[Index])) {
-
- *(pBuf + Offset) = SK_PNMI_VPD_RW;
- }
- else {
- *(pBuf + Offset) = SK_PNMI_VPD_RO;
- }
- Offset ++;
- }
- *pLen = Offset;
- break;
-
- case OID_SKGE_VPD_ACTION:
- Offset = LastIndex - FirstIndex;
- if (*pLen < Offset) {
-
- *pLen = Offset;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- SK_MEMSET(pBuf, 0, Offset);
- *pLen = Offset;
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
- SK_PNMI_ERR023MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- else {
- /* The only OID which can be set is VPD_ACTION */
- if (Id != OID_SKGE_VPD_ACTION) {
-
- if (Id == OID_SKGE_VPD_FREE_BYTES ||
- Id == OID_SKGE_VPD_ENTRIES_LIST ||
- Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
- Id == OID_SKGE_VPD_KEY ||
- Id == OID_SKGE_VPD_VALUE ||
- Id == OID_SKGE_VPD_ACCESS) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
- SK_PNMI_ERR024MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * From this point we handle VPD_ACTION. Check the buffer
- * length. It should at least have the size of one byte.
- */
- if (*pLen < 1) {
-
- *pLen = 1;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * The first byte contains the VPD action type we should
- * perform.
- */
- switch (*pBuf) {
-
- case SK_PNMI_VPD_IGNORE:
- /* Nothing to do */
- break;
-
- case SK_PNMI_VPD_CREATE:
- /*
- * We have to create a new VPD entry or we modify
- * an existing one. Check first the buffer length.
- */
- if (*pLen < 4) {
-
- *pLen = 4;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- KeyStr[0] = pBuf[1];
- KeyStr[1] = pBuf[2];
- KeyStr[2] = 0;
-
- /*
- * Is the entry writable or does it belong to the
- * read-only area?
- */
- if (!VpdMayWrite(KeyStr)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- Offset = (int)pBuf[3] & 0xFF;
-
- SK_MEMCPY(Buf, pBuf + 4, Offset);
- Buf[Offset] = 0;
-
- /* A preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Write the new entry or modify an existing one */
- Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
- if (Ret == SK_PNMI_VPD_NOWRITE ) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- else if (Ret != SK_PNMI_VPD_OK) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
- SK_PNMI_ERR025MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Perform an update of the VPD data. This is
- * not mandantory, but just to be sure.
- */
- Ret = VpdUpdate(pAC, IoC);
- if (Ret != SK_PNMI_VPD_OK) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
- SK_PNMI_ERR026MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- case SK_PNMI_VPD_DELETE:
- /* Check if the buffer size is plausible */
- if (*pLen < 3) {
-
- *pLen = 3;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- if (*pLen > 3) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- KeyStr[0] = pBuf[1];
- KeyStr[1] = pBuf[2];
- KeyStr[2] = 0;
-
- /* Find the passed key in the array */
- for (Index = 0; Index < KeyNo; Index ++) {
-
- if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
-
- break;
- }
- }
- /*
- * If we cannot find the key it is wrong, so we
- * return an appropriate error value.
- */
- if (Index == KeyNo) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Ok, you wanted it and you will get it */
- Ret = VpdDelete(pAC, IoC, KeyStr);
- if (Ret != SK_PNMI_VPD_OK) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
- SK_PNMI_ERR027MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Perform an update of the VPD data. This is
- * not mandantory, but just to be sure.
- */
- Ret = VpdUpdate(pAC, IoC);
- if (Ret != SK_PNMI_VPD_OK) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
- SK_PNMI_ERR028MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * General - OID handler function of various single instance OIDs
- *
- * Description:
- * The code is simple. No description necessary.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int General(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int Index;
- unsigned int Len;
- unsigned int Offset;
- unsigned int Val;
- SK_U8 Val8;
- SK_U16 Val16;
- SK_U32 Val32;
- SK_U64 Val64;
- SK_U64 Val64RxHwErrs = 0;
- SK_U64 Val64TxHwErrs = 0;
- SK_BOOL Is64BitReq = SK_FALSE;
- char Buf[256];
- int MacType;
-
- /*
- * Check instance. We only handle single instance variables.
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /*
- * Check action. We only allow get requests.
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- MacType = pAC->GIni.GIMacType;
-
- /*
- * Check length for the various supported OIDs
- */
- switch (Id) {
-
- case OID_GEN_XMIT_ERROR:
- case OID_GEN_RCV_ERROR:
- case OID_GEN_RCV_NO_BUFFER:
-#ifndef SK_NDIS_64BIT_CTR
- if (*pLen < sizeof(SK_U32)) {
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
-#else /* SK_NDIS_64BIT_CTR */
-
- /*
- * for compatibility, at least 32bit are required for oid
- */
- if (*pLen < sizeof(SK_U32)) {
- /*
- * but indicate handling for 64bit values,
- * if insufficient space is provided
- */
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
- break;
-
- case OID_SKGE_PORT_NUMBER:
- case OID_SKGE_DEVICE_TYPE:
- case OID_SKGE_RESULT:
- case OID_SKGE_RLMT_MONITOR_NUMBER:
- case OID_GEN_TRANSMIT_QUEUE_LENGTH:
- case OID_SKGE_TRAP_NUMBER:
- case OID_SKGE_MDB_VERSION:
- case OID_SKGE_BOARDLEVEL:
- case OID_SKGE_CHIPID:
- case OID_SKGE_RAMSIZE:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_CHIPSET:
- if (*pLen < sizeof(SK_U16)) {
-
- *pLen = sizeof(SK_U16);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_BUS_TYPE:
- case OID_SKGE_BUS_SPEED:
- case OID_SKGE_BUS_WIDTH:
- case OID_SKGE_SENSOR_NUMBER:
- case OID_SKGE_CHKSM_NUMBER:
- case OID_SKGE_VAUXAVAIL:
- if (*pLen < sizeof(SK_U8)) {
-
- *pLen = sizeof(SK_U8);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_TX_SW_QUEUE_LEN:
- case OID_SKGE_TX_SW_QUEUE_MAX:
- case OID_SKGE_TX_RETRY:
- case OID_SKGE_RX_INTR_CTS:
- case OID_SKGE_TX_INTR_CTS:
- case OID_SKGE_RX_NO_BUF_CTS:
- case OID_SKGE_TX_NO_BUF_CTS:
- case OID_SKGE_TX_USED_DESCR_NO:
- case OID_SKGE_RX_DELIVERED_CTS:
- case OID_SKGE_RX_OCTETS_DELIV_CTS:
- case OID_SKGE_RX_HW_ERROR_CTS:
- case OID_SKGE_TX_HW_ERROR_CTS:
- case OID_SKGE_IN_ERRORS_CTS:
- case OID_SKGE_OUT_ERROR_CTS:
- case OID_SKGE_ERR_RECOVERY_CTS:
- case OID_SKGE_SYSUPTIME:
- if (*pLen < sizeof(SK_U64)) {
-
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- /* Checked later */
- break;
- }
-
- /* Update statistic */
- if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
- Id == OID_SKGE_TX_HW_ERROR_CTS ||
- Id == OID_SKGE_IN_ERRORS_CTS ||
- Id == OID_SKGE_OUT_ERROR_CTS ||
- Id == OID_GEN_XMIT_ERROR ||
- Id == OID_GEN_RCV_ERROR) {
-
- /* Force the XMAC to update its statistic counters and
- * Increment semaphore to indicate that an update was
- * already done.
- */
- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
- if (Ret != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /*
- * Some OIDs consist of multiple hardware counters. Those
- * values which are contained in all of them will be added
- * now.
- */
- switch (Id) {
-
- case OID_SKGE_RX_HW_ERROR_CTS:
- case OID_SKGE_IN_ERRORS_CTS:
- case OID_GEN_RCV_ERROR:
- Val64RxHwErrs =
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
- break;
-
- case OID_SKGE_TX_HW_ERROR_CTS:
- case OID_SKGE_OUT_ERROR_CTS:
- case OID_GEN_XMIT_ERROR:
- Val64TxHwErrs =
- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
- break;
- }
- }
-
- /*
- * Retrieve value
- */
- switch (Id) {
-
- case OID_SKGE_SUPPORTED_LIST:
- Len = ID_TABLE_SIZE * sizeof(SK_U32);
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- for (Offset = 0, Index = 0; Offset < Len;
- Offset += sizeof(SK_U32), Index ++) {
-
- Val32 = (SK_U32)IdTable[Index].Id;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- }
- *pLen = Len;
- break;
-
- case OID_SKGE_BOARDLEVEL:
- Val32 = (SK_U32)pAC->GIni.GILevel;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_PORT_NUMBER:
- Val32 = (SK_U32)pAC->GIni.GIMacsFound;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_DEVICE_TYPE:
- Val32 = (SK_U32)pAC->Pnmi.DeviceType;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_DRIVER_DESCR:
- if (pAC->Pnmi.pDriverDescription == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
- SK_PNMI_ERR007MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
- SK_PNMI_ERR029MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_DRIVER_VERSION:
- if (pAC->Pnmi.pDriverVersion == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
- SK_PNMI_ERR030MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
- SK_PNMI_ERR031MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_DRIVER_RELDATE:
- if (pAC->Pnmi.pDriverReleaseDate == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
- SK_PNMI_ERR053MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
- SK_PNMI_ERR054MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_DRIVER_FILENAME:
- if (pAC->Pnmi.pDriverFileName == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
- SK_PNMI_ERR055MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
- SK_PNMI_ERR056MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_HW_DESCR:
- /*
- * The hardware description is located in the VPD. This
- * query may move to the initialisation routine. But
- * the VPD data is cached and therefore a call here
- * will not make much difference.
- */
- Len = 256;
- if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
- SK_PNMI_ERR032MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- Len ++;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
- SK_PNMI_ERR033MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, Buf, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_HW_VERSION:
- /* Oh, I love to do some string manipulation */
- if (*pLen < 5) {
-
- *pLen = 5;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
- pBuf[0] = 4;
- pBuf[1] = 'v';
- pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
- pBuf[3] = '.';
- pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
- *pLen = 5;
- break;
-
- case OID_SKGE_CHIPSET:
- Val16 = pAC->Pnmi.Chipset;
- SK_PNMI_STORE_U16(pBuf, Val16);
- *pLen = sizeof(SK_U16);
- break;
-
- case OID_SKGE_CHIPID:
- Val32 = pAC->GIni.GIChipId;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_RAMSIZE:
- Val32 = pAC->GIni.GIRamSize;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_VAUXAVAIL:
- *pBuf = (char) pAC->GIni.GIVauxAvail;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_BUS_TYPE:
- *pBuf = (char) SK_PNMI_BUS_PCI;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_BUS_SPEED:
- *pBuf = pAC->Pnmi.PciBusSpeed;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_BUS_WIDTH:
- *pBuf = pAC->Pnmi.PciBusWidth;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_RESULT:
- Val32 = pAC->Pnmi.TestResult;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_NUMBER:
- *pBuf = (char)pAC->I2c.MaxSens;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_CHKSM_NUMBER:
- *pBuf = SKCS_NUM_PROTOCOLS;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_TRAP_NUMBER:
- GetTrapQueueLen(pAC, &Len, &Val);
- Val32 = (SK_U32)Val;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_TRAP:
- GetTrapQueueLen(pAC, &Len, &Val);
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- CopyTrapQueue(pAC, pBuf);
- *pLen = Len;
- break;
-
- case OID_SKGE_RLMT_MONITOR_NUMBER:
-/* XXX Not yet implemented by RLMT therefore we return zero elements */
- Val32 = 0;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_TX_SW_QUEUE_LEN:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
- pAC->Pnmi.BufPort[1].TxSwQueueLen;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
- pAC->Pnmi.Port[1].TxSwQueueLen;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
-
- case OID_SKGE_TX_SW_QUEUE_MAX:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
- pAC->Pnmi.BufPort[1].TxSwQueueMax;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
- pAC->Pnmi.Port[1].TxSwQueueMax;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_RETRY:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
- pAC->Pnmi.BufPort[1].TxRetryCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxRetryCts +
- pAC->Pnmi.Port[1].TxRetryCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_INTR_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
- pAC->Pnmi.BufPort[1].RxIntrCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].RxIntrCts +
- pAC->Pnmi.Port[1].RxIntrCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_INTR_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
- pAC->Pnmi.BufPort[1].TxIntrCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxIntrCts +
- pAC->Pnmi.Port[1].TxIntrCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_NO_BUF_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
- pAC->Pnmi.BufPort[1].RxNoBufCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
- pAC->Pnmi.Port[1].RxNoBufCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_NO_BUF_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
- pAC->Pnmi.BufPort[1].TxNoBufCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
- pAC->Pnmi.Port[1].TxNoBufCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_USED_DESCR_NO:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
- pAC->Pnmi.BufPort[1].TxUsedDescrNo;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
- pAC->Pnmi.Port[1].TxUsedDescrNo;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_DELIVERED_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
- pAC->Pnmi.BufPort[1].RxDeliveredCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
- pAC->Pnmi.Port[1].RxDeliveredCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_OCTETS_DELIV_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
- pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
- pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_HW_ERROR_CTS:
- SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_HW_ERROR_CTS:
- SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_IN_ERRORS_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = Val64RxHwErrs +
- pAC->Pnmi.BufPort[0].RxNoBufCts +
- pAC->Pnmi.BufPort[1].RxNoBufCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = Val64RxHwErrs +
- pAC->Pnmi.Port[0].RxNoBufCts +
- pAC->Pnmi.Port[1].RxNoBufCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_OUT_ERROR_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = Val64TxHwErrs +
- pAC->Pnmi.BufPort[0].TxNoBufCts +
- pAC->Pnmi.BufPort[1].TxNoBufCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = Val64TxHwErrs +
- pAC->Pnmi.Port[0].TxNoBufCts +
- pAC->Pnmi.Port[1].TxNoBufCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_ERR_RECOVERY_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
- pAC->Pnmi.BufPort[1].ErrRecoveryCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
- pAC->Pnmi.Port[1].ErrRecoveryCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_SYSUPTIME:
- Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
- Val64 -= pAC->Pnmi.StartUpTime;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_MDB_VERSION:
- Val32 = SK_PNMI_MDB_VERSION;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_GEN_RCV_ERROR:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
- }
- else {
- Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
- }
-
- /*
- * by default 32bit values are evaluated
- */
- if (!Is64BitReq) {
- Val32 = (SK_U32)Val64;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- }
- else {
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- }
- break;
-
- case OID_GEN_XMIT_ERROR:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
- }
- else {
- Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
- }
-
- /*
- * by default 32bit values are evaluated
- */
- if (!Is64BitReq) {
- Val32 = (SK_U32)Val64;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- }
- else {
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- }
- break;
-
- case OID_GEN_RCV_NO_BUFFER:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
- }
- else {
- Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
- }
-
- /*
- * by default 32bit values are evaluated
- */
- if (!Is64BitReq) {
- Val32 = (SK_U32)Val64;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- }
- else {
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- }
- break;
-
- case OID_GEN_TRANSMIT_QUEUE_LENGTH:
- Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
- SK_PNMI_ERR034MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
- Id == OID_SKGE_TX_HW_ERROR_CTS ||
- Id == OID_SKGE_IN_ERRORS_CTS ||
- Id == OID_SKGE_OUT_ERROR_CTS ||
- Id == OID_GEN_XMIT_ERROR ||
- Id == OID_GEN_RCV_ERROR) {
-
- pAC->Pnmi.MacUpdatedFlag --;
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
- *
- * Description:
- * Get/Presets/Sets the RLMT OIDs.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Rlmt(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int PhysPortIndex;
- unsigned int PhysPortMax;
- SK_EVPARA EventParam;
- SK_U32 Val32;
- SK_U64 Val64;
-
-
- /*
- * Check instance. Only single instance OIDs are allowed here.
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /*
- * Perform the requested action.
- */
- if (Action == SK_PNMI_GET) {
-
- /*
- * Check if the buffer length is large enough.
- */
-
- switch (Id) {
-
- case OID_SKGE_RLMT_MODE:
- case OID_SKGE_RLMT_PORT_ACTIVE:
- case OID_SKGE_RLMT_PORT_PREFERRED:
- if (*pLen < sizeof(SK_U8)) {
-
- *pLen = sizeof(SK_U8);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_RLMT_PORT_NUMBER:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_RLMT_CHANGE_CTS:
- case OID_SKGE_RLMT_CHANGE_TIME:
- case OID_SKGE_RLMT_CHANGE_ESTIM:
- case OID_SKGE_RLMT_CHANGE_THRES:
- if (*pLen < sizeof(SK_U64)) {
-
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
- SK_PNMI_ERR035MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Update RLMT statistic and increment semaphores to indicate
- * that an update was already done. Maybe RLMT will hold its
- * statistic always up to date some time. Then we can
- * remove this type of call.
- */
- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.RlmtUpdatedFlag ++;
-
- /*
- * Retrieve Value
- */
- switch (Id) {
-
- case OID_SKGE_RLMT_MODE:
- *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_RLMT_PORT_NUMBER:
- Val32 = (SK_U32)pAC->GIni.GIMacsFound;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_RLMT_PORT_ACTIVE:
- *pBuf = 0;
- /*
- * If multiple ports may become active this OID
- * doesn't make sense any more. A new variable in
- * the port structure should be created. However,
- * for this variable the first active port is
- * returned.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
-
- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
- break;
- }
- }
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_RLMT_PORT_PREFERRED:
- *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_RLMT_CHANGE_CTS:
- Val64 = pAC->Pnmi.RlmtChangeCts;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_CHANGE_TIME:
- Val64 = pAC->Pnmi.RlmtChangeTime;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_CHANGE_ESTIM:
- Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_CHANGE_THRES:
- Val64 = pAC->Pnmi.RlmtChangeThreshold;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("Rlmt: Unknown OID should be handled before"));
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- }
- else {
- /* Perform a preset or set */
- switch (Id) {
-
- case OID_SKGE_RLMT_MODE:
- /* Check if the buffer length is plausible */
- if (*pLen < sizeof(char)) {
-
- *pLen = sizeof(char);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /* Check if the value range is correct */
- if (*pLen != sizeof(char) ||
- (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
- *(SK_U8 *)pBuf > 15) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_OK);
- }
- /* Send an event to RLMT to change the mode */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] |= (SK_U32)(*pBuf);
- EventParam.Para32[1] = 0;
- if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
- SK_PNMI_ERR037MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- case OID_SKGE_RLMT_PORT_PREFERRED:
- /* Check if the buffer length is plausible */
- if (*pLen < sizeof(char)) {
-
- *pLen = sizeof(char);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /* Check if the value range is correct */
- if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
- (SK_U8)pAC->GIni.GIMacsFound) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_OK);
- }
-
- /*
- * Send an event to RLMT change the preferred port.
- * A param of -1 means automatic mode. RLMT will
- * make the decision which is the preferred port.
- */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
- EventParam.Para32[1] = NetIndex;
- if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
- SK_PNMI_ERR038MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- case OID_SKGE_RLMT_CHANGE_THRES:
- /* Check if the buffer length is plausible */
- if (*pLen < sizeof(SK_U64)) {
-
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /*
- * There are not many restrictions to the
- * value range.
- */
- if (*pLen != sizeof(SK_U64)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- /* A preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_OK);
- }
- /*
- * Store the new threshold, which will be taken
- * on the next timer event.
- */
- SK_PNMI_READ_U64(pBuf, Val64);
- pAC->Pnmi.RlmtChangeThreshold = Val64;
- break;
-
- default:
- /* The other OIDs are not be able for set */
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
- *
- * Description:
- * Performs get requests on multiple instance variables.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int RlmtStat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int PhysPortMax;
- unsigned int PhysPortIndex;
- unsigned int Limit;
- unsigned int Offset;
- int Ret;
- SK_U32 Val32;
- SK_U64 Val64;
-
- /*
- * Calculate the port indexes from the instance.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
-
- if ((Instance != (SK_U32)(-1))) {
- /* Check instance range */
- if ((Instance < 1) || (Instance > PhysPortMax)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /* Single net mode */
- PhysPortIndex = Instance - 1;
-
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- PhysPortIndex = NetIndex;
- }
-
- /* Both net modes */
- Limit = PhysPortIndex + 1;
- }
- else {
- /* Single net mode */
- PhysPortIndex = 0;
- Limit = PhysPortMax;
-
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- PhysPortIndex = NetIndex;
- Limit = PhysPortIndex + 1;
- }
- }
-
- /*
- * Currently only get requests are allowed.
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /*
- * Check if the buffer length is large enough.
- */
- switch (Id) {
-
- case OID_SKGE_RLMT_PORT_INDEX:
- case OID_SKGE_RLMT_STATUS:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
-
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_RLMT_TX_HELLO_CTS:
- case OID_SKGE_RLMT_RX_HELLO_CTS:
- case OID_SKGE_RLMT_TX_SP_REQ_CTS:
- case OID_SKGE_RLMT_RX_SP_CTS:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
-
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
- SK_PNMI_ERR039MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
-
- }
-
- /*
- * Update statistic and increment semaphores to indicate that
- * an update was already done.
- */
- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.RlmtUpdatedFlag ++;
-
- /*
- * Get value
- */
- Offset = 0;
- for (; PhysPortIndex < Limit; PhysPortIndex ++) {
-
- switch (Id) {
-
- case OID_SKGE_RLMT_PORT_INDEX:
- Val32 = PhysPortIndex;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_RLMT_STATUS:
- if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
- SK_RLMT_PS_INIT ||
- pAC->Rlmt.Port[PhysPortIndex].PortState ==
- SK_RLMT_PS_DOWN) {
-
- Val32 = SK_PNMI_RLMT_STATUS_ERROR;
- }
- else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
- }
- else {
- Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
- }
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_RLMT_TX_HELLO_CTS:
- Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_RX_HELLO_CTS:
- Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_TX_SP_REQ_CTS:
- Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_RX_SP_CTS:
- Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("RlmtStat: Unknown OID should be errored before"));
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- *pLen = Offset;
-
- pAC->Pnmi.RlmtUpdatedFlag --;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateConf - OID handler function of OIDs concerning the configuration
- *
- * Description:
- * Get/Presets/Sets the OIDs concerning the configuration.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int MacPrivateConf(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int PhysPortMax;
- unsigned int PhysPortIndex;
- unsigned int LogPortMax;
- unsigned int LogPortIndex;
- unsigned int Limit;
- unsigned int Offset;
- char Val8;
- char *pBufPtr;
- int Ret;
- SK_EVPARA EventParam;
- SK_U32 Val32;
-
- /*
- * Calculate instance if wished. MAC index 0 is the virtual MAC.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
- LogPortMax--;
- }
-
- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
- /* Check instance range */
- if ((Instance < 1) || (Instance > LogPortMax)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
- Limit = LogPortIndex + 1;
- }
-
- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
- LogPortIndex = 0;
- Limit = LogPortMax;
- }
-
- /*
- * Perform action
- */
- if (Action == SK_PNMI_GET) {
-
- /* Check length */
- switch (Id) {
-
- case OID_SKGE_PMD:
- case OID_SKGE_CONNECTOR:
- case OID_SKGE_LINK_CAP:
- case OID_SKGE_LINK_MODE:
- case OID_SKGE_LINK_MODE_STATUS:
- case OID_SKGE_LINK_STATUS:
- case OID_SKGE_FLOWCTRL_CAP:
- case OID_SKGE_FLOWCTRL_MODE:
- case OID_SKGE_FLOWCTRL_STATUS:
- case OID_SKGE_PHY_OPERATION_CAP:
- case OID_SKGE_PHY_OPERATION_MODE:
- case OID_SKGE_PHY_OPERATION_STATUS:
- case OID_SKGE_SPEED_CAP:
- case OID_SKGE_SPEED_MODE:
- case OID_SKGE_SPEED_STATUS:
- if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
-
- *pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_MTU:
- case OID_SKGE_PHY_TYPE:
- if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
-
- *pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
- SK_PNMI_ERR041MSG);
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Update statistic and increment semaphore to indicate
- * that an update was already done.
- */
- if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.SirqUpdatedFlag ++;
-
- /*
- * Get value
- */
- Offset = 0;
- for (; LogPortIndex < Limit; LogPortIndex ++) {
-
- pBufPtr = pBuf + Offset;
-
- switch (Id) {
-
- case OID_SKGE_PMD:
- *pBufPtr = pAC->Pnmi.PMD;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_CONNECTOR:
- *pBufPtr = pAC->Pnmi.Connector;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_TYPE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- continue;
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
- SK_PNMI_STORE_U32(pBufPtr, Val32);
- }
- }
- else { /* DualNetMode */
-
- Val32 = pAC->GIni.GP[NetIndex].PhyType;
- SK_PNMI_STORE_U32(pBufPtr, Val32);
- }
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_LINK_CAP:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_LINK_MODE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_LINK_MODE_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr =
- CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_LINK_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_FLOWCTRL_CAP:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_FLOWCTRL_MODE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_FLOWCTRL_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_OPERATION_CAP:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_OPERATION_MODE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_OPERATION_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
- }
- }
- else {
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SPEED_CAP:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SPEED_MODE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SPEED_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_MTU:
- Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
- SK_PNMI_STORE_U32(pBufPtr, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("MacPrivateConf: Unknown OID should be handled before"));
-
- pAC->Pnmi.SirqUpdatedFlag --;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- *pLen = Offset;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- return (SK_PNMI_ERR_OK);
- }
-
- /*
- * From here SET or PRESET action. Check if the passed
- * buffer length is plausible.
- */
- switch (Id) {
-
- case OID_SKGE_LINK_MODE:
- case OID_SKGE_FLOWCTRL_MODE:
- case OID_SKGE_PHY_OPERATION_MODE:
- case OID_SKGE_SPEED_MODE:
- if (*pLen < Limit - LogPortIndex) {
-
- *pLen = Limit - LogPortIndex;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- if (*pLen != Limit - LogPortIndex) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- break;
-
- case OID_SKGE_MTU:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- if (*pLen != sizeof(SK_U32)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /*
- * Perform preset or set
- */
- Offset = 0;
- for (; LogPortIndex < Limit; LogPortIndex ++) {
-
- switch (Id) {
-
- case OID_SKGE_LINK_MODE:
- /* Check the value range */
- Val8 = *(pBuf + Offset);
- if (Val8 == 0) {
-
- Offset += sizeof(char);
- break;
- }
- if (Val8 < SK_LMODE_HALF ||
- (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
- (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- if (LogPortIndex == 0) {
-
- /*
- * The virtual port consists of all currently
- * active ports. Find them and send an event
- * with the new link mode to SIRQ.
- */
- for (PhysPortIndex = 0;
- PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (!pAC->Pnmi.Port[PhysPortIndex].
- ActiveFlag) {
-
- continue;
- }
-
- EventParam.Para32[0] = PhysPortIndex;
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_LMODE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR043,
- SK_PNMI_ERR043MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- }
- else {
- /*
- * Send an event with the new link mode to
- * the SIRQ module.
- */
- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR043,
- SK_PNMI_ERR043MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_FLOWCTRL_MODE:
- /* Check the value range */
- Val8 = *(pBuf + Offset);
- if (Val8 == 0) {
-
- Offset += sizeof(char);
- break;
- }
- if (Val8 < SK_FLOW_MODE_NONE ||
- (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
- (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- if (LogPortIndex == 0) {
-
- /*
- * The virtual port consists of all currently
- * active ports. Find them and send an event
- * with the new flow control mode to SIRQ.
- */
- for (PhysPortIndex = 0;
- PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (!pAC->Pnmi.Port[PhysPortIndex].
- ActiveFlag) {
-
- continue;
- }
-
- EventParam.Para32[0] = PhysPortIndex;
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_FLOWMODE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR044,
- SK_PNMI_ERR044MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- }
- else {
- /*
- * Send an event with the new flow control
- * mode to the SIRQ module.
- */
- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_FLOWMODE, EventParam)
- > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR044,
- SK_PNMI_ERR044MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_OPERATION_MODE :
- /* Check the value range */
- Val8 = *(pBuf + Offset);
- if (Val8 == 0) {
- /* mode of this port remains unchanged */
- Offset += sizeof(char);
- break;
- }
- if (Val8 < SK_MS_MODE_AUTO ||
- (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
- (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- if (LogPortIndex == 0) {
-
- /*
- * The virtual port consists of all currently
- * active ports. Find them and send an event
- * with new master/slave (role) mode to SIRQ.
- */
- for (PhysPortIndex = 0;
- PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (!pAC->Pnmi.Port[PhysPortIndex].
- ActiveFlag) {
-
- continue;
- }
-
- EventParam.Para32[0] = PhysPortIndex;
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_ROLE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR042,
- SK_PNMI_ERR042MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- }
- else {
- /*
- * Send an event with the new master/slave
- * (role) mode to the SIRQ module.
- */
- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_ROLE, EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR042,
- SK_PNMI_ERR042MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SPEED_MODE:
- /* Check the value range */
- Val8 = *(pBuf + Offset);
- if (Val8 == 0) {
-
- Offset += sizeof(char);
- break;
- }
- if (Val8 < (SK_LSPEED_AUTO) ||
- (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
- (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- if (LogPortIndex == 0) {
-
- /*
- * The virtual port consists of all currently
- * active ports. Find them and send an event
- * with the new flow control mode to SIRQ.
- */
- for (PhysPortIndex = 0;
- PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- continue;
- }
-
- EventParam.Para32[0] = PhysPortIndex;
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_SPEED,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR045,
- SK_PNMI_ERR045MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- }
- else {
- /*
- * Send an event with the new flow control
- * mode to the SIRQ module.
- */
- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_SPEED,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR045,
- SK_PNMI_ERR045MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_MTU :
- /* Check the value range */
- Val32 = *(SK_U32*)(pBuf + Offset);
- if (Val32 == 0) {
- /* mtu of this port remains unchanged */
- Offset += sizeof(SK_U32);
- break;
- }
- if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
- return (SK_PNMI_ERR_OK);
- }
-
- if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Offset += sizeof(SK_U32);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("MacPrivateConf: Unknown OID should be handled before set"));
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Monitor - OID handler function for RLMT_MONITOR_XXX
- *
- * Description:
- * Because RLMT currently does not support the monitoring of
- * remote adapter cards, we return always an empty table.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Monitor(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int Index;
- unsigned int Limit;
- unsigned int Offset;
- unsigned int Entries;
-
-
- /*
- * Calculate instance if wished.
- */
- /* XXX Not yet implemented. Return always an empty table. */
- Entries = 0;
-
- if ((Instance != (SK_U32)(-1))) {
-
- if ((Instance < 1) || (Instance > Entries)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- Index = (unsigned int)Instance - 1;
- Limit = (unsigned int)Instance;
- }
- else {
- Index = 0;
- Limit = Entries;
- }
-
- /*
- * Get/Set value
- */
- if (Action == SK_PNMI_GET) {
-
- for (Offset=0; Index < Limit; Index ++) {
-
- switch (Id) {
-
- case OID_SKGE_RLMT_MONITOR_INDEX:
- case OID_SKGE_RLMT_MONITOR_ADDR:
- case OID_SKGE_RLMT_MONITOR_ERRS:
- case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
- case OID_SKGE_RLMT_MONITOR_ADMIN:
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
- SK_PNMI_ERR046MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- *pLen = Offset;
- }
- else {
- /* Only MONITOR_ADMIN can be set */
- if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check if the length is plausible */
- if (*pLen < (Limit - Index)) {
-
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /* Okay, we have a wide value range */
- if (*pLen != (Limit - Index)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-/*
- for (Offset=0; Index < Limit; Index ++) {
- }
-*/
-/*
- * XXX Not yet implemented. Return always BAD_VALUE, because the table
- * is empty.
- */
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * VirtualConf - Calculates the values of configuration OIDs for virtual port
- *
- * Description:
- * We handle here the get of the configuration group OIDs, which are
- * a little bit complicated. The virtual port consists of all currently
- * active physical ports. If multiple ports are active and configured
- * differently we get in some trouble to return a single value. So we
- * get the value of the first active port and compare it with that of
- * the other active ports. If they are not the same, we return a value
- * that indicates that the state is indeterminated.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void VirtualConf(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf) /* Buffer used for the management data transfer */
-{
- unsigned int PhysPortMax;
- unsigned int PhysPortIndex;
- SK_U8 Val8;
- SK_U32 Val32;
- SK_BOOL PortActiveFlag;
- SK_GEPORT *pPrt;
-
- *pBuf = 0;
- PortActiveFlag = SK_FALSE;
- PhysPortMax = pAC->GIni.GIMacsFound;
-
- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- pPrt = &pAC->GIni.GP[PhysPortIndex];
-
- /* Check if the physical port is active */
- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- continue;
- }
-
- PortActiveFlag = SK_TRUE;
-
- switch (Id) {
-
- case OID_SKGE_PHY_TYPE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
- Val32 = pPrt->PhyType;
- SK_PNMI_STORE_U32(pBuf, Val32);
- continue;
- }
-
- case OID_SKGE_LINK_CAP:
-
- /*
- * Different capabilities should not happen, but
- * in the case of the cases OR them all together.
- * From a curious point of view the virtual port
- * is capable of all found capabilities.
- */
- *pBuf |= pPrt->PLinkCap;
- break;
-
- case OID_SKGE_LINK_MODE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PLinkModeConf;
- continue;
- }
-
- /*
- * If we find an active port with a different link
- * mode than the first one we return a value that
- * indicates that the link mode is indeterminated.
- */
- if (*pBuf != pPrt->PLinkModeConf) {
-
- *pBuf = SK_LMODE_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_LINK_MODE_STATUS:
- /* Get the link mode of the physical port */
- Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
-
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = Val8;
- continue;
- }
-
- /*
- * If we find an active port with a different link
- * mode status than the first one we return a value
- * that indicates that the link mode status is
- * indeterminated.
- */
- if (*pBuf != Val8) {
-
- *pBuf = SK_LMODE_STAT_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_LINK_STATUS:
- /* Get the link status of the physical port */
- Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
-
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = Val8;
- continue;
- }
-
- /*
- * If we find an active port with a different link
- * status than the first one, we return a value
- * that indicates that the link status is
- * indeterminated.
- */
- if (*pBuf != Val8) {
-
- *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_FLOWCTRL_CAP:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PFlowCtrlCap;
- continue;
- }
-
- /*
- * From a curious point of view the virtual port
- * is capable of all found capabilities.
- */
- *pBuf |= pPrt->PFlowCtrlCap;
- break;
-
- case OID_SKGE_FLOWCTRL_MODE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PFlowCtrlMode;
- continue;
- }
-
- /*
- * If we find an active port with a different flow
- * control mode than the first one, we return a value
- * that indicates that the mode is indeterminated.
- */
- if (*pBuf != pPrt->PFlowCtrlMode) {
-
- *pBuf = SK_FLOW_MODE_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_FLOWCTRL_STATUS:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PFlowCtrlStatus;
- continue;
- }
-
- /*
- * If we find an active port with a different flow
- * control status than the first one, we return a
- * value that indicates that the status is
- * indeterminated.
- */
- if (*pBuf != pPrt->PFlowCtrlStatus) {
-
- *pBuf = SK_FLOW_STAT_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_PHY_OPERATION_CAP:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PMSCap;
- continue;
- }
-
- /*
- * From a curious point of view the virtual port
- * is capable of all found capabilities.
- */
- *pBuf |= pPrt->PMSCap;
- break;
-
- case OID_SKGE_PHY_OPERATION_MODE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PMSMode;
- continue;
- }
-
- /*
- * If we find an active port with a different master/
- * slave mode than the first one, we return a value
- * that indicates that the mode is indeterminated.
- */
- if (*pBuf != pPrt->PMSMode) {
-
- *pBuf = SK_MS_MODE_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_PHY_OPERATION_STATUS:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PMSStatus;
- continue;
- }
-
- /*
- * If we find an active port with a different master/
- * slave status than the first one, we return a
- * value that indicates that the status is
- * indeterminated.
- */
- if (*pBuf != pPrt->PMSStatus) {
-
- *pBuf = SK_MS_STAT_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_SPEED_MODE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PLinkSpeed;
- continue;
- }
-
- /*
- * If we find an active port with a different flow
- * control mode than the first one, we return a value
- * that indicates that the mode is indeterminated.
- */
- if (*pBuf != pPrt->PLinkSpeed) {
-
- *pBuf = SK_LSPEED_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_SPEED_STATUS:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PLinkSpeedUsed;
- continue;
- }
-
- /*
- * If we find an active port with a different flow
- * control status than the first one, we return a
- * value that indicates that the status is
- * indeterminated.
- */
- if (*pBuf != pPrt->PLinkSpeedUsed) {
-
- *pBuf = SK_LSPEED_STAT_INDETERMINATED;
- }
- break;
- }
- }
-
- /*
- * If no port is active return an indeterminated answer
- */
- if (!PortActiveFlag) {
-
- switch (Id) {
-
- case OID_SKGE_LINK_CAP:
- *pBuf = SK_LMODE_CAP_INDETERMINATED;
- break;
-
- case OID_SKGE_LINK_MODE:
- *pBuf = SK_LMODE_INDETERMINATED;
- break;
-
- case OID_SKGE_LINK_MODE_STATUS:
- *pBuf = SK_LMODE_STAT_INDETERMINATED;
- break;
-
- case OID_SKGE_LINK_STATUS:
- *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
- break;
-
- case OID_SKGE_FLOWCTRL_CAP:
- case OID_SKGE_FLOWCTRL_MODE:
- *pBuf = SK_FLOW_MODE_INDETERMINATED;
- break;
-
- case OID_SKGE_FLOWCTRL_STATUS:
- *pBuf = SK_FLOW_STAT_INDETERMINATED;
- break;
-
- case OID_SKGE_PHY_OPERATION_CAP:
- *pBuf = SK_MS_CAP_INDETERMINATED;
- break;
-
- case OID_SKGE_PHY_OPERATION_MODE:
- *pBuf = SK_MS_MODE_INDETERMINATED;
- break;
-
- case OID_SKGE_PHY_OPERATION_STATUS:
- *pBuf = SK_MS_STAT_INDETERMINATED;
- break;
- case OID_SKGE_SPEED_CAP:
- *pBuf = SK_LSPEED_CAP_INDETERMINATED;
- break;
-
- case OID_SKGE_SPEED_MODE:
- *pBuf = SK_LSPEED_INDETERMINATED;
- break;
-
- case OID_SKGE_SPEED_STATUS:
- *pBuf = SK_LSPEED_STAT_INDETERMINATED;
- break;
- }
- }
-}
-
-/*****************************************************************************
- *
- * CalculateLinkStatus - Determins the link status of a physical port
- *
- * Description:
- * Determins the link status the following way:
- * LSTAT_PHY_DOWN: Link is down
- * LSTAT_AUTONEG: Auto-negotiation failed
- * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port
- * logically up.
- * LSTAT_LOG_UP: RLMT marked the port as up
- *
- * Returns:
- * Link status of physical port
- */
-PNMI_STATIC SK_U8 CalculateLinkStatus(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int PhysPortIndex) /* Physical port index */
-{
- SK_U8 Result;
-
- if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
-
- Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
- }
- else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
-
- Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
- }
- else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
-
- Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
- }
- else {
- Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
- }
-
- return (Result);
-}
-
-/*****************************************************************************
- *
- * CalculateLinkModeStatus - Determins the link mode status of a phys. port
- *
- * Description:
- * The COMMON module only tells us if the mode is half or full duplex.
- * But in the decade of auto sensing it is useful for the user to
- * know if the mode was negotiated or forced. Therefore we have a
- * look to the mode, which was last used by the negotiation process.
- *
- * Returns:
- * The link mode status
- */
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int PhysPortIndex) /* Physical port index */
-{
- SK_U8 Result;
-
- /* Get the current mode, which can be full or half duplex */
- Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
-
- /* Check if no valid mode could be found (link is down) */
- if (Result < SK_LMODE_STAT_HALF) {
-
- Result = SK_LMODE_STAT_UNKNOWN;
- }
- else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
-
- /*
- * Auto-negotiation was used to bring up the link. Change
- * the already found duplex status that it indicates
- * auto-negotiation was involved.
- */
- if (Result == SK_LMODE_STAT_HALF) {
-
- Result = SK_LMODE_STAT_AUTOHALF;
- }
- else if (Result == SK_LMODE_STAT_FULL) {
-
- Result = SK_LMODE_STAT_AUTOFULL;
- }
- }
-
- return (Result);
-}
-
-/*****************************************************************************
- *
- * GetVpdKeyArr - Obtain an array of VPD keys
- *
- * Description:
- * Read the VPD keys and build an array of VPD keys, which are
- * easy to access.
- *
- * Returns:
- * SK_PNMI_ERR_OK Task successfully performed.
- * SK_PNMI_ERR_GENERAL Something went wrong.
- */
-PNMI_STATIC int GetVpdKeyArr(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-char *pKeyArr, /* Ptr KeyArray */
-unsigned int KeyArrLen, /* Length of array in bytes */
-unsigned int *pKeyNo) /* Number of keys */
-{
- unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE;
- char BufKeys[SK_PNMI_VPD_BUFSIZE];
- unsigned int StartOffset;
- unsigned int Offset;
- int Index;
- int Ret;
-
-
- SK_MEMSET(pKeyArr, 0, KeyArrLen);
-
- /*
- * Get VPD key list
- */
- Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
- (int *)pKeyNo);
- if (Ret > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
- SK_PNMI_ERR014MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
- /* If no keys are available return now */
- if (*pKeyNo == 0 || BufKeysLen == 0) {
-
- return (SK_PNMI_ERR_OK);
- }
- /*
- * If the key list is too long for us trunc it and give a
- * errorlog notification. This case should not happen because
- * the maximum number of keys is limited due to RAM limitations
- */
- if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
- SK_PNMI_ERR015MSG);
-
- *pKeyNo = SK_PNMI_VPD_ENTRIES;
- }
-
- /*
- * Now build an array of fixed string length size and copy
- * the keys together.
- */
- for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
- Offset ++) {
-
- if (BufKeys[Offset] != 0) {
-
- continue;
- }
-
- if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
- SK_PNMI_ERR016MSG);
- return (SK_PNMI_ERR_GENERAL);
- }
-
- SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
- &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
-
- Index ++;
- StartOffset = Offset + 1;
- }
-
- /* Last key not zero terminated? Get it anyway */
- if (StartOffset < Offset) {
-
- SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
- &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SirqUpdate - Let the SIRQ update its internal values
- *
- * Description:
- * Just to be sure that the SIRQ module holds its internal data
- * structures up to date, we send an update event before we make
- * any access.
- *
- * Returns:
- * SK_PNMI_ERR_OK Task successfully performed.
- * SK_PNMI_ERR_GENERAL Something went wrong.
- */
-PNMI_STATIC int SirqUpdate(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC) /* IO context handle */
-{
- SK_EVPARA EventParam;
-
-
- /* Was the module already updated during the current PNMI call? */
- if (pAC->Pnmi.SirqUpdatedFlag > 0) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Send an synchronuous update event to the module */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
- SK_PNMI_ERR047MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtUpdate - Let the RLMT update its internal values
- *
- * Description:
- * Just to be sure that the RLMT module holds its internal data
- * structures up to date, we send an update event before we make
- * any access.
- *
- * Returns:
- * SK_PNMI_ERR_OK Task successfully performed.
- * SK_PNMI_ERR_GENERAL Something went wrong.
- */
-PNMI_STATIC int RlmtUpdate(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
-{
- SK_EVPARA EventParam;
-
-
- /* Was the module already updated during the current PNMI call? */
- if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Send an synchronuous update event to the module */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] = NetIndex;
- EventParam.Para32[1] = (SK_U32)-1;
- if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
- SK_PNMI_ERR048MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacUpdate - Force the XMAC to output the current statistic
- *
- * Description:
- * The XMAC holds its statistic internally. To obtain the current
- * values we must send a command so that the statistic data will
- * be written to a predefined memory area on the adapter.
- *
- * Returns:
- * SK_PNMI_ERR_OK Task successfully performed.
- * SK_PNMI_ERR_GENERAL Something went wrong.
- */
-PNMI_STATIC int MacUpdate(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int FirstMac, /* Index of the first Mac to be updated */
-unsigned int LastMac) /* Index of the last Mac to be updated */
-{
- unsigned int MacIndex;
-
- /*
- * Were the statistics already updated during the
- * current PNMI call?
- */
- if (pAC->Pnmi.MacUpdatedFlag > 0) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Send an update command to all MACs specified */
- for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
-
- /*
- * 2002-09-13 pweber: Freeze the current SW counters.
- * (That should be done as close as
- * possible to the update of the
- * HW counters)
- */
- if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
- pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
- }
-
- /* 2002-09-13 pweber: Update the HW counter */
- if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
-
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * GetStatVal - Retrieve an XMAC statistic counter
- *
- * Description:
- * Retrieves the statistic counter of a virtual or physical port. The
- * virtual port is identified by the index 0. It consists of all
- * currently active ports. To obtain the counter value for this port
- * we must add the statistic counter of all active ports. To grant
- * continuous counter values for the virtual port even when port
- * switches occur we must additionally add a delta value, which was
- * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
- *
- * Returns:
- * Requested statistic value
- */
-PNMI_STATIC SK_U64 GetStatVal(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int LogPortIndex, /* Index of the logical Port to be processed */
-unsigned int StatIndex, /* Index to statistic value */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
-{
- unsigned int PhysPortIndex;
- unsigned int PhysPortMax;
- SK_U64 Val = 0;
-
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-
- PhysPortIndex = NetIndex;
-
- Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
- }
- else { /* Single Net mode */
-
- if (LogPortIndex == 0) {
-
- PhysPortMax = pAC->GIni.GIMacsFound;
-
- /* Add counter of all active ports */
- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
- }
- }
-
- /* Correct value because of port switches */
- Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
- }
- else {
- /* Get counter value of physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-
- Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
- }
- }
- return (Val);
-}
-
-/*****************************************************************************
- *
- * GetPhysStatVal - Get counter value for physical port
- *
- * Description:
- * Builds a 64bit counter value. Except for the octet counters
- * the lower 32bit are counted in hardware and the upper 32bit
- * in software by monitoring counter overflow interrupts in the
- * event handler. To grant continous counter values during XMAC
- * resets (caused by a workaround) we must add a delta value.
- * The delta was calculated in the event handler when a
- * SK_PNMI_EVT_XMAC_RESET was received.
- *
- * Returns:
- * Counter value
- */
-PNMI_STATIC SK_U64 GetPhysStatVal(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int PhysPortIndex, /* Index of the logical Port to be processed */
-unsigned int StatIndex) /* Index to statistic value */
-{
- SK_U64 Val = 0;
- SK_U32 LowVal = 0;
- SK_U32 HighVal = 0;
- SK_U16 Word;
- int MacType;
- unsigned int HelpIndex;
- SK_GEPORT *pPrt;
-
- SK_PNMI_PORT *pPnmiPrt;
- SK_GEMACFUNC *pFnMac;
-
- pPrt = &pAC->GIni.GP[PhysPortIndex];
-
- MacType = pAC->GIni.GIMacType;
-
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
- }
- else {
- pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
- }
-
- pFnMac = &pAC->GIni.GIFunc;
-
- switch (StatIndex) {
- case SK_PNMI_HTX:
- if (MacType == SK_MAC_GMAC) {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
- &LowVal);
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
- &HighVal);
- LowVal += HighVal;
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
- &HighVal);
- LowVal += HighVal;
- }
- else {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- }
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HRX:
- if (MacType == SK_MAC_GMAC) {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
- &LowVal);
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
- &HighVal);
- LowVal += HighVal;
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
- &HighVal);
- LowVal += HighVal;
- }
- else {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- }
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HTX_OCTET:
- case SK_PNMI_HRX_OCTET:
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &HighVal);
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex + 1][MacType].Reg,
- &LowVal);
- break;
-
- case SK_PNMI_HTX_BURST:
- case SK_PNMI_HTX_EXCESS_DEF:
- case SK_PNMI_HTX_CARRIER:
- /* Not supported by GMAC */
- if (MacType == SK_MAC_GMAC) {
- return (Val);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HTX_MACC:
- /* GMAC only supports PAUSE MAC control frames */
- if (MacType == SK_MAC_GMAC) {
- HelpIndex = SK_PNMI_HTX_PMACC;
- }
- else {
- HelpIndex = StatIndex;
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[HelpIndex][MacType].Reg,
- &LowVal);
-
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HTX_COL:
- case SK_PNMI_HRX_UNDERSIZE:
- /* Not supported by XMAC */
- if (MacType == SK_MAC_XMAC) {
- return (Val);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HTX_DEFFERAL:
- /* Not supported by GMAC */
- if (MacType == SK_MAC_GMAC) {
- return (Val);
- }
-
- /*
- * XMAC counts frames with deferred transmission
- * even in full-duplex mode.
- *
- * In full-duplex mode the counter remains constant!
- */
- if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
- (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
-
- LowVal = 0;
- HighVal = 0;
- }
- else {
- /* Otherwise get contents of hardware register */
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- }
- break;
-
- case SK_PNMI_HRX_BADOCTET:
- /* Not supported by XMAC */
- if (MacType == SK_MAC_XMAC) {
- return (Val);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &HighVal);
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex + 1][MacType].Reg,
- &LowVal);
- break;
-
- case SK_PNMI_HTX_OCTETLOW:
- case SK_PNMI_HRX_OCTETLOW:
- case SK_PNMI_HRX_BADOCTETLOW:
- return (Val);
-
- case SK_PNMI_HRX_LONGFRAMES:
- /* For XMAC the SW counter is managed by PNMI */
- if (MacType == SK_MAC_XMAC) {
- return (pPnmiPrt->StatRxLongFrameCts);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HRX_TOO_LONG:
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
-
- Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
- if (MacType == SK_MAC_GMAC) {
- /* For GMAC the SW counter is additionally managed by PNMI */
- Val += pPnmiPrt->StatRxFrameTooLongCts;
- }
- else {
- /*
- * Frames longer than IEEE 802.3 frame max size are counted
- * by XMAC in frame_too_long counter even reception of long
- * frames was enabled and the frame was correct.
- * So correct the value by subtracting RxLongFrame counter.
- */
- Val -= pPnmiPrt->StatRxLongFrameCts;
- }
-
- LowVal = (SK_U32)Val;
- HighVal = (SK_U32)(Val >> 32);
- break;
-
- case SK_PNMI_HRX_SHORTS:
- /* Not supported by GMAC */
- if (MacType == SK_MAC_GMAC) {
- /* GM_RXE_FRAG?? */
- return (Val);
- }
-
- /*
- * XMAC counts short frame errors even if link down (#10620)
- *
- * If link-down the counter remains constant
- */
- if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
-
- /* Otherwise get incremental difference */
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
-
- Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
- Val -= pPnmiPrt->RxShortZeroMark;
-
- LowVal = (SK_U32)Val;
- HighVal = (SK_U32)(Val >> 32);
- }
- break;
-
- case SK_PNMI_HRX_MACC:
- case SK_PNMI_HRX_MACC_UNKWN:
- case SK_PNMI_HRX_BURST:
- case SK_PNMI_HRX_MISSED:
- case SK_PNMI_HRX_FRAMING:
- case SK_PNMI_HRX_CARRIER:
- case SK_PNMI_HRX_IRLENGTH:
- case SK_PNMI_HRX_SYMBOL:
- case SK_PNMI_HRX_CEXT:
- /* Not supported by GMAC */
- if (MacType == SK_MAC_GMAC) {
- return (Val);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HRX_PMACC_ERR:
- /* For GMAC the SW counter is managed by PNMI */
- if (MacType == SK_MAC_GMAC) {
- return (pPnmiPrt->StatRxPMaccErr);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- /* SW counter managed by PNMI */
- case SK_PNMI_HTX_SYNC:
- LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
- HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
- break;
-
- /* SW counter managed by PNMI */
- case SK_PNMI_HTX_SYNC_OCTET:
- LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
- HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
- break;
-
- case SK_PNMI_HRX_FCS:
- /*
- * Broadcom filters FCS errors and counts it in
- * Receive Error Counter register
- */
- if (pPrt->PhyType == SK_PHY_BCOM) {
- /* do not read while not initialized (PHY_READ hangs!)*/
- if (pPrt->PState != SK_PRT_RESET) {
- SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
-
- LowVal = Word;
- }
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- }
- else {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- }
- break;
-
- default:
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
- }
-
- Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
- /* Correct value because of possible XMAC reset. XMAC Errata #2 */
- Val += pPnmiPrt->CounterOffset[StatIndex];
-
- return (Val);
-}
-
-/*****************************************************************************
- *
- * ResetCounter - Set all counters and timestamps to zero
- *
- * Description:
- * Notifies other common modules which store statistic data to
- * reset their counters and finally reset our own counters.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void ResetCounter(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 NetIndex)
-{
- unsigned int PhysPortIndex;
- SK_EVPARA EventParam;
-
-
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-
- /* Notify sensor module */
- SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
-
- /* Notify RLMT module */
- EventParam.Para32[0] = NetIndex;
- EventParam.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
- EventParam.Para32[1] = 0;
-
- /* Notify SIRQ module */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
-
- /* Notify CSUM module */
-#ifdef SK_USE_CSUM
- EventParam.Para32[0] = NetIndex;
- EventParam.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
- EventParam);
-#endif /* SK_USE_CSUM */
-
- /* Clear XMAC statistic */
- for (PhysPortIndex = 0; PhysPortIndex <
- (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
-
- (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
-
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
- 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- CounterOffset, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].CounterOffset));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
- 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].StatSyncOctetsCts));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].StatRxLongFrameCts));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].StatRxFrameTooLongCts));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].StatRxPMaccErr));
- }
-
- /*
- * Clear local statistics
- */
- SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
- sizeof(pAC->Pnmi.VirtualCounterOffset));
- pAC->Pnmi.RlmtChangeCts = 0;
- pAC->Pnmi.RlmtChangeTime = 0;
- SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
- sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
- pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
- pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
- pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
- pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
- pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
- pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
- pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
- pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
- pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
- pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
- pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
- pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
-}
-
-/*****************************************************************************
- *
- * GetTrapEntry - Get an entry in the trap buffer
- *
- * Description:
- * The trap buffer stores various events. A user application somehow
- * gets notified that an event occured and retrieves the trap buffer
- * contens (or simply polls the buffer). The buffer is organized as
- * a ring which stores the newest traps at the beginning. The oldest
- * traps are overwritten by the newest ones. Each trap entry has a
- * unique number, so that applications may detect new trap entries.
- *
- * Returns:
- * A pointer to the trap entry
- */
-PNMI_STATIC char* GetTrapEntry(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_U32 TrapId, /* SNMP ID of the trap */
-unsigned int Size) /* Space needed for trap entry */
-{
- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
- unsigned int BufFree = pAC->Pnmi.TrapBufFree;
- unsigned int Beg = pAC->Pnmi.TrapQueueBeg;
- unsigned int End = pAC->Pnmi.TrapQueueEnd;
- char *pBuf = &pAC->Pnmi.TrapBuf[0];
- int Wrap;
- unsigned int NeededSpace;
- unsigned int EntrySize;
- SK_U32 Val32;
- SK_U64 Val64;
-
-
- /* Last byte of entry will get a copy of the entry length */
- Size ++;
-
- /*
- * Calculate needed buffer space */
- if (Beg >= Size) {
-
- NeededSpace = Size;
- Wrap = SK_FALSE;
- }
- else {
- NeededSpace = Beg + Size;
- Wrap = SK_TRUE;
- }
-
- /*
- * Check if enough buffer space is provided. Otherwise
- * free some entries. Leave one byte space between begin
- * and end of buffer to make it possible to detect whether
- * the buffer is full or empty
- */
- while (BufFree < NeededSpace + 1) {
-
- if (End == 0) {
-
- End = SK_PNMI_TRAP_QUEUE_LEN;
- }
-
- EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
- BufFree += EntrySize;
- End -= EntrySize;
-#ifdef DEBUG
- SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
-#endif /* DEBUG */
- if (End == BufPad) {
-#ifdef DEBUG
- SK_MEMSET(pBuf, (char)(-1), End);
-#endif /* DEBUG */
- BufFree += End;
- End = 0;
- BufPad = 0;
- }
- }
-
- /*
- * Insert new entry as first entry. Newest entries are
- * stored at the beginning of the queue.
- */
- if (Wrap) {
-
- BufPad = Beg;
- Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
- }
- else {
- Beg = Beg - Size;
- }
- BufFree -= NeededSpace;
-
- /* Save the current offsets */
- pAC->Pnmi.TrapQueueBeg = Beg;
- pAC->Pnmi.TrapQueueEnd = End;
- pAC->Pnmi.TrapBufPad = BufPad;
- pAC->Pnmi.TrapBufFree = BufFree;
-
- /* Initialize the trap entry */
- *(pBuf + Beg + Size - 1) = (char)Size;
- *(pBuf + Beg) = (char)Size;
- Val32 = (pAC->Pnmi.TrapUnique) ++;
- SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
- SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
- Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
- SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
-
- return (pBuf + Beg);
-}
-
-/*****************************************************************************
- *
- * CopyTrapQueue - Copies the trap buffer for the TRAP OID
- *
- * Description:
- * On a query of the TRAP OID the trap buffer contents will be
- * copied continuously to the request buffer, which must be large
- * enough. No length check is performed.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void CopyTrapQueue(
-SK_AC *pAC, /* Pointer to adapter context */
-char *pDstBuf) /* Buffer to which the queued traps will be copied */
-{
- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
- unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
- unsigned int End = pAC->Pnmi.TrapQueueEnd;
- char *pBuf = &pAC->Pnmi.TrapBuf[0];
- unsigned int Len;
- unsigned int DstOff = 0;
-
-
- while (Trap != End) {
-
- Len = (unsigned int)*(pBuf + Trap);
-
- /*
- * Last byte containing a copy of the length will
- * not be copied.
- */
- *(pDstBuf + DstOff) = (char)(Len - 1);
- SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
- DstOff += Len - 1;
-
- Trap += Len;
- if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
- Trap = BufPad;
- }
- }
-}
-
-/*****************************************************************************
- *
- * GetTrapQueueLen - Get the length of the trap buffer
- *
- * Description:
- * Evaluates the number of currently stored traps and the needed
- * buffer size to retrieve them.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void GetTrapQueueLen(
-SK_AC *pAC, /* Pointer to adapter context */
-unsigned int *pLen, /* Length in Bytes of all queued traps */
-unsigned int *pEntries) /* Returns number of trapes stored in queue */
-{
- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
- unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
- unsigned int End = pAC->Pnmi.TrapQueueEnd;
- char *pBuf = &pAC->Pnmi.TrapBuf[0];
- unsigned int Len;
- unsigned int Entries = 0;
- unsigned int TotalLen = 0;
-
-
- while (Trap != End) {
-
- Len = (unsigned int)*(pBuf + Trap);
- TotalLen += Len - 1;
- Entries ++;
-
- Trap += Len;
- if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
- Trap = BufPad;
- }
- }
-
- *pEntries = Entries;
- *pLen = TotalLen;
-}
-
-/*****************************************************************************
- *
- * QueueSimpleTrap - Store a simple trap to the trap buffer
- *
- * Description:
- * A simple trap is a trap with now additional data. It consists
- * simply of a trap code.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void QueueSimpleTrap(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_U32 TrapId) /* Type of sensor trap */
-{
- GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
-}
-
-/*****************************************************************************
- *
- * QueueSensorTrap - Stores a sensor trap in the trap buffer
- *
- * Description:
- * Gets an entry in the trap buffer and fills it with sensor related
- * data.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void QueueSensorTrap(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_U32 TrapId, /* Type of sensor trap */
-unsigned int SensorIndex) /* Index of sensor which caused the trap */
-{
- char *pBuf;
- unsigned int Offset;
- unsigned int DescrLen;
- SK_U32 Val32;
-
-
- /* Get trap buffer entry */
- DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
- pBuf = GetTrapEntry(pAC, TrapId,
- SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
- Offset = SK_PNMI_TRAP_SIMPLE_LEN;
-
- /* Store additionally sensor trap related data */
- Val32 = OID_SKGE_SENSOR_INDEX;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- *(pBuf + Offset + 4) = 4;
- Val32 = (SK_U32)SensorIndex;
- SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
- Offset += 9;
-
- Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- *(pBuf + Offset + 4) = (char)DescrLen;
- SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
- DescrLen);
- Offset += DescrLen + 5;
-
- Val32 = OID_SKGE_SENSOR_TYPE;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- *(pBuf + Offset + 4) = 1;
- *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
- Offset += 6;
-
- Val32 = OID_SKGE_SENSOR_VALUE;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- *(pBuf + Offset + 4) = 4;
- Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
- SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
-}
-
-/*****************************************************************************
- *
- * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
- *
- * Description:
- * Nothing further to explain.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void QueueRlmtNewMacTrap(
-SK_AC *pAC, /* Pointer to adapter context */
-unsigned int ActiveMac) /* Index (0..n) of the currently active port */
-{
- char *pBuf;
- SK_U32 Val32;
-
-
- pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
- SK_PNMI_TRAP_RLMT_CHANGE_LEN);
-
- Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
- SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
-}
-
-/*****************************************************************************
- *
- * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
- *
- * Description:
- * Nothing further to explain.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void QueueRlmtPortTrap(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_U32 TrapId, /* Type of RLMT port trap */
-unsigned int PortIndex) /* Index of the port, which changed its state */
-{
- char *pBuf;
- SK_U32 Val32;
-
-
- pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
-
- Val32 = OID_SKGE_RLMT_PORT_INDEX;
- SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
-}
-
-/*****************************************************************************
- *
- * CopyMac - Copies a MAC address
- *
- * Description:
- * Nothing further to explain.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void CopyMac(
-char *pDst, /* Pointer to destination buffer */
-SK_MAC_ADDR *pMac) /* Pointer of Source */
-{
- int i;
-
-
- for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
-
- *(pDst + i) = pMac->a[i];
- }
-}
-
-#ifdef SK_POWER_MGMT
-/*****************************************************************************
- *
- * PowerManagement - OID handler function of PowerManagement OIDs
- *
- * Description:
- * The code is simple. No description necessary.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-
-PNMI_STATIC int PowerManagement(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* Get/PreSet/Set action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer to which to mgmt data will be retrieved */
-unsigned int *pLen, /* On call: buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
-{
-
- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
-
- /*
- * Check instance. We only handle single instance variables
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
-
- /* Check length */
- switch (Id) {
-
- case OID_PNP_CAPABILITIES:
- if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
-
- *pLen = sizeof(SK_PNP_CAPABILITIES);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_PNP_SET_POWER:
- case OID_PNP_QUERY_POWER:
- if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
- {
- *pLen = sizeof(SK_DEVICE_POWER_STATE);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_PNP_ADD_WAKE_UP_PATTERN:
- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
- if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
-
- *pLen = sizeof(SK_PM_PACKET_PATTERN);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_PNP_ENABLE_WAKE_UP:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
- }
-
- /*
- * Perform action
- */
- if (Action == SK_PNMI_GET) {
-
- /*
- * Get value
- */
- switch (Id) {
-
- case OID_PNP_CAPABILITIES:
- RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
- break;
-
- case OID_PNP_QUERY_POWER:
- /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
- the miniport to indicate whether it can transition its NIC
- to the low-power state.
- A miniport driver must always return NDIS_STATUS_SUCCESS
- to a query of OID_PNP_QUERY_POWER. */
- *pLen = sizeof(SK_DEVICE_POWER_STATE);
- RetCode = SK_PNMI_ERR_OK;
- break;
-
- /* NDIS handles these OIDs as write-only.
- * So in case of get action the buffer with written length = 0
- * is returned
- */
- case OID_PNP_SET_POWER:
- case OID_PNP_ADD_WAKE_UP_PATTERN:
- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
- *pLen = 0;
- RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
- break;
-
- case OID_PNP_ENABLE_WAKE_UP:
- RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
- break;
-
- default:
- RetCode = SK_PNMI_ERR_GENERAL;
- break;
- }
-
- return (RetCode);
- }
-
-
- /*
- * Perform preset or set
- */
-
- /* POWER module does not support PRESET action */
- if (Action == SK_PNMI_PRESET) {
- return (SK_PNMI_ERR_OK);
- }
-
- switch (Id) {
- case OID_PNP_SET_POWER:
- RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);
- break;
-
- case OID_PNP_ADD_WAKE_UP_PATTERN:
- RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);
- break;
-
- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
- RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);
- break;
-
- case OID_PNP_ENABLE_WAKE_UP:
- RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
- break;
-
- default:
- RetCode = SK_PNMI_ERR_READ_ONLY;
- }
-
- return (RetCode);
-}
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-/*****************************************************************************
- *
- * DiagActions - OID handler function of Diagnostic driver
- *
- * Description:
- * The code is simple. No description necessary.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-
-PNMI_STATIC int DiagActions(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
-
- SK_U32 DiagStatus;
- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
-
- /*
- * Check instance. We only handle single instance variables.
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /*
- * Check length.
- */
- switch (Id) {
-
- case OID_SKGE_DIAG_MODE:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Perform action. */
-
- /* GET value. */
- if (Action == SK_PNMI_GET) {
-
- switch (Id) {
-
- case OID_SKGE_DIAG_MODE:
- DiagStatus = pAC->Pnmi.DiagAttached;
- SK_PNMI_STORE_U32(pBuf, DiagStatus);
- *pLen = sizeof(SK_U32);
- RetCode = SK_PNMI_ERR_OK;
- break;
-
- default:
- *pLen = 0;
- RetCode = SK_PNMI_ERR_GENERAL;
- break;
- }
- return (RetCode);
- }
-
- /* From here SET or PRESET value. */
-
- /* PRESET value is not supported. */
- if (Action == SK_PNMI_PRESET) {
- return (SK_PNMI_ERR_OK);
- }
-
- /* SET value. */
- switch (Id) {
- case OID_SKGE_DIAG_MODE:
-
- /* Handle the SET. */
- switch (*pBuf) {
-
- /* Attach the DIAG to this adapter. */
- case SK_DIAG_ATTACHED:
- /* Check if we come from running */
- if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
- RetCode = SkDrvLeaveDiagMode(pAC);
-
- }
- else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
-
- RetCode = SK_PNMI_ERR_OK;
- }
-
- else {
-
- RetCode = SK_PNMI_ERR_GENERAL;
-
- }
-
- if (RetCode == SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
- }
- break;
-
- /* Enter the DIAG mode in the driver. */
- case SK_DIAG_RUNNING:
- RetCode = SK_PNMI_ERR_OK;
-
- /*
- * If DiagAttached is set, we can tell the driver
- * to enter the DIAG mode.
- */
- if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
- /* If DiagMode is not active, we can enter it. */
- if (!pAC->DiagModeActive) {
-
- RetCode = SkDrvEnterDiagMode(pAC);
- }
- else {
-
- RetCode = SK_PNMI_ERR_GENERAL;
- }
- }
- else {
-
- RetCode = SK_PNMI_ERR_GENERAL;
- }
-
- if (RetCode == SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
- }
- break;
-
- case SK_DIAG_IDLE:
- /* Check if we come from running */
- if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
- RetCode = SkDrvLeaveDiagMode(pAC);
-
- }
- else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
-
- RetCode = SK_PNMI_ERR_OK;
- }
-
- else {
-
- RetCode = SK_PNMI_ERR_GENERAL;
-
- }
-
- if (RetCode == SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
- }
- break;
-
- default:
- RetCode = SK_PNMI_ERR_BAD_VALUE;
- break;
- }
- break;
-
- default:
- RetCode = SK_PNMI_ERR_GENERAL;
- }
-
- if (RetCode == SK_PNMI_ERR_OK) {
- *pLen = sizeof(SK_U32);
- }
- else {
-
- *pLen = 0;
- }
- return (RetCode);
-}
-#endif /* SK_DIAG_SUPPORT */
-
-/*****************************************************************************
- *
- * Vct - OID handler function of OIDs
- *
- * Description:
- * The code is simple. No description necessary.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was performed successfully.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter).
- * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed.
- *
- */
-
-PNMI_STATIC int Vct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_GEPORT *pPrt;
- SK_PNMI_VCT *pVctBackupData;
- SK_U32 LogPortMax;
- SK_U32 PhysPortMax;
- SK_U32 PhysPortIndex;
- SK_U32 Limit;
- SK_U32 Offset;
- SK_BOOL Link;
- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
- int i;
- SK_EVPARA Para;
- SK_U32 CableLength;
-
- /*
- * Calculate the port indexes from the instance.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
- /* Dual net mode? */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- LogPortMax--;
- }
-
- if ((Instance != (SK_U32) (-1))) {
- /* Check instance range. */
- if ((Instance < 2) || (Instance > LogPortMax)) {
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- PhysPortIndex = NetIndex;
- }
- else {
- PhysPortIndex = Instance - 2;
- }
- Limit = PhysPortIndex + 1;
- }
- else {
- /*
- * Instance == (SK_U32) (-1), get all Instances of that OID.
- *
- * Not implemented yet. May be used in future releases.
- */
- PhysPortIndex = 0;
- Limit = PhysPortMax;
- }
-
- pPrt = &pAC->GIni.GP[PhysPortIndex];
- if (pPrt->PHWLinkUp) {
- Link = SK_TRUE;
- }
- else {
- Link = SK_FALSE;
- }
-
- /* Check MAC type */
- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Initialize backup data pointer. */
- pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-
- /* Check action type */
- if (Action == SK_PNMI_GET) {
- /* Check length */
- switch (Id) {
-
- case OID_SKGE_VCT_GET:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_VCT_STATUS:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Get value */
- Offset = 0;
- for (; PhysPortIndex < Limit; PhysPortIndex++) {
- switch (Id) {
-
- case OID_SKGE_VCT_GET:
- if ((Link == SK_FALSE) &&
- (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
- RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
- if (RetCode == 0) {
- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
- pAC->Pnmi.VctStatus[PhysPortIndex] |=
- (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-
- /* Copy results for later use to PNMI struct. */
- for (i = 0; i < 4; i++) {
- if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
- if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
- pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
- }
- }
- if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
- CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
- }
- else {
- CableLength = 0;
- }
- pVctBackupData->PMdiPairLen[i] = CableLength;
- pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
- }
-
- Para.Para32[0] = PhysPortIndex;
- Para.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
- SkEventDispatcher(pAC, IoC);
- }
- else {
- ; /* VCT test is running. */
- }
- }
-
- /* Get all results. */
- CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
- Offset += sizeof(SK_U8);
- *(pBuf + Offset) = pPrt->PCableLen;
- Offset += sizeof(SK_U8);
- for (i = 0; i < 4; i++) {
- SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
- Offset += sizeof(SK_U32);
- }
- for (i = 0; i < 4; i++) {
- *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
- Offset += sizeof(SK_U8);
- }
-
- RetCode = SK_PNMI_ERR_OK;
- break;
-
- case OID_SKGE_VCT_STATUS:
- CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
- Offset += sizeof(SK_U8);
- RetCode = SK_PNMI_ERR_OK;
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- } /* for */
- *pLen = Offset;
- return (RetCode);
-
- } /* if SK_PNMI_GET */
-
- /*
- * From here SET or PRESET action. Check if the passed
- * buffer length is plausible.
- */
-
- /* Check length */
- switch (Id) {
- case OID_SKGE_VCT_SET:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Perform preset or set.
- */
-
- /* VCT does not support PRESET action. */
- if (Action == SK_PNMI_PRESET) {
- return (SK_PNMI_ERR_OK);
- }
-
- Offset = 0;
- for (; PhysPortIndex < Limit; PhysPortIndex++) {
- switch (Id) {
- case OID_SKGE_VCT_SET: /* Start VCT test. */
- if (Link == SK_FALSE) {
- SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
-
- RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
- if (RetCode == 0) { /* RetCode: 0 => Start! */
- pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
-
- /*
- * Start VCT timer counter.
- */
- SK_MEMSET((char *) &Para, 0, sizeof(Para));
- Para.Para32[0] = PhysPortIndex;
- Para.Para32[1] = -1;
- SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
- 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
- SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
- RetCode = SK_PNMI_ERR_OK;
- }
- else { /* RetCode: 2 => Running! */
- SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
- RetCode = SK_PNMI_ERR_OK;
- }
- }
- else { /* RetCode: 4 => Link! */
- RetCode = 4;
- SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
- RetCode = SK_PNMI_ERR_OK;
- }
- Offset += sizeof(SK_U32);
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- } /* for */
- *pLen = Offset;
- return (RetCode);
-
-} /* Vct */
-
-
-PNMI_STATIC void CheckVctStatus(
-SK_AC *pAC,
-SK_IOC IoC,
-char *pBuf,
-SK_U32 Offset,
-SK_U32 PhysPortIndex)
-{
- SK_GEPORT *pPrt;
- SK_PNMI_VCT *pVctData;
- SK_U32 RetCode;
-
- pPrt = &pAC->GIni.GP[PhysPortIndex];
-
- pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
- pVctData->VctStatus = SK_PNMI_VCT_NONE;
-
- if (!pPrt->PHWLinkUp) {
-
- /* Was a VCT test ever made before? */
- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
- if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
- pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
- }
- else {
- pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
- }
- }
-
- /* Check VCT test status. */
- RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
- if (RetCode == 2) { /* VCT test is running. */
- pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
- }
- else { /* VCT data was copied to pAC here. Check PENDING state. */
- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
- pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
- }
- }
-
- if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
- pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
- }
- }
- else {
-
- /* Was a VCT test ever made before? */
- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
- pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
- pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
- }
-
- /* DSP only valid in 100/1000 modes. */
- if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
- SK_LSPEED_STAT_10MBPS) {
- pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
- }
- }
-} /* CheckVctStatus */
-
-
-/*****************************************************************************
- *
- * SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
- * PNMI function depending on the subcommand and
- * returns all data belonging to the complete database
- * or OID request.
- *
- * Description:
- * Looks up the requested subcommand, calls the corresponding handler
- * function and passes all required parameters to it.
- * The function is called by the driver. It is needed to handle the new
- * generic PNMI IOCTL. This IOCTL is given to the driver and contains both
- * the OID and a subcommand to decide what kind of request has to be done.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed
- * SK_PNMI_ERR_GENERAL A general severe internal error occured
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
- * the data.
- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-int SkPnmiGenIoctl(
-SK_AC *pAC, /* Pointer to adapter context struct */
-SK_IOC IoC, /* I/O context */
-void *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* Length of buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
-SK_I32 Mode; /* Store value of subcommand. */
-SK_U32 Oid; /* Store value of OID. */
-int ReturnCode; /* Store return value to show status of PNMI action. */
-int HeaderLength; /* Length of desired action plus OID. */
-
- ReturnCode = SK_PNMI_ERR_GENERAL;
-
- SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
- SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
- HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
- *pLen = *pLen - HeaderLength;
- SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
-
- switch(Mode) {
- case SK_GET_SINGLE_VAR:
- ReturnCode = SkPnmiGetVar(pAC, IoC, Oid,
- (char *) pBuf + sizeof(SK_I32), pLen,
- ((SK_U32) (-1)), NetIndex);
- SK_PNMI_STORE_U32(pBuf, ReturnCode);
- *pLen = *pLen + sizeof(SK_I32);
- break;
- case SK_PRESET_SINGLE_VAR:
- ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid,
- (char *) pBuf + sizeof(SK_I32), pLen,
- ((SK_U32) (-1)), NetIndex);
- SK_PNMI_STORE_U32(pBuf, ReturnCode);
- *pLen = *pLen + sizeof(SK_I32);
- break;
- case SK_SET_SINGLE_VAR:
- ReturnCode = SkPnmiSetVar(pAC, IoC, Oid,
- (char *) pBuf + sizeof(SK_I32), pLen,
- ((SK_U32) (-1)), NetIndex);
- SK_PNMI_STORE_U32(pBuf, ReturnCode);
- *pLen = *pLen + sizeof(SK_I32);
- break;
- case SK_GET_FULL_MIB:
- ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
- break;
- case SK_PRESET_FULL_MIB:
- ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
- break;
- case SK_SET_FULL_MIB:
- ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
- break;
- default:
- break;
- }
-
- return (ReturnCode);
-
-} /* SkGeIocGen */
diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c
deleted file mode 100644
index 3e7aa49afd0..00000000000
--- a/drivers/net/sk98lin/skgesirq.c
+++ /dev/null
@@ -1,2229 +0,0 @@
-/******************************************************************************
- *
- * Name: skgesirq.c
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.92 $
- * Date: $Date: 2003/09/16 14:37:07 $
- * Purpose: Special IRQ module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * Special Interrupt handler
- *
- * The following abstract should show how this module is included
- * in the driver path:
- *
- * In the ISR of the driver the bits for frame transmission complete and
- * for receive complete are checked and handled by the driver itself.
- * The bits of the slow path mask are checked after that and then the
- * entry into the so-called "slow path" is prepared. It is an implementors
- * decision whether this is executed directly or just scheduled by
- * disabling the mask. In the interrupt service routine some events may be
- * generated, so it would be a good idea to call the EventDispatcher
- * right after this ISR.
- *
- * The Interrupt source register of the adapter is NOT read by this module.
- * SO if the drivers implementor needs a while loop around the
- * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
- * each loop entered.
- *
- * However, the MAC Interrupt status registers are read in a while loop.
- *
- */
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#ifndef SK_SLIM
-#include "h/skgepnmi.h" /* PNMI Definitions */
-#include "h/skrlmt.h" /* RLMT Definitions */
-#endif
-#include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */
-
-/* local function prototypes */
-#ifdef GENESIS
-static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* GENESIS */
-#ifdef YUKON
-static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* OTHER_PHY */
-
-#ifdef GENESIS
-/*
- * array of Rx counter from XMAC which are checked
- * in AutoSense mode to check whether a link is not able to auto-negotiate.
- */
-static const SK_U16 SkGeRxRegs[]= {
- XM_RXF_64B,
- XM_RXF_127B,
- XM_RXF_255B,
- XM_RXF_511B,
- XM_RXF_1023B,
- XM_RXF_MAX_SZ
-} ;
-#endif /* GENESIS */
-
-#ifdef __C2MAN__
-/*
- * Special IRQ function
- *
- * General Description:
- *
- */
-intro()
-{}
-#endif
-
-/******************************************************************************
- *
- * SkHWInitDefSense() - Default Autosensing mode initialization
- *
- * Description: sets the PLinkMode for HWInit
- *
- * Returns: N/A
- */
-static void SkHWInitDefSense(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- pPrt->PAutoNegTimeOut = 0;
-
- if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
- pPrt->PLinkMode = pPrt->PLinkModeConf;
- return;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("AutoSensing: First mode %d on Port %d\n",
- (int)SK_LMODE_AUTOFULL, Port));
-
- pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
-
- return;
-} /* SkHWInitDefSense */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkHWSenseGetNext() - Get Next Autosensing Mode
- *
- * Description: gets the appropriate next mode
- *
- * Note:
- *
- */
-static SK_U8 SkHWSenseGetNext(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- pPrt->PAutoNegTimeOut = 0;
-
- if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
- /* Leave all as configured */
- return(pPrt->PLinkModeConf);
- }
-
- if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
- /* Return next mode AUTOBOTH */
- return ((SK_U8)SK_LMODE_AUTOBOTH);
- }
-
- /* Return default autofull */
- return ((SK_U8)SK_LMODE_AUTOFULL);
-} /* SkHWSenseGetNext */
-
-
-/******************************************************************************
- *
- * SkHWSenseSetNext() - Autosensing Set next mode
- *
- * Description: sets the appropriate next mode
- *
- * Returns: N/A
- */
-static void SkHWSenseSetNext(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U8 NewMode) /* New Mode to be written in sense mode */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- pPrt->PAutoNegTimeOut = 0;
-
- if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
- return;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("AutoSensing: next mode %d on Port %d\n",
- (int)NewMode, Port));
-
- pPrt->PLinkMode = NewMode;
-
- return;
-} /* SkHWSenseSetNext */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkHWLinkDown() - Link Down handling
- *
- * Description: handles the hardware link down signal
- *
- * Returns: N/A
- */
-void SkHWLinkDown(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Disable all MAC interrupts */
- SkMacIrqDisable(pAC, IoC, Port);
-
- /* Disable Receiver and Transmitter */
- SkMacRxTxDisable(pAC, IoC, Port);
-
- /* Init default sense mode */
- SkHWInitDefSense(pAC, IoC, Port);
-
- if (pPrt->PHWLinkUp == SK_FALSE) {
- return;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link down Port %d\n", Port));
-
- /* Set Link to DOWN */
- pPrt->PHWLinkUp = SK_FALSE;
-
- /* Reset Port stati */
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
-
- /* Re-init Phy especially when the AutoSense default is set now */
- SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
- /* GP0: used for workaround of Rev. C Errata 2 */
-
- /* Do NOT signal to RLMT */
-
- /* Do NOT start the timer here */
-} /* SkHWLinkDown */
-
-
-/******************************************************************************
- *
- * SkHWLinkUp() - Link Up handling
- *
- * Description: handles the hardware link up signal
- *
- * Returns: N/A
- */
-static void SkHWLinkUp(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PHWLinkUp) {
- /* We do NOT need to proceed on active link */
- return;
- }
-
- pPrt->PHWLinkUp = SK_TRUE;
- pPrt->PAutoNegFail = SK_FALSE;
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-
- if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
- pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
- pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
- /* Link is up and no Auto-negotiation should be done */
-
- /* Link speed should be the configured one */
- switch (pPrt->PLinkSpeed) {
- case SK_LSPEED_AUTO:
- /* default is 1000 Mbps */
- case SK_LSPEED_1000MBPS:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
- break;
- case SK_LSPEED_100MBPS:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
- break;
- case SK_LSPEED_10MBPS:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
- break;
- }
-
- /* Set Link Mode Status */
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
- }
- else {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
- }
-
- /* No flow control without auto-negotiation */
- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-
- /* enable Rx/Tx */
- (void)SkMacRxTxEnable(pAC, IoC, Port);
- }
-} /* SkHWLinkUp */
-
-
-/******************************************************************************
- *
- * SkMacParity() - MAC parity workaround
- *
- * Description: handles MAC parity errors correctly
- *
- * Returns: N/A
- */
-static void SkMacParity(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index of the port failed */
-{
- SK_EVPARA Para;
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_U32 TxMax; /* Tx Max Size Counter */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Clear IRQ Tx Parity Error */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
- (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
- pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
- }
-#endif /* YUKON */
-
- if (pPrt->PCheckPar) {
-
- if (Port == MAC_1) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
- }
- Para.Para64 = Port;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-
- Para.Para32[0] = Port;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
- return;
- }
-
- /* Check whether frames with a size of 1k were sent */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* Snap statistic counters */
- (void)SkXmUpdateStats(pAC, IoC, Port);
-
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
- }
-#endif /* YUKON */
-
- if (TxMax > 0) {
- /* From now on check the parity */
- pPrt->PCheckPar = SK_TRUE;
- }
-} /* SkMacParity */
-
-
-/******************************************************************************
- *
- * SkGeHwErr() - Hardware Error service routine
- *
- * Description: handles all HW Error interrupts
- *
- * Returns: N/A
- */
-static void SkGeHwErr(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-SK_U32 HwStatus) /* Interrupt status word */
-{
- SK_EVPARA Para;
- SK_U16 Word;
-
- if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
- /* PCI Errors occured */
- if ((HwStatus & IS_IRQ_STAT) != 0) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
- }
-
- /* Reset all bits in the PCI STATUS register */
- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
- Para.Para64 = 0;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- if ((HwStatus & IS_NO_STAT_M1) != 0) {
- /* Ignore it */
- /* This situation is also indicated in the descriptor */
- SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
- }
-
- if ((HwStatus & IS_NO_STAT_M2) != 0) {
- /* Ignore it */
- /* This situation is also indicated in the descriptor */
- SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
- }
-
- if ((HwStatus & IS_NO_TIST_M1) != 0) {
- /* Ignore it */
- /* This situation is also indicated in the descriptor */
- SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
- }
-
- if ((HwStatus & IS_NO_TIST_M2) != 0) {
- /* Ignore it */
- /* This situation is also indicated in the descriptor */
- SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* This is necessary only for Rx timing measurements */
- if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
- /* increment Time Stamp Timer counter (high) */
- pAC->GIni.GITimeStampCnt++;
-
- /* Clear Time Stamp Timer IRQ */
- SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
- }
-
- if ((HwStatus & IS_IRQ_SENSOR) != 0) {
- /* no sensors on 32-bit Yukon */
- if (pAC->GIni.GIYukon32Bit) {
- /* disable HW Error IRQ */
- pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
- }
- }
- }
-#endif /* YUKON */
-
- if ((HwStatus & IS_RAM_RD_PAR) != 0) {
- SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
- Para.Para64 = 0;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
- }
-
- if ((HwStatus & IS_RAM_WR_PAR) != 0) {
- SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
- Para.Para64 = 0;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
- }
-
- if ((HwStatus & IS_M1_PAR_ERR) != 0) {
- SkMacParity(pAC, IoC, MAC_1);
- }
-
- if ((HwStatus & IS_M2_PAR_ERR) != 0) {
- SkMacParity(pAC, IoC, MAC_2);
- }
-
- if ((HwStatus & IS_R1_PAR_ERR) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
-
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
- Para.Para64 = MAC_1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-
- Para.Para32[0] = MAC_1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((HwStatus & IS_R2_PAR_ERR) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
-
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
- Para.Para64 = MAC_2;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-
- Para.Para32[0] = MAC_2;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-} /* SkGeHwErr */
-
-
-/******************************************************************************
- *
- * SkGeSirqIsr() - Special Interrupt Service Routine
- *
- * Description: handles all non data transfer specific interrupts (slow path)
- *
- * Returns: N/A
- */
-void SkGeSirqIsr(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-SK_U32 Istatus) /* Interrupt status word */
-{
- SK_EVPARA Para;
- SK_U32 RegVal32; /* Read register value */
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_U16 PhyInt;
- int i;
-
- if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
- /* read the HW Error Interrupt source */
- SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-
- SkGeHwErr(pAC, IoC, RegVal32);
- }
-
- /*
- * Packet Timeout interrupts
- */
- /* Check whether MACs are correctly initialized */
- if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
- pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
- /* MAC 1 was not initialized but Packet timeout occured */
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
- SKERR_SIRQ_E004MSG);
- }
-
- if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
- pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
- /* MAC 2 was not initialized but Packet timeout occured */
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
- SKERR_SIRQ_E005MSG);
- }
-
- if ((Istatus & IS_PA_TO_RX1) != 0) {
- /* Means network is filling us up */
- SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
- SKERR_SIRQ_E002MSG);
- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
- }
-
- if ((Istatus & IS_PA_TO_RX2) != 0) {
- /* Means network is filling us up */
- SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
- SKERR_SIRQ_E003MSG);
- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
- }
-
- if ((Istatus & IS_PA_TO_TX1) != 0) {
-
- pPrt = &pAC->GIni.GP[0];
-
- /* May be a normal situation in a server with a slow network */
- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /*
- * workaround: if in half duplex mode, check for Tx hangup.
- * Read number of TX'ed bytes, wait for 10 ms, then compare
- * the number with current value. If nothing changed, we assume
- * that Tx is hanging and do a FIFO flush (see event routine).
- */
- if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
- !pPrt->HalfDupTimerActive) {
- /*
- * many more pack. arb. timeouts may come in between,
- * we ignore those
- */
- pPrt->HalfDupTimerActive = SK_TRUE;
- /* Snap statistic counters */
- (void)SkXmUpdateStats(pAC, IoC, 0);
-
- (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
-
- pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-
- (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
-
- pPrt->LastOctets += RegVal32;
-
- Para.Para32[0] = 0;
- SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
- SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
- }
- }
-#endif /* GENESIS */
- }
-
- if ((Istatus & IS_PA_TO_TX2) != 0) {
-
- pPrt = &pAC->GIni.GP[1];
-
- /* May be a normal situation in a server with a slow network */
- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* workaround: see above */
- if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
- !pPrt->HalfDupTimerActive) {
- pPrt->HalfDupTimerActive = SK_TRUE;
- /* Snap statistic counters */
- (void)SkXmUpdateStats(pAC, IoC, 1);
-
- (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
-
- pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-
- (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
-
- pPrt->LastOctets += RegVal32;
-
- Para.Para32[0] = 1;
- SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
- SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
- }
- }
-#endif /* GENESIS */
- }
-
- /* Check interrupts of the particular queues */
- if ((Istatus & IS_R1_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
- SKERR_SIRQ_E006MSG);
- Para.Para64 = MAC_1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_R2_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
- SKERR_SIRQ_E007MSG);
- Para.Para64 = MAC_2;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_2;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_XS1_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
- SKERR_SIRQ_E008MSG);
- Para.Para64 = MAC_1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_XA1_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
- SKERR_SIRQ_E009MSG);
- Para.Para64 = MAC_1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_XS2_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
- SKERR_SIRQ_E010MSG);
- Para.Para64 = MAC_2;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_2;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_XA2_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
- SKERR_SIRQ_E011MSG);
- Para.Para64 = MAC_2;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_2;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- /* External reg interrupt */
- if ((Istatus & IS_EXT_REG) != 0) {
- /* Test IRQs from PHY */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
- pPrt = &pAC->GIni.GP[i];
-
- if (pPrt->PState == SK_PRT_RESET) {
- continue;
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- switch (pPrt->PhyType) {
-
- case SK_PHY_XMAC:
- break;
-
- case SK_PHY_BCOM:
- SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
-
- if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Port %d Bcom Int: 0x%04X\n",
- i, PhyInt));
- SkPhyIsrBcom(pAC, IoC, i, PhyInt);
- }
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
-
- if ((PhyInt & PHY_L_DEF_MSK) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Port %d Lone Int: %x\n",
- i, PhyInt));
- SkPhyIsrLone(pAC, IoC, i, PhyInt);
- }
- break;
-#endif /* OTHER_PHY */
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* Read PHY Interrupt Status */
- SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
-
- if ((PhyInt & PHY_M_DEF_MSK) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Port %d Marv Int: 0x%04X\n",
- i, PhyInt));
- SkPhyIsrGmac(pAC, IoC, i, PhyInt);
- }
- }
-#endif /* YUKON */
- }
- }
-
- /* I2C Ready interrupt */
- if ((Istatus & IS_I2C_READY) != 0) {
-#ifdef SK_SLIM
- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-#else
- SkI2cIsr(pAC, IoC);
-#endif
- }
-
- /* SW forced interrupt */
- if ((Istatus & IS_IRQ_SW) != 0) {
- /* clear the software IRQ */
- SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
- }
-
- if ((Istatus & IS_LNK_SYNC_M1) != 0) {
- /*
- * We do NOT need the Link Sync interrupt, because it shows
- * us only a link going down.
- */
- /* clear interrupt */
- SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
- }
-
- /* Check MAC after link sync counter */
- if ((Istatus & IS_MAC1) != 0) {
- /* IRQ from MAC 1 */
- SkMacIrq(pAC, IoC, MAC_1);
- }
-
- if ((Istatus & IS_LNK_SYNC_M2) != 0) {
- /*
- * We do NOT need the Link Sync interrupt, because it shows
- * us only a link going down.
- */
- /* clear interrupt */
- SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
- }
-
- /* Check MAC after link sync counter */
- if ((Istatus & IS_MAC2) != 0) {
- /* IRQ from MAC 2 */
- SkMacIrq(pAC, IoC, MAC_2);
- }
-
- /* Timer interrupt (served last) */
- if ((Istatus & IS_TIMINT) != 0) {
- /* check for HW Errors */
- if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
- /* read the HW Error Interrupt source */
- SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-
- SkGeHwErr(pAC, IoC, RegVal32);
- }
-
- SkHwtIsr(pAC, IoC);
- }
-
-} /* SkGeSirqIsr */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- */
-static int SkGePortCheckShorts(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port) /* Which port should be checked */
-{
- SK_U32 Shorts; /* Short Event Counter */
- SK_U32 CheckShorts; /* Check value for Short Event Counter */
- SK_U64 RxCts; /* Rx Counter (packets on network) */
- SK_U32 RxTmp; /* Rx temp. Counter */
- SK_U32 FcsErrCts; /* FCS Error Counter */
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Rtv; /* Return value */
- int i;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Default: no action */
- Rtv = SK_HW_PS_NONE;
-
- (void)SkXmUpdateStats(pAC, IoC, Port);
-
- /* Extra precaution: check for short Event counter */
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
-
- /*
- * Read Rx counters (packets seen on the network and not necessarily
- * really received.
- */
- RxCts = 0;
-
- for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
-
- (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
-
- RxCts += (SK_U64)RxTmp;
- }
-
- /* On default: check shorts against zero */
- CheckShorts = 0;
-
- /* Extra precaution on active links */
- if (pPrt->PHWLinkUp) {
- /* Reset Link Restart counter */
- pPrt->PLinkResCt = 0;
- pPrt->PAutoNegTOCt = 0;
-
- /* If link is up check for 2 */
- CheckShorts = 2;
-
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
-
- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
- pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
- (pPrt->PLinkMode == SK_LMODE_HALF ||
- pPrt->PLinkMode == SK_LMODE_FULL)) {
- /*
- * This is autosensing and we are in the fallback
- * manual full/half duplex mode.
- */
- if (RxCts == pPrt->PPrevRx) {
- /* Nothing received, restart link */
- pPrt->PPrevFcs = FcsErrCts;
- pPrt->PPrevShorts = Shorts;
-
- return(SK_HW_PS_RESTART);
- }
- else {
- pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
- }
- }
-
- if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
- (!(FcsErrCts - pPrt->PPrevFcs))) {
- /*
- * Note: The compare with zero above has to be done the way shown,
- * otherwise the Linux driver will have a problem.
- */
- /*
- * We received a bunch of frames or no CRC error occured on the
- * network -> ok.
- */
- pPrt->PPrevRx = RxCts;
- pPrt->PPrevFcs = FcsErrCts;
- pPrt->PPrevShorts = Shorts;
-
- return(SK_HW_PS_NONE);
- }
-
- pPrt->PPrevFcs = FcsErrCts;
- }
-
-
- if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Short Event Count Restart Port %d \n", Port));
- Rtv = SK_HW_PS_RESTART;
- }
-
- pPrt->PPrevShorts = Shorts;
- pPrt->PPrevRx = RxCts;
-
- return(Rtv);
-} /* SkGePortCheckShorts */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUp() - Check if the link is up
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUp(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port) /* Which port should be checked */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
- int Rtv; /* Return value */
-
- Rtv = SK_HW_PS_NONE;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- AutoNeg = SK_FALSE;
- }
- else {
- AutoNeg = SK_TRUE;
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- switch (pPrt->PhyType) {
-
- case SK_PHY_XMAC:
- Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
- break;
- case SK_PHY_BCOM:
- Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
- break;
- case SK_PHY_NAT:
- Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
- break;
-#endif /* OTHER_PHY */
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
- }
-#endif /* YUKON */
-
- return(Rtv);
-} /* SkGePortCheckUp */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpXmac(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- SK_U32 Shorts; /* Short Event Counter */
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Done;
- SK_U32 GpReg; /* General Purpose register value */
- SK_U16 Isrc; /* Interrupt source register */
- SK_U16 IsrcSum; /* Interrupt source register sum */
- SK_U16 LpAb; /* Link Partner Ability */
- SK_U16 ResAb; /* Resolved Ability */
- SK_U16 ExtStat; /* Extended Status Register */
- SK_U8 NextMode; /* Next AutoSensing Mode */
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PHWLinkUp) {
- if (pPrt->PhyType != SK_PHY_XMAC) {
- return(SK_HW_PS_NONE);
- }
- else {
- return(SkGePortCheckShorts(pAC, IoC, Port));
- }
- }
-
- IsrcSum = pPrt->PIsave;
- pPrt->PIsave = 0;
-
- /* Now wait for each port's link */
- if (pPrt->PLinkBroken) {
- /* Link was broken */
- XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
-
- if ((GpReg & XM_GP_INP_ASS) == 0) {
- /* The Link is in sync */
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
- SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-
- if ((Isrc & XM_IS_INP_ASS) == 0) {
- /* It has been in sync since last time */
- /* Restart the PORT */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link in sync Restart Port %d\n", Port));
-
- (void)SkXmUpdateStats(pAC, IoC, Port);
-
- /* We now need to reinitialize the PrevShorts counter */
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
- pPrt->PPrevShorts = Shorts;
-
- pPrt->PLinkBroken = SK_FALSE;
-
- /*
- * Link Restart Workaround:
- * it may be possible that the other Link side
- * restarts its link as well an we detect
- * another LinkBroken. To prevent this
- * happening we check for a maximum number
- * of consecutive restart. If those happens,
- * we do NOT restart the active link and
- * check whether the link is now o.k.
- */
- pPrt->PLinkResCt++;
-
- pPrt->PAutoNegTimeOut = 0;
-
- if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
- return(SK_HW_PS_RESTART);
- }
-
- pPrt->PLinkResCt = 0;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
- }
- else {
- pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
-
- /* Do nothing more if link is broken */
- return(SK_HW_PS_NONE);
- }
- }
- else {
- /* Do nothing more if link is broken */
- return(SK_HW_PS_NONE);
- }
-
- }
- else {
- /* Link was not broken, check if it is */
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
- if ((Isrc & XM_IS_INP_ASS) != 0) {
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
- if ((Isrc & XM_IS_INP_ASS) != 0) {
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
- if ((Isrc & XM_IS_INP_ASS) != 0) {
- pPrt->PLinkBroken = SK_TRUE;
- /* Re-Init Link partner Autoneg flag */
- pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link broken Port %d\n", Port));
-
- /* Cable removed-> reinit sense mode */
- SkHWInitDefSense(pAC, IoC, Port);
-
- return(SK_HW_PS_RESTART);
- }
- }
- }
- else {
- SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
-
- if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
- return(SK_HW_PS_RESTART);
- }
- }
- }
-
- /*
- * here we usually can check whether the link is in sync and
- * auto-negotiation is done.
- */
- XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
-
- SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-
- if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
- if ((GpReg & XM_GP_INP_ASS) == 0) {
- /* Save Auto-negotiation Done interrupt only if link is in sync */
- pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
- }
-#ifdef DEBUG
- if ((pPrt->PIsave & XM_IS_AND) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg done rescheduled Port %d\n", Port));
- }
-#endif /* DEBUG */
- return(SK_HW_PS_NONE);
- }
-
- if (AutoNeg) {
- if ((IsrcSum & XM_IS_AND) != 0) {
- SkHWLinkUp(pAC, IoC, Port);
- Done = SkMacAutoNegDone(pAC, IoC, Port);
- if (Done != SK_AND_OK) {
- /* Get PHY parameters, for debugging only */
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
- Port, LpAb, ResAb));
-
- /* Try next possible mode */
- NextMode = SkHWSenseGetNext(pAC, IoC, Port);
- SkHWLinkDown(pAC, IoC, Port);
- if (Done == SK_AND_DUP_CAP) {
- /* GoTo next mode */
- SkHWSenseSetNext(pAC, IoC, Port, NextMode);
- }
-
- return(SK_HW_PS_RESTART);
- }
- /*
- * Dummy Read extended status to prevent extra link down/ups
- * (clear Page Received bit if set)
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
-
- return(SK_HW_PS_LINK);
- }
-
- /* AutoNeg not done, but HW link is up. Check for timeouts */
- pPrt->PAutoNegTimeOut++;
- if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
- /* Increase the Timeout counter */
- pPrt->PAutoNegTOCt++;
-
- /* Timeout occured */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("AutoNeg timeout Port %d\n", Port));
- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
- pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
- /* Set Link manually up */
- SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Set manual full duplex Port %d\n", Port));
- }
-
- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
- pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
- pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
- /*
- * This is rather complicated.
- * we need to check here whether the LIPA_AUTO
- * we saw before is false alert. We saw at one
- * switch ( SR8800) that on boot time it sends
- * just one auto-neg packet and does no further
- * auto-negotiation.
- * Solution: we restart the autosensing after
- * a few timeouts.
- */
- pPrt->PAutoNegTOCt = 0;
- pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
- SkHWInitDefSense(pAC, IoC, Port);
- }
-
- /* Do the restart */
- return(SK_HW_PS_RESTART);
- }
- }
- else {
- /* Link is up and we don't need more */
-#ifdef DEBUG
- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("ERROR: Lipa auto detected on port %d\n", Port));
- }
-#endif /* DEBUG */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link sync(GP), Port %d\n", Port));
- SkHWLinkUp(pAC, IoC, Port);
-
- /*
- * Link sync (GP) and so assume a good connection. But if not received
- * a bunch of frames received in a time slot (maybe broken tx cable)
- * the port is restart.
- */
- return(SK_HW_PS_LINK);
- }
-
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpXmac */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpBcom(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Done;
- SK_U16 Isrc; /* Interrupt source register */
- SK_U16 PhyStat; /* Phy Status Register */
- SK_U16 ResAb; /* Master/Slave resolution */
- SK_U16 Ctrl; /* Broadcom control flags */
-#ifdef DEBUG
- SK_U16 LpAb;
- SK_U16 ExtStat;
-#endif /* DEBUG */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Check for No HCD Link events (#10523) */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
-
-#ifdef xDEBUG
- if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) ==
- (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
-
- SK_U32 Stat1, Stat2, Stat3;
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "CheckUp1 - Stat: %x, Mask: %x",
- (void *)Isrc,
- (void *)Stat1);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "Ctrl/Stat: %x, AN Adv/LP: %x",
- (void *)Stat1,
- (void *)Stat2);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
- (void *)Stat1,
- (void *)Stat2);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
- (void *)Stat1,
- (void *)Stat2);
- }
-#endif /* DEBUG */
-
- if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
- /*
- * Workaround BCom Errata:
- * enable and disable loopback mode if "NO HCD" occurs.
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
- (SK_U16)(Ctrl | PHY_CT_LOOP));
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
- (SK_U16)(Ctrl & ~PHY_CT_LOOP));
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("No HCD Link event, Port %d\n", Port));
-#ifdef xDEBUG
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "No HCD link event, port %d.",
- (void *)Port,
- (void *)NULL);
-#endif /* DEBUG */
- }
-
- /* Not obsolete: link status bit is latched to 0 and autoclearing! */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
- if (pPrt->PHWLinkUp) {
- return(SK_HW_PS_NONE);
- }
-
-#ifdef xDEBUG
- {
- SK_U32 Stat1, Stat2, Stat3;
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "CheckUp1a - Stat: %x, Mask: %x",
- (void *)Isrc,
- (void *)Stat1);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
- Stat1 = Stat1 << 16 | PhyStat;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "Ctrl/Stat: %x, AN Adv/LP: %x",
- (void *)Stat1,
- (void *)Stat2);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
- Stat2 = Stat2 << 16 | ResAb;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
- (void *)Stat1,
- (void *)Stat2);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
- (void *)Stat1,
- (void *)Stat2);
- }
-#endif /* DEBUG */
-
- /*
- * Here we usually can check whether the link is in sync and
- * auto-negotiation is done.
- */
-
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-
- if ((ResAb & PHY_B_1000S_MSF) != 0) {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault port %d\n", Port));
-
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
-
- return(SK_HW_PS_RESTART);
- }
-
- if ((PhyStat & PHY_ST_LSYNC) == 0) {
- return(SK_HW_PS_NONE);
- }
-
- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Port %d, ResAb: 0x%04X\n", Port, ResAb));
-
- if (AutoNeg) {
- if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-
- SkHWLinkUp(pAC, IoC, Port);
-
- Done = SkMacAutoNegDone(pAC, IoC, Port);
-
- if (Done != SK_AND_OK) {
-#ifdef DEBUG
- /* Get PHY parameters, for debugging only */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
- Port, LpAb, ExtStat));
-#endif /* DEBUG */
- return(SK_HW_PS_RESTART);
- }
- else {
-#ifdef xDEBUG
- /* Dummy read ISR to prevent extra link downs/ups */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
- if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "CheckUp2 - Stat: %x",
- (void *)ExtStat,
- (void *)NULL);
- }
-#endif /* DEBUG */
- return(SK_HW_PS_LINK);
- }
- }
- }
- else { /* !AutoNeg */
- /* Link is up and we don't need more. */
-#ifdef DEBUG
- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("ERROR: Lipa auto detected on port %d\n", Port));
- }
-#endif /* DEBUG */
-
-#ifdef xDEBUG
- /* Dummy read ISR to prevent extra link downs/ups */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
- if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "CheckUp3 - Stat: %x",
- (void *)ExtStat,
- (void *)NULL);
- }
-#endif /* DEBUG */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link sync(GP), Port %d\n", Port));
- SkHWLinkUp(pAC, IoC, Port);
-
- return(SK_HW_PS_LINK);
- }
-
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpGmac(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Done;
- SK_U16 PhyIsrc; /* PHY Interrupt source */
- SK_U16 PhyStat; /* PPY Status */
- SK_U16 PhySpecStat;/* PHY Specific Status */
- SK_U16 ResAb; /* Master/Slave resolution */
- SK_EVPARA Para;
-#ifdef DEBUG
- SK_U16 Word; /* I/O helper */
-#endif /* DEBUG */
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PHWLinkUp) {
- return(SK_HW_PS_NONE);
- }
-
- /* Read PHY Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
- /* Read PHY Interrupt Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
-
- if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
- }
-
- if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
- }
-
- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-
- if ((ResAb & PHY_B_1000S_MSF) != 0) {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault port %d\n", Port));
-
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
-
- return(SK_HW_PS_RESTART);
- }
-
- /* Read PHY Specific Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
-
-#ifdef DEBUG
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
-
- if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
- (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) {
- /* Read PHY Next Page Link Partner */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Page Received, NextPage: 0x%04X\n", Word));
- }
-#endif /* DEBUG */
-
- if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
- return(SK_HW_PS_NONE);
- }
-
- if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
- (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
- /* Downshift detected */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
-
- Para.Para64 = Port;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
- }
-
- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-
- pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
-
- if (AutoNeg) {
- /* Auto-Negotiation Over ? */
- if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-
- SkHWLinkUp(pAC, IoC, Port);
-
- Done = SkMacAutoNegDone(pAC, IoC, Port);
-
- if (Done != SK_AND_OK) {
- return(SK_HW_PS_RESTART);
- }
-
- return(SK_HW_PS_LINK);
- }
- }
- else { /* !AutoNeg */
- /* Link is up and we don't need more */
-#ifdef DEBUG
- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("ERROR: Lipa auto detected on port %d\n", Port));
- }
-#endif /* DEBUG */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link sync, Port %d\n", Port));
- SkHWLinkUp(pAC, IoC, Port);
-
- return(SK_HW_PS_LINK);
- }
-
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpLone(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Done;
- SK_U16 Isrc; /* Interrupt source register */
- SK_U16 LpAb; /* Link Partner Ability */
- SK_U16 ExtStat; /* Extended Status Register */
- SK_U16 PhyStat; /* Phy Status Register */
- SK_U16 StatSum;
- SK_U8 NextMode; /* Next AutoSensing Mode */
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PHWLinkUp) {
- return(SK_HW_PS_NONE);
- }
-
- StatSum = pPrt->PIsave;
- pPrt->PIsave = 0;
-
- /*
- * here we usually can check whether the link is in sync and
- * auto-negotiation is done.
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
- StatSum |= PhyStat;
-
- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-
- if ((PhyStat & PHY_ST_LSYNC) == 0) {
- /* Save Auto-negotiation Done bit */
- pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
-#ifdef DEBUG
- if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg done rescheduled Port %d\n", Port));
- }
-#endif /* DEBUG */
- return(SK_HW_PS_NONE);
- }
-
- if (AutoNeg) {
- if ((StatSum & PHY_ST_AN_OVER) != 0) {
- SkHWLinkUp(pAC, IoC, Port);
- Done = SkMacAutoNegDone(pAC, IoC, Port);
- if (Done != SK_AND_OK) {
- /* Get PHY parameters, for debugging only */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
- Port, LpAb, ExtStat));
-
- /* Try next possible mode */
- NextMode = SkHWSenseGetNext(pAC, IoC, Port);
- SkHWLinkDown(pAC, IoC, Port);
- if (Done == SK_AND_DUP_CAP) {
- /* GoTo next mode */
- SkHWSenseSetNext(pAC, IoC, Port, NextMode);
- }
-
- return(SK_HW_PS_RESTART);
-
- }
- else {
- /*
- * Dummy Read interrupt status to prevent
- * extra link down/ups
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
- return(SK_HW_PS_LINK);
- }
- }
-
- /* AutoNeg not done, but HW link is up. Check for timeouts */
- pPrt->PAutoNegTimeOut++;
- if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
- /* Timeout occured */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("AutoNeg timeout Port %d\n", Port));
- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
- pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
- /* Set Link manually up */
- SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Set manual full duplex Port %d\n", Port));
- }
-
- /* Do the restart */
- return(SK_HW_PS_RESTART);
- }
- }
- else {
- /* Link is up and we don't need more */
-#ifdef DEBUG
- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("ERROR: Lipa auto detected on port %d\n", Port));
- }
-#endif /* DEBUG */
-
- /*
- * Dummy Read interrupt status to prevent
- * extra link down/ups
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link sync(GP), Port %d\n", Port));
- SkHWLinkUp(pAC, IoC, Port);
-
- return(SK_HW_PS_LINK);
- }
-
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpLone */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpNat() - Check if the link is up on National PHY
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpNat(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- /* todo: National */
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- * SkGeSirqEvent() - Event Service Routine
- *
- * Description:
- *
- * Notes:
- */
-int SkGeSirqEvent(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* Io Context */
-SK_U32 Event, /* Module specific Event */
-SK_EVPARA Para) /* Event specific Parameter */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_U32 Port;
- SK_U32 Val32;
- int PortStat;
- SK_U8 Val8;
-#ifdef GENESIS
- SK_U64 Octets;
-#endif /* GENESIS */
-
- Port = Para.Para32[0];
- pPrt = &pAC->GIni.GP[Port];
-
- switch (Event) {
- case SK_HWEV_WATIM:
- if (pPrt->PState == SK_PRT_RESET) {
-
- PortStat = SK_HW_PS_NONE;
- }
- else {
- /* Check whether port came up */
- PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
- }
-
- switch (PortStat) {
- case SK_HW_PS_RESTART:
- if (pPrt->PHWLinkUp) {
- /* Set Link to down */
- SkHWLinkDown(pAC, IoC, (int)Port);
-
- /*
- * Signal directly to RLMT to ensure correct
- * sequence of SWITCH and RESET event.
- */
- SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
- }
-
- /* Restart needed */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
- break;
-
- case SK_HW_PS_LINK:
- /* Signal to RLMT */
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
- break;
- }
-
- /* Start again the check Timer */
- if (pPrt->PHWLinkUp) {
- Val32 = SK_WA_ACT_TIME;
- }
- else {
- Val32 = SK_WA_INA_TIME;
- }
-
- /* Todo: still needed for non-XMAC PHYs??? */
- /* Start workaround Errata #2 timer */
- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
- SKGE_HWAC, SK_HWEV_WATIM, Para);
- break;
-
- case SK_HWEV_PORT_START:
- if (pPrt->PHWLinkUp) {
- /*
- * Signal directly to RLMT to ensure correct
- * sequence of SWITCH and RESET event.
- */
- SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
- }
-
- SkHWLinkDown(pAC, IoC, (int)Port);
-
- /* Schedule Port RESET */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-
- /* Start workaround Errata #2 timer */
- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
- SKGE_HWAC, SK_HWEV_WATIM, Para);
- break;
-
- case SK_HWEV_PORT_STOP:
- if (pPrt->PHWLinkUp) {
- /*
- * Signal directly to RLMT to ensure correct
- * sequence of SWITCH and RESET event.
- */
- SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
- }
-
- /* Stop Workaround Timer */
- SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
-
- SkHWLinkDown(pAC, IoC, (int)Port);
- break;
-
- case SK_HWEV_UPDATE_STAT:
- /* We do NOT need to update any statistics */
- break;
-
- case SK_HWEV_CLEAR_STAT:
- /* We do NOT need to clear any statistics */
- for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
- pPrt->PPrevRx = 0;
- pPrt->PPrevFcs = 0;
- pPrt->PPrevShorts = 0;
- }
- break;
-
- case SK_HWEV_SET_LMODE:
- Val8 = (SK_U8)Para.Para32[1];
- if (pPrt->PLinkModeConf != Val8) {
- /* Set New link mode */
- pPrt->PLinkModeConf = Val8;
-
- /* Restart Port */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
- }
- break;
-
- case SK_HWEV_SET_FLOWMODE:
- Val8 = (SK_U8)Para.Para32[1];
- if (pPrt->PFlowCtrlMode != Val8) {
- /* Set New Flow Control mode */
- pPrt->PFlowCtrlMode = Val8;
-
- /* Restart Port */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
- }
- break;
-
- case SK_HWEV_SET_ROLE:
- /* not possible for fiber */
- if (!pAC->GIni.GICopperType) {
- break;
- }
- Val8 = (SK_U8)Para.Para32[1];
- if (pPrt->PMSMode != Val8) {
- /* Set New Role (Master/Slave) mode */
- pPrt->PMSMode = Val8;
-
- /* Restart Port */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
- }
- break;
-
- case SK_HWEV_SET_SPEED:
- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
- break;
- }
- Val8 = (SK_U8)Para.Para32[1];
- if (pPrt->PLinkSpeed != Val8) {
- /* Set New Speed parameter */
- pPrt->PLinkSpeed = Val8;
-
- /* Restart Port */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
- }
- break;
-
-#ifdef GENESIS
- case SK_HWEV_HALFDUP_CHK:
- if (pAC->GIni.GIGenesis) {
- /*
- * half duplex hangup workaround.
- * See packet arbiter timeout interrupt for description
- */
- pPrt->HalfDupTimerActive = SK_FALSE;
- if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
- /* Snap statistic counters */
- (void)SkXmUpdateStats(pAC, IoC, Port);
-
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
-
- Octets = (SK_U64)Val32 << 32;
-
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
-
- Octets += Val32;
-
- if (pPrt->LastOctets == Octets) {
- /* Tx hanging, a FIFO flush restarts it */
- SkMacFlushTxFifo(pAC, IoC, Port);
- }
- }
- }
- break;
-#endif /* GENESIS */
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
- break;
- }
-
- return(0);
-} /* SkGeSirqEvent */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkPhyIsrBcom() - PHY interrupt service routine
- *
- * Description: handles all interrupts from BCom PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrBcom(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* Io Context */
-int Port, /* Port Num = PHY Num */
-SK_U16 IStatus) /* Interrupt Status */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_EVPARA Para;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if ((IStatus & PHY_B_IS_PSE) != 0) {
- /* Incorrectable pair swap error */
- SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
- SKERR_SIRQ_E022MSG);
- }
-
- if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
-
- SkHWLinkDown(pAC, IoC, Port);
-
- Para.Para32[0] = (SK_U32)Port;
- /* Signal to RLMT */
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
- /* Start workaround Errata #2 timer */
- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
- SKGE_HWAC, SK_HWEV_WATIM, Para);
- }
-
-} /* SkPhyIsrBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkPhyIsrGmac() - PHY interrupt service routine
- *
- * Description: handles all interrupts from Marvell PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrGmac(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* Io Context */
-int Port, /* Port Num = PHY Num */
-SK_U16 IStatus) /* Interrupt Status */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_EVPARA Para;
- SK_U16 Word;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
-
- SkHWLinkDown(pAC, IoC, Port);
-
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg.Adv: 0x%04X\n", Word));
-
- /* Set Auto-negotiation advertisement */
- if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
- /* restore Asymmetric Pause bit */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
- (SK_U16)(Word | PHY_M_AN_ASP));
- }
-
- Para.Para32[0] = (SK_U32)Port;
- /* Signal to RLMT */
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
- /* Auto-Negotiation Error */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
- }
-
- if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
- /* FIFO Overflow/Underrun Error */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
- }
-
-} /* SkPhyIsrGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkPhyIsrLone() - PHY interrupt service routine
- *
- * Description: handles all interrupts from LONE PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrLone(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* Io Context */
-int Port, /* Port Num = PHY Num */
-SK_U16 IStatus) /* Interrupt Status */
-{
- SK_EVPARA Para;
-
- if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
-
- SkHWLinkDown(pAC, IoC, Port);
-
- Para.Para32[0] = (SK_U32)Port;
- /* Signal to RLMT */
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
-} /* SkPhyIsrLone */
-#endif /* OTHER_PHY */
-
-/* End of File */
diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c
deleted file mode 100644
index 79bf57cb532..00000000000
--- a/drivers/net/sk98lin/ski2c.c
+++ /dev/null
@@ -1,1296 +0,0 @@
-/******************************************************************************
- *
- * Name: ski2c.c
- * Project: Gigabit Ethernet Adapters, TWSI-Module
- * Version: $Revision: 1.59 $
- * Date: $Date: 2003/10/20 09:07:25 $
- * Purpose: Functions to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * I2C Protocol
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- I2C protocol implementation.
-
- General Description:
-
- The I2C protocol is used for the temperature sensors and for
- the serial EEPROM which hold the configuration.
-
- This file covers functions that allow to read write and do
- some bulk requests a specified I2C address.
-
- The Genesis has 2 I2C buses. One for the EEPROM which holds
- the VPD Data and one for temperature and voltage sensor.
- The following picture shows the I2C buses, I2C devices and
- their control registers.
-
- Note: The VPD functions are in skvpd.c
-.
-. PCI Config I2C Bus for VPD Data:
-.
-. +------------+
-. | VPD EEPROM |
-. +------------+
-. |
-. | <-- I2C
-. |
-. +-----------+-----------+
-. | |
-. +-----------------+ +-----------------+
-. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG |
-. +-----------------+ +-----------------+
-.
-.
-. I2C Bus for LM80 sensor:
-.
-. +-----------------+
-. | Temperature and |
-. | Voltage Sensor |
-. | LM80 |
-. +-----------------+
-. |
-. |
-. I2C --> |
-. |
-. +----+
-. +-------------->| OR |<--+
-. | +----+ |
-. +------+------+ |
-. | | |
-. +--------+ +--------+ +----------+
-. | B2_I2C | | B2_I2C | | B2_I2C |
-. | _CTRL | | _DATA | | _SW |
-. +--------+ +--------+ +----------+
-.
- The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
- and B2_I2C_DATA registers.
- For driver software it is recommended to use the I2C control and
- data register, because I2C bus timing is done by the ASIC and
- an interrupt may be received when the I2C request is completed.
-
- Clock Rate Timing: MIN MAX generated by
- VPD EEPROM: 50 kHz 100 kHz HW
- LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW
- LM80 over B2_I2C_SW register 0 400 kHz SW
-
- Note: The clock generated by the hardware is dependend on the
- PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
- clock is 50 kHz.
- */
-intro()
-{}
-#endif
-
-#ifdef SK_DIAG
-/*
- * I2C Fast Mode timing values used by the LM80.
- * If new devices are added to the I2C bus the timing values have to be checked.
- */
-#ifndef I2C_SLOW_TIMING
-#define T_CLK_LOW 1300L /* clock low time in ns */
-#define T_CLK_HIGH 600L /* clock high time in ns */
-#define T_DATA_IN_SETUP 100L /* data in Set-up Time */
-#define T_START_HOLD 600L /* start condition hold time */
-#define T_START_SETUP 600L /* start condition Set-up time */
-#define T_STOP_SETUP 600L /* stop condition Set-up time */
-#define T_BUS_IDLE 1300L /* time the bus must free after Tx */
-#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */
-#else /* I2C_SLOW_TIMING */
-/* I2C Standard Mode Timing */
-#define T_CLK_LOW 4700L /* clock low time in ns */
-#define T_CLK_HIGH 4000L /* clock high time in ns */
-#define T_DATA_IN_SETUP 250L /* data in Set-up Time */
-#define T_START_HOLD 4000L /* start condition hold time */
-#define T_START_SETUP 4700L /* start condition Set-up time */
-#define T_STOP_SETUP 4000L /* stop condition Set-up time */
-#define T_BUS_IDLE 4700L /* time the bus must free after Tx */
-#endif /* !I2C_SLOW_TIMING */
-
-#define NS2BCLK(x) (((x)*125)/10000)
-
-/*
- * I2C Wire Operations
- *
- * About I2C_CLK_LOW():
- *
- * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
- * clock to low, to prevent the ASIC and the I2C data client from driving the
- * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client
- * send an 'ACK'). See also Concentrator Bugreport No. 10192.
- */
-#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA)
-#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA)
-#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
-#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
-#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK)
-#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
-#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK)
-
-#define NS2CLKT(x) ((x*125L)/10000)
-
-/*--------------- I2C Interface Register Functions --------------- */
-
-/*
- * sending one bit
- */
-void SkI2cSndBit(
-SK_IOC IoC, /* I/O Context */
-SK_U8 Bit) /* Bit to send */
-{
- I2C_DATA_OUT(IoC);
- if (Bit) {
- I2C_DATA_HIGH(IoC);
- }
- else {
- I2C_DATA_LOW(IoC);
- }
- SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
- I2C_CLK_HIGH(IoC);
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
- I2C_CLK_LOW(IoC);
-} /* SkI2cSndBit*/
-
-
-/*
- * Signal a start to the I2C Bus.
- *
- * A start is signaled when data goes to low in a high clock cycle.
- *
- * Ends with Clock Low.
- *
- * Status: not tested
- */
-void SkI2cStart(
-SK_IOC IoC) /* I/O Context */
-{
- /* Init data and Clock to output lines */
- /* Set Data high */
- I2C_DATA_OUT(IoC);
- I2C_DATA_HIGH(IoC);
- /* Set Clock high */
- I2C_CLK_HIGH(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
-
- /* Set Data Low */
- I2C_DATA_LOW(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
-
- /* Clock low without Data to Input */
- I2C_START_COND(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
-} /* SkI2cStart */
-
-
-void SkI2cStop(
-SK_IOC IoC) /* I/O Context */
-{
- /* Init data and Clock to output lines */
- /* Set Data low */
- I2C_DATA_OUT(IoC);
- I2C_DATA_LOW(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
- /* Set Clock high */
- I2C_CLK_HIGH(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
-
- /*
- * Set Data High: Do it by setting the Data Line to Input.
- * Because of a pull up resistor the Data Line
- * floods to high.
- */
- I2C_DATA_IN(IoC);
-
- /*
- * When I2C activity is stopped
- * o DATA should be set to input and
- * o CLOCK should be set to high!
- */
- SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
-} /* SkI2cStop */
-
-
-/*
- * Receive just one bit via the I2C bus.
- *
- * Note: Clock must be set to LOW before calling this function.
- *
- * Returns The received bit.
- */
-int SkI2cRcvBit(
-SK_IOC IoC) /* I/O Context */
-{
- int Bit;
- SK_U8 I2cSwCtrl;
-
- /* Init data as input line */
- I2C_DATA_IN(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
- I2C_CLK_HIGH(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
-
- SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-
- Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
-
- I2C_CLK_LOW(IoC);
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
-
- return(Bit);
-} /* SkI2cRcvBit */
-
-
-/*
- * Receive an ACK.
- *
- * returns 0 If acknowledged
- * 1 in case of an error
- */
-int SkI2cRcvAck(
-SK_IOC IoC) /* I/O Context */
-{
- /*
- * Received bit must be zero.
- */
- return(SkI2cRcvBit(IoC) != 0);
-} /* SkI2cRcvAck */
-
-
-/*
- * Send an NACK.
- */
-void SkI2cSndNAck(
-SK_IOC IoC) /* I/O Context */
-{
- /*
- * Received bit must be zero.
- */
- SkI2cSndBit(IoC, 1);
-} /* SkI2cSndNAck */
-
-
-/*
- * Send an ACK.
- */
-void SkI2cSndAck(
-SK_IOC IoC) /* I/O Context */
-{
- /*
- * Received bit must be zero.
- */
- SkI2cSndBit(IoC, 0);
-} /* SkI2cSndAck */
-
-
-/*
- * Send one byte to the I2C device and wait for ACK.
- *
- * Return acknowleged status.
- */
-int SkI2cSndByte(
-SK_IOC IoC, /* I/O Context */
-int Byte) /* byte to send */
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- if (Byte & (1<<(7-i))) {
- SkI2cSndBit(IoC, 1);
- }
- else {
- SkI2cSndBit(IoC, 0);
- }
- }
-
- return(SkI2cRcvAck(IoC));
-} /* SkI2cSndByte */
-
-
-/*
- * Receive one byte and ack it.
- *
- * Return byte.
- */
-int SkI2cRcvByte(
-SK_IOC IoC, /* I/O Context */
-int Last) /* Last Byte Flag */
-{
- int i;
- int Byte = 0;
-
- for (i = 0; i < 8; i++) {
- Byte <<= 1;
- Byte |= SkI2cRcvBit(IoC);
- }
-
- if (Last) {
- SkI2cSndNAck(IoC);
- }
- else {
- SkI2cSndAck(IoC);
- }
-
- return(Byte);
-} /* SkI2cRcvByte */
-
-
-/*
- * Start dialog and send device address
- *
- * Return 0 if acknowleged, 1 in case of an error
- */
-int SkI2cSndDev(
-SK_IOC IoC, /* I/O Context */
-int Addr, /* Device Address */
-int Rw) /* Read / Write Flag */
-{
- SkI2cStart(IoC);
- Rw = ~Rw;
- Rw &= I2C_WRITE;
- return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
-} /* SkI2cSndDev */
-
-#endif /* SK_DIAG */
-
-/*----------------- I2C CTRL Register Functions ----------*/
-
-/*
- * waits for a completion of an I2C transfer
- *
- * returns 0: success, transfer completes
- * 1: error, transfer does not complete, I2C transfer
- * killed, wait loop terminated.
- */
-static int SkI2cWait(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */
-{
- SK_U64 StartTime;
- SK_U64 CurrentTime;
- SK_U32 I2cCtrl;
-
- StartTime = SkOsGetTime(pAC);
-
- do {
- CurrentTime = SkOsGetTime(pAC);
-
- if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
-
- SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
-#endif /* !SK_DIAG */
- return(1);
- }
-
- SK_I2C_GET_CTL(IoC, &I2cCtrl);
-
-#ifdef xYUKON_DBG
- printf("StartTime=%lu, CurrentTime=%lu\n",
- StartTime, CurrentTime);
- if (kbhit()) {
- return(1);
- }
-#endif /* YUKON_DBG */
-
- } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
-
- return(0);
-} /* SkI2cWait */
-
-
-/*
- * waits for a completion of an I2C transfer
- *
- * Returns
- * Nothing
- */
-void SkI2cWaitIrq(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC) /* I/O Context */
-{
- SK_SENSOR *pSen;
- SK_U64 StartTime;
- SK_U32 IrqSrc;
-
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-
- if (pSen->SenState == SK_SEN_IDLE) {
- return;
- }
-
- StartTime = SkOsGetTime(pAC);
-
- do {
- if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
-
- SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
-#endif /* !SK_DIAG */
- return;
- }
-
- SK_IN32(IoC, B0_ISRC, &IrqSrc);
-
- } while ((IrqSrc & IS_I2C_READY) == 0);
-
- pSen->SenState = SK_SEN_IDLE;
- return;
-} /* SkI2cWaitIrq */
-
-/*
- * writes a single byte or 4 bytes into the I2C device
- *
- * returns 0: success
- * 1: error
- */
-static int SkI2cWrite(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 I2cData, /* I2C Data to write */
-int I2cDev, /* I2C Device Address */
-int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int I2cReg, /* I2C Device Register Address */
-int I2cBurst) /* I2C Burst Flag */
-{
- SK_OUT32(IoC, B2_I2C_DATA, I2cData);
-
- SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-
- return(SkI2cWait(pAC, IoC, I2C_WRITE));
-} /* SkI2cWrite*/
-
-
-#ifdef SK_DIAG
-/*
- * reads a single byte or 4 bytes from the I2C device
- *
- * returns the word read
- */
-SK_U32 SkI2cRead(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int I2cDev, /* I2C Device Address */
-int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int I2cReg, /* I2C Device Register Address */
-int I2cBurst) /* I2C Burst Flag */
-{
- SK_U32 Data;
-
- SK_OUT32(IoC, B2_I2C_DATA, 0);
- SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-
- if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
- w_print("%s\n", SKERR_I2C_E002MSG);
- }
-
- SK_IN32(IoC, B2_I2C_DATA, &Data);
-
- return(Data);
-} /* SkI2cRead */
-#endif /* SK_DIAG */
-
-
-/*
- * read a sensor's value
- *
- * This function reads a sensor's value from the I2C sensor chip. The sensor
- * is defined by its index into the sensors database in the struct pAC points
- * to.
- * Returns
- * 1 if the read is completed
- * 0 if the read must be continued (I2C Bus still allocated)
- */
-static int SkI2cReadSensor(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_SENSOR *pSen) /* Sensor to be read */
-{
- if (pSen->SenRead != NULL) {
- return((*pSen->SenRead)(pAC, IoC, pSen));
- }
- else {
- return(0); /* no success */
- }
-} /* SkI2cReadSensor */
-
-/*
- * Do the Init state 0 initialization
- */
-static int SkI2cInit0(
-SK_AC *pAC) /* Adapter Context */
-{
- int i;
-
- /* Begin with first sensor */
- pAC->I2c.CurrSens = 0;
-
- /* Begin with timeout control for state machine */
- pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-
- /* Set sensor number to zero */
- pAC->I2c.MaxSens = 0;
-
-#ifndef SK_DIAG
- /* Initialize Number of Dummy Reads */
- pAC->I2c.DummyReads = SK_MAX_SENSORS;
-#endif
-
- for (i = 0; i < SK_MAX_SENSORS; i++) {
- pAC->I2c.SenTable[i].SenDesc = "unknown";
- pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN;
- pAC->I2c.SenTable[i].SenThreErrHigh = 0;
- pAC->I2c.SenTable[i].SenThreErrLow = 0;
- pAC->I2c.SenTable[i].SenThreWarnHigh = 0;
- pAC->I2c.SenTable[i].SenThreWarnLow = 0;
- pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
- pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE;
- pAC->I2c.SenTable[i].SenValue = 0;
- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
- pAC->I2c.SenTable[i].SenErrCts = 0;
- pAC->I2c.SenTable[i].SenBegErrTS = 0;
- pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
- pAC->I2c.SenTable[i].SenRead = NULL;
- pAC->I2c.SenTable[i].SenDev = 0;
- }
-
- /* Now we are "INIT data"ed */
- pAC->I2c.InitLevel = SK_INIT_DATA;
- return(0);
-} /* SkI2cInit0*/
-
-
-/*
- * Do the init state 1 initialization
- *
- * initialize the following register of the LM80:
- * Configuration register:
- * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
- *
- * Interrupt Mask Register 1:
- * - all interrupts are Disabled (0xff)
- *
- * Interrupt Mask Register 2:
- * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
- *
- * Fan Divisor/RST_OUT register:
- * - Divisors set to 1 (bits 00), all others 0s.
- *
- * OS# Configuration/Temperature resolution Register:
- * - all 0s
- *
- */
-static int SkI2cInit1(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC) /* I/O Context */
-{
- int i;
- SK_U8 I2cSwCtrl;
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- if (pAC->I2c.InitLevel != SK_INIT_DATA) {
- /* ReInit not needed in I2C module */
- return(0);
- }
-
- /* Set the Direction of I2C-Data Pin to IN */
- SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
- /* Check for 32-Bit Yukon with Low at I2C-Data Pin */
- SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-
- if ((I2cSwCtrl & I2C_DATA) == 0) {
- /* this is a 32-Bit board */
- pAC->GIni.GIYukon32Bit = SK_TRUE;
- return(0);
- }
-
- /* Check for 64 Bit Yukon without sensors */
- if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
- return(0);
- }
-
- (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
-
- (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
-
- (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
-
- (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-
- (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
- LM80_CFG, 0);
-
- /*
- * MaxSens has to be updated here, because PhyType is not
- * set when performing Init Level 0
- */
- pAC->I2c.MaxSens = 5;
-
- pPrt = &pAC->GIni.GP[0];
-
- if (pAC->GIni.GIGenesis) {
- if (pPrt->PhyType == SK_PHY_BCOM) {
- if (pAC->GIni.GIMacsFound == 1) {
- pAC->I2c.MaxSens += 1;
- }
- else {
- pAC->I2c.MaxSens += 3;
- }
- }
- }
- else {
- pAC->I2c.MaxSens += 3;
- }
-
- for (i = 0; i < pAC->I2c.MaxSens; i++) {
- switch (i) {
- case 0:
- pAC->I2c.SenTable[i].SenDesc = "Temperature";
- pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN;
- break;
- case 1:
- pAC->I2c.SenTable[i].SenDesc = "Voltage PCI";
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN;
- break;
- case 2:
- pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO";
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN;
- pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO;
- break;
- case 3:
- pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC";
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN;
- break;
- case 4:
- if (pAC->GIni.GIGenesis) {
- if (pPrt->PhyType == SK_PHY_BCOM) {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PMA";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
- }
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
- if (pAC->GIni.GIVauxAvail) {
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
- }
- else {
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
- }
- }
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
- break;
- case 5:
- if (pAC->GIni.GIGenesis) {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
- }
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
- break;
- case 6:
- if (pAC->GIni.GIGenesis) {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
- }
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN;
- break;
- case 7:
- if (pAC->GIni.GIGenesis) {
- pAC->I2c.SenTable[i].SenDesc = "Speed Fan";
- pAC->I2c.SenTable[i].SenType = SK_SEN_FAN;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN;
- }
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
- SKERR_I2C_E001, SKERR_I2C_E001MSG);
- break;
- }
-
- pAC->I2c.SenTable[i].SenValue = 0;
- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
- pAC->I2c.SenTable[i].SenErrCts = 0;
- pAC->I2c.SenTable[i].SenBegErrTS = 0;
- pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
- pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor;
- pAC->I2c.SenTable[i].SenDev = LM80_ADDR;
- }
-
-#ifndef SK_DIAG
- pAC->I2c.DummyReads = pAC->I2c.MaxSens;
-#endif /* !SK_DIAG */
-
- /* Clear I2C IRQ */
- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-
- /* Now we are I/O initialized */
- pAC->I2c.InitLevel = SK_INIT_IO;
- return(0);
-} /* SkI2cInit1 */
-
-
-/*
- * Init level 2: Start first sensor read.
- */
-static int SkI2cInit2(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC) /* I/O Context */
-{
- int ReadComplete;
- SK_SENSOR *pSen;
-
- if (pAC->I2c.InitLevel != SK_INIT_IO) {
- /* ReInit not needed in I2C module */
- /* Init0 and Init2 not permitted */
- return(0);
- }
-
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
- if (ReadComplete) {
- SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
- }
-
- /* Now we are correctly initialized */
- pAC->I2c.InitLevel = SK_INIT_RUN;
-
- return(0);
-} /* SkI2cInit2*/
-
-
-/*
- * Initialize I2C devices
- *
- * Get the first voltage value and discard it.
- * Go into temperature read mode. A default pointer is not set.
- *
- * The things to be done depend on the init level in the parameter list:
- * Level 0:
- * Initialize only the data structures. Do NOT access hardware.
- * Level 1:
- * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
- * Level 2:
- * Everything is possible. Interrupts may be used from now on.
- *
- * return:
- * 0 = success
- * other = error.
- */
-int SkI2cInit(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */
-int Level) /* Init Level */
-{
-
- switch (Level) {
- case SK_INIT_DATA:
- return(SkI2cInit0(pAC));
- case SK_INIT_IO:
- return(SkI2cInit1(pAC, IoC));
- case SK_INIT_RUN:
- return(SkI2cInit2(pAC, IoC));
- default:
- break;
- }
-
- return(0);
-} /* SkI2cInit */
-
-
-#ifndef SK_DIAG
-
-/*
- * Interrupt service function for the I2C Interface
- *
- * Clears the Interrupt source
- *
- * Reads the register and check it for sending a trap.
- *
- * Starts the timer if necessary.
- */
-void SkI2cIsr(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC) /* I/O Context */
-{
- SK_EVPARA Para;
-
- /* Clear I2C IRQ */
- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-
- Para.Para64 = 0;
- SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
-} /* SkI2cIsr */
-
-
-/*
- * Check this sensors Value against the threshold and send events.
- */
-static void SkI2cCheckSensor(
-SK_AC *pAC, /* Adapter Context */
-SK_SENSOR *pSen)
-{
- SK_EVPARA ParaLocal;
- SK_BOOL TooHigh; /* Is sensor too high? */
- SK_BOOL TooLow; /* Is sensor too low? */
- SK_U64 CurrTime; /* Current Time */
- SK_BOOL DoTrapSend; /* We need to send a trap */
- SK_BOOL DoErrLog; /* We need to log the error */
- SK_BOOL IsError; /* We need to log the error */
-
- /* Check Dummy Reads first */
- if (pAC->I2c.DummyReads > 0) {
- pAC->I2c.DummyReads--;
- return;
- }
-
- /* Get the current time */
- CurrTime = SkOsGetTime(pAC);
-
- /* Set para to the most useful setting: The current sensor. */
- ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
-
- /* Check the Value against the thresholds. First: Error Thresholds */
- TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
- TooLow = (pSen->SenValue < pSen->SenThreErrLow);
-
- IsError = SK_FALSE;
- if (TooHigh || TooLow) {
- /* Error condition is satisfied */
- DoTrapSend = SK_TRUE;
- DoErrLog = SK_TRUE;
-
- /* Now error condition is satisfied */
- IsError = SK_TRUE;
-
- if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
- /* This state is the former one */
-
- /* So check first whether we have to send a trap */
- if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
- CurrTime) {
- /*
- * Do NOT send the Trap. The hold back time
- * has to run out first.
- */
- DoTrapSend = SK_FALSE;
- }
-
- /* Check now whether we have to log an Error */
- if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
- CurrTime) {
- /*
- * Do NOT log the error. The hold back time
- * has to run out first.
- */
- DoErrLog = SK_FALSE;
- }
- }
- else {
- /* We came from a different state -> Set Begin Time Stamp */
- pSen->SenBegErrTS = CurrTime;
- pSen->SenErrFlag = SK_SEN_ERR_ERR;
- }
-
- if (DoTrapSend) {
- /* Set current Time */
- pSen->SenLastErrTrapTS = CurrTime;
- pSen->SenErrCts++;
-
- /* Queue PNMI Event */
- SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
- SK_PNMI_EVT_SEN_ERR_UPP :
- SK_PNMI_EVT_SEN_ERR_LOW),
- ParaLocal);
- }
-
- if (DoErrLog) {
- /* Set current Time */
- pSen->SenLastErrLogTS = CurrTime;
-
- if (pSen->SenType == SK_SEN_TEMP) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
- }
- else if (pSen->SenType == SK_SEN_VOLT) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
- }
- }
- }
-
- /* Check the Value against the thresholds */
- /* 2nd: Warning thresholds */
- TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
- TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
-
- if (!IsError && (TooHigh || TooLow)) {
- /* Error condition is satisfied */
- DoTrapSend = SK_TRUE;
- DoErrLog = SK_TRUE;
-
- if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
- /* This state is the former one */
-
- /* So check first whether we have to send a trap */
- if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
- /*
- * Do NOT send the Trap. The hold back time
- * has to run out first.
- */
- DoTrapSend = SK_FALSE;
- }
-
- /* Check now whether we have to log an Error */
- if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
- /*
- * Do NOT log the error. The hold back time
- * has to run out first.
- */
- DoErrLog = SK_FALSE;
- }
- }
- else {
- /* We came from a different state -> Set Begin Time Stamp */
- pSen->SenBegWarnTS = CurrTime;
- pSen->SenErrFlag = SK_SEN_ERR_WARN;
- }
-
- if (DoTrapSend) {
- /* Set current Time */
- pSen->SenLastWarnTrapTS = CurrTime;
- pSen->SenWarnCts++;
-
- /* Queue PNMI Event */
- SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
- SK_PNMI_EVT_SEN_WAR_UPP :
- SK_PNMI_EVT_SEN_WAR_LOW),
- ParaLocal);
- }
-
- if (DoErrLog) {
- /* Set current Time */
- pSen->SenLastWarnLogTS = CurrTime;
-
- if (pSen->SenType == SK_SEN_TEMP) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
- }
- else if (pSen->SenType == SK_SEN_VOLT) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
- }
- }
- }
-
- /* Check for NO error at all */
- if (!IsError && !TooHigh && !TooLow) {
- /* Set o.k. Status if no error and no warning condition */
- pSen->SenErrFlag = SK_SEN_ERR_OK;
- }
-
- /* End of check against the thresholds */
-
- /* Bug fix AF: 16.Aug.2001: Correct the init base
- * of LM80 sensor.
- */
- if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
-
- pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
- if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
- /* 5V PCI-IO Voltage */
- pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
- pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
- }
- else {
- /* 3.3V PCI-IO Voltage */
- pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
- pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
- }
- }
-
-#ifdef TEST_ONLY
- /* Dynamic thresholds also for VAUX of LM80 sensor */
- if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
-
- pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
- /* 3.3V VAUX Voltage */
- if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
- pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
- pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
- }
- /* 0V VAUX Voltage */
- else {
- pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
- pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
- }
- }
-
- /*
- * Check initialization state:
- * The VIO Thresholds need adaption
- */
- if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
- pSen->SenValue > SK_SEN_WARNLOW2C &&
- pSen->SenValue < SK_SEN_WARNHIGH2) {
- pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
- pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
- pSen->SenInit = SK_TRUE;
- }
-
- if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
- pSen->SenValue > SK_SEN_WARNLOW2 &&
- pSen->SenValue < SK_SEN_WARNHIGH2C) {
- pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
- pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
- pSen->SenInit = SK_TRUE;
- }
-#endif
-
- if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
- }
-} /* SkI2cCheckSensor */
-
-
-/*
- * The only Event to be served is the timeout event
- *
- */
-int SkI2cEvent(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Event, /* Module specific Event */
-SK_EVPARA Para) /* Event specific Parameter */
-{
- int ReadComplete;
- SK_SENSOR *pSen;
- SK_U32 Time;
- SK_EVPARA ParaLocal;
- int i;
-
- /* New case: no sensors */
- if (pAC->I2c.MaxSens == 0) {
- return(0);
- }
-
- switch (Event) {
- case SK_I2CEV_IRQ:
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
- if (ReadComplete) {
- /* Check sensor against defined thresholds */
- SkI2cCheckSensor(pAC, pSen);
-
- /* Increment Current sensor and set appropriate Timeout */
- pAC->I2c.CurrSens++;
- if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
- pAC->I2c.CurrSens = 0;
- Time = SK_I2C_TIM_LONG;
- }
- else {
- Time = SK_I2C_TIM_SHORT;
- }
-
- /* Start Timer */
- ParaLocal.Para64 = (SK_U64)0;
-
- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
- }
- else {
- /* Start Timer */
- ParaLocal.Para64 = (SK_U64)0;
-
- pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-
- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
- }
- break;
- case SK_I2CEV_TIM:
- if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
-
- ParaLocal.Para64 = (SK_U64)0;
- SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
-
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
- if (ReadComplete) {
- /* Check sensor against defined thresholds */
- SkI2cCheckSensor(pAC, pSen);
-
- /* Increment Current sensor and set appropriate Timeout */
- pAC->I2c.CurrSens++;
- if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
- pAC->I2c.CurrSens = 0;
- Time = SK_I2C_TIM_LONG;
- }
- else {
- Time = SK_I2C_TIM_SHORT;
- }
-
- /* Start Timer */
- ParaLocal.Para64 = (SK_U64)0;
-
- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
- }
- }
- else {
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
- pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
- SK_I2C_STOP(IoC);
-
- /* Increment Current sensor and set appropriate Timeout */
- pAC->I2c.CurrSens++;
- if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
- pAC->I2c.CurrSens = 0;
- Time = SK_I2C_TIM_LONG;
- }
- else {
- Time = SK_I2C_TIM_SHORT;
- }
-
- /* Start Timer */
- ParaLocal.Para64 = (SK_U64)0;
-
- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
- }
- break;
- case SK_I2CEV_CLEAR:
- for (i = 0; i < SK_MAX_SENSORS; i++) {
- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
- pAC->I2c.SenTable[i].SenErrCts = 0;
- pAC->I2c.SenTable[i].SenWarnCts = 0;
- pAC->I2c.SenTable[i].SenBegErrTS = 0;
- pAC->I2c.SenTable[i].SenBegWarnTS = 0;
- pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0;
- pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0;
- pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0;
- pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0;
- }
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
- }
-
- return(0);
-} /* SkI2cEvent*/
-
-#endif /* !SK_DIAG */
diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c
deleted file mode 100644
index a204f5bb55d..00000000000
--- a/drivers/net/sk98lin/sklm80.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/******************************************************************************
- *
- * Name: sklm80.c
- * Project: Gigabit Ethernet Adapters, TWSI-Module
- * Version: $Revision: 1.22 $
- * Date: $Date: 2003/10/20 09:08:21 $
- * Purpose: Functions to access Voltage and Temperature Sensor (LM80)
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- LM80 functions
-*/
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#define BREAK_OR_WAIT(pAC,IoC,Event) break
-
-/*
- * read a sensors value (LM80 specific)
- *
- * This function reads a sensors value from the I2C sensor chip LM80.
- * The sensor is defined by its index into the sensors database in the struct
- * pAC points to.
- *
- * Returns 1 if the read is completed
- * 0 if the read must be continued (I2C Bus still allocated)
- */
-int SkLm80ReadSensor(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context needed in level 1 and 2 */
-SK_SENSOR *pSen) /* Sensor to be read */
-{
- SK_I32 Value;
-
- switch (pSen->SenState) {
- case SK_SEN_IDLE:
- /* Send address to ADDR register */
- SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0);
-
- pSen->SenState = SK_SEN_VALUE ;
- BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-
- case SK_SEN_VALUE:
- /* Read value from data register */
- SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
-
- Value &= 0xff; /* only least significant byte is valid */
-
- /* Do NOT check the Value against the thresholds */
- /* Checking is done in the calling instance */
-
- if (pSen->SenType == SK_SEN_VOLT) {
- /* Voltage sensor */
- pSen->SenValue = Value * SK_LM80_VT_LSB;
- pSen->SenState = SK_SEN_IDLE ;
- return(1);
- }
-
- if (pSen->SenType == SK_SEN_FAN) {
- if (Value != 0 && Value != 0xff) {
- /* Fan speed counter */
- pSen->SenValue = SK_LM80_FAN_FAKTOR/Value;
- }
- else {
- /* Indicate Fan error */
- pSen->SenValue = 0;
- }
- pSen->SenState = SK_SEN_IDLE ;
- return(1);
- }
-
- /* First: correct the value: it might be negative */
- if ((Value & 0x80) != 0) {
- /* Value is negative */
- Value = Value - 256;
- }
-
- /* We have a temperature sensor and need to get the signed extension.
- * For now we get the extension from the last reading, so in the normal
- * case we won't see flickering temperatures.
- */
- pSen->SenValue = (Value * SK_LM80_TEMP_LSB) +
- (pSen->SenValue % SK_LM80_TEMP_LSB);
-
- /* Send address to ADDR register */
- SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-
- pSen->SenState = SK_SEN_VALEXT ;
- BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-
- case SK_SEN_VALEXT:
- /* Read value from data register */
- SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
- Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */
-
- /* cut the LSB bit */
- pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) *
- SK_LM80_TEMP_LSB);
-
- if (pSen->SenValue < 0) {
- /* Value negative: The bit value must be subtracted */
- pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
- }
- else {
- /* Value positive: The bit value must be added */
- pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
- }
-
- pSen->SenState = SK_SEN_IDLE ;
- return(1);
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG);
- return(1);
- }
-
- /* Not completed */
- return(0);
-}
-
diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c
deleted file mode 100644
index 0275b4f71d9..00000000000
--- a/drivers/net/sk98lin/skqueue.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name: skqueue.c
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.20 $
- * Date: $Date: 2003/09/16 13:44:00 $
- * Purpose: Management of an event queue.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- * Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/skqueue.h" /* Queue Definitions */
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- Event queue management.
-
- General Description:
-
- */
-intro()
-{}
-#endif
-
-#define PRINTF(a,b,c)
-
-/*
- * init event queue management
- *
- * Must be called during init level 0.
- */
-void SkEventInit(
-SK_AC *pAC, /* Adapter context */
-SK_IOC Ioc, /* IO context */
-int Level) /* Init level */
-{
- switch (Level) {
- case SK_INIT_DATA:
- pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue;
- break;
- default:
- break;
- }
-}
-
-/*
- * add event to queue
- */
-void SkEventQueue(
-SK_AC *pAC, /* Adapters context */
-SK_U32 Class, /* Event Class */
-SK_U32 Event, /* Event to be queued */
-SK_EVPARA Para) /* Event parameter */
-{
- pAC->Event.EvPut->Class = Class;
- pAC->Event.EvPut->Event = Event;
- pAC->Event.EvPut->Para = Para;
-
- if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
- pAC->Event.EvPut = pAC->Event.EvQueue;
-
- if (pAC->Event.EvPut == pAC->Event.EvGet) {
- SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
- }
-}
-
-/*
- * event dispatcher
- * while event queue is not empty
- * get event from queue
- * send command to state machine
- * end
- * return error reported by individual Event function
- * 0 if no error occured.
- */
-int SkEventDispatcher(
-SK_AC *pAC, /* Adapters Context */
-SK_IOC Ioc) /* Io context */
-{
- SK_EVENTELEM *pEv; /* pointer into queue */
- SK_U32 Class;
- int Rtv;
-
- pEv = pAC->Event.EvGet;
-
- PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put);
-
- while (pEv != pAC->Event.EvPut) {
- PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event);
-
- switch (Class = pEv->Class) {
-#ifndef SK_USE_LAC_EV
-#ifndef SK_SLIM
- case SKGE_RLMT: /* RLMT Event */
- Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_I2C: /* I2C Event */
- Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_PNMI: /* PNMI Event */
- Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#endif /* not SK_SLIM */
-#endif /* not SK_USE_LAC_EV */
- case SKGE_DRV: /* Driver Event */
- Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#ifndef SK_USE_SW_TIMER
- case SKGE_HWAC:
- Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#else /* !SK_USE_SW_TIMER */
- case SKGE_SWT :
- Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#endif /* !SK_USE_SW_TIMER */
-#ifdef SK_USE_LAC_EV
- case SKGE_LACP :
- Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_RSF :
- Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_MARKER :
- Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_FD :
- Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#endif /* SK_USE_LAC_EV */
-#ifdef SK_USE_CSUM
- case SKGE_CSUM :
- Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#endif /* SK_USE_CSUM */
- default :
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG);
- Rtv = 0;
- }
-
- if (Rtv != 0) {
- return(Rtv);
- }
-
- if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT])
- pEv = pAC->Event.EvQueue;
-
- /* Renew get: it is used in queue_events to detect overruns */
- pAC->Event.EvGet = pEv;
- }
-
- return(0);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c
deleted file mode 100644
index be8d1ccddf6..00000000000
--- a/drivers/net/sk98lin/skrlmt.c
+++ /dev/null
@@ -1,3257 +0,0 @@
-/******************************************************************************
- *
- * Name: skrlmt.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.69 $
- * Date: $Date: 2003/04/15 09:39:22 $
- * Purpose: Manage links on SK-NET Adapters, esp. redundant ones.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters.
- * It is mainly intended for adapters with more than one link.
- * For such adapters, this module realizes Redundant Link ManagemenT (RLMT).
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef lint
-static const char SysKonnectFileId[] =
- "@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell.";
-#endif /* !defined(lint) */
-
-#define __SKRLMT_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-#ifndef SK_HWAC_LINK_LED
-#define SK_HWAC_LINK_LED(a,b,c,d)
-#endif /* !defined(SK_HWAC_LINK_LED) */
-
-#ifndef DEBUG
-#define RLMT_STATIC static
-#else /* DEBUG */
-#define RLMT_STATIC
-
-#ifndef SK_LITTLE_ENDIAN
-/* First 32 bits */
-#define OFFS_LO32 1
-
-/* Second 32 bits */
-#define OFFS_HI32 0
-#else /* SK_LITTLE_ENDIAN */
-/* First 32 bits */
-#define OFFS_LO32 0
-
-/* Second 32 bits */
-#define OFFS_HI32 1
-#endif /* SK_LITTLE_ENDIAN */
-
-#endif /* DEBUG */
-
-/* ----- Private timeout values ----- */
-
-#define SK_RLMT_MIN_TO_VAL 125000 /* 1/8 sec. */
-#define SK_RLMT_DEF_TO_VAL 1000000 /* 1 sec. */
-#define SK_RLMT_PORTDOWN_TIM_VAL 900000 /* another 0.9 sec. */
-#define SK_RLMT_PORTSTART_TIM_VAL 100000 /* 0.1 sec. */
-#define SK_RLMT_PORTUP_TIM_VAL 2500000 /* 2.5 sec. */
-#define SK_RLMT_SEG_TO_VAL 900000000 /* 15 min. */
-
-/* Assume tick counter increment is 1 - may be set OS-dependent. */
-#ifndef SK_TICK_INCR
-#define SK_TICK_INCR SK_CONSTU64(1)
-#endif /* !defined(SK_TICK_INCR) */
-
-/*
- * Amount that a time stamp must be later to be recognized as "substantially
- * later". This is about 1/128 sec, but above 1 tick counter increment.
- */
-#define SK_RLMT_BC_DELTA (1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \
- (SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR))
-
-/* ----- Private RLMT defaults ----- */
-
-#define SK_RLMT_DEF_PREF_PORT 0 /* "Lower" port. */
-#define SK_RLMT_DEF_MODE SK_RLMT_CHECK_LINK /* Default RLMT Mode. */
-
-/* ----- Private RLMT checking states ----- */
-
-#define SK_RLMT_RCS_SEG 1 /* RLMT Check State: check seg. */
-#define SK_RLMT_RCS_START_SEG 2 /* RLMT Check State: start check seg. */
-#define SK_RLMT_RCS_SEND_SEG 4 /* RLMT Check State: send BPDU packet */
-#define SK_RLMT_RCS_REPORT_SEG 8 /* RLMT Check State: report seg. */
-
-/* ----- Private PORT checking states ----- */
-
-#define SK_RLMT_PCS_TX 1 /* Port Check State: check tx. */
-#define SK_RLMT_PCS_RX 2 /* Port Check State: check rx. */
-
-/* ----- Private PORT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_PORTSTART_TIM 1100 /* Port start timeout. */
-#define SK_RLMT_PORTUP_TIM 1101 /* Port can now go up. */
-#define SK_RLMT_PORTDOWN_RX_TIM 1102 /* Port did not receive once ... */
-#define SK_RLMT_PORTDOWN 1103 /* Port went down. */
-#define SK_RLMT_PORTDOWN_TX_TIM 1104 /* Partner did not receive ... */
-
-/* ----- Private RLMT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_TIM 2100 /* RLMT timeout. */
-#define SK_RLMT_SEG_TIM 2101 /* RLMT segmentation check timeout. */
-
-#define TO_SHORTEN(tim) ((tim) / 2)
-
-/* Error numbers and messages. */
-#define SKERR_RLMT_E001 (SK_ERRBASE_RLMT + 0)
-#define SKERR_RLMT_E001_MSG "No Packet."
-#define SKERR_RLMT_E002 (SKERR_RLMT_E001 + 1)
-#define SKERR_RLMT_E002_MSG "Short Packet."
-#define SKERR_RLMT_E003 (SKERR_RLMT_E002 + 1)
-#define SKERR_RLMT_E003_MSG "Unknown RLMT event."
-#define SKERR_RLMT_E004 (SKERR_RLMT_E003 + 1)
-#define SKERR_RLMT_E004_MSG "PortsUp incorrect."
-#define SKERR_RLMT_E005 (SKERR_RLMT_E004 + 1)
-#define SKERR_RLMT_E005_MSG \
- "Net seems to be segmented (different root bridges are reported on the ports)."
-#define SKERR_RLMT_E006 (SKERR_RLMT_E005 + 1)
-#define SKERR_RLMT_E006_MSG "Duplicate MAC Address detected."
-#define SKERR_RLMT_E007 (SKERR_RLMT_E006 + 1)
-#define SKERR_RLMT_E007_MSG "LinksUp incorrect."
-#define SKERR_RLMT_E008 (SKERR_RLMT_E007 + 1)
-#define SKERR_RLMT_E008_MSG "Port not started but link came up."
-#define SKERR_RLMT_E009 (SKERR_RLMT_E008 + 1)
-#define SKERR_RLMT_E009_MSG "Corrected illegal setting of Preferred Port."
-#define SKERR_RLMT_E010 (SKERR_RLMT_E009 + 1)
-#define SKERR_RLMT_E010_MSG "Ignored illegal Preferred Port."
-
-/* LLC field values. */
-#define LLC_COMMAND_RESPONSE_BIT 1
-#define LLC_TEST_COMMAND 0xE3
-#define LLC_UI 0x03
-
-/* RLMT Packet fields. */
-#define SK_RLMT_DSAP 0
-#define SK_RLMT_SSAP 0
-#define SK_RLMT_CTRL (LLC_TEST_COMMAND)
-#define SK_RLMT_INDICATOR0 0x53 /* S */
-#define SK_RLMT_INDICATOR1 0x4B /* K */
-#define SK_RLMT_INDICATOR2 0x2D /* - */
-#define SK_RLMT_INDICATOR3 0x52 /* R */
-#define SK_RLMT_INDICATOR4 0x4C /* L */
-#define SK_RLMT_INDICATOR5 0x4D /* M */
-#define SK_RLMT_INDICATOR6 0x54 /* T */
-#define SK_RLMT_PACKET_VERSION 0
-
-/* RLMT SPT Flag values. */
-#define SK_RLMT_SPT_FLAG_CHANGE 0x01
-#define SK_RLMT_SPT_FLAG_CHANGE_ACK 0x80
-
-/* RLMT SPT Packet fields. */
-#define SK_RLMT_SPT_DSAP 0x42
-#define SK_RLMT_SPT_SSAP 0x42
-#define SK_RLMT_SPT_CTRL (LLC_UI)
-#define SK_RLMT_SPT_PROTOCOL_ID0 0x00
-#define SK_RLMT_SPT_PROTOCOL_ID1 0x00
-#define SK_RLMT_SPT_PROTOCOL_VERSION_ID 0x00
-#define SK_RLMT_SPT_BPDU_TYPE 0x00
-#define SK_RLMT_SPT_FLAGS 0x00 /* ?? */
-#define SK_RLMT_SPT_ROOT_ID0 0xFF /* Lowest possible priority. */
-#define SK_RLMT_SPT_ROOT_ID1 0xFF /* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define SK_RLMT_SPT_ROOT_PATH_COST0 0x00
-#define SK_RLMT_SPT_ROOT_PATH_COST1 0x00
-#define SK_RLMT_SPT_ROOT_PATH_COST2 0x00
-#define SK_RLMT_SPT_ROOT_PATH_COST3 0x00
-#define SK_RLMT_SPT_BRIDGE_ID0 0xFF /* Lowest possible priority. */
-#define SK_RLMT_SPT_BRIDGE_ID1 0xFF /* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define SK_RLMT_SPT_PORT_ID0 0xFF /* Lowest possible priority. */
-#define SK_RLMT_SPT_PORT_ID1 0xFF /* Lowest possible priority. */
-#define SK_RLMT_SPT_MSG_AGE0 0x00
-#define SK_RLMT_SPT_MSG_AGE1 0x00
-#define SK_RLMT_SPT_MAX_AGE0 0x00
-#define SK_RLMT_SPT_MAX_AGE1 0xFF
-#define SK_RLMT_SPT_HELLO_TIME0 0x00
-#define SK_RLMT_SPT_HELLO_TIME1 0xFF
-#define SK_RLMT_SPT_FWD_DELAY0 0x00
-#define SK_RLMT_SPT_FWD_DELAY1 0x40
-
-/* Size defines. */
-#define SK_RLMT_MIN_PACKET_SIZE 34
-#define SK_RLMT_MAX_PACKET_SIZE (SK_RLMT_MAX_TX_BUF_SIZE)
-#define SK_PACKET_DATA_LEN (SK_RLMT_MAX_PACKET_SIZE - \
- SK_RLMT_MIN_PACKET_SIZE)
-
-/* ----- RLMT packet types ----- */
-#define SK_PACKET_ANNOUNCE 1 /* Port announcement. */
-#define SK_PACKET_ALIVE 2 /* Alive packet to port. */
-#define SK_PACKET_ADDR_CHANGED 3 /* Port address changed. */
-#define SK_PACKET_CHECK_TX 4 /* Check your tx line. */
-
-#ifdef SK_LITTLE_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \
- SK_U8 *_Addr = (SK_U8*)(Addr); \
- SK_U16 _Val = (SK_U16)(Val); \
- *_Addr++ = (SK_U8)(_Val >> 8); \
- *_Addr = (SK_U8)(_Val & 0xFF); \
-}
-#endif /* SK_LITTLE_ENDIAN */
-
-#ifdef SK_BIG_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))
-#endif /* SK_BIG_ENDIAN */
-
-#define AUTONEG_FAILED SK_FALSE
-#define AUTONEG_SUCCESS SK_TRUE
-
-
-/* typedefs *******************************************************************/
-
-/* RLMT packet. Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */
-typedef struct s_RlmtPacket {
- SK_U8 DstAddr[SK_MAC_ADDR_LEN];
- SK_U8 SrcAddr[SK_MAC_ADDR_LEN];
- SK_U8 TypeLen[2];
- SK_U8 DSap;
- SK_U8 SSap;
- SK_U8 Ctrl;
- SK_U8 Indicator[7];
- SK_U8 RlmtPacketType[2];
- SK_U8 Align1[2];
- SK_U8 Random[4]; /* Random value of requesting(!) station. */
- SK_U8 RlmtPacketVersion[2]; /* RLMT Packet version. */
- SK_U8 Data[SK_PACKET_DATA_LEN];
-} SK_RLMT_PACKET;
-
-typedef struct s_SpTreeRlmtPacket {
- SK_U8 DstAddr[SK_MAC_ADDR_LEN];
- SK_U8 SrcAddr[SK_MAC_ADDR_LEN];
- SK_U8 TypeLen[2];
- SK_U8 DSap;
- SK_U8 SSap;
- SK_U8 Ctrl;
- SK_U8 ProtocolId[2];
- SK_U8 ProtocolVersionId;
- SK_U8 BpduType;
- SK_U8 Flags;
- SK_U8 RootId[8];
- SK_U8 RootPathCost[4];
- SK_U8 BridgeId[8];
- SK_U8 PortId[2];
- SK_U8 MessageAge[2];
- SK_U8 MaxAge[2];
- SK_U8 HelloTime[2];
- SK_U8 ForwardDelay[2];
-} SK_SPTREE_PACKET;
-
-/* global variables ***********************************************************/
-
-SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}};
-SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}};
-
-/* local variables ************************************************************/
-
-/* None. */
-
-/* functions ******************************************************************/
-
-RLMT_STATIC void SkRlmtCheckSwitch(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 NetIdx);
-RLMT_STATIC void SkRlmtCheckSeg(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 NetIdx);
-RLMT_STATIC void SkRlmtEvtSetNets(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_EVPARA Para);
-
-/******************************************************************************
- *
- * SkRlmtInit - initialize data, set state to init
- *
- * Description:
- *
- * SK_INIT_DATA
- * ============
- *
- * This routine initializes all RLMT-related variables to a known state.
- * The initial state is SK_RLMT_RS_INIT.
- * All ports are initialized to SK_RLMT_PS_INIT.
- *
- *
- * SK_INIT_IO
- * ==========
- *
- * Nothing.
- *
- *
- * SK_INIT_RUN
- * ===========
- *
- * Determine the adapter's random value.
- * Set the hw registers, the "logical MAC address", the
- * RLMT multicast address, and eventually the BPDU multicast address.
- *
- * Context:
- * init, pageable
- *
- * Returns:
- * Nothing.
- */
-void SkRlmtInit(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Level) /* Initialization Level */
-{
- SK_U32 i, j;
- SK_U64 Random;
- SK_EVPARA Para;
- SK_MAC_ADDR VirtualMacAddress;
- SK_MAC_ADDR PhysicalAMacAddress;
- SK_BOOL VirtualMacAddressSet;
- SK_BOOL PhysicalAMacAddressSet;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
- ("RLMT Init level %d.\n", Level))
-
- switch (Level) {
- case SK_INIT_DATA: /* Initialize data structures. */
- SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT));
-
- for (i = 0; i < SK_MAX_MACS; i++) {
- pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT;
- pAC->Rlmt.Port[i].LinkDown = SK_TRUE;
- pAC->Rlmt.Port[i].PortDown = SK_TRUE;
- pAC->Rlmt.Port[i].PortStarted = SK_FALSE;
- pAC->Rlmt.Port[i].PortNoRx = SK_FALSE;
- pAC->Rlmt.Port[i].RootIdSet = SK_FALSE;
- pAC->Rlmt.Port[i].PortNumber = i;
- pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0];
- pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i];
- }
-
- pAC->Rlmt.NumNets = 1;
- for (i = 0; i < SK_MAX_NETS; i++) {
- pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
- pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
- pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
- pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */
- /* Just assuming. */
- pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
- pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
- pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
- pAC->Rlmt.Net[i].NetNumber = i;
- }
-
- pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0];
- pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1];
-#if SK_MAX_NETS > 1
- pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1];
-#endif /* SK_MAX_NETS > 1 */
- break;
-
- case SK_INIT_IO: /* GIMacsFound first available here. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
- ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound))
-
- pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
- /* Initialize HW registers? */
- if (pAC->GIni.GIMacsFound == 1) {
- Para.Para32[0] = SK_RLMT_MODE_CLS;
- Para.Para32[1] = 0;
- (void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para);
- }
- break;
-
- case SK_INIT_RUN:
- /* Ensure RLMT is set to one net. */
- if (pAC->Rlmt.NumNets > 1) {
- Para.Para32[0] = 1;
- Para.Para32[1] = -1;
- SkRlmtEvtSetNets(pAC, IoC, Para);
- }
-
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- Random = SkOsGetTime(pAC);
- *(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random;
-
- for (j = 0; j < 4; j++) {
- pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort->
- CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j];
- }
-
- (void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-
- /* Add RLMT MC address. */
- (void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
- if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) {
- /* Add BPDU MC address. */
- (void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT);
- }
-
- (void)SkAddrMcUpdate(pAC, IoC, i);
- }
-
- VirtualMacAddressSet = SK_FALSE;
- /* Read virtual MAC address from Control Register File. */
- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-
- SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]);
- VirtualMacAddressSet |= VirtualMacAddress.a[j];
- }
-
- PhysicalAMacAddressSet = SK_FALSE;
- /* Read physical MAC address for MAC A from Control Register File. */
- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-
- SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]);
- PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j];
- }
-
- /* check if the two mac addresses contain reasonable values */
- if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) {
-
- pAC->Rlmt.RlmtOff = SK_TRUE;
- }
-
- /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
- and the RLMT_LOOKAHEAD macros */
- else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) {
-
- pAC->Rlmt.RlmtOff = SK_TRUE;
- }
- else {
- pAC->Rlmt.RlmtOff = SK_FALSE;
- }
- break;
-
- default: /* error */
- break;
- }
- return;
-} /* SkRlmtInit */
-
-
-/******************************************************************************
- *
- * SkRlmtBuildCheckChain - build the check chain
- *
- * Description:
- * This routine builds the local check chain:
- * - Each port that is up checks the next port.
- * - The last port that is up checks the first port that is up.
- *
- * Notes:
- * - Currently only local ports are considered when building the chain.
- * - Currently the SuspectState is just reset;
- * it would be better to save it ...
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtBuildCheckChain(
-SK_AC *pAC, /* Adapter Context */
-SK_U32 NetIdx) /* Net Number */
-{
- SK_U32 i;
- SK_U32 NumMacsUp;
- SK_RLMT_PORT * FirstMacUp;
- SK_RLMT_PORT * PrevMacUp;
-
- FirstMacUp = NULL;
- PrevMacUp = NULL;
-
- if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
- for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) {
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
- }
- return; /* Done. */
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SkRlmtBuildCheckChain.\n"))
-
- NumMacsUp = 0;
-
- for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0;
- pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &=
- ~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX);
-
- /*
- * If more than two links are detected we should consider
- * checking at least two other ports:
- * 1. the next port that is not LinkDown and
- * 2. the next port that is not PortDown.
- */
- if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
- if (NumMacsUp == 0) {
- FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
- }
- else {
- PrevMacUp->PortCheck[
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr =
- pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress;
- PrevMacUp->PortCheck[
- PrevMacUp->PortsChecked].SuspectTx = SK_FALSE;
- PrevMacUp->PortsChecked++;
- }
- PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
- NumMacsUp++;
- }
- }
-
- if (NumMacsUp > 1) {
- PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr =
- FirstMacUp->AddrPort->CurrentMacAddress;
- PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx =
- SK_FALSE;
- PrevMacUp->PortsChecked++;
- }
-
-#ifdef DEBUG
- for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Port %d checks %d other ports: %2X.\n", i,
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked,
- pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]))
- }
-#endif /* DEBUG */
-
- return;
-} /* SkRlmtBuildCheckChain */
-
-
-/******************************************************************************
- *
- * SkRlmtBuildPacket - build an RLMT packet
- *
- * Description:
- * This routine sets up an RLMT packet.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF *SkRlmtBuildPacket(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber, /* Sending port */
-SK_U16 PacketType, /* RLMT packet type */
-SK_MAC_ADDR *SrcAddr, /* Source address */
-SK_MAC_ADDR *DestAddr) /* Destination address */
-{
- int i;
- SK_U16 Length;
- SK_MBUF *pMb;
- SK_RLMT_PACKET *pPacket;
-
-#ifdef DEBUG
- SK_U8 CheckSrc = 0;
- SK_U8 CheckDest = 0;
-
- for (i = 0; i < SK_MAC_ADDR_LEN; ++i) {
- CheckSrc |= SrcAddr->a[i];
- CheckDest |= DestAddr->a[i];
- }
-
- if ((CheckSrc == 0) || (CheckDest == 0)) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,
- ("SkRlmtBuildPacket: Invalid %s%saddr.\n",
- (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")))
- }
-#endif
-
- if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) {
- pPacket = (SK_RLMT_PACKET*)pMb->pData;
- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
- pPacket->DstAddr[i] = DestAddr->a[i];
- pPacket->SrcAddr[i] = SrcAddr->a[i];
- }
- pPacket->DSap = SK_RLMT_DSAP;
- pPacket->SSap = SK_RLMT_SSAP;
- pPacket->Ctrl = SK_RLMT_CTRL;
- pPacket->Indicator[0] = SK_RLMT_INDICATOR0;
- pPacket->Indicator[1] = SK_RLMT_INDICATOR1;
- pPacket->Indicator[2] = SK_RLMT_INDICATOR2;
- pPacket->Indicator[3] = SK_RLMT_INDICATOR3;
- pPacket->Indicator[4] = SK_RLMT_INDICATOR4;
- pPacket->Indicator[5] = SK_RLMT_INDICATOR5;
- pPacket->Indicator[6] = SK_RLMT_INDICATOR6;
-
- SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]);
-
- for (i = 0; i < 4; i++) {
- pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i];
- }
-
- SK_U16_TO_NETWORK_ORDER(
- SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]);
-
- for (i = 0; i < SK_PACKET_DATA_LEN; i++) {
- pPacket->Data[i] = 0x00;
- }
-
- Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */
- pMb->Length = Length;
- pMb->PortIdx = PortNumber;
- Length -= 14;
- SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);
-
- if (PacketType == SK_PACKET_ALIVE) {
- pAC->Rlmt.Port[PortNumber].TxHelloCts++;
- }
- }
-
- return (pMb);
-} /* SkRlmtBuildPacket */
-
-
-/******************************************************************************
- *
- * SkRlmtBuildSpanningTreePacket - build spanning tree check packet
- *
- * Description:
- * This routine sets up a BPDU packet for spanning tree check.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF *SkRlmtBuildSpanningTreePacket(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Sending port */
-{
- unsigned i;
- SK_U16 Length;
- SK_MBUF *pMb;
- SK_SPTREE_PACKET *pSPacket;
-
- if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=
- NULL) {
- pSPacket = (SK_SPTREE_PACKET*)pMb->pData;
- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
- pSPacket->DstAddr[i] = BridgeMcAddr.a[i];
- pSPacket->SrcAddr[i] =
- pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
- }
- pSPacket->DSap = SK_RLMT_SPT_DSAP;
- pSPacket->SSap = SK_RLMT_SPT_SSAP;
- pSPacket->Ctrl = SK_RLMT_SPT_CTRL;
-
- pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0;
- pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1;
- pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID;
- pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE;
- pSPacket->Flags = SK_RLMT_SPT_FLAGS;
- pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0;
- pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1;
- pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0;
- pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1;
- pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2;
- pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3;
- pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0;
- pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1;
-
- /*
- * Use logical MAC address as bridge ID and filter these packets
- * on receive.
- */
- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
- pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] =
- pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber].
- CurrentMacAddress.a[i];
- }
- pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0;
- pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1;
- pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0;
- pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1;
- pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0;
- pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1;
- pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0;
- pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1;
- pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0;
- pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1;
-
- Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */
- pMb->Length = Length;
- pMb->PortIdx = PortNumber;
- Length -= 14;
- SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]);
-
- pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++;
- }
-
- return (pMb);
-} /* SkRlmtBuildSpanningTreePacket */
-
-
-/******************************************************************************
- *
- * SkRlmtSend - build and send check packets
- *
- * Description:
- * Depending on the RLMT state and the checking state, several packets
- * are sent through the indicated port.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtSend(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Sending port */
-{
- unsigned j;
- SK_EVPARA Para;
- SK_RLMT_PORT *pRPort;
-
- pRPort = &pAC->Rlmt.Port[PortNumber];
- if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
- if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) {
- /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
- if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
- SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
- &SkRlmtMcAddr)) != NULL) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- }
- else {
- /*
- * Send a directed RLMT packet to all ports that are
- * checked by the indicated port.
- */
- for (j = 0; j < pRPort->PortsChecked; j++) {
- if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
- SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
- &pRPort->PortCheck[j].CheckAddr)) != NULL) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- }
- }
- }
-
- if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
- (pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) {
- /*
- * Send a BPDU packet to make a connected switch tell us
- * the correct root bridge.
- */
- if ((Para.pParaPtr =
- SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) {
- pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG;
- pRPort->RootIdSet = SK_FALSE;
-
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX,
- ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber))
- }
- }
- return;
-} /* SkRlmtSend */
-
-
-/******************************************************************************
- *
- * SkRlmtPortReceives - check if port is (going) down and bring it up
- *
- * Description:
- * This routine checks if a port who received a non-BPDU packet
- * needs to go up or needs to be stopped going down.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtPortReceives(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Port to check */
-{
- SK_RLMT_PORT *pRPort;
- SK_EVPARA Para;
-
- pRPort = &pAC->Rlmt.Port[PortNumber];
- pRPort->PortNoRx = SK_FALSE;
-
- if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
- !(pRPort->CheckingState & SK_RLMT_PCS_TX)) {
- /*
- * Port is marked down (rx), but received a non-BPDU packet.
- * Bring it up.
- */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Received on PortDown.\n"))
-
- pRPort->PortState = SK_RLMT_PS_GOING_UP;
- pRPort->GuTimeStamp = SkOsGetTime(pAC);
- Para.Para32[0] = PortNumber;
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
- SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para);
- pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
- /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- } /* PortDown && !SuspectTx */
- else if (pRPort->CheckingState & SK_RLMT_PCS_RX) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Stop bringing port down.\n"))
- SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
- pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
- /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- } /* PortGoingDown */
-
- return;
-} /* SkRlmtPortReceives */
-
-
-/******************************************************************************
- *
- * SkRlmtPacketReceive - receive a packet for closer examination
- *
- * Description:
- * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtPacketReceive(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_MBUF *pMb) /* Received packet */
-{
-#ifdef xDEBUG
- extern void DumpData(char *p, int size);
-#endif /* DEBUG */
- int i;
- unsigned j;
- SK_U16 PacketType;
- SK_U32 PortNumber;
- SK_ADDR_PORT *pAPort;
- SK_RLMT_PORT *pRPort;
- SK_RLMT_PACKET *pRPacket;
- SK_SPTREE_PACKET *pSPacket;
- SK_EVPARA Para;
-
- PortNumber = pMb->PortIdx;
- pAPort = &pAC->Addr.Port[PortNumber];
- pRPort = &pAC->Rlmt.Port[PortNumber];
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber))
-
- pRPacket = (SK_RLMT_PACKET*)pMb->pData;
- pSPacket = (SK_SPTREE_PACKET*)pRPacket;
-
-#ifdef xDEBUG
- DumpData((char *)pRPacket, 32);
-#endif /* DEBUG */
-
- if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) {
- SkRlmtPortReceives(pAC, IoC, PortNumber);
- }
-
- /* Check destination address. */
-
- if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) &&
- !SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) &&
- !SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) {
-
- /* Not sent to current MAC or registered MC address => Trash it. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Not for me.\n"))
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- return;
- }
- else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) {
-
- /*
- * Was sent by same port (may happen during port switching
- * or in case of duplicate MAC addresses).
- */
-
- /*
- * Check for duplicate address here:
- * If Packet.Random != My.Random => DupAddr.
- */
- for (i = 3; i >= 0; i--) {
- if (pRPort->Random[i] != pRPacket->Random[i]) {
- break;
- }
- }
-
- /*
- * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
- * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
- * pRPacket->SSap).
- */
- if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP &&
- pRPacket->Ctrl == SK_RLMT_CTRL &&
- pRPacket->SSap == SK_RLMT_SSAP &&
- pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
- pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
- pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
- pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
- pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
- pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
- pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
-
- /* Error Log entry. */
- SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG);
- }
- else {
- /* Simply trash it. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Sent by me.\n"))
- }
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- return;
- }
-
- /* Check SuspectTx entries. */
- if (pRPort->PortsSuspect > 0) {
- for (j = 0; j < pRPort->PortsChecked; j++) {
- if (pRPort->PortCheck[j].SuspectTx &&
- SK_ADDR_EQUAL(
- pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) {
- pRPort->PortCheck[j].SuspectTx = SK_FALSE;
- pRPort->PortsSuspect--;
- break;
- }
- }
- }
-
- /* Determine type of packet. */
- if (pRPacket->DSap == SK_RLMT_DSAP &&
- pRPacket->Ctrl == SK_RLMT_CTRL &&
- (pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP &&
- pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
- pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
- pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
- pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
- pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
- pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
- pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
-
- /* It's an RLMT packet. */
- PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) |
- pRPacket->RlmtPacketType[1]);
-
- switch (PacketType) {
- case SK_PACKET_ANNOUNCE: /* Not yet used. */
-#if 0
- /* Build the check chain. */
- SkRlmtBuildCheckChain(pAC);
-#endif /* 0 */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Announce.\n"))
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- break;
-
- case SK_PACKET_ALIVE:
- if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Alive Reply.\n"))
-
- if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) ||
- SK_ADDR_EQUAL(
- pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) {
- /* Obviously we could send something. */
- if (pRPort->CheckingState & SK_RLMT_PCS_TX) {
- pRPort->CheckingState &= ~SK_RLMT_PCS_TX;
- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
- }
-
- if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
- !(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
- pRPort->PortState = SK_RLMT_PS_GOING_UP;
- pRPort->GuTimeStamp = SkOsGetTime(pAC);
-
- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
- Para.Para32[0] = PortNumber;
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->UpTimer,
- SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT,
- SK_RLMT_PORTUP_TIM, Para);
- }
- }
-
- /* Mark sending port as alive? */
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- }
- else { /* Alive Request Packet. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Alive Request.\n"))
-
- pRPort->RxHelloCts++;
-
- /* Answer. */
- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
- pRPacket->DstAddr[i] = pRPacket->SrcAddr[i];
- pRPacket->SrcAddr[i] =
- pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
- }
- pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT;
-
- Para.pParaPtr = pMb;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- break;
-
- case SK_PACKET_CHECK_TX:
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Check your tx line.\n"))
-
- /* A port checking us requests us to check our tx line. */
- pRPort->CheckingState |= SK_RLMT_PCS_TX;
-
- /* Start PortDownTx timer. */
- Para.Para32[0] = PortNumber;
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->DownTxTimer,
- SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
- SK_RLMT_PORTDOWN_TX_TIM, Para);
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-
- if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
- SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
- &SkRlmtMcAddr)) != NULL) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- break;
-
- case SK_PACKET_ADDR_CHANGED:
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Address Change.\n"))
-
- /* Build the check chain. */
- SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
-
- /* RA;:;: ??? */
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- }
- }
- else if (pSPacket->DSap == SK_RLMT_SPT_DSAP &&
- pSPacket->Ctrl == SK_RLMT_SPT_CTRL &&
- (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: BPDU Packet.\n"))
-
- /* Spanning Tree packet. */
- pRPort->RxSpHelloCts++;
-
- if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt.
- Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) {
- /*
- * Check segmentation if a new root bridge is set and
- * the segmentation check is not currently running.
- */
- if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) &&
- (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
- (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG)
- != 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState &
- SK_RLMT_RCS_SEG) == 0) {
- pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
- SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
- }
-
- /* Store tree view of this port. */
- for (i = 0; i < 8; i++) {
- pRPort->Root.Id[i] = pSPacket->RootId[i];
- }
- pRPort->RootIdSet = SK_TRUE;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
- ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
- PortNumber,
- pRPort->Root.Id[0], pRPort->Root.Id[1],
- pRPort->Root.Id[2], pRPort->Root.Id[3],
- pRPort->Root.Id[4], pRPort->Root.Id[5],
- pRPort->Root.Id[6], pRPort->Root.Id[7]))
- }
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState &
- SK_RLMT_RCS_REPORT_SEG) != 0) {
- SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber);
- }
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Unknown Packet Type.\n"))
-
- /* Unknown packet. */
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- }
- return;
-} /* SkRlmtPacketReceive */
-
-
-/******************************************************************************
- *
- * SkRlmtCheckPort - check if a port works
- *
- * Description:
- * This routine checks if a port whose link is up received something
- * and if it seems to transmit successfully.
- *
- * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
- * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
- * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
- *
- * if (Rx - RxBpdu == 0) { # No rx.
- * if (state == PsUp) {
- * PortCheckingState |= ChkRx
- * }
- * if (ModeCheckSeg && (Timeout ==
- * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
- * RlmtCheckingState |= ChkSeg)
- * PortCheckingState |= ChkSeg
- * }
- * NewTimeout = TO_SHORTEN(Timeout)
- * if (NewTimeout < RLMT_MIN_TIMEOUT) {
- * NewTimeout = RLMT_MIN_TIMEOUT
- * PortState = PsDown
- * ...
- * }
- * }
- * else { # something was received
- * # Set counter to 0 at LinkDown?
- * # No - rx may be reported after LinkDown ???
- * PortCheckingState &= ~ChkRx
- * NewTimeout = RLMT_DEFAULT_TIMEOUT
- * if (RxAck == 0) {
- * possible reasons:
- * is my tx line bad? --
- * send RLMT multicast and report
- * back internally? (only possible
- * between ports on same adapter)
- * }
- * if (RxChk == 0) {
- * possible reasons:
- * - tx line of port set to check me
- * maybe bad
- * - no other port/adapter available or set
- * to check me
- * - adapter checking me has a longer
- * timeout
- * ??? anything that can be done here?
- * }
- * }
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * New timeout value.
- */
-RLMT_STATIC SK_U32 SkRlmtCheckPort(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Port to check */
-{
- unsigned i;
- SK_U32 NewTimeout;
- SK_RLMT_PORT *pRPort;
- SK_EVPARA Para;
-
- pRPort = &pAC->Rlmt.Port[PortNumber];
-
- if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
- PortNumber, pRPort->PacketsPerTimeSlot))
-
- /*
- * Check segmentation if there was no receive at least twice
- * in a row (PortNoRx is already set) and the segmentation
- * check is not currently running.
- */
-
- if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
- (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
- !(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) {
- pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
- SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
- pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX))
-
- if (pRPort->PortState != SK_RLMT_PS_DOWN) {
- NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue);
- if (NewTimeout < SK_RLMT_MIN_TO_VAL) {
- NewTimeout = SK_RLMT_MIN_TO_VAL;
- }
-
- if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
- Para.Para32[0] = PortNumber;
- pRPort->CheckingState |= SK_RLMT_PCS_RX;
-
- /*
- * What shall we do if the port checked by this one receives
- * our request frames? What's bad - our rx line or his tx line?
- */
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->DownRxTimer,
- SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
- SK_RLMT_PORTDOWN_RX_TIM, Para);
-
- for (i = 0; i < pRPort->PortsChecked; i++) {
- if (pRPort->PortCheck[i].SuspectTx) {
- continue;
- }
- pRPort->PortCheck[i].SuspectTx = SK_TRUE;
- pRPort->PortsSuspect++;
- if ((Para.pParaPtr =
- SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX,
- &pAC->Addr.Port[PortNumber].CurrentMacAddress,
- &pRPort->PortCheck[i].CheckAddr)) != NULL) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- }
- }
- }
- else { /* PortDown -- or all partners suspect. */
- NewTimeout = SK_RLMT_DEF_TO_VAL;
- }
- pRPort->PortNoRx = SK_TRUE;
- }
- else { /* A non-BPDU packet was received. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
- PortNumber,
- pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot,
- pRPort->PacketsPerTimeSlot))
-
- SkRlmtPortReceives(pAC, IoC, PortNumber);
- if (pAC->Rlmt.CheckSwitch) {
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- }
-
- NewTimeout = SK_RLMT_DEF_TO_VAL;
- }
-
- return (NewTimeout);
-} /* SkRlmtCheckPort */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
- *
- * Description:
- * This routine selects the port that received a broadcast frame
- * substantially later than all other ports.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectBcRx(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect) /* New active port */
-{
- SK_U64 BcTimeStamp;
- SK_U32 i;
- SK_BOOL PortFound;
-
- BcTimeStamp = 0; /* Not totally necessary, but feeling better. */
- PortFound = SK_FALSE;
-
- /* Select port with the latest TimeStamp. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
- i,
- pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx,
- *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32),
- *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)))
-
- if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) {
- if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) {
- BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp;
- *pSelect = i;
- PortFound = SK_TRUE;
- }
- }
- }
-
- if (PortFound) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Port %d received the last broadcast.\n", *pSelect))
-
- /* Look if another port's time stamp is similar. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (i == *pSelect) {
- continue;
- }
- if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx &&
- (pAC->Rlmt.Port[i].BcTimeStamp >
- BcTimeStamp - SK_RLMT_BC_DELTA ||
- pAC->Rlmt.Port[i].BcTimeStamp +
- SK_RLMT_BC_DELTA > BcTimeStamp)) {
- PortFound = SK_FALSE;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Port %d received a broadcast at a similar time.\n", i))
- break;
- }
- }
- }
-
-#ifdef DEBUG
- if (PortFound) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
- "latest broadcast (%u).\n",
- *pSelect,
- BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp))
- }
-#endif /* DEBUG */
-
- return (PortFound);
-} /* SkRlmtSelectBcRx */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
- *
- * Description:
- * This routine selects a good port (it is PortUp && !SuspectRx).
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectNotSuspect(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect) /* New active port */
-{
- SK_U32 i;
- SK_BOOL PortFound;
-
- PortFound = SK_FALSE;
-
- /* Select first port that is PortUp && !SuspectRx. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Rlmt.Port[i].PortDown &&
- !(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) {
- *pSelect = i;
- if (!pAC->Rlmt.Port[Active].PortDown &&
- !(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) {
- *pSelect = Active;
- }
- if (!pAC->Rlmt.Port[PrefPort].PortDown &&
- !(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) {
- *pSelect = PrefPort;
- }
- PortFound = SK_TRUE;
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
- *pSelect))
- break;
- }
- }
- return (PortFound);
-} /* SkRlmtSelectNotSuspect */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
- *
- * Description:
- * This routine selects a port that is up.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectUp(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect, /* New active port */
-SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */
-{
- SK_U32 i;
- SK_BOOL PortFound;
-
- PortFound = SK_FALSE;
-
- /* Select first port that is PortUp. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP &&
- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
- *pSelect = i;
- if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP &&
- pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
- *pSelect = Active;
- }
- if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP &&
- pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
- *pSelect = PrefPort;
- }
- PortFound = SK_TRUE;
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect))
- break;
- }
- }
- return (PortFound);
-} /* SkRlmtSelectUp */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
- *
- * Description:
- * This routine selects the port that is going up for the longest time.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect, /* New active port */
-SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */
-{
- SK_U64 GuTimeStamp;
- SK_U32 i;
- SK_BOOL PortFound;
-
- GuTimeStamp = 0;
- PortFound = SK_FALSE;
-
- /* Select port that is PortGoingUp for the longest time. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
- GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
- *pSelect = i;
- PortFound = SK_TRUE;
- break;
- }
- }
-
- if (!PortFound) {
- return (SK_FALSE);
- }
-
- for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
- pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp &&
- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
- GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
- *pSelect = i;
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect))
- return (SK_TRUE);
-} /* SkRlmtSelectGoingUp */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
- *
- * Description:
- * This routine selects a port that is down.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectDown(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect, /* New active port */
-SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */
-{
- SK_U32 i;
- SK_BOOL PortFound;
-
- PortFound = SK_FALSE;
-
- /* Select first port that is PortDown. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN &&
- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
- *pSelect = i;
- if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN &&
- pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
- *pSelect = Active;
- }
- if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN &&
- pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
- *pSelect = PrefPort;
- }
- PortFound = SK_TRUE;
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect))
- break;
- }
- }
- return (PortFound);
-} /* SkRlmtSelectDown */
-
-
-/******************************************************************************
- *
- * SkRlmtCheckSwitch - select new active port and switch to it
- *
- * Description:
- * This routine decides which port should be the active one and queues
- * port switching if necessary.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtCheckSwitch(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 NetIdx) /* Net index */
-{
- SK_EVPARA Para;
- SK_U32 Active;
- SK_U32 PrefPort;
- SK_U32 i;
- SK_BOOL PortFound;
-
- Active = pAC->Rlmt.Net[NetIdx].ActivePort; /* Index of active port. */
- PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort; /* Index of preferred port. */
- PortFound = SK_FALSE;
- pAC->Rlmt.CheckSwitch = SK_FALSE;
-
-#if 0 /* RW 2001/10/18 - active port becomes always prefered one */
- if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */
- /* disable auto-fail back */
- PrefPort = Active;
- }
-#endif
-
- if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) {
- /* Last link went down - shut down the net. */
- pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN;
- Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP;
- Para.Para32[1] = NetIdx;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para);
-
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
- Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
- Para.Para32[1] = NetIdx;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
- return;
- } /* pAC->Rlmt.LinksUp == 0 */
- else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 &&
- pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) {
- /* First link came up - get the net up. */
- pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP;
-
- /*
- * If pAC->Rlmt.ActivePort != Para.Para32[0],
- * the DRV switches to the port that came up.
- */
- for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
- if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
- if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) {
- i = Active;
- }
- if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) {
- i = PrefPort;
- }
- PortFound = SK_TRUE;
- break;
- }
- }
-
- if (PortFound) {
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
- Para.Para32[1] = NetIdx;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
-
- pAC->Rlmt.Net[NetIdx].ActivePort = i;
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
- Para.Para32[1] = NetIdx;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
-
- if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
- (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
- pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
- SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
- CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
- /*
- * Send announce packet to RLMT multicast address to force
- * switches to learn the new location of the logical MAC address.
- */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG);
- }
-
- return;
- } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
- else { /* Cannot be reached in dual-net mode. */
- Para.Para32[0] = Active;
-
- /*
- * Preselection:
- * If RLMT Mode != CheckLinkState
- * select port that received a broadcast frame substantially later
- * than all other ports
- * else select first port that is not SuspectRx
- * else select first port that is PortUp
- * else select port that is PortGoingUp for the longest time
- * else select first port that is PortDown
- * else stop.
- *
- * For the preselected port:
- * If ActivePort is equal in quality, select ActivePort.
- *
- * If PrefPort is equal in quality, select PrefPort.
- *
- * If ActivePort != SelectedPort,
- * If old ActivePort is LinkDown,
- * SwitchHard
- * else
- * SwitchSoft
- */
- /* check of ChgBcPrio flag added */
- if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
- (!pAC->Rlmt.Net[0].ChgBcPrio)) {
-
- if (!PortFound) {
- PortFound = SkRlmtSelectBcRx(
- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectNotSuspect(
- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
- }
- } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
- /* with changed priority for last broadcast received */
- if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
- (pAC->Rlmt.Net[0].ChgBcPrio)) {
- if (!PortFound) {
- PortFound = SkRlmtSelectNotSuspect(
- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectBcRx(
- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
- }
- } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
- if (!PortFound) {
- PortFound = SkRlmtSelectUp(
- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectUp(
- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectGoingUp(
- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectGoingUp(
- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
- }
-
- if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) {
- if (!PortFound) {
- PortFound = SkRlmtSelectDown(pAC, IoC,
- Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectDown(pAC, IoC,
- Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
- }
- } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
- if (PortFound) {
-
- if (Para.Para32[1] != Active) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Active: %d, Para1: %d.\n", Active, Para.Para32[1]))
- pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1];
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
- Port[Para.Para32[0]]->PortNumber;
- Para.Para32[1] = pAC->Rlmt.Net[NetIdx].
- Port[Para.Para32[1]]->PortNumber;
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE);
- if (pAC->Rlmt.Port[Active].LinkDown) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para);
- }
- else {
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para);
- }
- Para.Para32[1] = NetIdx;
- Para.Para32[0] =
- pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
- Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
- if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
- (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0],
- SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress,
- &SkRlmtMcAddr)) != NULL) {
- /*
- * Send announce packet to RLMT multicast address to force
- * switches to learn the new location of the logical
- * MAC address.
- */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
- } /* Para.Para32[1] != Active */
- } /* PortFound */
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG);
- }
- } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
- return;
-} /* SkRlmtCheckSwitch */
-
-
-/******************************************************************************
- *
- * SkRlmtCheckSeg - Report if segmentation is detected
- *
- * Description:
- * This routine checks if the ports see different root bridges and reports
- * segmentation in such a case.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtCheckSeg(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 NetIdx) /* Net number */
-{
- SK_EVPARA Para;
- SK_RLMT_NET *pNet;
- SK_U32 i, j;
- SK_BOOL Equal;
-
- pNet = &pAC->Rlmt.Net[NetIdx];
- pNet->RootIdSet = SK_FALSE;
- Equal = SK_TRUE;
-
- for (i = 0; i < pNet->NumPorts; i++) {
- if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) {
- continue;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
- ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i,
- pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1],
- pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3],
- pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5],
- pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]))
-
- if (!pNet->RootIdSet) {
- pNet->Root = pNet->Port[i]->Root;
- pNet->RootIdSet = SK_TRUE;
- continue;
- }
-
- for (j = 0; j < 8; j ++) {
- Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j];
- if (!Equal) {
- break;
- }
- }
-
- if (!Equal) {
- SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG);
- Para.Para32[0] = NetIdx;
- Para.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para);
-
- pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG;
-
- /* 2000-03-06 RA: New. */
- Para.Para32[0] = NetIdx;
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL,
- SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
- break;
- }
- } /* for (i = 0; i < pNet->NumPorts; i++) */
-
- /* 2000-03-06 RA: Moved here. */
- /* Segmentation check not running anymore. */
- pNet->CheckingState &= ~SK_RLMT_RCS_SEG;
-
-} /* SkRlmtCheckSeg */
-
-
-/******************************************************************************
- *
- * SkRlmtPortStart - initialize port variables and start port
- *
- * Description:
- * This routine initializes a port's variables and issues a PORT_START
- * to the HWAC module. This handles retries if the start fails or the
- * link eventually goes down.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtPortStart(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Port number */
-{
- SK_EVPARA Para;
-
- pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN;
- pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE;
- pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE;
- pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE;
- pAC->Rlmt.Port[PortNumber].CheckingState = 0;
- pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
- Para.Para32[0] = PortNumber;
- Para.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-} /* SkRlmtPortStart */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPortStartTim - PORT_START_TIM
- *
- * Description:
- * This routine handles PORT_START_TIM events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPortStartTim(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
-{
- SK_U32 i;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
- return;
- }
-
- /*
- * Used to start non-preferred ports if the preferred one
- * does not come up.
- * This timeout needs only be set when starting the first
- * (preferred) port.
- */
- if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
- /* PORT_START failed. */
- for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) {
- if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) {
- SkRlmtPortStart(pAC, IoC,
- pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber);
- }
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
-} /* SkRlmtEvtPortStartTim */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtLinkUp - LINK_UP
- *
- * Description:
- * This routine handles LLINK_UP events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtLinkUp(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */
-{
- SK_U32 i;
- SK_RLMT_PORT *pRPort;
- SK_EVPARA Para2;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]))
-
- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
- if (!pRPort->PortStarted) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_UP Event EMPTY.\n"))
- return;
- }
-
- if (!pRPort->LinkDown) {
- /* RA;:;: Any better solution? */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_UP Event EMPTY.\n"))
- return;
- }
-
- SkTimerStop(pAC, IoC, &pRPort->UpTimer);
- SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
- /* Do something if timer already fired? */
-
- pRPort->LinkDown = SK_FALSE;
- pRPort->PortState = SK_RLMT_PS_GOING_UP;
- pRPort->GuTimeStamp = SkOsGetTime(pAC);
- pRPort->BcTimeStamp = 0;
- pRPort->Net->LinksUp++;
- if (pRPort->Net->LinksUp == 1) {
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE);
- }
- else {
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
- }
-
- for (i = 0; i < pRPort->Net->NumPorts; i++) {
- if (!pRPort->Net->Port[i]->PortStarted) {
- SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber);
- }
- }
-
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-
- if (pRPort->Net->LinksUp >= 2) {
- if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
- /* Build the check chain. */
- SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
- }
- }
-
- /* If the first link comes up, start the periodical RLMT timeout. */
- if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 &&
- (pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) {
- Para2.Para32[0] = pRPort->Net->NetNumber;
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer,
- pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2);
- }
-
- Para2 = Para;
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
- SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2);
-
- /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
- if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
- (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
- (Para2.pParaPtr =
- SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
- &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
- ) != NULL) {
- /* Send "new" packet to RLMT multicast address. */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
- }
-
- if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) {
- if ((Para2.pParaPtr =
- SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) {
- pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE;
- pRPort->Net->CheckingState |=
- SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
-
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer,
- SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_UP Event END.\n"))
-} /* SkRlmtEvtLinkUp */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPortUpTim - PORT_UP_TIM
- *
- * Description:
- * This routine handles PORT_UP_TIM events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPortUpTim(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
-{
- SK_RLMT_PORT *pRPort;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
- return;
- }
-
- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
- if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]))
- return;
- }
-
- pRPort->PortDown = SK_FALSE;
- pRPort->PortState = SK_RLMT_PS_UP;
- pRPort->Net->PortsUp++;
- if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
- if (pAC->Rlmt.NumNets <= 1) {
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- }
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTUP_TIM Event END.\n"))
-} /* SkRlmtEvtPortUpTim */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPortDownTim - PORT_DOWN_*
- *
- * Description:
- * This routine handles PORT_DOWN_* events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPortDownX(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Event, /* Event code */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
-{
- SK_RLMT_PORT *pRPort;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
- Para.Para32[0], Event))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
- return;
- }
-
- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
- if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM &&
- !(pRPort->CheckingState & SK_RLMT_PCS_TX))) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event))
- return;
- }
-
- /* Stop port's timers. */
- SkTimerStop(pAC, IoC, &pRPort->UpTimer);
- SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
- if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) {
- pRPort->PortState = SK_RLMT_PS_DOWN;
- }
-
- if (!pRPort->PortDown) {
- pRPort->Net->PortsUp--;
- pRPort->PortDown = SK_TRUE;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para);
- }
-
- pRPort->PacketsPerTimeSlot = 0;
- /* pRPort->DataPacketsPerTimeSlot = 0; */
- pRPort->BpduPacketsPerTimeSlot = 0;
- pRPort->BcTimeStamp = 0;
-
- /*
- * RA;:;: To be checked:
- * - actions at RLMT_STOP: We should not switch anymore.
- */
- if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
- if (Para.Para32[0] ==
- pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) {
- /* Active Port went down. */
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event))
-} /* SkRlmtEvtPortDownX */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtLinkDown - LINK_DOWN
- *
- * Description:
- * This routine handles LINK_DOWN events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtLinkDown(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */
-{
- SK_RLMT_PORT *pRPort;
-
- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
- pRPort->Net->LinksUp--;
- pRPort->LinkDown = SK_TRUE;
- pRPort->PortState = SK_RLMT_PS_LINK_DOWN;
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF);
-
- if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) {
- /* Build the check chain. */
- SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
- }
-
- /* Ensure that port is marked down. */
- Para.Para32[1] = -1;
- (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_DOWN Event END.\n"))
-} /* SkRlmtEvtLinkDown */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPortAddr - PORT_ADDR
- *
- * Description:
- * This routine handles PORT_ADDR events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPortAddr(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
-{
- SK_U32 i, j;
- SK_RLMT_PORT *pRPort;
- SK_MAC_ADDR *pOldMacAddr;
- SK_MAC_ADDR *pNewMacAddr;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
- return;
- }
-
- /* Port's physical MAC address changed. */
- pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress;
- pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress;
-
- /*
- * NOTE: This is not scalable for solutions where ports are
- * checked remotely. There, we need to send an RLMT
- * address change packet - and how do we ensure delivery?
- */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- pRPort = &pAC->Rlmt.Port[i];
- for (j = 0; j < pRPort->PortsChecked; j++) {
- if (SK_ADDR_EQUAL(
- pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) {
- pRPort->PortCheck[j].CheckAddr = *pNewMacAddr;
- }
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORT_ADDR Event END.\n"))
-} /* SkRlmtEvtPortAddr */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtStart - START
- *
- * Description:
- * This routine handles START events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtStart(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_EVPARA Para2;
- SK_U32 PortIdx;
- SK_U32 PortNumber;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("All nets should have been started.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >=
- pAC->Rlmt.Net[Para.Para32[0]].NumPorts) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG);
-
- /* Change PrefPort to internal default. */
- Para2.Para32[0] = 0xFFFFFFFF;
- Para2.Para32[1] = Para.Para32[0];
- (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2);
- }
-
- PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort;
- PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber;
-
- pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0;
- pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0;
- pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0;
- pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN;
-
- /* Start preferred port. */
- SkRlmtPortStart(pAC, IoC, PortNumber);
-
- /* Start Timer (for first port only). */
- Para2.Para32[0] = PortNumber;
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer,
- SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2);
-
- pAC->Rlmt.NetsStarted++;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event END.\n"))
-} /* SkRlmtEvtStart */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtStop - STOP
- *
- * Description:
- * This routine handles STOP events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtStop(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_EVPARA Para2;
- SK_U32 PortNumber;
- SK_U32 i;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.NetsStarted == 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("All nets are stopped.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event EMPTY.\n"))
- return;
- }
-
- /* Stop RLMT timers. */
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer);
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer);
-
- /* Stop net. */
- pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT;
- pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE;
- Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL;
- Para2.Para32[1] = Para.Para32[0]; /* Net# */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2);
-
- /* Stop ports. */
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
- PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
- if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) {
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer);
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer);
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer);
-
- pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT;
- pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
- pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE;
- Para2.Para32[0] = PortNumber;
- Para2.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2);
- }
- }
-
- pAC->Rlmt.NetsStarted--;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event END.\n"))
-} /* SkRlmtEvtStop */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtTim - TIM
- *
- * Description:
- * This routine handles TIM events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtTim(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_RLMT_PORT *pRPort;
- SK_U32 Timeout;
- SK_U32 NewTimeout;
- SK_U32 PortNumber;
- SK_U32 i;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_TIM Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_TIM Event EMPTY.\n"))
- return;
- }
-
- if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 ||
- pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) {
- /* Mode changed or all links down: No more link checking. */
- return;
- }
-
-#if 0
- pAC->Rlmt.SwitchCheckCounter--;
- if (pAC->Rlmt.SwitchCheckCounter == 0) {
- pAC->Rlmt.SwitchCheckCounter;
- }
-#endif /* 0 */
-
- NewTimeout = SK_RLMT_DEF_TO_VAL;
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
- PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
- pRPort = &pAC->Rlmt.Port[PortNumber];
- if (!pRPort->LinkDown) {
- Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber);
- if (Timeout < NewTimeout) {
- NewTimeout = Timeout;
- }
-
- /*
- * These counters should be set to 0 for all ports before the
- * first frame is sent in the next loop.
- */
- pRPort->PacketsPerTimeSlot = 0;
- /* pRPort->DataPacketsPerTimeSlot = 0; */
- pRPort->BpduPacketsPerTimeSlot = 0;
- }
- }
- pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout;
-
- if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) {
- /*
- * If checking remote ports, also send packets if
- * (LinksUp == 1) &&
- * this port checks at least one (remote) port.
- */
-
- /*
- * Must be new loop, as SkRlmtCheckPort can request to
- * check segmentation when e.g. checking the last port.
- */
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
- if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) {
- SkRlmtSend(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber);
- }
- }
- }
-
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer,
- pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM,
- Para);
-
- if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 &&
- (pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) &&
- (pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) {
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer,
- SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
- pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG;
- pAC->Rlmt.Net[Para.Para32[0]].CheckingState |=
- SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_TIM Event END.\n"))
-} /* SkRlmtEvtTim */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtSegTim - SEG_TIM
- *
- * Description:
- * This routine handles SEG_TIM events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtSegTim(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
-#ifdef xDEBUG
- int j;
-#endif /* DEBUG */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SEG_TIM Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SEG_TIM Event EMPTY.\n"))
- return;
- }
-
-#ifdef xDEBUG
- for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) {
- SK_ADDR_PORT *pAPort;
- SK_U32 k;
- SK_U16 *InAddr;
- SK_U8 InAddr8[6];
-
- InAddr = (SK_U16 *)&InAddr8[0];
- pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort;
- for (k = 0; k < pAPort->NextExactMatchRlmt; k++) {
- /* Get exact match address k from port j. */
- XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
- XM_EXM(k), InAddr);
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n",
- k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
- InAddr8[0], InAddr8[1], InAddr8[2],
- InAddr8[3], InAddr8[4], InAddr8[5],
- pAPort->Exact[k].a[0], pAPort->Exact[k].a[1],
- pAPort->Exact[k].a[2], pAPort->Exact[k].a[3],
- pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]))
- }
- }
-#endif /* xDEBUG */
-
- SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SEG_TIM Event END.\n"))
-} /* SkRlmtEvtSegTim */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPacketRx - PACKET_RECEIVED
- *
- * Description:
- * This routine handles PACKET_RECEIVED events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPacketRx(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_MBUF *pMb */
-{
- SK_MBUF *pMb;
- SK_MBUF *pNextMb;
- SK_U32 NetNumber;
-
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
-
- /* Should we ignore frames during port switching? */
-
-#ifdef DEBUG
- pMb = Para.pParaPtr;
- if (pMb == NULL) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"))
- }
- else if (pMb->pNext != NULL) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("More than one mbuf or pMb->pNext not set.\n"))
- }
-#endif /* DEBUG */
-
- for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) {
- pNextMb = pMb->pNext;
- pMb->pNext = NULL;
-
- NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber;
- if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) {
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- }
- else {
- SkRlmtPacketReceive(pAC, IoC, pMb);
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PACKET_RECEIVED Event END.\n"))
-} /* SkRlmtEvtPacketRx */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtStatsClear - STATS_CLEAR
- *
- * Description:
- * This routine handles STATS_CLEAR events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtStatsClear(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_U32 i;
- SK_RLMT_PORT *pRPort;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
- return;
- }
-
- /* Clear statistics for logical and physical ports. */
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
- pRPort =
- &pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber];
- pRPort->TxHelloCts = 0;
- pRPort->RxHelloCts = 0;
- pRPort->TxSpHelloReqCts = 0;
- pRPort->RxSpHelloCts = 0;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_CLEAR Event END.\n"))
-} /* SkRlmtEvtStatsClear */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtStatsUpdate - STATS_UPDATE
- *
- * Description:
- * This routine handles STATS_UPDATE events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtStatsUpdate(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
- return;
- }
-
- /* Update statistics - currently always up-to-date. */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_UPDATE Event END.\n"))
-} /* SkRlmtEvtStatsUpdate */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPrefportChange - PREFPORT_CHANGE
- *
- * Description:
- * This routine handles PREFPORT_CHANGE events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPrefportChange(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[1]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
- return;
- }
-
- /* 0xFFFFFFFF == auto-mode. */
- if (Para.Para32[0] == 0xFFFFFFFF) {
- pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT;
- }
- else {
- if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
- return;
- }
-
- pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0];
- }
-
- pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0];
-
- if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
- SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
-} /* SkRlmtEvtPrefportChange */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtSetNets - SET_NETS
- *
- * Description:
- * This routine handles SET_NETS events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtSetNets(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */
-{
- int i;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS ||
- Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad number of nets: %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- /* Entering and leaving dual mode only allowed while nets are stopped. */
- if (pAC->Rlmt.NetsStarted > 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Changing dual mode only allowed while all nets are stopped.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] == 1) {
- if (pAC->Rlmt.NumNets > 1) {
- /* Clear logical MAC addr from second net's active port. */
- (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
- Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL);
- pAC->Rlmt.Net[1].NumPorts = 0;
- }
-
- pAC->Rlmt.NumNets = Para.Para32[0];
- for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
- pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
- pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
- pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */
- pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
- /* Just assuming. */
- pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
- pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
- pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
- pAC->Rlmt.Net[i].NetNumber = i;
- }
-
- pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0];
- pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("RLMT: Changed to one net with two ports.\n"))
- }
- else if (Para.Para32[0] == 2) {
- pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1];
- pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1;
- pAC->Rlmt.Net[0].NumPorts =
- pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts;
-
- pAC->Rlmt.NumNets = Para.Para32[0];
- for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
- pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
- pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
- pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */
- pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
- /* Just assuming. */
- pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
- pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
- pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-
- pAC->Rlmt.Net[i].NetNumber = i;
- }
-
- /* Set logical MAC addr on second net's active port. */
- (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
- Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL);
-
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("RLMT: Changed to two nets with one port each.\n"))
- }
- else {
- /* Not implemented for more than two nets. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SetNets not implemented for more than two nets.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event END.\n"))
-} /* SkRlmtSetNets */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtModeChange - MODE_CHANGE
- *
- * Description:
- * This routine handles MODE_CHANGE events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtModeChange(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */
-{
- SK_EVPARA Para2;
- SK_U32 i;
- SK_U32 PrevRlmtMode;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
-
- if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[1]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
- return;
- }
-
- Para.Para32[0] |= SK_RLMT_CHECK_LINK;
-
- if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) &&
- Para.Para32[0] != SK_RLMT_MODE_CLS) {
- pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS;
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Forced RLMT mode to CLS on single port net.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
- return;
- }
-
- /* Update RLMT mode. */
- PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode;
- pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0];
-
- if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) !=
- (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
- /* SK_RLMT_CHECK_LOC_LINK bit changed. */
- if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 &&
- pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 &&
- pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) {
- /* 20001207 RA: Was "PortsUp == 1". */
- Para2.Para32[0] = Para.Para32[1];
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer,
- pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue,
- SKGE_RLMT, SK_RLMT_TIM, Para2);
- }
- }
-
- if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) !=
- (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) {
- /* SK_RLMT_CHECK_SEG bit changed. */
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) {
- (void)SkAddrMcClear(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
- SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-
- /* Add RLMT MC address. */
- (void)SkAddrMcAdd(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
- &SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
- if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode &
- SK_RLMT_CHECK_SEG) != 0) {
- /* Add BPDU MC address. */
- (void)SkAddrMcAdd(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
- &BridgeMcAddr, SK_ADDR_PERMANENT);
-
- if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
- if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown &&
- (Para2.pParaPtr = SkRlmtBuildSpanningTreePacket(
- pAC, IoC, i)) != NULL) {
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet =
- SK_FALSE;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
- }
- }
- }
- (void)SkAddrMcUpdate(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber);
- } /* for ... */
-
- if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) {
- Para2.Para32[0] = Para.Para32[1];
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer,
- SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2);
- }
- } /* SK_RLMT_CHECK_SEG bit changed. */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_MODE_CHANGE Event END.\n"))
-} /* SkRlmtEvtModeChange */
-
-
-/******************************************************************************
- *
- * SkRlmtEvent - a PORT- or an RLMT-specific event happened
- *
- * Description:
- * This routine calls subroutines to handle PORT- and RLMT-specific events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * 0
- */
-int SkRlmtEvent(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Event, /* Event code */
-SK_EVPARA Para) /* Event-specific parameter */
-{
- switch (Event) {
-
- /* ----- PORT events ----- */
-
- case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */
- SkRlmtEvtPortStartTim(pAC, IoC, Para);
- break;
- case SK_RLMT_LINK_UP: /* From SIRQ. */
- SkRlmtEvtLinkUp(pAC, IoC, Para);
- break;
- case SK_RLMT_PORTUP_TIM: /* From RLMT via TIME. */
- SkRlmtEvtPortUpTim(pAC, IoC, Para);
- break;
- case SK_RLMT_PORTDOWN: /* From RLMT. */
- case SK_RLMT_PORTDOWN_RX_TIM: /* From RLMT via TIME. */
- case SK_RLMT_PORTDOWN_TX_TIM: /* From RLMT via TIME. */
- SkRlmtEvtPortDownX(pAC, IoC, Event, Para);
- break;
- case SK_RLMT_LINK_DOWN: /* From SIRQ. */
- SkRlmtEvtLinkDown(pAC, IoC, Para);
- break;
- case SK_RLMT_PORT_ADDR: /* From ADDR. */
- SkRlmtEvtPortAddr(pAC, IoC, Para);
- break;
-
- /* ----- RLMT events ----- */
-
- case SK_RLMT_START: /* From DRV. */
- SkRlmtEvtStart(pAC, IoC, Para);
- break;
- case SK_RLMT_STOP: /* From DRV. */
- SkRlmtEvtStop(pAC, IoC, Para);
- break;
- case SK_RLMT_TIM: /* From RLMT via TIME. */
- SkRlmtEvtTim(pAC, IoC, Para);
- break;
- case SK_RLMT_SEG_TIM:
- SkRlmtEvtSegTim(pAC, IoC, Para);
- break;
- case SK_RLMT_PACKET_RECEIVED: /* From DRV. */
- SkRlmtEvtPacketRx(pAC, IoC, Para);
- break;
- case SK_RLMT_STATS_CLEAR: /* From PNMI. */
- SkRlmtEvtStatsClear(pAC, IoC, Para);
- break;
- case SK_RLMT_STATS_UPDATE: /* From PNMI. */
- SkRlmtEvtStatsUpdate(pAC, IoC, Para);
- break;
- case SK_RLMT_PREFPORT_CHANGE: /* From PNMI. */
- SkRlmtEvtPrefportChange(pAC, IoC, Para);
- break;
- case SK_RLMT_MODE_CHANGE: /* From PNMI. */
- SkRlmtEvtModeChange(pAC, IoC, Para);
- break;
- case SK_RLMT_SET_NETS: /* From DRV. */
- SkRlmtEvtSetNets(pAC, IoC, Para);
- break;
-
- /* ----- Unknown events ----- */
-
- default: /* Create error log entry. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Unknown RLMT Event %d.\n", Event))
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG);
- break;
- } /* switch() */
-
- return (0);
-} /* SkRlmtEvent */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c
deleted file mode 100644
index 4e462955ecd..00000000000
--- a/drivers/net/sk98lin/sktimer.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/******************************************************************************
- *
- * Name: sktimer.c
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.14 $
- * Date: $Date: 2003/09/16 13:46:51 $
- * Purpose: High level timer functions.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- * Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- Event queue management.
-
- General Description:
-
- */
-intro()
-{}
-#endif
-
-
-/* Forward declaration */
-static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
-
-
-/*
- * Inits the software timer
- *
- * needs to be called during Init level 1.
- */
-void SkTimerInit(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-int Level) /* Init Level */
-{
- switch (Level) {
- case SK_INIT_DATA:
- pAC->Tim.StQueue = NULL;
- break;
- case SK_INIT_IO:
- SkHwtInit(pAC, Ioc);
- SkTimerDone(pAC, Ioc);
- break;
- default:
- break;
- }
-}
-
-/*
- * Stops a high level timer
- * - If a timer is not in the queue the function returns normally, too.
- */
-void SkTimerStop(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-SK_TIMER *pTimer) /* Timer Pointer to be started */
-{
- SK_TIMER **ppTimPrev;
- SK_TIMER *pTm;
-
- /*
- * remove timer from queue
- */
- pTimer->TmActive = SK_FALSE;
-
- if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
- SkHwtStop(pAC, Ioc);
- }
-
- for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
- ppTimPrev = &pTm->TmNext ) {
-
- if (pTm == pTimer) {
- /*
- * Timer found in queue
- * - dequeue it and
- * - correct delta of the next timer
- */
- *ppTimPrev = pTm->TmNext;
-
- if (pTm->TmNext) {
- /* correct delta of next timer in queue */
- pTm->TmNext->TmDelta += pTm->TmDelta;
- }
- return;
- }
- }
-}
-
-/*
- * Start a high level software timer
- */
-void SkTimerStart(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-SK_TIMER *pTimer, /* Timer Pointer to be started */
-SK_U32 Time, /* Time value */
-SK_U32 Class, /* Event Class for this timer */
-SK_U32 Event, /* Event Value for this timer */
-SK_EVPARA Para) /* Event Parameter for this timer */
-{
- SK_TIMER **ppTimPrev;
- SK_TIMER *pTm;
- SK_U32 Delta;
-
- Time /= 16; /* input is uS, clock ticks are 16uS */
-
- if (!Time)
- Time = 1;
-
- SkTimerStop(pAC, Ioc, pTimer);
-
- pTimer->TmClass = Class;
- pTimer->TmEvent = Event;
- pTimer->TmPara = Para;
- pTimer->TmActive = SK_TRUE;
-
- if (!pAC->Tim.StQueue) {
- /* First Timer to be started */
- pAC->Tim.StQueue = pTimer;
- pTimer->TmNext = NULL;
- pTimer->TmDelta = Time;
-
- SkHwtStart(pAC, Ioc, Time);
-
- return;
- }
-
- /*
- * timer correction
- */
- timer_done(pAC, Ioc, 0);
-
- /*
- * find position in queue
- */
- Delta = 0;
- for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
- ppTimPrev = &pTm->TmNext ) {
-
- if (Delta + pTm->TmDelta > Time) {
- /* Position found */
- /* Here the timer needs to be inserted. */
- break;
- }
- Delta += pTm->TmDelta;
- }
-
- /* insert in queue */
- *ppTimPrev = pTimer;
- pTimer->TmNext = pTm;
- pTimer->TmDelta = Time - Delta;
-
- if (pTm) {
- /* There is a next timer
- * -> correct its Delta value.
- */
- pTm->TmDelta -= pTimer->TmDelta;
- }
-
- /* restart with first */
- SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
-}
-
-
-void SkTimerDone(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- timer_done(pAC, Ioc, 1);
-}
-
-
-static void timer_done(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-int Restart) /* Do we need to restart the Hardware timer ? */
-{
- SK_U32 Delta;
- SK_TIMER *pTm;
- SK_TIMER *pTComp; /* Timer completed now now */
- SK_TIMER **ppLast; /* Next field of Last timer to be deq */
- int Done = 0;
-
- Delta = SkHwtRead(pAC, Ioc);
-
- ppLast = &pAC->Tim.StQueue;
- pTm = pAC->Tim.StQueue;
- while (pTm && !Done) {
- if (Delta >= pTm->TmDelta) {
- /* Timer ran out */
- pTm->TmActive = SK_FALSE;
- Delta -= pTm->TmDelta;
- ppLast = &pTm->TmNext;
- pTm = pTm->TmNext;
- }
- else {
- /* We found the first timer that did not run out */
- pTm->TmDelta -= Delta;
- Delta = 0;
- Done = 1;
- }
- }
- *ppLast = NULL;
- /*
- * pTm points to the first Timer that did not run out.
- * StQueue points to the first Timer that run out.
- */
-
- for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
- SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
- }
-
- /* Set head of timer queue to the first timer that did not run out */
- pAC->Tim.StQueue = pTm;
-
- if (Restart && pAC->Tim.StQueue) {
- /* Restart HW timer */
- SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
- }
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c
deleted file mode 100644
index 1e662aaebf8..00000000000
--- a/drivers/net/sk98lin/skvpd.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/******************************************************************************
- *
- * Name: skvpd.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.37 $
- * Date: $Date: 2003/01/13 10:42:45 $
- * Purpose: Shared software to read and write VPD data
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2003 SysKonnect GmbH.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- Please refer skvpd.txt for information how to include this module
- */
-static const char SysKonnectFileId[] =
- "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/skdebug.h"
-#include "h/skdrv2nd.h"
-
-/*
- * Static functions
- */
-#ifndef SK_KR_PROTO
-static SK_VPD_PARA *vpd_find_para(
- SK_AC *pAC,
- const char *key,
- SK_VPD_PARA *p);
-#else /* SK_KR_PROTO */
-static SK_VPD_PARA *vpd_find_para();
-#endif /* SK_KR_PROTO */
-
-/*
- * waits for a completion of a VPD transfer
- * The VPD transfer must complete within SK_TICKS_PER_SEC/16
- *
- * returns 0: success, transfer completes
- * error exit(9) with a error message
- */
-static int VpdWait(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-int event) /* event to wait for (VPD_READ / VPD_write) completion*/
-{
- SK_U64 start_time;
- SK_U16 state;
-
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD wait for %s\n", event?"Write":"Read"));
- start_time = SkOsGetTime(pAC);
- do {
- if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
-
- /* Bug fix AF: Thu Mar 28 2002
- * Do not call: VPD_STOP(pAC, IoC);
- * A pending VPD read cycle can not be aborted by writing
- * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
- * Although the write threshold in the OUR-register protects
- * VPD read only space from being overwritten this does not
- * protect a VPD read from being `converted` into a VPD write
- * operation (on the fly). As a consequence the VPD_STOP would
- * delete VPD read only data. In case of any problems with the
- * I2C bus we exit the loop here. The I2C read operation can
- * not be aborted except by a reset (->LR).
- */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
- ("ERROR:VPD wait timeout\n"));
- return(1);
- }
-
- VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("state = %x, event %x\n",state,event));
- } while((int)(state & PCI_VPD_FLAG) == event);
-
- return(0);
-}
-
-#ifdef SKDIAG
-
-/*
- * Read the dword at address 'addr' from the VPD EEPROM.
- *
- * Needed Time: MIN 1,3 ms MAX 2,6 ms
- *
- * Note: The DWord is returned in the endianess of the machine the routine
- * is running on.
- *
- * Returns the data read.
- */
-SK_U32 VpdReadDWord(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-int addr) /* VPD address */
-{
- SK_U32 Rtv;
-
- /* start VPD read */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD read dword at 0x%x\n",addr));
- addr &= ~VPD_WRITE; /* ensure the R/W bit is set to read */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
-
- /* ignore return code here */
- (void)VpdWait(pAC, IoC, VPD_READ);
-
- /* Don't swap here, it's a data stream of bytes */
- Rtv = 0;
-
- VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD read dword data = 0x%x\n",Rtv));
- return(Rtv);
-}
-
-#endif /* SKDIAG */
-
-/*
- * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- * or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdWriteStream(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-char *buf, /* data buffer */
-int Addr, /* VPD start address */
-int Len) /* number of bytes to read / to write */
-{
- int i;
- int j;
- SK_U16 AdrReg;
- int Rtv;
- SK_U8 * pComp; /* Compare pointer */
- SK_U8 Data; /* Input Data for Compare */
-
- /* Init Compare Pointer */
- pComp = (SK_U8 *) buf;
-
- for (i = 0; i < Len; i++, buf++) {
- if ((i%sizeof(SK_U32)) == 0) {
- /*
- * At the begin of each cycle read the Data Reg
- * So it is initialized even if only a few bytes
- * are written.
- */
- AdrReg = (SK_U16) Addr;
- AdrReg &= ~VPD_WRITE; /* READ operation */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
- /* Wait for termination */
- Rtv = VpdWait(pAC, IoC, VPD_READ);
- if (Rtv != 0) {
- return(i);
- }
- }
-
- /* Write current Byte */
- VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
- *(SK_U8*)buf);
-
- if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
- /* New Address needs to be written to VPD_ADDR reg */
- AdrReg = (SK_U16) Addr;
- Addr += sizeof(SK_U32);
- AdrReg |= VPD_WRITE; /* WRITE operation */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
- /* Wait for termination */
- Rtv = VpdWait(pAC, IoC, VPD_WRITE);
- if (Rtv != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("Write Timed Out\n"));
- return(i - (i%sizeof(SK_U32)));
- }
-
- /*
- * Now re-read to verify
- */
- AdrReg &= ~VPD_WRITE; /* READ operation */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
- /* Wait for termination */
- Rtv = VpdWait(pAC, IoC, VPD_READ);
- if (Rtv != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("Verify Timed Out\n"));
- return(i - (i%sizeof(SK_U32)));
- }
-
- for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
-
- VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
-
- if (Data != *pComp) {
- /* Verify Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("WriteStream Verify Error\n"));
- return(i - (i%sizeof(SK_U32)) + j);
- }
- }
- }
- }
-
- return(Len);
-}
-
-
-/*
- * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- * or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdReadStream(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-char *buf, /* data buffer */
-int Addr, /* VPD start address */
-int Len) /* number of bytes to read / to write */
-{
- int i;
- SK_U16 AdrReg;
- int Rtv;
-
- for (i = 0; i < Len; i++, buf++) {
- if ((i%sizeof(SK_U32)) == 0) {
- /* New Address needs to be written to VPD_ADDR reg */
- AdrReg = (SK_U16) Addr;
- Addr += sizeof(SK_U32);
- AdrReg &= ~VPD_WRITE; /* READ operation */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
- /* Wait for termination */
- Rtv = VpdWait(pAC, IoC, VPD_READ);
- if (Rtv != 0) {
- return(i);
- }
- }
- VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
- (SK_U8 *)buf);
- }
-
- return(Len);
-}
-
-/*
- * Read ore writes 'len' bytes of VPD data, starting at 'addr' from
- * or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdTransferBlock(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-char *buf, /* data buffer */
-int addr, /* VPD start address */
-int len, /* number of bytes to read / to write */
-int dir) /* transfer direction may be VPD_READ or VPD_WRITE */
-{
- int Rtv; /* Return value */
- int vpd_rom_size;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD %s block, addr = 0x%x, len = %d\n",
- dir ? "write" : "read", addr, len));
-
- if (len == 0)
- return(0);
-
- vpd_rom_size = pAC->vpd.rom_size;
-
- if (addr > vpd_rom_size - 4) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Address error: 0x%x, exp. < 0x%x\n",
- addr, vpd_rom_size - 4));
- return(0);
- }
-
- if (addr + len > vpd_rom_size) {
- len = vpd_rom_size - addr;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("Warning: len was cut to %d\n", len));
- }
-
- if (dir == VPD_READ) {
- Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
- }
- else {
- Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
- }
-
- return(Rtv);
-}
-
-#ifdef SKDIAG
-
-/*
- * Read 'len' bytes of VPD data, starting at 'addr'.
- *
- * Returns number of bytes read.
- */
-int VpdReadBlock(
-SK_AC *pAC, /* pAC pointer */
-SK_IOC IoC, /* IO Context */
-char *buf, /* buffer were the data should be stored */
-int addr, /* start reading at the VPD address */
-int len) /* number of bytes to read */
-{
- return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
-}
-
-/*
- * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
- *
- * Returns number of bytes writes.
- */
-int VpdWriteBlock(
-SK_AC *pAC, /* pAC pointer */
-SK_IOC IoC, /* IO Context */
-char *buf, /* buffer, holds the data to write */
-int addr, /* start writing at the VPD address */
-int len) /* number of bytes to write */
-{
- return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
-}
-#endif /* SKDIAG */
-
-/*
- * (re)initialize the VPD buffer
- *
- * Reads the VPD data from the EEPROM into the VPD buffer.
- * Get the remaining read only and read / write space.
- *
- * return 0: success
- * 1: fatal VPD error
- */
-static int VpdInit(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC) /* IO Context */
-{
- SK_VPD_PARA *r, rp; /* RW or RV */
- int i;
- unsigned char x;
- int vpd_size;
- SK_U16 dev_id;
- SK_U32 our_reg2;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
-
- VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
-
- VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
-
- pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
-
- /*
- * this function might get used before the hardware is initialized
- * therefore we cannot always trust in GIChipId
- */
- if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
- dev_id != VPD_DEV_ID_GENESIS) ||
- ((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
- !pAC->GIni.GIGenesis)) {
-
- /* for Yukon the VPD size is always 256 */
- vpd_size = VPD_SIZE_YUKON;
- }
- else {
- /* Genesis uses the maximum ROM size up to 512 for VPD */
- if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
- vpd_size = VPD_SIZE_GENESIS;
- }
- else {
- vpd_size = pAC->vpd.rom_size;
- }
- }
-
- /* read the VPD data into the VPD buffer */
- if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ)
- != vpd_size) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("Block Read Error\n"));
- return(1);
- }
-
- pAC->vpd.vpd_size = vpd_size;
-
- /* Asus K8V Se Deluxe bugfix. Correct VPD content */
- /* MBo April 2004 */
- if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) &&
- ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
- ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) {
- printk("sk98lin: Asus mainboard with buggy VPD? "
- "Correcting data.\n");
- pAC->vpd.vpd_buf[0x40] = 0x38;
- }
-
-
- /* find the end tag of the RO area */
- if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: RV Tag not found\n"));
- return(1);
- }
-
- if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: Invalid VPD struct size\n"));
- return(1);
- }
- pAC->vpd.v.vpd_free_ro = r->p_len - 1;
-
- /* test the checksum */
- for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
- x += pAC->vpd.vpd_buf[i];
- }
-
- if (x != 0) {
- /* checksum error */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("VPD Checksum Error\n"));
- return(1);
- }
-
- /* find and check the end tag of the RW area */
- if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: RV Tag not found\n"));
- return(1);
- }
-
- if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: Invalid VPD struct size\n"));
- return(1);
- }
- pAC->vpd.v.vpd_free_rw = r->p_len;
-
- /* everything seems to be ok */
- if (pAC->GIni.GIChipId != 0) {
- pAC->vpd.v.vpd_status |= VPD_VALID;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
- ("done. Free RO = %d, Free RW = %d\n",
- pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
- return(0);
-}
-
-/*
- * find the Keyword 'key' in the VPD buffer and fills the
- * parameter struct 'p' with it's values
- *
- * returns *p success
- * 0: parameter was not found or VPD encoding error
- */
-static SK_VPD_PARA *vpd_find_para(
-SK_AC *pAC, /* common data base */
-const char *key, /* keyword to find (e.g. "MN") */
-SK_VPD_PARA *p) /* parameter description struct */
-{
- char *v ; /* points to VPD buffer */
- int max; /* Maximum Number of Iterations */
-
- v = pAC->vpd.vpd_buf;
- max = 128;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD find para %s .. ",key));
-
- /* check mandatory resource type ID string (Product Name) */
- if (*v != (char)RES_ID) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Error: 0x%x missing\n", RES_ID));
- return NULL;
- }
-
- if (strcmp(key, VPD_NAME) == 0) {
- p->p_len = VPD_GET_RES_LEN(v);
- p->p_val = VPD_GET_VAL(v);
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("found, len = %d\n", p->p_len));
- return(p);
- }
-
- v += 3 + VPD_GET_RES_LEN(v) + 3;
- for (;; ) {
- if (SK_MEMCMP(key,v,2) == 0) {
- p->p_len = VPD_GET_VPD_LEN(v);
- p->p_val = VPD_GET_VAL(v);
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("found, len = %d\n",p->p_len));
- return(p);
- }
-
- /* exit when reaching the "RW" Tag or the maximum of itera. */
- max--;
- if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
- break;
- }
-
- if (SK_MEMCMP(VPD_RV,v,2) == 0) {
- v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */
- }
- else {
- v += 3 + VPD_GET_VPD_LEN(v);
- }
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("scanning '%c%c' len = %d\n",v[0],v[1],v[2]));
- }
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
- if (max == 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Key/Len Encoding error\n"));
- }
-#endif /* DEBUG */
- return NULL;
-}
-
-/*
- * Move 'n' bytes. Begin with the last byte if 'n' is > 0,
- * Start with the last byte if n is < 0.
- *
- * returns nothing
- */
-static void vpd_move_para(
-char *start, /* start of memory block */
-char *end, /* end of memory block to move */
-int n) /* number of bytes the memory block has to be moved */
-{
- char *p;
- int i; /* number of byte copied */
-
- if (n == 0)
- return;
-
- i = (int) (end - start + 1);
- if (n < 0) {
- p = start + n;
- while (i != 0) {
- *p++ = *start++;
- i--;
- }
- }
- else {
- p = end + n;
- while (i != 0) {
- *p-- = *end--;
- i--;
- }
- }
-}
-
-/*
- * setup the VPD keyword 'key' at 'ip'.
- *
- * returns nothing
- */
-static void vpd_insert_key(
-const char *key, /* keyword to insert */
-const char *buf, /* buffer with the keyword value */
-int len, /* length of the value string */
-char *ip) /* inseration point */
-{
- SK_VPD_KEY *p;
-
- p = (SK_VPD_KEY *) ip;
- p->p_key[0] = key[0];
- p->p_key[1] = key[1];
- p->p_len = (unsigned char) len;
- SK_MEMCPY(&p->p_val,buf,len);
-}
-
-/*
- * Setup the VPD end tag "RV" / "RW".
- * Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
- *
- * returns 0: success
- * 1: encoding error
- */
-static int vpd_mod_endtag(
-SK_AC *pAC, /* common data base */
-char *etp) /* end pointer input position */
-{
- SK_VPD_KEY *p;
- unsigned char x;
- int i;
- int vpd_size;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1]));
-
- vpd_size = pAC->vpd.vpd_size;
-
- p = (SK_VPD_KEY *) etp;
-
- if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
- /* something wrong here, encoding error */
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: invalid end tag\n"));
- return(1);
- }
- if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
- /* create "RW" tag */
- p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
- pAC->vpd.v.vpd_free_rw = (int) p->p_len;
- i = pAC->vpd.v.vpd_free_rw;
- etp += 3;
- }
- else {
- /* create "RV" tag */
- p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
- pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
-
- /* setup checksum */
- for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
- x += pAC->vpd.vpd_buf[i];
- }
- p->p_val = (char) 0 - x;
- i = pAC->vpd.v.vpd_free_ro;
- etp += 4;
- }
- while (i) {
- *etp++ = 0x00;
- i--;
- }
-
- return(0);
-}
-
-/*
- * Insert a VPD keyword into the VPD buffer.
- *
- * The keyword 'key' is inserted at the position 'ip' in the
- * VPD buffer.
- * The keywords behind the input position will
- * be moved. The VPD end tag "RV" or "RW" is generated again.
- *
- * returns 0: success
- * 2: value string was cut
- * 4: VPD full, keyword was not written
- * 6: fatal VPD error
- *
- */
-static int VpdSetupPara(
-SK_AC *pAC, /* common data base */
-const char *key, /* keyword to insert */
-const char *buf, /* buffer with the keyword value */
-int len, /* length of the keyword value */
-int type, /* VPD_RO_KEY or VPD_RW_KEY */
-int op) /* operation to do: ADD_KEY or OWR_KEY */
-{
- SK_VPD_PARA vp;
- char *etp; /* end tag position */
- int free; /* remaining space in selected area */
- char *ip; /* input position inside the VPD buffer */
- int rtv; /* return code */
- int head; /* additional haeder bytes to move */
- int found; /* additinoal bytes if the keyword was found */
- int vpd_size;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD setup para key = %s, val = %s\n",key,buf));
-
- vpd_size = pAC->vpd.vpd_size;
-
- rtv = 0;
- ip = NULL;
- if (type == VPD_RW_KEY) {
- /* end tag is "RW" */
- free = pAC->vpd.v.vpd_free_rw;
- etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
- }
- else {
- /* end tag is "RV" */
- free = pAC->vpd.v.vpd_free_ro;
- etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
- }
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("Free RO = %d, Free RW = %d\n",
- pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
- head = 0;
- found = 0;
- if (op == OWR_KEY) {
- if (vpd_find_para(pAC, key, &vp)) {
- found = 3;
- ip = vp.p_val - 3;
- free += vp.p_len + 3;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("Overwrite Key\n"));
- }
- else {
- op = ADD_KEY;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("Add Key\n"));
- }
- }
- if (op == ADD_KEY) {
- ip = etp;
- vp.p_len = 0;
- head = 3;
- }
-
- if (len + 3 > free) {
- if (free < 7) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD Buffer Overflow, keyword not written\n"));
- return(4);
- }
- /* cut it again */
- len = free - 3;
- rtv = 2;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD Buffer Full, Keyword was cut\n"));
- }
-
- vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
- vpd_insert_key(key, buf, len, ip);
- if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
- pAC->vpd.v.vpd_status &= ~VPD_VALID;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD Encoding Error\n"));
- return(6);
- }
-
- return(rtv);
-}
-
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the
- * VPD buffer if not already done.
- *
- * return: A pointer to the vpd_status structure. The structure contains
- * this fields.
- */
-SK_VPD_STATUS *VpdStat(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC) /* IO Context */
-{
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- (void)VpdInit(pAC, IoC);
- }
- return(&pAC->vpd.v);
-}
-
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the VPD
- * buffer if not already done.
- * Scan the VPD buffer for VPD keywords and create the VPD
- * keyword list by copying the keywords to 'buf', all after
- * each other and terminated with a '\0'.
- *
- * Exceptions: o The Resource Type ID String (product name) is called "Name"
- * o The VPD end tags 'RV' and 'RW' are not listed
- *
- * The number of copied keywords is counted in 'elements'.
- *
- * returns 0: success
- * 2: buffer overfull, one or more keywords are missing
- * 6: fatal VPD error
- *
- * example values after returning:
- *
- * buf = "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
- * *len = 30
- * *elements = 9
- */
-int VpdKeys(
-SK_AC *pAC, /* common data base */
-SK_IOC IoC, /* IO Context */
-char *buf, /* buffer where to copy the keywords */
-int *len, /* buffer length */
-int *elements) /* number of keywords returned */
-{
- char *v;
- int n;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
- *elements = 0;
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- if (VpdInit(pAC, IoC) != 0) {
- *len = 0;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD Init Error, terminated\n"));
- return(6);
- }
- }
-
- if ((signed)strlen(VPD_NAME) + 1 <= *len) {
- v = pAC->vpd.vpd_buf;
- strcpy(buf,VPD_NAME);
- n = strlen(VPD_NAME) + 1;
- buf += n;
- *elements = 1;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
- ("'%c%c' ",v[0],v[1]));
- }
- else {
- *len = 0;
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
- ("buffer overflow\n"));
- return(2);
- }
-
- v += 3 + VPD_GET_RES_LEN(v) + 3;
- for (;; ) {
- /* exit when reaching the "RW" Tag */
- if (SK_MEMCMP(VPD_RW,v,2) == 0) {
- break;
- }
-
- if (SK_MEMCMP(VPD_RV,v,2) == 0) {
- v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */
- continue;
- }
-
- if (n+3 <= *len) {
- SK_MEMCPY(buf,v,2);
- buf += 2;
- *buf++ = '\0';
- n += 3;
- v += 3 + VPD_GET_VPD_LEN(v);
- *elements += 1;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
- ("'%c%c' ",v[0],v[1]));
- }
- else {
- *len = n;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("buffer overflow\n"));
- return(2);
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
- *len = n;
- return(0);
-}
-
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the
- * VPD buffer if not already done. Search for the VPD keyword
- * 'key' and copy its value to 'buf'. Add a terminating '\0'.
- * If the value does not fit into the buffer cut it after
- * 'len' - 1 bytes.
- *
- * returns 0: success
- * 1: keyword not found
- * 2: value string was cut
- * 3: VPD transfer timeout
- * 6: fatal VPD error
- */
-int VpdRead(
-SK_AC *pAC, /* common data base */
-SK_IOC IoC, /* IO Context */
-const char *key, /* keyword to read (e.g. "MN") */
-char *buf, /* buffer where to copy the keyword value */
-int *len) /* buffer length */
-{
- SK_VPD_PARA *p, vp;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- if (VpdInit(pAC, IoC) != 0) {
- *len = 0;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD init error\n"));
- return(6);
- }
- }
-
- if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
- if (p->p_len > (*(unsigned *)len)-1) {
- p->p_len = *len - 1;
- }
- SK_MEMCPY(buf, p->p_val, p->p_len);
- buf[p->p_len] = '\0';
- *len = p->p_len;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
- ("%c%c%c%c.., len = %d\n",
- buf[0],buf[1],buf[2],buf[3],*len));
- }
- else {
- *len = 0;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
- return(1);
- }
- return(0);
-}
-
-
-/*
- * Check whether a given key may be written
- *
- * returns
- * SK_TRUE Yes it may be written
- * SK_FALSE No it may be written
- */
-SK_BOOL VpdMayWrite(
-char *key) /* keyword to write (allowed values "Yx", "Vx") */
-{
- if ((*key != 'Y' && *key != 'V') ||
- key[1] < '0' || key[1] > 'Z' ||
- (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
- return(SK_FALSE);
- }
- return(SK_TRUE);
-}
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the VPD
- * buffer if not already done. Insert/overwrite the keyword 'key'
- * in the VPD buffer. Cut the keyword value if it does not fit
- * into the VPD read / write area.
- *
- * returns 0: success
- * 2: value string was cut
- * 3: VPD transfer timeout
- * 4: VPD full, keyword was not written
- * 5: keyword cannot be written
- * 6: fatal VPD error
- */
-int VpdWrite(
-SK_AC *pAC, /* common data base */
-SK_IOC IoC, /* IO Context */
-const char *key, /* keyword to write (allowed values "Yx", "Vx") */
-const char *buf) /* buffer where the keyword value can be read from */
-{
- int len; /* length of the keyword to write */
- int rtv; /* return code */
- int rtv2;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
- ("VPD write %s = %s\n",key,buf));
-
- if ((*key != 'Y' && *key != 'V') ||
- key[1] < '0' || key[1] > 'Z' ||
- (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("illegal key tag, keyword not written\n"));
- return(5);
- }
-
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- if (VpdInit(pAC, IoC) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD init error\n"));
- return(6);
- }
- }
-
- rtv = 0;
- len = strlen(buf);
- if (len > VPD_MAX_LEN) {
- /* cut it */
- len = VPD_MAX_LEN;
- rtv = 2;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
- }
- if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD write error\n"));
- return(rtv2);
- }
-
- return(rtv);
-}
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the
- * VPD buffer if not already done. Remove the VPD keyword
- * 'key' from the VPD buffer.
- * Only the keywords in the read/write area can be deleted.
- * Keywords in the read only area cannot be deleted.
- *
- * returns 0: success, keyword was removed
- * 1: keyword not found
- * 5: keyword cannot be deleted
- * 6: fatal VPD error
- */
-int VpdDelete(
-SK_AC *pAC, /* common data base */
-SK_IOC IoC, /* IO Context */
-char *key) /* keyword to read (e.g. "MN") */
-{
- SK_VPD_PARA *p, vp;
- char *etp;
- int vpd_size;
-
- vpd_size = pAC->vpd.vpd_size;
-
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- if (VpdInit(pAC, IoC) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD init error\n"));
- return(6);
- }
- }
-
- if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
- if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
- /* try to delete read only keyword */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("cannot delete RO keyword\n"));
- return(5);
- }
-
- etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
-
- vpd_move_para(vp.p_val+vp.p_len, etp+2,
- - ((int)(vp.p_len + 3)));
- if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
- pAC->vpd.v.vpd_status &= ~VPD_VALID;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD encoding error\n"));
- return(6);
- }
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("keyword not found\n"));
- return(1);
- }
-
- return(0);
-}
-
-/*
- * If the VPD buffer contains valid data write the VPD
- * read/write area back to the VPD EEPROM.
- *
- * returns 0: success
- * 3: VPD transfer timeout
- */
-int VpdUpdate(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC) /* IO Context */
-{
- int vpd_size;
-
- vpd_size = pAC->vpd.vpd_size;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
- if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
- if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
- vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("transfer timed out\n"));
- return(3);
- }
- }
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));
- return(0);
-}
-
diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
deleted file mode 100644
index b4e75022a65..00000000000
--- a/drivers/net/sk98lin/skxmac2.c
+++ /dev/null
@@ -1,4160 +0,0 @@
-/******************************************************************************
- *
- * Name: skxmac2.c
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.102 $
- * Date: $Date: 2003/10/02 16:53:58 $
- * Purpose: Contains functions to initialize the MACs and PHYs
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * 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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* typedefs *******************************************************************/
-
-/* BCOM PHY magic pattern list */
-typedef struct s_PhyHack {
- int PhyReg; /* Phy register */
- SK_U16 PhyVal; /* Value to write */
-} BCOM_HACK;
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#ifdef GENESIS
-static BCOM_HACK BcomRegA1Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
- { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
- { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-static BCOM_HACK BcomRegC0Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
- { 0x15, 0x0A04 }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-#endif
-
-/* function prototypes ********************************************************/
-#ifdef GENESIS
-static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
-static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
-#endif /* GENESIS */
-#ifdef YUKON
-static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
-static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
-#endif /* OTHER_PHY */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmPhyRead() - Read from XMAC PHY register
- *
- * Description: reads a 16-bit word from XMAC PHY or ext. PHY
- *
- * Returns:
- * nothing
- */
-void SkXmPhyRead(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 SK_FAR *pVal) /* Pointer to Value */
-{
- SK_U16 Mmu;
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* write the PHY register's address */
- XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-
- /* get the PHY register's value */
- XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- do {
- XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
- /* wait until 'Ready' is set */
- } while ((Mmu & XM_MMU_PHY_RDY) == 0);
-
- /* get the PHY register's value */
- XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
- }
-} /* SkXmPhyRead */
-
-
-/******************************************************************************
- *
- * SkXmPhyWrite() - Write to XMAC PHY register
- *
- * Description: writes a 16-bit word to XMAC PHY or ext. PHY
- *
- * Returns:
- * nothing
- */
-void SkXmPhyWrite(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 Val) /* Value */
-{
- SK_U16 Mmu;
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- do {
- XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
- /* wait until 'Busy' is cleared */
- } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
- }
-
- /* write the PHY register's address */
- XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-
- /* write the PHY register's value */
- XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- do {
- XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
- /* wait until 'Busy' is cleared */
- } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
- }
-} /* SkXmPhyWrite */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmPhyRead() - Read from GPHY register
- *
- * Description: reads a 16-bit word from GPHY through MDIO
- *
- * Returns:
- * nothing
- */
-void SkGmPhyRead(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 SK_FAR *pVal) /* Pointer to Value */
-{
- SK_U16 Ctrl;
- SK_GEPORT *pPrt;
-#ifdef VCPU
- u_long SimCyle;
- u_long SimLowTime;
-
- VCPUgetTime(&SimCyle, &SimLowTime);
- VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
- PhyReg, SimCyle, SimLowTime);
-#endif /* VCPU */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* set PHY-Register offset and 'Read' OpCode (= 1) */
- *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
- GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
-
- GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
-
- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
- /* additional check for MDC/MDIO activity */
- if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
- *pVal = 0;
- return;
- }
-
- *pVal |= GM_SMI_CT_BUSY;
-
- do {
-#ifdef VCPU
- VCPUwaitTime(1000);
-#endif /* VCPU */
-
- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
- /* wait until 'ReadValid' is set */
- } while (Ctrl == *pVal);
-
- /* get the PHY register's value */
- GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
-
-#ifdef VCPU
- VCPUgetTime(&SimCyle, &SimLowTime);
- VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
- SimCyle, SimLowTime);
-#endif /* VCPU */
-
-} /* SkGmPhyRead */
-
-
-/******************************************************************************
- *
- * SkGmPhyWrite() - Write to GPHY register
- *
- * Description: writes a 16-bit word to GPHY through MDIO
- *
- * Returns:
- * nothing
- */
-void SkGmPhyWrite(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 Val) /* Value */
-{
- SK_U16 Ctrl;
- SK_GEPORT *pPrt;
-#ifdef VCPU
- SK_U32 DWord;
- u_long SimCyle;
- u_long SimLowTime;
-
- VCPUgetTime(&SimCyle, &SimLowTime);
- VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
- PhyReg, Val, SimCyle, SimLowTime);
-#endif /* VCPU */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* write the PHY register's value */
- GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
-
- /* set PHY-Register offset and 'Write' OpCode (= 0) */
- Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
-
- GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
-
- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
- /* additional check for MDC/MDIO activity */
- if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
- return;
- }
-
- Val |= GM_SMI_CT_BUSY;
-
- do {
-#ifdef VCPU
- /* read Timer value */
- SK_IN32(IoC, B2_TI_VAL, &DWord);
-
- VCPUwaitTime(1000);
-#endif /* VCPU */
-
- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
- /* wait until 'Busy' is cleared */
- } while (Ctrl == Val);
-
-#ifdef VCPU
- VCPUgetTime(&SimCyle, &SimLowTime);
- VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
- SimCyle, SimLowTime);
-#endif /* VCPU */
-
-} /* SkGmPhyWrite */
-#endif /* YUKON */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- * SkGePhyRead() - Read from PHY register
- *
- * Description: calls a read PHY routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkGePhyRead(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 *pVal) /* Pointer to Value */
-{
- void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
-
- if (pAC->GIni.GIGenesis) {
- r_func = SkXmPhyRead;
- }
- else {
- r_func = SkGmPhyRead;
- }
-
- r_func(pAC, IoC, Port, PhyReg, pVal);
-} /* SkGePhyRead */
-
-
-/******************************************************************************
- *
- * SkGePhyWrite() - Write to PHY register
- *
- * Description: calls a write PHY routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkGePhyWrite(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 Val) /* Value */
-{
- void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
-
- if (pAC->GIni.GIGenesis) {
- w_func = SkXmPhyWrite;
- }
- else {
- w_func = SkGmPhyWrite;
- }
-
- w_func(pAC, IoC, Port, PhyReg, Val);
-} /* SkGePhyWrite */
-#endif /* SK_DIAG */
-
-
-/******************************************************************************
- *
- * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
- *
- * Description:
- * enables / disables promiscuous mode by setting Mode Register (XMAC) or
- * Receive Control Register (GMAC) dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacPromiscMode(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
-#ifdef YUKON
- SK_U16 RcReg;
-#endif
-#ifdef GENESIS
- SK_U32 MdReg;
-#endif
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
- /* enable or disable promiscuous mode */
- if (Enable) {
- MdReg |= XM_MD_ENA_PROM;
- }
- else {
- MdReg &= ~XM_MD_ENA_PROM;
- }
- /* setup Mode Register */
- XM_OUT32(IoC, Port, XM_MODE, MdReg);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-
- /* enable or disable unicast and multicast filtering */
- if (Enable) {
- RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
- }
- else {
- RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
- }
- /* setup Receive Control Register */
- GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
- }
-#endif /* YUKON */
-
-} /* SkMacPromiscMode*/
-
-
-/******************************************************************************
- *
- * SkMacHashing() - Enable / Disable Hashing
- *
- * Description:
- * enables / disables hashing by setting Mode Register (XMAC) or
- * Receive Control Register (GMAC) dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacHashing(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
-#ifdef YUKON
- SK_U16 RcReg;
-#endif
-#ifdef GENESIS
- SK_U32 MdReg;
-#endif
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
- /* enable or disable hashing */
- if (Enable) {
- MdReg |= XM_MD_ENA_HASH;
- }
- else {
- MdReg &= ~XM_MD_ENA_HASH;
- }
- /* setup Mode Register */
- XM_OUT32(IoC, Port, XM_MODE, MdReg);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-
- /* enable or disable multicast filtering */
- if (Enable) {
- RcReg |= GM_RXCR_MCF_ENA;
- }
- else {
- RcReg &= ~GM_RXCR_MCF_ENA;
- }
- /* setup Receive Control Register */
- GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
- }
-#endif /* YUKON */
-
-} /* SkMacHashing*/
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
- *
- * Description:
- * The features
- * - FCS stripping, SK_STRIP_FCS_ON/OFF
- * - pad byte stripping, SK_STRIP_PAD_ON/OFF
- * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF
- * for inrange length error frames
- * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF
- * for frames > 1514 bytes
- * - enable Rx of own packets SK_SELF_RX_ON/OFF
- *
- * for incoming packets may be enabled/disabled by this function.
- * Additional modes may be added later.
- * Multiple modes can be enabled/disabled at the same time.
- * The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- * nothing
- */
-static void SkXmSetRxCmd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
- SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
- SK_U16 OldRxCmd;
- SK_U16 RxCmd;
-
- XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
-
- RxCmd = OldRxCmd;
-
- switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
- case SK_STRIP_FCS_ON:
- RxCmd |= XM_RX_STRIP_FCS;
- break;
- case SK_STRIP_FCS_OFF:
- RxCmd &= ~XM_RX_STRIP_FCS;
- break;
- }
-
- switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
- case SK_STRIP_PAD_ON:
- RxCmd |= XM_RX_STRIP_PAD;
- break;
- case SK_STRIP_PAD_OFF:
- RxCmd &= ~XM_RX_STRIP_PAD;
- break;
- }
-
- switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
- case SK_LENERR_OK_ON:
- RxCmd |= XM_RX_LENERR_OK;
- break;
- case SK_LENERR_OK_OFF:
- RxCmd &= ~XM_RX_LENERR_OK;
- break;
- }
-
- switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
- case SK_BIG_PK_OK_ON:
- RxCmd |= XM_RX_BIG_PK_OK;
- break;
- case SK_BIG_PK_OK_OFF:
- RxCmd &= ~XM_RX_BIG_PK_OK;
- break;
- }
-
- switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
- case SK_SELF_RX_ON:
- RxCmd |= XM_RX_SELF_RX;
- break;
- case SK_SELF_RX_OFF:
- RxCmd &= ~XM_RX_SELF_RX;
- break;
- }
-
- /* Write the new mode to the Rx command register if required */
- if (OldRxCmd != RxCmd) {
- XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
- }
-} /* SkXmSetRxCmd */
-
-
-/******************************************************************************
- *
- * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
- *
- * Description:
- * The features
- * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF
- * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF
- * for frames > 1514 bytes
- * - enable Rx of own packets SK_SELF_RX_ON/OFF
- *
- * for incoming packets may be enabled/disabled by this function.
- * Additional modes may be added later.
- * Multiple modes can be enabled/disabled at the same time.
- * The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- * nothing
- */
-static void SkGmSetRxCmd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
- SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
- SK_U16 OldRxCmd;
- SK_U16 RxCmd;
-
- if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
-
- GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
-
- RxCmd = OldRxCmd;
-
- if ((Mode & SK_STRIP_FCS_ON) != 0) {
- RxCmd |= GM_RXCR_CRC_DIS;
- }
- else {
- RxCmd &= ~GM_RXCR_CRC_DIS;
- }
- /* Write the new mode to the Rx control register if required */
- if (OldRxCmd != RxCmd) {
- GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
- }
- }
-
- if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
-
- GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
-
- RxCmd = OldRxCmd;
-
- if ((Mode & SK_BIG_PK_OK_ON) != 0) {
- RxCmd |= GM_SMOD_JUMBO_ENA;
- }
- else {
- RxCmd &= ~GM_SMOD_JUMBO_ENA;
- }
- /* Write the new mode to the Rx control register if required */
- if (OldRxCmd != RxCmd) {
- GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
- }
- }
-} /* SkGmSetRxCmd */
-
-
-/******************************************************************************
- *
- * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
- *
- * Description: modifies the MAC's Rx Control reg. dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacSetRxCmd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-int Mode) /* Rx Mode */
-{
- if (pAC->GIni.GIGenesis) {
-
- SkXmSetRxCmd(pAC, IoC, Port, Mode);
- }
- else {
-
- SkGmSetRxCmd(pAC, IoC, Port, Mode);
- }
-
-} /* SkMacSetRxCmd */
-
-
-/******************************************************************************
- *
- * SkMacCrcGener() - Enable / Disable CRC Generation
- *
- * Description: enables / disables CRC generation dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacCrcGener(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
- SK_U16 Word;
-
- if (pAC->GIni.GIGenesis) {
-
- XM_IN16(IoC, Port, XM_TX_CMD, &Word);
-
- if (Enable) {
- Word &= ~XM_TX_NO_CRC;
- }
- else {
- Word |= XM_TX_NO_CRC;
- }
- /* setup Tx Command Register */
- XM_OUT16(IoC, Port, XM_TX_CMD, Word);
- }
- else {
-
- GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
-
- if (Enable) {
- Word &= ~GM_TXCR_CRC_DIS;
- }
- else {
- Word |= GM_TXCR_CRC_DIS;
- }
- /* setup Tx Control Register */
- GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
- }
-
-} /* SkMacCrcGener*/
-
-#endif /* SK_DIAG */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmClrExactAddr() - Clear Exact Match Address Registers
- *
- * Description:
- * All Exact Match Address registers of the XMAC 'Port' will be
- * cleared starting with 'StartNum' up to (and including) the
- * Exact Match address number of 'StopNum'.
- *
- * Returns:
- * nothing
- */
-void SkXmClrExactAddr(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-int StartNum, /* Begin with this Address Register Index (0..15) */
-int StopNum) /* Stop after finished with this Register Idx (0..15) */
-{
- int i;
- SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
-
- if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
- StartNum > StopNum) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
- return;
- }
-
- for (i = StartNum; i <= StopNum; i++) {
- XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
- }
-} /* SkXmClrExactAddr */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
- *
- * Description:
- * Flush the transmit FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- * nothing
- */
-void SkMacFlushTxFifo(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
- SK_U32 MdReg;
-
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
- XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* no way to flush the FIFO we have to issue a reset */
- /* TBD */
- }
-#endif /* YUKON */
-
-} /* SkMacFlushTxFifo */
-
-
-/******************************************************************************
- *
- * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
- *
- * Description:
- * Flush the receive FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- * nothing
- */
-static void SkMacFlushRxFifo(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
- SK_U32 MdReg;
-
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
- XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* no way to flush the FIFO we have to issue a reset */
- /* TBD */
- }
-#endif /* YUKON */
-
-} /* SkMacFlushRxFifo */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmSoftRst() - Do a XMAC software reset
- *
- * Description:
- * The PHY registers should not be destroyed during this
- * kind of software reset. Therefore the XMAC Software Reset
- * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
- *
- * The software reset is done by
- * - disabling the Rx and Tx state machine,
- * - resetting the statistics module,
- * - clear all other significant XMAC Mode,
- * Command, and Control Registers
- * - clearing the Hash Register and the
- * Exact Match Address registers, and
- * - flushing the XMAC's Rx and Tx FIFOs.
- *
- * Note:
- * Another requirement when stopping the XMAC is to
- * avoid sending corrupted frames on the network.
- * Disabling the Tx state machine will NOT interrupt
- * the currently transmitted frame. But we must take care
- * that the Tx FIFO is cleared AFTER the current frame
- * is complete sent to the network.
- *
- * It takes about 12ns to send a frame with 1538 bytes.
- * One PCI clock goes at least 15ns (66MHz). Therefore
- * after reading XM_GP_PORT back, we are sure that the
- * transmitter is disabled AND idle. And this means
- * we may flush the transmit FIFO now.
- *
- * Returns:
- * nothing
- */
-static void SkXmSoftRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
-
- /* reset the statistics module */
- XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
-
- /* disable all XMAC IRQs */
- XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
-
- XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */
-
- XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */
- XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */
-
- /* disable all PHY IRQs */
- switch (pAC->GIni.GP[Port].PhyType) {
- case SK_PHY_BCOM:
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
- break;
- case SK_PHY_NAT:
- /* todo: National
- SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
- break;
-#endif /* OTHER_PHY */
- }
-
- /* clear the Hash Register */
- XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
-
- /* clear the Exact Match Address registers */
- SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
-
- /* clear the Source Check Address registers */
- XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
-
-} /* SkXmSoftRst */
-
-
-/******************************************************************************
- *
- * SkXmHardRst() - Do a XMAC hardware reset
- *
- * Description:
- * The XMAC of the specified 'Port' and all connected devices
- * (PHY and SERDES) will receive a reset signal on its *Reset pins.
- * External PHYs must be reset by clearing a bit in the GPIO register
- * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
- *
- * ATTENTION:
- * It is absolutely necessary to reset the SW_RST Bit first
- * before calling this function.
- *
- * Returns:
- * nothing
- */
-static void SkXmHardRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U32 Reg;
- int i;
- int TOut;
- SK_U16 Word;
-
- for (i = 0; i < 4; i++) {
- /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
- TOut = 0;
- do {
- if (TOut++ > 10000) {
- /*
- * Adapter seems to be in RESET state.
- * Registers cannot be written.
- */
- return;
- }
-
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
-
- SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
-
- } while ((Word & MFF_SET_MAC_RST) == 0);
- }
-
- /* For external PHYs there must be special handling */
- if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-
- SK_IN32(IoC, B2_GP_IO, &Reg);
-
- if (Port == 0) {
- Reg |= GP_DIR_0; /* set to output */
- Reg &= ~GP_IO_0; /* set PHY reset (active low) */
- }
- else {
- Reg |= GP_DIR_2; /* set to output */
- Reg &= ~GP_IO_2; /* set PHY reset (active low) */
- }
- /* reset external PHY */
- SK_OUT32(IoC, B2_GP_IO, Reg);
-
- /* short delay */
- SK_IN32(IoC, B2_GP_IO, &Reg);
- }
-} /* SkXmHardRst */
-
-
-/******************************************************************************
- *
- * SkXmClearRst() - Release the PHY & XMAC reset
- *
- * Description:
- *
- * Returns:
- * nothing
- */
-static void SkXmClearRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U32 DWord;
-
- /* clear HW reset */
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
- if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-
- SK_IN32(IoC, B2_GP_IO, &DWord);
-
- if (Port == 0) {
- DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
- }
- else {
- DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
- }
- /* Clear PHY reset */
- SK_OUT32(IoC, B2_GP_IO, DWord);
-
- /* Enable GMII interface */
- XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
- }
-} /* SkXmClearRst */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmSoftRst() - Do a GMAC software reset
- *
- * Description:
- * The GPHY registers should not be destroyed during this
- * kind of software reset.
- *
- * Returns:
- * nothing
- */
-static void SkGmSoftRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
- SK_U16 RxCtrl;
-
- /* reset the statistics module */
-
- /* disable all GMAC IRQs */
- SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-
- /* disable all PHY IRQs */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-
- /* clear the Hash Register */
- GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
-
- /* Enable Unicast and Multicast filtering */
- GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
-
- GM_OUT16(IoC, Port, GM_RX_CTRL,
- (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
-
-} /* SkGmSoftRst */
-
-
-/******************************************************************************
- *
- * SkGmHardRst() - Do a GMAC hardware reset
- *
- * Description:
- *
- * Returns:
- * nothing
- */
-static void SkGmHardRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U32 DWord;
-
- /* WA code for COMA mode */
- if (pAC->GIni.GIYukonLite &&
- pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-
- SK_IN32(IoC, B2_GP_IO, &DWord);
-
- DWord |= (GP_DIR_9 | GP_IO_9);
-
- /* set PHY reset */
- SK_OUT32(IoC, B2_GP_IO, DWord);
- }
-
- /* set GPHY Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
-
- /* set GMAC Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-
-} /* SkGmHardRst */
-
-
-/******************************************************************************
- *
- * SkGmClearRst() - Release the GPHY & GMAC reset
- *
- * Description:
- *
- * Returns:
- * nothing
- */
-static void SkGmClearRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U32 DWord;
-
-#ifdef XXX
- /* clear GMAC Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
-
- /* set GMAC Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-#endif /* XXX */
-
- /* WA code for COMA mode */
- if (pAC->GIni.GIYukonLite &&
- pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-
- SK_IN32(IoC, B2_GP_IO, &DWord);
-
- DWord |= GP_DIR_9; /* set to output */
- DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
-
- /* clear PHY reset */
- SK_OUT32(IoC, B2_GP_IO, DWord);
- }
-
- /* set HWCFG_MODE */
- DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
- GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
- (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
- GPC_HWCFG_GMII_FIB);
-
- /* set GPHY Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
-
- /* release GPHY Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
-
-#ifdef VCPU
- VCpuWait(9000);
-#endif /* VCPU */
-
- /* clear GMAC Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
-
-#ifdef VCPU
- VCpuWait(2000);
-
- SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
-
- SK_IN32(IoC, B0_ISRC, &DWord);
-#endif /* VCPU */
-
-} /* SkGmClearRst */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- * SkMacSoftRst() - Do a MAC software reset
- *
- * Description: calls a MAC software reset routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacSoftRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* disable receiver and transmitter */
- SkMacRxTxDisable(pAC, IoC, Port);
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- SkXmSoftRst(pAC, IoC, Port);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- SkGmSoftRst(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
- /* flush the MAC's Rx and Tx FIFOs */
- SkMacFlushTxFifo(pAC, IoC, Port);
-
- SkMacFlushRxFifo(pAC, IoC, Port);
-
- pPrt->PState = SK_PRT_STOP;
-
-} /* SkMacSoftRst */
-
-
-/******************************************************************************
- *
- * SkMacHardRst() - Do a MAC hardware reset
- *
- * Description: calls a MAC hardware reset routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacHardRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- SkXmHardRst(pAC, IoC, Port);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- SkGmHardRst(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
- pAC->GIni.GP[Port].PState = SK_PRT_RESET;
-
-} /* SkMacHardRst */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmInitMac() - Initialize the XMAC II
- *
- * Description:
- * Initialize the XMAC of the specified port.
- * The XMAC must be reset or stopped before calling this function.
- *
- * Note:
- * The XMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- * nothing
- */
-void SkXmInitMac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- int i;
- SK_U16 SWord;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PState == SK_PRT_STOP) {
- /* Port State: SK_PRT_STOP */
- /* Verify that the reset bit is cleared */
- SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
-
- if ((SWord & MFF_SET_MAC_RST) != 0) {
- /* PState does not match HW state */
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
- /* Correct it */
- pPrt->PState = SK_PRT_RESET;
- }
- }
-
- if (pPrt->PState == SK_PRT_RESET) {
-
- SkXmClearRst(pAC, IoC, Port);
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- /* read Id from external PHY (all have the same address) */
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
-
- /*
- * Optimize MDIO transfer by suppressing preamble.
- * Must be done AFTER first access to BCOM chip.
- */
- XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
-
- XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
-
- if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
- /*
- * Workaround BCOM Errata for the C0 type.
- * Write magic patterns to reserved registers.
- */
- i = 0;
- while (BcomRegC0Hack[i].PhyReg != 0) {
- SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
- BcomRegC0Hack[i].PhyVal);
- i++;
- }
- }
- else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
- /*
- * Workaround BCOM Errata for the A1 type.
- * Write magic patterns to reserved registers.
- */
- i = 0;
- while (BcomRegA1Hack[i].PhyReg != 0) {
- SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
- BcomRegA1Hack[i].PhyVal);
- i++;
- }
- }
-
- /*
- * Workaround BCOM Errata (#10523) for all BCom PHYs.
- * Disable Power Management after reset.
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
-
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
- (SK_U16)(SWord | PHY_B_AC_DIS_PM));
-
- /* PHY LED initialization is done in SkGeXmitLED() */
- }
-
- /* Dummy read the Interrupt source register */
- XM_IN16(IoC, Port, XM_ISRC, &SWord);
-
- /*
- * The auto-negotiation process starts immediately after
- * clearing the reset. The auto-negotiation process should be
- * started by the SIRQ, therefore stop it here immediately.
- */
- SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
-#ifdef TEST_ONLY
- /* temp. code: enable signal detect */
- /* WARNING: do not override GMII setting above */
- XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
-#endif
- }
-
- /*
- * configure the XMACs Station Address
- * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
- * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
- */
- for (i = 0; i < 3; i++) {
- /*
- * The following 2 statements are together endianess
- * independent. Remember this when changing.
- */
- SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-
- XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
- }
-
- /* Tx Inter Packet Gap (XM_TX_IPG): use default */
- /* Tx High Water Mark (XM_TX_HI_WM): use default */
- /* Tx Low Water Mark (XM_TX_LO_WM): use default */
- /* Host Request Threshold (XM_HT_THR): use default */
- /* Rx Request Threshold (XM_RX_THR): use default */
- /* Rx Low Water Mark (XM_RX_LO_WM): use default */
-
- /* configure Rx High Water Mark (XM_RX_HI_WM) */
- XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
-
- /* Configure Tx Request Threshold */
- SWord = SK_XM_THR_SL; /* for single port */
-
- if (pAC->GIni.GIMacsFound > 1) {
- switch (pAC->GIni.GIPortUsage) {
- case SK_RED_LINK:
- SWord = SK_XM_THR_REDL; /* redundant link */
- break;
- case SK_MUL_LINK:
- SWord = SK_XM_THR_MULL; /* load balancing */
- break;
- case SK_JUMBO_LINK:
- SWord = SK_XM_THR_JUMBO; /* jumbo frames */
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
- break;
- }
- }
- XM_OUT16(IoC, Port, XM_TX_THR, SWord);
-
- /* setup register defaults for the Tx Command Register */
- XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
-
- /* setup register defaults for the Rx Command Register */
- SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
-
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
- SWord |= XM_RX_BIG_PK_OK;
- }
-
- if (pPrt->PLinkMode == SK_LMODE_HALF) {
- /*
- * If in manual half duplex mode the other side might be in
- * full duplex mode, so ignore if a carrier extension is not seen
- * on frames received
- */
- SWord |= XM_RX_DIS_CEXT;
- }
-
- XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
-
- /*
- * setup register defaults for the Mode Register
- * - Don't strip error frames to avoid Store & Forward
- * on the Rx side.
- * - Enable 'Check Station Address' bit
- * - Enable 'Check Address Array' bit
- */
- XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
-
- /*
- * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
- * - Enable all bits excepting 'Octets Rx OK Low CntOv'
- * and 'Octets Rx OK Hi Cnt Ov'.
- */
- XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
-
- /*
- * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
- * - Enable all bits excepting 'Octets Tx OK Low CntOv'
- * and 'Octets Tx OK Hi Cnt Ov'.
- */
- XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
-
- /*
- * Do NOT init XMAC interrupt mask here.
- * All interrupts remain disable until link comes up!
- */
-
- /*
- * Any additional configuration changes may be done now.
- * The last action is to enable the Rx and Tx state machine.
- * This should be done after the auto-negotiation process
- * has been completed successfully.
- */
-} /* SkXmInitMac */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmInitMac() - Initialize the GMAC
- *
- * Description:
- * Initialize the GMAC of the specified port.
- * The GMAC must be reset or stopped before calling this function.
- *
- * Note:
- * The GMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- * nothing
- */
-void SkGmInitMac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- int i;
- SK_U16 SWord;
- SK_U32 DWord;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PState == SK_PRT_STOP) {
- /* Port State: SK_PRT_STOP */
- /* Verify that the reset bit is cleared */
- SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
-
- if ((DWord & GMC_RST_SET) != 0) {
- /* PState does not match HW state */
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
- /* Correct it */
- pPrt->PState = SK_PRT_RESET;
- }
- }
-
- if (pPrt->PState == SK_PRT_RESET) {
-
- SkGmHardRst(pAC, IoC, Port);
-
- SkGmClearRst(pAC, IoC, Port);
-
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- /* Auto-negotiation disabled */
-
- /* get General Purpose Control */
- GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
-
- /* disable auto-update for speed, duplex and flow-control */
- SWord |= GM_GPCR_AU_ALL_DIS;
-
- /* setup General Purpose Control Register */
- GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-
- SWord = GM_GPCR_AU_ALL_DIS;
- }
- else {
- SWord = 0;
- }
-
- /* speed settings */
- switch (pPrt->PLinkSpeed) {
- case SK_LSPEED_AUTO:
- case SK_LSPEED_1000MBPS:
- SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
- break;
- case SK_LSPEED_100MBPS:
- SWord |= GM_GPCR_SPEED_100;
- break;
- case SK_LSPEED_10MBPS:
- break;
- }
-
- /* duplex settings */
- if (pPrt->PLinkMode != SK_LMODE_HALF) {
- /* set full duplex */
- SWord |= GM_GPCR_DUP_FULL;
- }
-
- /* flow-control settings */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- /* set Pause Off */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
- /* disable Tx & Rx flow-control */
- SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- /* disable Rx flow-control */
- SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- case SK_FLOW_MODE_SYM_OR_REM:
- /* enable Tx & Rx flow-control */
- break;
- }
-
- /* setup General Purpose Control Register */
- GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-
- /* dummy read the Interrupt Source Register */
- SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
-
-#ifndef VCPU
- /* read Id from PHY */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
-
- SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
-#endif /* VCPU */
- }
-
- (void)SkGmResetCounter(pAC, IoC, Port);
-
- /* setup Transmit Control Register */
- GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
-
- /* setup Receive Control Register */
- GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
- GM_RXCR_CRC_DIS);
-
- /* setup Transmit Flow Control Register */
- GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
-
- /* setup Transmit Parameter Register */
-#ifdef VCPU
- GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
-#endif /* VCPU */
-
- SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
- TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
- TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
-
- GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
-
- /* configure the Serial Mode Register */
-#ifdef VCPU
- GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
-#endif /* VCPU */
-
- SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
-
- if (pPrt->PMacLimit4) {
- /* reset of collision counter after 4 consecutive collisions */
- SWord |= GM_SMOD_LIMIT_4;
- }
-
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
- /* enable jumbo mode (Max. Frame Length = 9018) */
- SWord |= GM_SMOD_JUMBO_ENA;
- }
-
- GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
-
- /*
- * configure the GMACs Station Addresses
- * in PROM you can find our addresses at:
- * B2_MAC_1 = xx xx xx xx xx x0 virtual address
- * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
- * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
- */
-
- for (i = 0; i < 3; i++) {
- /*
- * The following 2 statements are together endianess
- * independent. Remember this when changing.
- */
- /* physical address: will be used for pause frames */
- SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-
-#ifdef WA_DEV_16
- /* WA for deviation #16 */
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
- /* swap the address bytes */
- SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
-
- /* write to register in reversed order */
- GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
- }
- else {
- GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
- }
-#else
- GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
-#endif /* WA_DEV_16 */
-
- /* virtual address: will be used for data */
- SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
-
- GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
-
- /* reset Multicast filtering Hash registers 1-3 */
- GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
- }
-
- /* reset Multicast filtering Hash register 4 */
- GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
-
- /* enable interrupt mask for counter overflows */
- GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
- GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
- GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
-
-#if defined(SK_DIAG) || defined(DEBUG)
- /* read General Purpose Status */
- GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("MAC Stat Reg.=0x%04X\n", SWord));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
- c_print("MAC Stat Reg=0x%04X\n", SWord);
-#endif /* SK_DIAG */
-
-} /* SkGmInitMac */
-#endif /* YUKON */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
- *
- * Description:
- * This function initializes the XMACs Duplex Mode.
- * It should be called after successfully finishing
- * the Auto-negotiation Process
- *
- * Returns:
- * nothing
- */
-static void SkXmInitDupMd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- switch (pAC->GIni.GP[Port].PLinkModeStatus) {
- case SK_LMODE_STAT_AUTOHALF:
- case SK_LMODE_STAT_HALF:
- /* Configuration Actions for Half Duplex Mode */
- /*
- * XM_BURST = default value. We are probable not quick
- * enough at the 'XMAC' bus to burst 8kB.
- * The XMAC stops bursting if no transmit frames
- * are available or the burst limit is exceeded.
- */
- /* XM_TX_RT_LIM = default value (15) */
- /* XM_TX_STIME = default value (0xff = 4096 bit times) */
- break;
- case SK_LMODE_STAT_AUTOFULL:
- case SK_LMODE_STAT_FULL:
- /* Configuration Actions for Full Duplex Mode */
- /*
- * The duplex mode is configured by the PHY,
- * therefore it seems to be that there is nothing
- * to do here.
- */
- break;
- case SK_LMODE_STAT_UNKNOWN:
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
- break;
- }
-} /* SkXmInitDupMd */
-
-
-/******************************************************************************
- *
- * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
- *
- * Description:
- * This function initializes the Pause Mode which should
- * be used for this port.
- * It should be called after successfully finishing
- * the Auto-negotiation Process
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPauseMd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U32 DWord;
- SK_U16 Word;
-
- pPrt = &pAC->GIni.GP[Port];
-
- XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-
- if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
- pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
- /* Disable Pause Frame Reception */
- Word |= XM_MMU_IGN_PF;
- }
- else {
- /*
- * enabling pause frame reception is required for 1000BT
- * because the XMAC is not reset if the link is going down
- */
- /* Enable Pause Frame Reception */
- Word &= ~XM_MMU_IGN_PF;
- }
-
- XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
-
- XM_IN32(IoC, Port, XM_MODE, &DWord);
-
- if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
- pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
- /*
- * Configure Pause Frame Generation
- * Use internal and external Pause Frame Generation.
- * Sending pause frames is edge triggered.
- * Send a Pause frame with the maximum pause time if
- * internal oder external FIFO full condition occurs.
- * Send a zero pause time frame to re-start transmission.
- */
-
- /* XM_PAUSE_DA = '010000C28001' (default) */
-
- /* XM_MAC_PTIME = 0xffff (maximum) */
- /* remember this value is defined in big endian (!) */
- XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
-
- /* Set Pause Mode in Mode Register */
- DWord |= XM_PAUSE_MODE;
-
- /* Set Pause Mode in MAC Rx FIFO */
- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
- }
- else {
- /*
- * disable pause frame generation is required for 1000BT
- * because the XMAC is not reset if the link is going down
- */
- /* Disable Pause Mode in Mode Register */
- DWord &= ~XM_PAUSE_MODE;
-
- /* Disable Pause Mode in MAC Rx FIFO */
- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
- }
-
- XM_OUT32(IoC, Port, XM_MODE, DWord);
-} /* SkXmInitPauseMd*/
-
-
-/******************************************************************************
- *
- * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
- *
- * Description: initializes all the XMACs Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPhyXmac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
- SK_U16 Ctrl;
-
- pPrt = &pAC->GIni.GP[Port];
- Ctrl = 0;
-
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
- /* Set DuplexMode in Config register */
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- Ctrl |= PHY_CT_DUP_MD;
- }
-
- /*
- * Do NOT enable Auto-negotiation here. This would hold
- * the link down because no IDLEs are transmitted
- */
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
- /* Set Auto-negotiation advertisement */
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- Ctrl |= PHY_X_AN_HD;
- break;
- case SK_LMODE_AUTOFULL:
- Ctrl |= PHY_X_AN_FD;
- break;
- case SK_LMODE_AUTOBOTH:
- Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- Ctrl |= PHY_X_P_NO_PAUSE;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- Ctrl |= PHY_X_P_ASYM_MD;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- Ctrl |= PHY_X_P_SYM_MD;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- Ctrl |= PHY_X_P_BOTH_MD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
-
- /* Write AutoNeg Advertisement Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
-
- /* Restart Auto-negotiation */
- Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
- }
-
- if (DoLoop) {
- /* Set the Phy Loopback bit, too */
- Ctrl |= PHY_CT_LOOP;
- }
-
- /* Write to the Phy control register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
-} /* SkXmInitPhyXmac */
-
-
-/******************************************************************************
- *
- * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
- *
- * Description: initializes all the Broadcom Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPhyBcom(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
- SK_U16 Ctrl1;
- SK_U16 Ctrl2;
- SK_U16 Ctrl3;
- SK_U16 Ctrl4;
- SK_U16 Ctrl5;
-
- Ctrl1 = PHY_CT_SP1000;
- Ctrl2 = 0;
- Ctrl3 = PHY_SEL_TYPE;
- Ctrl4 = PHY_B_PEC_EN_LTR;
- Ctrl5 = PHY_B_AC_TX_TST;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* manually Master/Slave ? */
- if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
- Ctrl2 |= PHY_B_1000C_MSE;
-
- if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
- Ctrl2 |= PHY_B_1000C_MSC;
- }
- }
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
- /* Set DuplexMode in Config register */
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- Ctrl1 |= PHY_CT_DUP_MD;
- }
-
- /* Determine Master/Slave manually if not already done */
- if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
- Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
- }
-
- /*
- * Do NOT enable Auto-negotiation here. This would hold
- * the link down because no IDLES are transmitted
- */
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
- /* Set Auto-negotiation advertisement */
-
- /*
- * Workaround BCOM Errata #1 for the C5 type.
- * 1000Base-T Link Acquisition Failure in Slave Mode
- * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
- */
- Ctrl2 |= PHY_B_1000C_RD;
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- Ctrl2 |= PHY_B_1000C_AHD;
- break;
- case SK_LMODE_AUTOFULL:
- Ctrl2 |= PHY_B_1000C_AFD;
- break;
- case SK_LMODE_AUTOBOTH:
- Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- Ctrl3 |= PHY_B_P_NO_PAUSE;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- Ctrl3 |= PHY_B_P_ASYM_MD;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- Ctrl3 |= PHY_B_P_SYM_MD;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- Ctrl3 |= PHY_B_P_BOTH_MD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
-
- /* Restart Auto-negotiation */
- Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
- }
-
- /* Initialize LED register here? */
- /* No. Please do it in SkDgXmitLed() (if required) and swap
- init order of LEDs and XMAC. (MAl) */
-
- /* Write 1000Base-T Control Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-
- /* Write AutoNeg Advertisement Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-
- if (DoLoop) {
- /* Set the Phy Loopback bit, too */
- Ctrl1 |= PHY_CT_LOOP;
- }
-
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
- /* configure FIFO to high latency for transmission of ext. packets */
- Ctrl4 |= PHY_B_PEC_HIGH_LA;
-
- /* configure reception of extended packets */
- Ctrl5 |= PHY_B_AC_LONG_PACK;
-
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
- }
-
- /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
-
- /* Write to the Phy control register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Control Reg=0x%04X\n", Ctrl1));
-} /* SkXmInitPhyBcom */
-#endif /* GENESIS */
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
- *
- * Description: initializes all the Marvell Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkGmInitPhyMarv(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
- SK_U16 PhyCtrl;
- SK_U16 C1000BaseT;
- SK_U16 AutoNegAdv;
- SK_U16 ExtPhyCtrl;
- SK_U16 LedCtrl;
- SK_BOOL AutoNeg;
-#if defined(SK_DIAG) || defined(DEBUG)
- SK_U16 PhyStat;
- SK_U16 PhyStat1;
- SK_U16 PhySpecStat;
-#endif /* SK_DIAG || DEBUG */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- AutoNeg = SK_FALSE;
- }
- else {
- AutoNeg = SK_TRUE;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyMarv: Port %d, auto-negotiation %s\n",
- Port, AutoNeg ? "ON" : "OFF"));
-
-#ifdef VCPU
- VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
- Port, DoLoop);
-#else /* VCPU */
- if (DoLoop) {
- /* Set 'MAC Power up'-bit, set Manual MDI configuration */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
- PHY_M_PC_MAC_POW_UP);
- }
- else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
- /* Read Ext. PHY Specific Control */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
-
- ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
- PHY_M_EC_MAC_S_MSK);
-
- ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
- PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
-
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
- }
-
- /* Read PHY Control */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
-
- if (!AutoNeg) {
- /* Disable Auto-negotiation */
- PhyCtrl &= ~PHY_CT_ANE;
- }
-
- PhyCtrl |= PHY_CT_RESET;
- /* Assert software reset */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
-#endif /* VCPU */
-
- PhyCtrl = 0 /* PHY_CT_COL_TST */;
- C1000BaseT = 0;
- AutoNegAdv = PHY_SEL_TYPE;
-
- /* manually Master/Slave ? */
- if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
- /* enable Manual Master/Slave */
- C1000BaseT |= PHY_M_1000C_MSE;
-
- if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
- C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
- }
- }
-
- /* Auto-negotiation ? */
- if (!AutoNeg) {
-
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- /* Set Full Duplex Mode */
- PhyCtrl |= PHY_CT_DUP_MD;
- }
-
- /* Set Master/Slave manually if not already done */
- if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
- C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
- }
-
- /* Set Speed */
- switch (pPrt->PLinkSpeed) {
- case SK_LSPEED_AUTO:
- case SK_LSPEED_1000MBPS:
- PhyCtrl |= PHY_CT_SP1000;
- break;
- case SK_LSPEED_100MBPS:
- PhyCtrl |= PHY_CT_SP100;
- break;
- case SK_LSPEED_10MBPS:
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
- SKERR_HWI_E019MSG);
- }
-
- if (!DoLoop) {
- PhyCtrl |= PHY_CT_RESET;
- }
- }
- else {
- /* Set Auto-negotiation advertisement */
-
- if (pAC->GIni.GICopperType) {
- /* Set Speed capabilities */
- switch (pPrt->PLinkSpeed) {
- case SK_LSPEED_AUTO:
- C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
- AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
- PHY_M_AN_10_FD | PHY_M_AN_10_HD;
- break;
- case SK_LSPEED_1000MBPS:
- C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
- break;
- case SK_LSPEED_100MBPS:
- AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
- /* advertise 10Base-T also */
- PHY_M_AN_10_FD | PHY_M_AN_10_HD;
- break;
- case SK_LSPEED_10MBPS:
- AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
- SKERR_HWI_E019MSG);
- }
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- C1000BaseT &= ~PHY_M_1000C_AFD;
- AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
- break;
- case SK_LMODE_AUTOFULL:
- C1000BaseT &= ~PHY_M_1000C_AHD;
- AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
- break;
- case SK_LMODE_AUTOBOTH:
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- AutoNegAdv |= PHY_B_P_NO_PAUSE;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- AutoNegAdv |= PHY_B_P_ASYM_MD;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- AutoNegAdv |= PHY_B_P_SYM_MD;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- AutoNegAdv |= PHY_B_P_BOTH_MD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
- }
- else { /* special defines for FIBER (88E1011S only) */
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- AutoNegAdv |= PHY_M_AN_1000X_AHD;
- break;
- case SK_LMODE_AUTOFULL:
- AutoNegAdv |= PHY_M_AN_1000X_AFD;
- break;
- case SK_LMODE_AUTOBOTH:
- AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- AutoNegAdv |= PHY_M_P_ASYM_MD_X;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- AutoNegAdv |= PHY_M_P_SYM_MD_X;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- AutoNegAdv |= PHY_M_P_BOTH_MD_X;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
- }
-
- if (!DoLoop) {
- /* Restart Auto-negotiation */
- PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
- }
- }
-
-#ifdef VCPU
- /*
- * E-mail from Gu Lin (08-03-2002):
- */
-
- /* Program PHY register 30 as 16'h0708 for simulation speed up */
- SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
-
- VCpuWait(2000);
-
-#else /* VCPU */
-
- /* Write 1000Base-T Control Register */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
-
- /* Write AutoNeg Advertisement Register */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-#endif /* VCPU */
-
- if (DoLoop) {
- /* Set the PHY Loopback bit */
- PhyCtrl |= PHY_CT_LOOP;
-
-#ifdef XXX
- /* Program PHY register 16 as 16'h0400 to force link good */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
-#endif /* XXX */
-
-#ifndef VCPU
- if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
- /* Write Ext. PHY Specific Control */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
- (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
- }
-#endif /* VCPU */
- }
-#ifdef TEST_ONLY
- else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
- /* Write PHY Specific Control */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
- PHY_M_PC_EN_DET_MSK);
- }
-#endif
-
- /* Write to the PHY Control register */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-
-#ifdef VCPU
- VCpuWait(2000);
-#else
-
- LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
-
- if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
- LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
- }
-
- if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
- LedCtrl |= PHY_M_LEDC_DP_CTRL;
- }
-
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
-
- if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
- /* only in forced 100 Mbps mode */
- if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
-
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
- PHY_M_LED_MO_100(MO_LED_ON));
- }
- }
-
-#ifdef SK_DIAG
- c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
- c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
- c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
- c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
-#endif /* SK_DIAG */
-
-#if defined(SK_DIAG) || defined(DEBUG)
- /* Read PHY Control */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-
- /* Read 1000Base-T Control Register */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
-
- /* Read AutoNeg Advertisement Register */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-
- /* Read Ext. PHY Specific Control */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
-
- /* Read PHY Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Stat Reg.=0x%04X\n", PhyStat));
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Stat Reg.=0x%04X\n", PhyStat1));
-
- /* Read PHY Specific Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Spec Stat=0x%04X\n", PhySpecStat));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
- c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
- c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
- c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
- c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
- c_print("PHY Stat Reg=0x%04X\n", PhyStat);
- c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
- c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
-#endif /* SK_DIAG */
-
-#endif /* VCPU */
-
-} /* SkGmInitPhyMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkXmInitPhyLone() - Initialize the Level One Phy registers
- *
- * Description: initializes all the Level One Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPhyLone(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
- SK_U16 Ctrl1;
- SK_U16 Ctrl2;
- SK_U16 Ctrl3;
-
- Ctrl1 = PHY_CT_SP1000;
- Ctrl2 = 0;
- Ctrl3 = PHY_SEL_TYPE;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* manually Master/Slave ? */
- if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
- Ctrl2 |= PHY_L_1000C_MSE;
-
- if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
- Ctrl2 |= PHY_L_1000C_MSC;
- }
- }
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- /*
- * level one spec say: "1000 Mbps: manual mode not allowed"
- * but lets see what happens...
- */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyLone: no auto-negotiation Port %d\n", Port));
- /* Set DuplexMode in Config register */
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- Ctrl1 |= PHY_CT_DUP_MD;
- }
-
- /* Determine Master/Slave manually if not already done */
- if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
- Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
- }
-
- /*
- * Do NOT enable Auto-negotiation here. This would hold
- * the link down because no IDLES are transmitted
- */
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyLone: with auto-negotiation Port %d\n", Port));
- /* Set Auto-negotiation advertisement */
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- Ctrl2 |= PHY_L_1000C_AHD;
- break;
- case SK_LMODE_AUTOFULL:
- Ctrl2 |= PHY_L_1000C_AFD;
- break;
- case SK_LMODE_AUTOBOTH:
- Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- Ctrl3 |= PHY_L_P_NO_PAUSE;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- Ctrl3 |= PHY_L_P_ASYM_MD;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- Ctrl3 |= PHY_L_P_SYM_MD;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- Ctrl3 |= PHY_L_P_BOTH_MD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
-
- /* Restart Auto-negotiation */
- Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
- }
-
- /* Write 1000Base-T Control Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-
- /* Write AutoNeg Advertisement Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-
- if (DoLoop) {
- /* Set the Phy Loopback bit, too */
- Ctrl1 |= PHY_CT_LOOP;
- }
-
- /* Write to the Phy control register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Control Reg=0x%04X\n", Ctrl1));
-} /* SkXmInitPhyLone */
-
-
-/******************************************************************************
- *
- * SkXmInitPhyNat() - Initialize the National Phy registers
- *
- * Description: initializes all the National Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPhyNat(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
-/* todo: National */
-} /* SkXmInitPhyNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- * SkMacInitPhy() - Initialize the PHY registers
- *
- * Description: calls the Init PHY routines dep. on board type
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-void SkMacInitPhy(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- switch (pPrt->PhyType) {
- case SK_PHY_XMAC:
- SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
- break;
- case SK_PHY_BCOM:
- SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
- break;
- case SK_PHY_NAT:
- SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
- break;
-#endif /* OTHER_PHY */
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
- }
-#endif /* YUKON */
-
-} /* SkMacInitPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmAutoNegDoneXmac() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkXmAutoNegDoneXmac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 ResAb; /* Resolved Ability */
- SK_U16 LPAb; /* Link Partner Ability */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegDoneXmac, Port %d\n", Port));
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Get PHY parameters */
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
-
- if ((LPAb & PHY_X_AN_RFB) != 0) {
- /* At least one of the remote fault bit is set */
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_OTHER);
- }
-
- /* Check Duplex mismatch */
- if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
- }
- else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
- }
- else {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_DUP_CAP);
- }
-
- /* Check PAUSE mismatch */
- /* We are NOT using chapter 4.23 of the Xaqti manual */
- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
- if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
- pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
- (LPAb & PHY_X_P_SYM_MD) != 0) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
- (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
- /* Enable PAUSE receive, disable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
- }
- else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
- (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
- /* Disable PAUSE receive, enable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
- }
- else {
- /* PAUSE mismatch -> no PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
- }
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
- return(SK_AND_OK);
-} /* SkXmAutoNegDoneXmac */
-
-
-/******************************************************************************
- *
- * SkXmAutoNegDoneBcom() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkXmAutoNegDoneBcom(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 LPAb; /* Link Partner Ability */
- SK_U16 AuxStat; /* Auxiliary Status */
-
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
- SK_U16 ResAb; /* Resolved Ability */
-#endif /* 0 */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegDoneBcom, Port %d\n", Port));
- pPrt = &pAC->GIni.GP[Port];
-
- /* Get PHY parameters */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-#endif /* 0 */
-
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
-
- if ((LPAb & PHY_B_AN_RF) != 0) {
- /* Remote fault bit is set: Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_OTHER);
- }
-
- /* Check Duplex mismatch */
- if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
- }
- else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
- }
- else {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_DUP_CAP);
- }
-
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
- /* Check Master/Slave resolution */
- if ((ResAb & PHY_B_1000S_MSF) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
- return(SK_AND_OTHER);
- }
-
- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-#endif /* 0 */
-
- /* Check PAUSE mismatch ??? */
- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
- if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
- /* Enable PAUSE receive, disable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
- }
- else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
- /* Disable PAUSE receive, enable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
- }
- else {
- /* PAUSE mismatch -> no PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
- }
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
- return(SK_AND_OK);
-} /* SkXmAutoNegDoneBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmAutoNegDoneMarv() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkGmAutoNegDoneMarv(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 LPAb; /* Link Partner Ability */
- SK_U16 ResAb; /* Resolved Ability */
- SK_U16 AuxStat; /* Auxiliary Status */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegDoneMarv, Port %d\n", Port));
- pPrt = &pAC->GIni.GP[Port];
-
- /* Get PHY parameters */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Link P.Abil.=0x%04X\n", LPAb));
-
- if ((LPAb & PHY_M_AN_RF) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_OTHER);
- }
-
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-
- /* Check Master/Slave resolution */
- if ((ResAb & PHY_B_1000S_MSF) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
- return(SK_AND_OTHER);
- }
-
- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
- (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
-
- /* Read PHY Specific Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
-
- /* Check Speed & Duplex resolved */
- if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
- return(SK_AND_DUP_CAP);
- }
-
- if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
- }
- else {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
- }
-
- /* Check PAUSE mismatch ??? */
- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
- if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
- /* Enable PAUSE receive, disable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
- }
- else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
- /* Disable PAUSE receive, enable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
- }
- else {
- /* PAUSE mismatch -> no PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
- }
-
- /* set used link speed */
- switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
- case (unsigned)PHY_M_PS_SPEED_1000:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
- break;
- case PHY_M_PS_SPEED_100:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
- break;
- default:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
- }
-
- return(SK_AND_OK);
-} /* SkGmAutoNegDoneMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkXmAutoNegDoneLone() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkXmAutoNegDoneLone(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 ResAb; /* Resolved Ability */
- SK_U16 LPAb; /* Link Partner Ability */
- SK_U16 QuickStat; /* Auxiliary Status */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegDoneLone, Port %d\n", Port));
- pPrt = &pAC->GIni.GP[Port];
-
- /* Get PHY parameters */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
-
- if ((LPAb & PHY_L_AN_RF) != 0) {
- /* Remote fault bit is set */
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_OTHER);
- }
-
- /* Check Duplex mismatch */
- if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
- }
- else {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
- }
-
- /* Check Master/Slave resolution */
- if ((ResAb & PHY_L_1000S_MSF) != 0) {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
- return(SK_AND_OTHER);
- }
- else if (ResAb & PHY_L_1000S_MSR) {
- pPrt->PMSStatus = SK_MS_STAT_MASTER;
- }
- else {
- pPrt->PMSStatus = SK_MS_STAT_SLAVE;
- }
-
- /* Check PAUSE mismatch */
- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
- /* we must manually resolve the abilities here */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- /* default */
- break;
- case SK_FLOW_MODE_LOC_SEND:
- if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
- (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
- /* Disable PAUSE receive, enable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
- }
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
- PHY_L_QS_AS_PAUSE) {
- /* Enable PAUSE receive, disable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
- }
- else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
-
- return(SK_AND_OK);
-} /* SkXmAutoNegDoneLone */
-
-
-/******************************************************************************
- *
- * SkXmAutoNegDoneNat() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkXmAutoNegDoneNat(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-/* todo: National */
- return(SK_AND_OK);
-} /* SkXmAutoNegDoneNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- * SkMacAutoNegDone() - Auto-negotiation handling
- *
- * Description: calls the auto-negotiation done routines dep. on board type
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-int SkMacAutoNegDone(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- int Rtv;
-
- Rtv = SK_AND_OK;
-
- pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- switch (pPrt->PhyType) {
-
- case SK_PHY_XMAC:
- Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
- break;
- case SK_PHY_BCOM:
- Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
- break;
- case SK_PHY_NAT:
- Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
- break;
-#endif /* OTHER_PHY */
- default:
- return(SK_AND_OTHER);
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
- if (Rtv != SK_AND_OK) {
- return(Rtv);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg done Port %d\n", Port));
-
- /* We checked everything and may now enable the link */
- pPrt->PAutoNegFail = SK_FALSE;
-
- SkMacRxTxEnable(pAC, IoC, Port);
-
- return(SK_AND_OK);
-} /* SkMacAutoNegDone */
-
-
-/******************************************************************************
- *
- * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
- *
- * Description: enables Rx/Tx dep. on board type
- *
- * Returns:
- * 0 o.k.
- * != 0 Error happened
- */
-int SkMacRxTxEnable(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 Reg; /* 16-bit register value */
- SK_U16 IntMask; /* MAC interrupt mask */
-#ifdef GENESIS
- SK_U16 SWord;
-#endif
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (!pPrt->PHWLinkUp) {
- /* The Hardware link is NOT up */
- return(0);
- }
-
- if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
- pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
- pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
- pPrt->PAutoNegFail) {
- /* Auto-negotiation is not done or failed */
- return(0);
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* set Duplex Mode and Pause Mode */
- SkXmInitDupMd(pAC, IoC, Port);
-
- SkXmInitPauseMd(pAC, IoC, Port);
-
- /*
- * Initialize the Interrupt Mask Register. Default IRQs are...
- * - Link Asynchronous Event
- * - Link Partner requests config
- * - Auto Negotiation Done
- * - Rx Counter Event Overflow
- * - Tx Counter Event Overflow
- * - Transmit FIFO Underrun
- */
- IntMask = XM_DEF_MSK;
-
-#ifdef DEBUG
- /* add IRQ for Receive FIFO Overflow */
- IntMask &= ~XM_IS_RXF_OV;
-#endif /* DEBUG */
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- /* disable GP0 interrupt bit */
- IntMask |= XM_IS_INP_ASS;
- }
- XM_OUT16(IoC, Port, XM_IMSK, IntMask);
-
- /* get MMU Command Reg. */
- XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
-
- if (pPrt->PhyType != SK_PHY_XMAC &&
- (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
- /* set to Full Duplex */
- Reg |= XM_MMU_GMII_FD;
- }
-
- switch (pPrt->PhyType) {
- case SK_PHY_BCOM:
- /*
- * Workaround BCOM Errata (#10523) for all BCom Phys
- * Enable Power Management after link up
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
- (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
- (SK_U16)PHY_B_DEF_MSK);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
- break;
- case SK_PHY_NAT:
- /* todo National:
- SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
- /* no interrupts possible from National ??? */
- break;
-#endif /* OTHER_PHY */
- }
-
- /* enable Rx/Tx */
- XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /*
- * Initialize the Interrupt Mask Register. Default IRQs are...
- * - Rx Counter Event Overflow
- * - Tx Counter Event Overflow
- * - Transmit FIFO Underrun
- */
- IntMask = GMAC_DEF_MSK;
-
-#ifdef DEBUG
- /* add IRQ for Receive FIFO Overrun */
- IntMask |= GM_IS_RX_FF_OR;
-#endif /* DEBUG */
-
- SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
-
- /* get General Purpose Control */
- GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
-
- if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
- /* set to Full Duplex */
- Reg |= GM_GPCR_DUP_FULL;
- }
-
- /* enable Rx/Tx */
- GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
- GM_GPCR_TX_ENA));
-
-#ifndef VCPU
- /* Enable all PHY interrupts */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
- (SK_U16)PHY_M_DEF_MSK);
-#endif /* VCPU */
- }
-#endif /* YUKON */
-
- return(0);
-
-} /* SkMacRxTxEnable */
-
-
-/******************************************************************************
- *
- * SkMacRxTxDisable() - Disable Receiver and Transmitter
- *
- * Description: disables Rx/Tx dep. on board type
- *
- * Returns: N/A
- */
-void SkMacRxTxDisable(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 Word;
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-
- XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
-
- /* dummy read to ensure writing */
- XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
-
- GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
- GM_GPCR_TX_ENA)));
-
- /* dummy read to ensure writing */
- GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
- }
-#endif /* YUKON */
-
-} /* SkMacRxTxDisable */
-
-
-/******************************************************************************
- *
- * SkMacIrqDisable() - Disable IRQ from MAC
- *
- * Description: sets the IRQ-mask to disable IRQ dep. on board type
- *
- * Returns: N/A
- */
-void SkMacIrqDisable(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
-#ifdef GENESIS
- SK_U16 Word;
-#endif
-
- pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- /* disable all XMAC IRQs */
- XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
-
- /* Disable all PHY interrupts */
- switch (pPrt->PhyType) {
- case SK_PHY_BCOM:
- /* Make sure that PHY is initialized */
- if (pPrt->PState != SK_PRT_RESET) {
- /* NOT allowed if BCOM is in RESET state */
- /* Workaround BCOM Errata (#10523) all BCom */
- /* Disable Power Management if link is down */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
- (SK_U16)(Word | PHY_B_AC_DIS_PM));
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
- }
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
- break;
- case SK_PHY_NAT:
- /* todo: National
- SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
- break;
-#endif /* OTHER_PHY */
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* disable all GMAC IRQs */
- SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-
-#ifndef VCPU
- /* Disable all PHY interrupts */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-#endif /* VCPU */
- }
-#endif /* YUKON */
-
-} /* SkMacIrqDisable */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- * SkXmSendCont() - Enable / Disable Send Continuous Mode
- *
- * Description: enable / disable Send Continuous Mode on XMAC
- *
- * Returns:
- * nothing
- */
-void SkXmSendCont(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
- SK_U32 MdReg;
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
- if (Enable) {
- MdReg |= XM_MD_TX_CONT;
- }
- else {
- MdReg &= ~XM_MD_TX_CONT;
- }
- /* setup Mode Register */
- XM_OUT32(IoC, Port, XM_MODE, MdReg);
-
-} /* SkXmSendCont */
-
-
-/******************************************************************************
- *
- * SkMacTimeStamp() - Enable / Disable Time Stamp
- *
- * Description: enable / disable Time Stamp generation for Rx packets
- *
- * Returns:
- * nothing
- */
-void SkMacTimeStamp(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
- SK_U32 MdReg;
- SK_U8 TimeCtrl;
-
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
- if (Enable) {
- MdReg |= XM_MD_ATS;
- }
- else {
- MdReg &= ~XM_MD_ATS;
- }
- /* setup Mode Register */
- XM_OUT32(IoC, Port, XM_MODE, MdReg);
- }
- else {
- if (Enable) {
- TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
- }
- else {
- TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
- }
- /* Start/Stop Time Stamp Timer */
- SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
- }
-
-} /* SkMacTimeStamp*/
-
-#else /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
- *
- * This function analyses the Interrupt status word. If any of the
- * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
- * is set true.
- */
-void SkXmAutoNegLipaXmac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U16 IStatus) /* Interrupt Status word to analyse */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
- (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
- Port, IStatus));
- pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
- }
-} /* SkXmAutoNegLipaXmac */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
- *
- * This function analyses the PHY status word.
- * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
- * is set true.
- */
-void SkMacAutoNegLipaPhy(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U16 PhyStat) /* PHY Status word to analyse */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
- (PhyStat & PHY_ST_AN_OVER) != 0) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
- Port, PhyStat));
- pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
- }
-} /* SkMacAutoNegLipaPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmIrq() - Interrupt Service Routine
- *
- * Description: services an Interrupt Request of the XMAC
- *
- * Note:
- * With an external PHY, some interrupt bits are not meaningfull any more:
- * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
- * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
- * - Page Received (bit #9) XM_IS_RX_PAGE
- * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
- * - AutoNegDone (bit #7) XM_IS_AND
- * Also probably not valid any more is the GP0 input bit:
- * - GPRegisterBit0set XM_IS_INP_ASS
- *
- * Returns:
- * nothing
- */
-static void SkXmIrq(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_EVPARA Para;
- SK_U16 IStatus; /* Interrupt status read from the XMAC */
- SK_U16 IStatus2;
-#ifdef SK_SLIM
- SK_U64 OverflowStatus;
-#endif
-
- pPrt = &pAC->GIni.GP[Port];
-
- XM_IN16(IoC, Port, XM_ISRC, &IStatus);
-
- /* LinkPartner Auto-negable? */
- if (pPrt->PhyType == SK_PHY_XMAC) {
- SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
- }
- else {
- /* mask bits that are not used with ext. PHY */
- IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
- XM_IS_RX_PAGE | XM_IS_TX_PAGE |
- XM_IS_AND | XM_IS_INP_ASS);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
- if (!pPrt->PHWLinkUp) {
- /* Spurious XMAC interrupt */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("SkXmIrq: spurious interrupt on Port %d\n", Port));
- return;
- }
-
- if ((IStatus & XM_IS_INP_ASS) != 0) {
- /* Reread ISR Register if link is not in sync */
- XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
- Port, IStatus, IStatus2));
- IStatus &= ~XM_IS_INP_ASS;
- IStatus |= IStatus2;
- }
-
- if ((IStatus & XM_IS_LNK_AE) != 0) {
- /* not used, GP0 is used instead */
- }
-
- if ((IStatus & XM_IS_TX_ABORT) != 0) {
- /* not used */
- }
-
- if ((IStatus & XM_IS_FRC_INT) != 0) {
- /* not used, use ASIC IRQ instead if needed */
- }
-
- if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
- SkHWLinkDown(pAC, IoC, Port);
-
- /* Signal to RLMT */
- Para.Para32[0] = (SK_U32)Port;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
- /* Start workaround Errata #2 timer */
- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
- SKGE_HWAC, SK_HWEV_WATIM, Para);
- }
-
- if ((IStatus & XM_IS_RX_PAGE) != 0) {
- /* not used */
- }
-
- if ((IStatus & XM_IS_TX_PAGE) != 0) {
- /* not used */
- }
-
- if ((IStatus & XM_IS_AND) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("SkXmIrq: AND on link that is up Port %d\n", Port));
- }
-
- if ((IStatus & XM_IS_TSC_OV) != 0) {
- /* not used */
- }
-
- /* Combined Tx & Rx Counter Overflow SIRQ Event */
- if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
-#ifdef SK_SLIM
- SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
- Para.Para32[0] = (SK_U32)Port;
- Para.Para32[1] = (SK_U32)IStatus;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif /* SK_SLIM */
- }
-
- if ((IStatus & XM_IS_RXF_OV) != 0) {
- /* normal situation -> no effect */
-#ifdef DEBUG
- pPrt->PRxOverCnt++;
-#endif /* DEBUG */
- }
-
- if ((IStatus & XM_IS_TXF_UR) != 0) {
- /* may NOT happen -> error log */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
- }
-
- if ((IStatus & XM_IS_TX_COMP) != 0) {
- /* not served here */
- }
-
- if ((IStatus & XM_IS_RX_COMP) != 0) {
- /* not served here */
- }
-} /* SkXmIrq */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmIrq() - Interrupt Service Routine
- *
- * Description: services an Interrupt Request of the GMAC
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkGmIrq(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U8 IStatus; /* Interrupt status */
-#ifdef SK_SLIM
- SK_U64 OverflowStatus;
-#else
- SK_EVPARA Para;
-#endif
-
- pPrt = &pAC->GIni.GP[Port];
-
- SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
-
-#ifdef XXX
- /* LinkPartner Auto-negable? */
- SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
-#endif /* XXX */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
- /* Combined Tx & Rx Counter Overflow SIRQ Event */
- if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
- /* these IRQs will be cleared by reading GMACs register */
-#ifdef SK_SLIM
- SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
- Para.Para32[0] = (SK_U32)Port;
- Para.Para32[1] = (SK_U32)IStatus;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif
- }
-
- if (IStatus & GM_IS_RX_FF_OR) {
- /* clear GMAC Rx FIFO Overrun IRQ */
- SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
-#ifdef DEBUG
- pPrt->PRxOverCnt++;
-#endif /* DEBUG */
- }
-
- if (IStatus & GM_IS_TX_FF_UR) {
- /* clear GMAC Tx FIFO Underrun IRQ */
- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
- /* may NOT happen -> error log */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
- }
-
- if (IStatus & GM_IS_TX_COMPL) {
- /* not served here */
- }
-
- if (IStatus & GM_IS_RX_COMPL) {
- /* not served here */
- }
-} /* SkGmIrq */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- * SkMacIrq() - Interrupt Service Routine for MAC
- *
- * Description: calls the Interrupt Service Routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacIrq(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* IRQ from XMAC */
- SkXmIrq(pAC, IoC, Port);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* IRQ from GMAC */
- SkGmIrq(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
-} /* SkMacIrq */
-
-#endif /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmUpdateStats() - Force the XMAC to output the current statistic
- *
- * Description:
- * The XMAC holds its statistic internally. To obtain the current
- * values a command must be sent so that the statistic data will
- * be written to a predefined memory area on the adapter.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkXmUpdateStats(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 StatReg;
- int WaitIndex;
-
- pPrt = &pAC->GIni.GP[Port];
- WaitIndex = 0;
-
- /* Send an update command to XMAC specified */
- XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
-
- /*
- * It is an auto-clearing register. If the command bits
- * went to zero again, the statistics are transferred.
- * Normally the command should be executed immediately.
- * But just to be sure we execute a loop.
- */
- do {
-
- XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
-
- if (++WaitIndex > 10) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
-
- return(1);
- }
- } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
-
- return(0);
-} /* SkXmUpdateStats */
-
-
-/******************************************************************************
- *
- * SkXmMacStatistic() - Get XMAC counter value
- *
- * Description:
- * Gets the 32bit counter value. Except for the octet counters
- * the lower 32bit are counted in hardware and the upper 32bit
- * must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkXmMacStatistic(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port, /* Port Index (MAC_1 + n) */
-SK_U16 StatAddr, /* MIB counter base address */
-SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
-{
- if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-
- return(1);
- }
-
- XM_IN32(IoC, Port, StatAddr, pVal);
-
- return(0);
-} /* SkXmMacStatistic */
-
-
-/******************************************************************************
- *
- * SkXmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- * Force the XMAC to clear its statistic counter.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkXmResetCounter(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port) /* Port Index (MAC_1 + n) */
-{
- XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
- /* Clear two times according to Errata #3 */
- XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
-
- return(0);
-} /* SkXmResetCounter */
-
-
-/******************************************************************************
- *
- * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- * Checks the source causing an counter overflow interrupt. On success the
- * resulting counter overflow status is written to <pStatus>, whereas the
- * upper dword stores the XMAC ReceiveCounterEvent register and the lower
- * dword the XMAC TransmitCounterEvent register.
- *
- * Note:
- * For XMAC the interrupt source is a self-clearing register, so the source
- * must be checked only once. SIRQ module does another check to be sure
- * that no interrupt get lost during process time.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkXmOverflowStatus(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port, /* Port Index (MAC_1 + n) */
-SK_U16 IStatus, /* Interupt Status from MAC */
-SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
-{
- SK_U64 Status; /* Overflow status */
- SK_U32 RegVal;
-
- Status = 0;
-
- if ((IStatus & XM_IS_RXC_OV) != 0) {
-
- XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
- Status |= (SK_U64)RegVal << 32;
- }
-
- if ((IStatus & XM_IS_TXC_OV) != 0) {
-
- XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
- Status |= (SK_U64)RegVal;
- }
-
- *pStatus = Status;
-
- return(0);
-} /* SkXmOverflowStatus */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmUpdateStats() - Force the GMAC to output the current statistic
- *
- * Description:
- * Empty function for GMAC. Statistic data is accessible in direct way.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkGmUpdateStats(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port) /* Port Index (MAC_1 + n) */
-{
- return(0);
-}
-
-
-/******************************************************************************
- *
- * SkGmMacStatistic() - Get GMAC counter value
- *
- * Description:
- * Gets the 32bit counter value. Except for the octet counters
- * the lower 32bit are counted in hardware and the upper 32bit
- * must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkGmMacStatistic(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port, /* Port Index (MAC_1 + n) */
-SK_U16 StatAddr, /* MIB counter base address */
-SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
-{
-
- if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
- return(1);
- }
-
- GM_IN32(IoC, Port, StatAddr, pVal);
-
- return(0);
-} /* SkGmMacStatistic */
-
-
-/******************************************************************************
- *
- * SkGmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- * Force GMAC to clear its statistic counter.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkGmResetCounter(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 Reg; /* Phy Address Register */
- SK_U16 Word;
- int i;
-
- GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
-
- /* set MIB Clear Counter Mode */
- GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
-
- /* read all MIB Counters with Clear Mode set */
- for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
- /* the reset is performed only when the lower 16 bits are read */
- GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
- }
-
- /* clear MIB Clear Counter Mode */
- GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
-
- return(0);
-} /* SkGmResetCounter */
-
-
-/******************************************************************************
- *
- * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- * Checks the source causing an counter overflow interrupt. On success the
- * resulting counter overflow status is written to <pStatus>, whereas the
- * the following bit coding is used:
- * 63:56 - unused
- * 55:48 - TxRx interrupt register bit7:0
- * 32:47 - Rx interrupt register
- * 31:24 - unused
- * 23:16 - TxRx interrupt register bit15:8
- * 15:0 - Tx interrupt register
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkGmOverflowStatus(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port, /* Port Index (MAC_1 + n) */
-SK_U16 IStatus, /* Interupt Status from MAC */
-SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
-{
- SK_U64 Status; /* Overflow status */
- SK_U16 RegVal;
-
- Status = 0;
-
- if ((IStatus & GM_IS_RX_CO_OV) != 0) {
- /* this register is self-clearing after read */
- GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
- Status |= (SK_U64)RegVal << 32;
- }
-
- if ((IStatus & GM_IS_TX_CO_OV) != 0) {
- /* this register is self-clearing after read */
- GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
- Status |= (SK_U64)RegVal;
- }
-
- /* this register is self-clearing after read */
- GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
- /* Rx overflow interrupt register bits (LoByte)*/
- Status |= (SK_U64)((SK_U8)RegVal) << 48;
- /* Tx overflow interrupt register bits (HiByte)*/
- Status |= (SK_U64)(RegVal >> 8) << 16;
-
- *pStatus = Status;
-
- return(0);
-} /* SkGmOverflowStatus */
-
-
-#ifndef SK_SLIM
-/******************************************************************************
- *
- * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
- *
- * Description:
- * starts the cable diagnostic test if 'StartTest' is true
- * gets the results if 'StartTest' is true
- *
- * NOTE: this test is meaningful only when link is down
- *
- * Returns:
- * 0: success
- * 1: no YUKON copper
- * 2: test in progress
- */
-int SkGmCableDiagStatus(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL StartTest) /* flag for start / get result */
-{
- int i;
- SK_U16 RegVal;
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-
- return(1);
- }
-
- if (StartTest) {
- /* only start the cable test */
- if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
- /* apply TDR workaround from Marvell */
- SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
-
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
- }
-
- /* set address to 0 for MDI[0] */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
-
- /* Read Cable Diagnostic Reg */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
- /* start Cable Diagnostic Test */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
- (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
-
- return(0);
- }
-
- /* Read Cable Diagnostic Reg */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Cable Diag.=0x%04X\n", RegVal));
-
- if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
- /* test is running */
- return(2);
- }
-
- /* get the test results */
- for (i = 0; i < 4; i++) {
- /* set address to i for MDI[i] */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
-
- /* get Cable Diagnostic values */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
- pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
-
- pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
- }
-
- return(0);
-} /* SkGmCableDiagStatus */
-#endif /* !SK_SLIM */
-#endif /* YUKON */
-
-/* End of file */
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index fe01b961b59..a2f32151559 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -39,6 +39,7 @@
#include <linux/workqueue.h>
#include <linux/if_vlan.h>
#include <linux/prefetch.h>
+#include <linux/debugfs.h>
#include <linux/mii.h>
#include <asm/irq.h>
@@ -50,7 +51,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.14"
+#define DRV_VERSION "1.16"
#define PFX DRV_NAME " "
/*
@@ -64,7 +65,6 @@
#define RX_MAX_PENDING (RX_LE_SIZE/6 - 2)
#define RX_DEF_PENDING RX_MAX_PENDING
#define RX_SKB_ALIGN 8
-#define RX_BUF_WRITE 16
#define TX_RING_SIZE 512
#define TX_DEF_PENDING (TX_RING_SIZE - 1)
@@ -77,6 +77,9 @@
#define NAPI_WEIGHT 64
#define PHY_RETRIES 1000
+#define SKY2_EEPROM_MAGIC 0x9955aabb
+
+
#define RING_NEXT(x,s) (((x)+1) & ((s)-1))
static const u32 default_msg =
@@ -96,7 +99,7 @@ static int disable_msi = 0;
module_param(disable_msi, int, 0);
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
-static int idle_timeout = 0;
+static int idle_timeout = 100;
module_param(idle_timeout, int, 0);
MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
@@ -130,7 +133,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */
-// { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
{ 0 }
};
@@ -217,13 +220,24 @@ static void sky2_power_on(struct sky2_hw *hw)
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
- u32 reg1;
+ u32 reg;
- sky2_pci_write32(hw, PCI_DEV_REG3, 0);
- reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
- reg1 &= P_ASPM_CONTROL_MSK;
- sky2_pci_write32(hw, PCI_DEV_REG4, reg1);
- sky2_pci_write32(hw, PCI_DEV_REG5, 0);
+ reg = sky2_pci_read32(hw, PCI_DEV_REG4);
+ /* set all bits to 0 except bits 15..12 and 8 */
+ reg &= P_ASPM_CONTROL_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG4, reg);
+
+ reg = sky2_pci_read32(hw, PCI_DEV_REG5);
+ /* set all bits to 0 except bits 28 & 27 */
+ reg &= P_CTL_TIM_VMAIN_AV_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG5, reg);
+
+ sky2_pci_write32(hw, PCI_CFG_REG_1, 0);
+
+ /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */
+ reg = sky2_read32(hw, B2_GP_IO);
+ reg |= GLB_GPIO_STAT_RACE_DIS;
+ sky2_write32(hw, B2_GP_IO, reg);
}
}
@@ -650,6 +664,30 @@ static void sky2_wol_init(struct sky2_port *sky2)
}
+static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
+{
+ if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_STFW_ENA |
+ (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS);
+ } else {
+ if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+ /* set Tx GMAC FIFO Almost Empty Threshold */
+ sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+ (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_JUMBO_ENA | TX_STFW_DIS);
+
+ /* Can't do offload because of lack of store/forward */
+ hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG
+ | NETIF_F_ALL_CSUM);
+ } else
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_JUMBO_DIS | TX_STFW_ENA);
+ }
+}
+
static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
{
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@@ -730,8 +768,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
/* Configure Rx MAC FIFO */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
- sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
- GMF_OPER_ON | GMF_RX_F_FL_ON);
+ reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ reg |= GMF_RX_OVER_ON;
+
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
/* Flush Rx MAC FIFO on any flow control or error */
sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
@@ -747,16 +788,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
- /* set Tx GMAC FIFO Almost Empty Threshold */
- sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
- (ECU_JUMBO_WM << 16) | ECU_AE_THR);
-
- if (hw->dev[port]->mtu > ETH_DATA_LEN)
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_ENA | TX_STFW_DIS);
- else
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_DIS | TX_STFW_ENA);
+ sky2_set_tx_stfwd(hw, port);
}
}
@@ -861,24 +893,18 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
return le;
}
-/* Return high part of DMA address (could be 32 or 64 bit) */
-static inline u32 high32(dma_addr_t a)
-{
- return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
-}
-
/* Build description to hardware for one receive segment */
static void sky2_rx_add(struct sky2_port *sky2, u8 op,
dma_addr_t map, unsigned len)
{
struct sky2_rx_le *le;
- u32 hi = high32(map);
+ u32 hi = upper_32_bits(map);
if (sky2->rx_addr64 != hi) {
le = sky2_next_rx(sky2);
le->addr = cpu_to_le32(hi);
le->opcode = OP_ADDR64 | HW_OWNER;
- sky2->rx_addr64 = high32(map + len);
+ sky2->rx_addr64 = upper_32_bits(map + len);
}
le = sky2_next_rx(sky2);
@@ -939,14 +965,16 @@ static void rx_set_checksum(struct sky2_port *sky2)
{
struct sky2_rx_le *le;
- le = sky2_next_rx(sky2);
- le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
- le->ctrl = 0;
- le->opcode = OP_TCPSTART | HW_OWNER;
+ if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
+ le = sky2_next_rx(sky2);
+ le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+ le->ctrl = 0;
+ le->opcode = OP_TCPSTART | HW_OWNER;
- sky2_write32(sky2->hw,
- Q_ADDR(rxqaddr[sky2->port], Q_CSR),
- sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ }
}
@@ -1106,6 +1134,11 @@ nomem:
return NULL;
}
+static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq)
+{
+ sky2_put_idx(sky2->hw, rxq, sky2->rx_put);
+}
+
/*
* Allocate and setup receiver buffer pool.
* Normal case this ends up creating one list element for skb
@@ -1134,15 +1167,14 @@ static int sky2_rx_start(struct sky2_port *sky2)
if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
(hw->chip_rev == CHIP_REV_YU_EC_U_A1
|| hw->chip_rev == CHIP_REV_YU_EC_U_B0))
- sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
+ sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS);
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
rx_set_checksum(sky2);
/* Space needed for frame data + headers rounded up */
- size = ALIGN(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8)
- + 8;
+ size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
/* Stopping point for hardware truncation */
thresh = (size - 8) / sizeof(u32);
@@ -1197,7 +1229,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
}
/* Tell chip about available buffers */
- sky2_put_idx(hw, rxq, sky2->rx_put);
+ sky2_rx_update(sky2, rxq);
return 0;
nomem:
sky2_rx_clean(sky2);
@@ -1234,6 +1266,8 @@ static int sky2_up(struct net_device *dev)
if (netif_msg_ifup(sky2))
printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
+ netif_carrier_off(dev);
+
/* must be power of 2 */
sky2->tx_le = pci_alloc_consistent(hw->pdev,
TX_RING_SIZE *
@@ -1285,6 +1319,10 @@ static int sky2_up(struct net_device *dev)
sky2_qset(hw, txqaddr[port]);
+ /* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */
+ if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0)
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF);
+
/* Set almost empty threshold */
if (hw->chip_id == CHIP_ID_YUKON_EC_U
&& hw->chip_rev == CHIP_REV_YU_EC_U_A0)
@@ -1380,27 +1418,30 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
len = skb_headlen(skb);
mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
- addr64 = high32(mapping);
+ addr64 = upper_32_bits(mapping);
/* Send high bits if changed or crosses boundary */
- if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) {
+ if (addr64 != sky2->tx_addr64 ||
+ upper_32_bits(mapping + len) != sky2->tx_addr64) {
le = get_tx_le(sky2);
le->addr = cpu_to_le32(addr64);
le->opcode = OP_ADDR64 | HW_OWNER;
- sky2->tx_addr64 = high32(mapping + len);
+ sky2->tx_addr64 = upper_32_bits(mapping + len);
}
/* Check for TCP Segmentation Offload */
mss = skb_shinfo(skb)->gso_size;
if (mss != 0) {
- mss += tcp_optlen(skb); /* TCP options */
- mss += ip_hdrlen(skb) + sizeof(struct tcphdr);
- mss += ETH_HLEN;
-
- if (mss != sky2->tx_last_mss) {
- le = get_tx_le(sky2);
- le->addr = cpu_to_le32(mss);
- le->opcode = OP_LRGLEN | HW_OWNER;
+ if (hw->chip_id != CHIP_ID_YUKON_EX)
+ mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
+
+ if (mss != sky2->tx_last_mss) {
+ le = get_tx_le(sky2);
+ le->addr = cpu_to_le32(mss);
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ le->opcode = OP_MSS | HW_OWNER;
+ else
+ le->opcode = OP_LRGLEN | HW_OWNER;
sky2->tx_last_mss = mss;
}
}
@@ -1422,24 +1463,30 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
/* Handle TCP checksum offload */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- const unsigned offset = skb_transport_offset(skb);
- u32 tcpsum;
-
- tcpsum = offset << 16; /* sum start */
- tcpsum |= offset + skb->csum_offset; /* sum write */
-
- ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
- if (ip_hdr(skb)->protocol == IPPROTO_UDP)
- ctrl |= UDPTCP;
-
- if (tcpsum != sky2->tx_tcpsum) {
- sky2->tx_tcpsum = tcpsum;
-
- le = get_tx_le(sky2);
- le->addr = cpu_to_le32(tcpsum);
- le->length = 0; /* initial checksum value */
- le->ctrl = 1; /* one packet */
- le->opcode = OP_TCPLISW | HW_OWNER;
+ /* On Yukon EX (some versions) encoding change. */
+ if (hw->chip_id == CHIP_ID_YUKON_EX
+ && hw->chip_rev != CHIP_REV_YU_EX_B0)
+ ctrl |= CALSUM; /* auto checksum */
+ else {
+ const unsigned offset = skb_transport_offset(skb);
+ u32 tcpsum;
+
+ tcpsum = offset << 16; /* sum start */
+ tcpsum |= offset + skb->csum_offset; /* sum write */
+
+ ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+ if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ ctrl |= UDPTCP;
+
+ if (tcpsum != sky2->tx_tcpsum) {
+ sky2->tx_tcpsum = tcpsum;
+
+ le = get_tx_le(sky2);
+ le->addr = cpu_to_le32(tcpsum);
+ le->length = 0; /* initial checksum value */
+ le->ctrl = 1; /* one packet */
+ le->opcode = OP_TCPLISW | HW_OWNER;
+ }
}
}
@@ -1459,7 +1506,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
frag->size, PCI_DMA_TODEVICE);
- addr64 = high32(mapping);
+ addr64 = upper_32_bits(mapping);
if (addr64 != sky2->tx_addr64) {
le = get_tx_le(sky2);
le->addr = cpu_to_le32(addr64);
@@ -1529,13 +1576,13 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
if (unlikely(netif_msg_tx_done(sky2)))
printk(KERN_DEBUG "%s: tx done %u\n",
dev->name, idx);
+
sky2->net_stats.tx_packets++;
sky2->net_stats.tx_bytes += re->skb->len;
dev_kfree_skb_any(re->skb);
+ sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE);
}
-
- le->opcode = 0; /* paranoia */
}
sky2->tx_cons = idx;
@@ -1573,7 +1620,6 @@ static int sky2_down(struct net_device *dev)
/* Stop more packets from being queued */
netif_stop_queue(dev);
- netif_carrier_off(dev);
/* Disable port IRQ */
imask = sky2_read32(hw, B0_IMSK);
@@ -1625,6 +1671,8 @@ static int sky2_down(struct net_device *dev)
sky2_phy_power(hw, port, 0);
+ netif_carrier_off(dev);
+
/* turn off LED's */
sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
@@ -1689,7 +1737,6 @@ static void sky2_link_up(struct sky2_port *sky2)
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
netif_carrier_on(sky2->netdev);
- netif_wake_queue(sky2->netdev);
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
@@ -1741,7 +1788,6 @@ static void sky2_link_down(struct sky2_port *sky2)
gma_write16(hw, port, GM_GP_CTRL, reg);
netif_carrier_off(sky2->netdev);
- netif_stop_queue(sky2->netdev);
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
@@ -1913,15 +1959,8 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
synchronize_irq(hw->pdev->irq);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
- if (new_mtu > ETH_DATA_LEN) {
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_ENA | TX_STFW_DIS);
- dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
- } else
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_DIS | TX_STFW_ENA);
- }
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+ sky2_set_tx_stfwd(hw, port);
ctl = gma_read16(hw, port, GM_GP_CTRL);
gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
@@ -2019,8 +2058,6 @@ static struct sk_buff *receive_new(struct sky2_port *sky2,
struct sk_buff *skb, *nskb;
unsigned hdr_space = sky2->rx_data_size;
- pr_debug(PFX "receive new length=%d\n", length);
-
/* Don't be tricky about reusing pages (yet) */
nskb = sky2_rx_alloc(sky2);
if (unlikely(!nskb))
@@ -2064,6 +2101,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
if (!(status & GMR_FS_RX_OK))
goto resubmit;
+ if (status >> 16 != length)
+ goto len_mismatch;
+
if (length < copybreak)
skb = receive_copy(sky2, re, length);
else
@@ -2073,6 +2113,11 @@ resubmit:
return skb;
+len_mismatch:
+ /* Truncation of overlength packets
+ causes PHY length to not match MAC length */
+ ++sky2->net_stats.rx_length_errors;
+
error:
++sky2->net_stats.rx_errors;
if (status & GMR_FS_RX_FF_OV) {
@@ -2109,15 +2154,16 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
/* Process status response ring */
static int sky2_status_intr(struct sky2_hw *hw, int to_do)
{
- struct sky2_port *sky2;
int work_done = 0;
- unsigned buf_write[2] = { 0, 0 };
+ unsigned rx[2] = { 0, 0 };
u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
rmb();
while (hw->st_idx != hwidx) {
+ struct sky2_port *sky2;
struct sky2_status_le *le = hw->st_le + hw->st_idx;
+ unsigned port = le->css & CSS_LINK_BIT;
struct net_device *dev;
struct sk_buff *skb;
u32 status;
@@ -2125,19 +2171,28 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
- BUG_ON(le->link >= 2);
- dev = hw->dev[le->link];
-
+ dev = hw->dev[port];
sky2 = netdev_priv(dev);
length = le16_to_cpu(le->length);
status = le32_to_cpu(le->status);
switch (le->opcode & ~HW_OWNER) {
case OP_RXSTAT:
+ ++rx[port];
skb = sky2_receive(dev, length, status);
if (unlikely(!skb)) {
sky2->net_stats.rx_dropped++;
- goto force_update;
+ break;
+ }
+
+ /* This chip reports checksum status differently */
+ if (hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (sky2->rx_csum &&
+ (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
+ (le->css & CSS_TCPUDPCSOK))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
}
skb->protocol = eth_type_trans(skb, dev);
@@ -2154,13 +2209,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
#endif
netif_receive_skb(skb);
- /* Update receiver after 16 frames */
- if (++buf_write[le->link] == RX_BUF_WRITE) {
-force_update:
- sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put);
- buf_write[le->link] = 0;
- }
-
/* Stop after net poll weight */
if (++work_done >= to_do)
goto exit_loop;
@@ -2179,6 +2227,9 @@ force_update:
if (!sky2->rx_csum)
break;
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ break;
+
/* Both checksum counters are programmed to start at
* the same offset, so unless there is a problem they
* should match. This failure is an early indication that
@@ -2194,7 +2245,7 @@ force_update:
dev->name, status);
sky2->rx_csum = 0;
sky2_write32(sky2->hw,
- Q_ADDR(rxqaddr[le->link], Q_CSR),
+ Q_ADDR(rxqaddr[port], Q_CSR),
BMU_DIS_RX_CHKSUM);
}
break;
@@ -2213,24 +2264,18 @@ force_update:
if (net_ratelimit())
printk(KERN_WARNING PFX
"unknown status opcode 0x%x\n", le->opcode);
- goto exit_loop;
}
}
/* Fully processed status ring so clear irq */
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
- mmiowb();
exit_loop:
- if (buf_write[0]) {
- sky2 = netdev_priv(hw->dev[0]);
- sky2_put_idx(hw, Q_R1, sky2->rx_put);
- }
+ if (rx[0])
+ sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1);
- if (buf_write[1]) {
- sky2 = netdev_priv(hw->dev[1]);
- sky2_put_idx(hw, Q_R2, sky2->rx_put);
- }
+ if (rx[1])
+ sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2);
return work_done;
}
@@ -2427,8 +2472,7 @@ static void sky2_err_intr(struct sky2_hw *hw, u32 status)
static int sky2_poll(struct net_device *dev0, int *budget)
{
struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
- int work_limit = min(dev0->quota, *budget);
- int work_done = 0;
+ int work_done;
u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
if (unlikely(status & Y2_IS_ERROR))
@@ -2440,18 +2484,25 @@ static int sky2_poll(struct net_device *dev0, int *budget)
if (status & Y2_IS_IRQ_PHY2)
sky2_phy_intr(hw, 1);
- work_done = sky2_status_intr(hw, work_limit);
- if (work_done < work_limit) {
- netif_rx_complete(dev0);
+ work_done = sky2_status_intr(hw, min(dev0->quota, *budget));
+ *budget -= work_done;
+ dev0->quota -= work_done;
- /* end of interrupt, re-enables also acts as I/O synchronization */
- sky2_read32(hw, B0_Y2_SP_LISR);
- return 0;
- } else {
- *budget -= work_done;
- dev0->quota -= work_done;
+ /* More work? */
+ if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX))
return 1;
+
+ /* Bug/Errata workaround?
+ * Need to kick the TX irq moderation timer.
+ */
+ if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
}
+ netif_rx_complete(dev0);
+
+ sky2_read32(hw, B0_Y2_SP_LISR);
+ return 0;
}
static irqreturn_t sky2_intr(int irq, void *dev_id)
@@ -2513,6 +2564,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
{
u8 t8;
+ /* Enable all clocks */
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
sky2_write8(hw, B0_CTST, CS_RST_CLR);
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
@@ -2522,14 +2576,6 @@ static int __devinit sky2_init(struct sky2_hw *hw)
return -EOPNOTSUPP;
}
- if (hw->chip_id == CHIP_ID_YUKON_EX)
- dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n"
- "Please report success or failure to <netdev@vger.kernel.org>\n");
-
- /* Make sure and enable all clocks */
- if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
- sky2_pci_write32(hw, PCI_DEV_REG3, 0);
-
hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
/* This rev is really old, and requires untested workarounds */
@@ -2589,6 +2635,11 @@ static void sky2_reset(struct sky2_hw *hw)
for (i = 0; i < hw->ports; i++) {
sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ sky2_write16(hw, SK_REG(i, GMAC_CTRL),
+ GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON
+ | GMC_BYP_RETR_ON);
}
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
@@ -2675,8 +2726,6 @@ static void sky2_restart(struct work_struct *work)
struct net_device *dev;
int i, err;
- dev_dbg(&hw->pdev->dev, "restarting\n");
-
del_timer_sync(&hw->idle_timer);
rtnl_lock();
@@ -2735,7 +2784,7 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
sky2->wol = wol->wolopts;
- if (hw->chip_id == CHIP_ID_YUKON_EC_U)
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
sky2_write32(hw, B0_CTST, sky2->wol
? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
@@ -3330,7 +3379,7 @@ static int sky2_get_regs_len(struct net_device *dev)
/*
* Returns copy of control register region
- * Note: access to the RAM address register set will cause timeouts.
+ * Note: ethtool_get_regs always provides full size (16k) buffer
*/
static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
@@ -3338,15 +3387,19 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
const struct sky2_port *sky2 = netdev_priv(dev);
const void __iomem *io = sky2->hw->regs;
- BUG_ON(regs->len < B3_RI_WTO_R1);
regs->version = 1;
memset(p, 0, regs->len);
memcpy_fromio(p, io, B3_RAM_ADDR);
- memcpy_fromio(p + B3_RI_WTO_R1,
- io + B3_RI_WTO_R1,
- regs->len - B3_RI_WTO_R1);
+ /* skip diagnostic ram region */
+ memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1);
+
+ /* copy GMAC registers */
+ memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000);
+ if (sky2->hw->ports > 1)
+ memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000);
+
}
/* In order to do Jumbo packets on these chips, need to turn off the
@@ -3357,9 +3410,7 @@ static int no_tx_offload(struct net_device *dev)
const struct sky2_port *sky2 = netdev_priv(dev);
const struct sky2_hw *hw = sky2->hw;
- return dev->mtu > ETH_DATA_LEN &&
- (hw->chip_id == CHIP_ID_YUKON_EX
- || hw->chip_id == CHIP_ID_YUKON_EC_U);
+ return dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U;
}
static int sky2_set_tx_csum(struct net_device *dev, u32 data)
@@ -3379,39 +3430,315 @@ static int sky2_set_tso(struct net_device *dev, u32 data)
return ethtool_op_set_tso(dev, data);
}
+static int sky2_get_eeprom_len(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ u16 reg2;
+
+ reg2 = sky2_pci_read32(sky2->hw, PCI_DEV_REG2);
+ return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
+}
+
+static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset)
+{
+ sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset);
+
+ while (!(sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F))
+ cpu_relax();
+ return sky2_pci_read32(hw, cap + PCI_VPD_DATA);
+}
+
+static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val)
+{
+ sky2_pci_write32(hw, cap + PCI_VPD_DATA, val);
+ sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
+ do {
+ cpu_relax();
+ } while (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F);
+}
+
+static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+ int length = eeprom->len;
+ u16 offset = eeprom->offset;
+
+ if (!cap)
+ return -EINVAL;
+
+ eeprom->magic = SKY2_EEPROM_MAGIC;
+
+ while (length > 0) {
+ u32 val = sky2_vpd_read(sky2->hw, cap, offset);
+ int n = min_t(int, length, sizeof(val));
+
+ memcpy(data, &val, n);
+ length -= n;
+ data += n;
+ offset += n;
+ }
+ return 0;
+}
+
+static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+ int length = eeprom->len;
+ u16 offset = eeprom->offset;
+
+ if (!cap)
+ return -EINVAL;
+
+ if (eeprom->magic != SKY2_EEPROM_MAGIC)
+ return -EINVAL;
+
+ while (length > 0) {
+ u32 val;
+ int n = min_t(int, length, sizeof(val));
+
+ if (n < sizeof(val))
+ val = sky2_vpd_read(sky2->hw, cap, offset);
+ memcpy(&val, data, n);
+
+ sky2_vpd_write(sky2->hw, cap, offset, val);
+
+ length -= n;
+ data += n;
+ offset += n;
+ }
+ return 0;
+}
+
+
static const struct ethtool_ops sky2_ethtool_ops = {
- .get_settings = sky2_get_settings,
- .set_settings = sky2_set_settings,
- .get_drvinfo = sky2_get_drvinfo,
- .get_wol = sky2_get_wol,
- .set_wol = sky2_set_wol,
- .get_msglevel = sky2_get_msglevel,
- .set_msglevel = sky2_set_msglevel,
- .nway_reset = sky2_nway_reset,
- .get_regs_len = sky2_get_regs_len,
- .get_regs = sky2_get_regs,
- .get_link = ethtool_op_get_link,
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
- .get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = sky2_set_tx_csum,
- .get_tso = ethtool_op_get_tso,
- .set_tso = sky2_set_tso,
- .get_rx_csum = sky2_get_rx_csum,
- .set_rx_csum = sky2_set_rx_csum,
- .get_strings = sky2_get_strings,
- .get_coalesce = sky2_get_coalesce,
- .set_coalesce = sky2_set_coalesce,
- .get_ringparam = sky2_get_ringparam,
- .set_ringparam = sky2_set_ringparam,
+ .get_settings = sky2_get_settings,
+ .set_settings = sky2_set_settings,
+ .get_drvinfo = sky2_get_drvinfo,
+ .get_wol = sky2_get_wol,
+ .set_wol = sky2_set_wol,
+ .get_msglevel = sky2_get_msglevel,
+ .set_msglevel = sky2_set_msglevel,
+ .nway_reset = sky2_nway_reset,
+ .get_regs_len = sky2_get_regs_len,
+ .get_regs = sky2_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_eeprom_len = sky2_get_eeprom_len,
+ .get_eeprom = sky2_get_eeprom,
+ .set_eeprom = sky2_set_eeprom,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = sky2_set_tx_csum,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = sky2_set_tso,
+ .get_rx_csum = sky2_get_rx_csum,
+ .set_rx_csum = sky2_set_rx_csum,
+ .get_strings = sky2_get_strings,
+ .get_coalesce = sky2_get_coalesce,
+ .set_coalesce = sky2_set_coalesce,
+ .get_ringparam = sky2_get_ringparam,
+ .set_ringparam = sky2_set_ringparam,
.get_pauseparam = sky2_get_pauseparam,
.set_pauseparam = sky2_set_pauseparam,
- .phys_id = sky2_phys_id,
+ .phys_id = sky2_phys_id,
.get_stats_count = sky2_get_stats_count,
.get_ethtool_stats = sky2_get_ethtool_stats,
.get_perm_addr = ethtool_op_get_perm_addr,
};
+#ifdef CONFIG_SKY2_DEBUG
+
+static struct dentry *sky2_debug;
+
+static int sky2_debug_show(struct seq_file *seq, void *v)
+{
+ struct net_device *dev = seq->private;
+ const struct sky2_port *sky2 = netdev_priv(dev);
+ const struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ unsigned idx, last;
+ int sop;
+
+ if (!netif_running(dev))
+ return -ENETDOWN;
+
+ seq_printf(seq, "IRQ src=%x mask=%x control=%x\n",
+ sky2_read32(hw, B0_ISRC),
+ sky2_read32(hw, B0_IMSK),
+ sky2_read32(hw, B0_Y2_SP_ICR));
+
+ netif_poll_disable(hw->dev[0]);
+ last = sky2_read16(hw, STAT_PUT_IDX);
+
+ if (hw->st_idx == last)
+ seq_puts(seq, "Status ring (empty)\n");
+ else {
+ seq_puts(seq, "Status ring\n");
+ for (idx = hw->st_idx; idx != last && idx < STATUS_RING_SIZE;
+ idx = RING_NEXT(idx, STATUS_RING_SIZE)) {
+ const struct sky2_status_le *le = hw->st_le + idx;
+ seq_printf(seq, "[%d] %#x %d %#x\n",
+ idx, le->opcode, le->length, le->status);
+ }
+ seq_puts(seq, "\n");
+ }
+
+ seq_printf(seq, "Tx ring pending=%u...%u report=%d done=%d\n",
+ sky2->tx_cons, sky2->tx_prod,
+ sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
+ sky2_read16(hw, Q_ADDR(txqaddr[port], Q_DONE)));
+
+ /* Dump contents of tx ring */
+ sop = 1;
+ for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < TX_RING_SIZE;
+ idx = RING_NEXT(idx, TX_RING_SIZE)) {
+ const struct sky2_tx_le *le = sky2->tx_le + idx;
+ u32 a = le32_to_cpu(le->addr);
+
+ if (sop)
+ seq_printf(seq, "%u:", idx);
+ sop = 0;
+
+ switch(le->opcode & ~HW_OWNER) {
+ case OP_ADDR64:
+ seq_printf(seq, " %#x:", a);
+ break;
+ case OP_LRGLEN:
+ seq_printf(seq, " mtu=%d", a);
+ break;
+ case OP_VLAN:
+ seq_printf(seq, " vlan=%d", be16_to_cpu(le->length));
+ break;
+ case OP_TCPLISW:
+ seq_printf(seq, " csum=%#x", a);
+ break;
+ case OP_LARGESEND:
+ seq_printf(seq, " tso=%#x(%d)", a, le16_to_cpu(le->length));
+ break;
+ case OP_PACKET:
+ seq_printf(seq, " %#x(%d)", a, le16_to_cpu(le->length));
+ break;
+ case OP_BUFFER:
+ seq_printf(seq, " frag=%#x(%d)", a, le16_to_cpu(le->length));
+ break;
+ default:
+ seq_printf(seq, " op=%#x,%#x(%d)", le->opcode,
+ a, le16_to_cpu(le->length));
+ }
+
+ if (le->ctrl & EOP) {
+ seq_putc(seq, '\n');
+ sop = 1;
+ }
+ }
+
+ seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n",
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)),
+ last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));
+
+ netif_poll_enable(hw->dev[0]);
+ return 0;
+}
+
+static int sky2_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, sky2_debug_show, inode->i_private);
+}
+
+static const struct file_operations sky2_debug_fops = {
+ .owner = THIS_MODULE,
+ .open = sky2_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*
+ * Use network device events to create/remove/rename
+ * debugfs file entries
+ */
+static int sky2_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+
+ if (dev->open == sky2_up) {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ switch(event) {
+ case NETDEV_CHANGENAME:
+ if (!netif_running(dev))
+ break;
+ /* fallthrough */
+ case NETDEV_DOWN:
+ case NETDEV_GOING_DOWN:
+ if (sky2->debugfs) {
+ printk(KERN_DEBUG PFX "%s: remove debugfs\n",
+ dev->name);
+ debugfs_remove(sky2->debugfs);
+ sky2->debugfs = NULL;
+ }
+
+ if (event != NETDEV_CHANGENAME)
+ break;
+ /* fallthrough for changename */
+ case NETDEV_UP:
+ if (sky2_debug) {
+ struct dentry *d;
+ d = debugfs_create_file(dev->name, S_IRUGO,
+ sky2_debug, dev,
+ &sky2_debug_fops);
+ if (d == NULL || IS_ERR(d))
+ printk(KERN_INFO PFX
+ "%s: debugfs create failed\n",
+ dev->name);
+ else
+ sky2->debugfs = d;
+ }
+ break;
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block sky2_notifier = {
+ .notifier_call = sky2_device_event,
+};
+
+
+static __init void sky2_debug_init(void)
+{
+ struct dentry *ent;
+
+ ent = debugfs_create_dir("sky2", NULL);
+ if (!ent || IS_ERR(ent))
+ return;
+
+ sky2_debug = ent;
+ register_netdevice_notifier(&sky2_notifier);
+}
+
+static __exit void sky2_debug_cleanup(void)
+{
+ if (sky2_debug) {
+ unregister_netdevice_notifier(&sky2_notifier);
+ debugfs_remove(sky2_debug);
+ sky2_debug = NULL;
+ }
+}
+
+#else
+#define sky2_debug_init()
+#define sky2_debug_cleanup()
+#endif
+
+
/* Initialize network device */
static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
unsigned port,
@@ -3486,10 +3813,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- /* device is off until link detection */
- netif_carrier_off(dev);
- netif_stop_queue(dev);
-
return dev;
}
@@ -3906,12 +4229,14 @@ static struct pci_driver sky2_driver = {
static int __init sky2_init_module(void)
{
+ sky2_debug_init();
return pci_register_driver(&sky2_driver);
}
static void __exit sky2_cleanup_module(void)
{
pci_unregister_driver(&sky2_driver);
+ sky2_debug_cleanup();
}
module_init(sky2_init_module);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index b8c4a3b5ead..dce4d276d44 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -14,6 +14,8 @@ enum {
PCI_DEV_REG3 = 0x80,
PCI_DEV_REG4 = 0x84,
PCI_DEV_REG5 = 0x88,
+ PCI_CFG_REG_0 = 0x90,
+ PCI_CFG_REG_1 = 0x94,
};
enum {
@@ -28,6 +30,7 @@ enum {
enum pci_dev_reg_1 {
PCI_Y2_PIG_ENA = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
PCI_Y2_DLL_DIS = 1<<30, /* Disable PCI DLL (YUKON-2) */
+ PCI_SW_PWR_ON_RST= 1<<30, /* SW Power on Reset (Yukon-EX) */
PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */
PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */
PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */
@@ -67,6 +70,80 @@ enum pci_dev_reg_4 {
| P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY,
};
+/* PCI_OUR_REG_5 32 bit Our Register 5 (Yukon-ECU only) */
+enum pci_dev_reg_5 {
+ /* Bit 31..27: for A3 & later */
+ P_CTL_DIV_CORE_CLK_ENA = 1<<31, /* Divide Core Clock Enable */
+ P_CTL_SRESET_VMAIN_AV = 1<<30, /* Soft Reset for Vmain_av De-Glitch */
+ P_CTL_BYPASS_VMAIN_AV = 1<<29, /* Bypass En. for Vmain_av De-Glitch */
+ P_CTL_TIM_VMAIN_AV_MSK = 3<<27, /* Bit 28..27: Timer Vmain_av Mask */
+ /* Bit 26..16: Release Clock on Event */
+ P_REL_PCIE_RST_DE_ASS = 1<<26, /* PCIe Reset De-Asserted */
+ P_REL_GPHY_REC_PACKET = 1<<25, /* GPHY Received Packet */
+ P_REL_INT_FIFO_N_EMPTY = 1<<24, /* Internal FIFO Not Empty */
+ P_REL_MAIN_PWR_AVAIL = 1<<23, /* Main Power Available */
+ P_REL_CLKRUN_REQ_REL = 1<<22, /* CLKRUN Request Release */
+ P_REL_PCIE_RESET_ASS = 1<<21, /* PCIe Reset Asserted */
+ P_REL_PME_ASSERTED = 1<<20, /* PME Asserted */
+ P_REL_PCIE_EXIT_L1_ST = 1<<19, /* PCIe Exit L1 State */
+ P_REL_LOADER_NOT_FIN = 1<<18, /* EPROM Loader Not Finished */
+ P_REL_PCIE_RX_EX_IDLE = 1<<17, /* PCIe Rx Exit Electrical Idle State */
+ P_REL_GPHY_LINK_UP = 1<<16, /* GPHY Link Up */
+
+ /* Bit 10.. 0: Mask for Gate Clock */
+ P_GAT_PCIE_RST_ASSERTED = 1<<10,/* PCIe Reset Asserted */
+ P_GAT_GPHY_N_REC_PACKET = 1<<9, /* GPHY Not Received Packet */
+ P_GAT_INT_FIFO_EMPTY = 1<<8, /* Internal FIFO Empty */
+ P_GAT_MAIN_PWR_N_AVAIL = 1<<7, /* Main Power Not Available */
+ P_GAT_CLKRUN_REQ_REL = 1<<6, /* CLKRUN Not Requested */
+ P_GAT_PCIE_RESET_ASS = 1<<5, /* PCIe Reset Asserted */
+ P_GAT_PME_DE_ASSERTED = 1<<4, /* PME De-Asserted */
+ P_GAT_PCIE_ENTER_L1_ST = 1<<3, /* PCIe Enter L1 State */
+ P_GAT_LOADER_FINISHED = 1<<2, /* EPROM Loader Finished */
+ P_GAT_PCIE_RX_EL_IDLE = 1<<1, /* PCIe Rx Electrical Idle State */
+ P_GAT_GPHY_LINK_DOWN = 1<<0, /* GPHY Link Down */
+
+ PCIE_OUR5_EVENT_CLK_D3_SET = P_REL_GPHY_REC_PACKET |
+ P_REL_INT_FIFO_N_EMPTY |
+ P_REL_PCIE_EXIT_L1_ST |
+ P_REL_PCIE_RX_EX_IDLE |
+ P_GAT_GPHY_N_REC_PACKET |
+ P_GAT_INT_FIFO_EMPTY |
+ P_GAT_PCIE_ENTER_L1_ST |
+ P_GAT_PCIE_RX_EL_IDLE,
+};
+
+#/* PCI_CFG_REG_1 32 bit Config Register 1 (Yukon-Ext only) */
+enum pci_cfg_reg1 {
+ P_CF1_DIS_REL_EVT_RST = 1<<24, /* Dis. Rel. Event during PCIE reset */
+ /* Bit 23..21: Release Clock on Event */
+ P_CF1_REL_LDR_NOT_FIN = 1<<23, /* EEPROM Loader Not Finished */
+ P_CF1_REL_VMAIN_AVLBL = 1<<22, /* Vmain available */
+ P_CF1_REL_PCIE_RESET = 1<<21, /* PCI-E reset */
+ /* Bit 20..18: Gate Clock on Event */
+ P_CF1_GAT_LDR_NOT_FIN = 1<<20, /* EEPROM Loader Finished */
+ P_CF1_GAT_PCIE_RX_IDLE = 1<<19, /* PCI-E Rx Electrical idle */
+ P_CF1_GAT_PCIE_RESET = 1<<18, /* PCI-E Reset */
+ P_CF1_PRST_PHY_CLKREQ = 1<<17, /* Enable PCI-E rst & PM2PHY gen. CLKREQ */
+ P_CF1_PCIE_RST_CLKREQ = 1<<16, /* Enable PCI-E rst generate CLKREQ */
+
+ P_CF1_ENA_CFG_LDR_DONE = 1<<8, /* Enable core level Config loader done */
+
+ P_CF1_ENA_TXBMU_RD_IDLE = 1<<1, /* Enable TX BMU Read IDLE for ASPM */
+ P_CF1_ENA_TXBMU_WR_IDLE = 1<<0, /* Enable TX BMU Write IDLE for ASPM */
+
+ PCIE_CFG1_EVENT_CLK_D3_SET = P_CF1_DIS_REL_EVT_RST |
+ P_CF1_REL_LDR_NOT_FIN |
+ P_CF1_REL_VMAIN_AVLBL |
+ P_CF1_REL_PCIE_RESET |
+ P_CF1_GAT_LDR_NOT_FIN |
+ P_CF1_GAT_PCIE_RESET |
+ P_CF1_PRST_PHY_CLKREQ |
+ P_CF1_ENA_CFG_LDR_DONE |
+ P_CF1_ENA_TXBMU_RD_IDLE |
+ P_CF1_ENA_TXBMU_WR_IDLE,
+};
+
#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -364,6 +441,20 @@ enum {
TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
};
+/* B2_GPIO */
+enum {
+ GLB_GPIO_CLK_DEB_ENA = 1<<31, /* Clock Debug Enable */
+ GLB_GPIO_CLK_DBG_MSK = 0xf<<26, /* Clock Debug */
+
+ GLB_GPIO_INT_RST_D3_DIS = 1<<15, /* Disable Internal Reset After D3 to D0 */
+ GLB_GPIO_LED_PAD_SPEED_UP = 1<<14, /* LED PAD Speed Up */
+ GLB_GPIO_STAT_RACE_DIS = 1<<13, /* Status Race Disable */
+ GLB_GPIO_TEST_SEL_MSK = 3<<11, /* Testmode Select */
+ GLB_GPIO_TEST_SEL_BASE = 1<<11,
+ GLB_GPIO_RAND_ENA = 1<<10, /* Random Enable */
+ GLB_GPIO_RAND_BIT_1 = 1<<9, /* Random Bit 1 */
+};
+
/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
enum {
CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */
@@ -392,6 +483,11 @@ enum {
CHIP_REV_YU_FE_A2 = 2,
};
+enum yukon_ex_rev {
+ CHIP_REV_YU_EX_A0 = 1,
+ CHIP_REV_YU_EX_B0 = 2,
+};
+
/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
enum {
@@ -515,23 +611,15 @@ enum {
enum {
B8_Q_REGS = 0x0400, /* base of Queue registers */
Q_D = 0x00, /* 8*32 bit Current Descriptor */
- Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */
- Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */
+ Q_VLAN = 0x20, /* 16 bit Current VLAN Tag */
+ Q_DONE = 0x24, /* 16 bit Done Index */
Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */
Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */
Q_BC = 0x30, /* 32 bit Current Byte Counter */
Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */
- Q_F = 0x38, /* 32 bit Flag Register */
- Q_T1 = 0x3c, /* 32 bit Test Register 1 */
- Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */
- Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */
- Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */
- Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */
- Q_T2 = 0x40, /* 32 bit Test Register 2 */
- Q_T3 = 0x44, /* 32 bit Test Register 3 */
+ Q_TEST = 0x38, /* 32 bit Test/Control Register */
/* Yukon-2 */
- Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */
Q_WM = 0x40, /* 16 bit FIFO Watermark */
Q_AL = 0x42, /* 8 bit FIFO Alignment */
Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */
@@ -545,15 +633,16 @@ enum {
};
#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
-/* Q_F 32 bit Flag Register */
+/* Q_TEST 32 bit Test Register */
enum {
- F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */
- F_EMPTY = 1<<27, /* Tx FIFO: empty flag */
- F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */
- F_WM_REACHED = 1<<25, /* Watermark reached */
+ /* Transmit */
+ F_TX_CHK_AUTO_OFF = 1<<31, /* Tx checksum auto calc off (Yukon EX) */
+ F_TX_CHK_AUTO_ON = 1<<30, /* Tx checksum auto calc off (Yukon EX) */
+
+ /* Receive */
F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */
- F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */
- F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */
+
+ /* Hardware testbits not used */
};
/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
@@ -1608,6 +1697,16 @@ enum {
RX_VLAN_STRIP_ON = 1<<25, /* enable VLAN stripping */
RX_VLAN_STRIP_OFF = 1<<24, /* disable VLAN stripping */
+ RX_MACSEC_FLUSH_ON = 1<<23,
+ RX_MACSEC_FLUSH_OFF = 1<<22,
+ RX_MACSEC_ASF_FLUSH_ON = 1<<21,
+ RX_MACSEC_ASF_FLUSH_OFF = 1<<20,
+
+ GMF_RX_OVER_ON = 1<<19, /* enable flushing on receive overrun */
+ GMF_RX_OVER_OFF = 1<<18, /* disable flushing on receive overrun */
+ GMF_ASF_RX_OVER_ON = 1<<17, /* enable flushing of ASF when overrun */
+ GMF_ASF_RX_OVER_OFF = 1<<16, /* disable flushing of ASF when overrun */
+
GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */
GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */
GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */
@@ -1720,6 +1819,15 @@ enum {
/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
enum {
+ GMC_SET_RST = 1<<15,/* MAC SEC RST */
+ GMC_SEC_RST_OFF = 1<<14,/* MAC SEC RSt OFF */
+ GMC_BYP_MACSECRX_ON = 1<<13,/* Bypass macsec RX */
+ GMC_BYP_MACSECRX_OFF= 1<<12,/* Bypass macsec RX off */
+ GMC_BYP_MACSECTX_ON = 1<<11,/* Bypass macsec TX */
+ GMC_BYP_MACSECTX_OFF= 1<<10,/* Bypass macsec TX off*/
+ GMC_BYP_RETR_ON = 1<<9, /* Bypass retransmit FIFO On */
+ GMC_BYP_RETR_OFF= 1<<8, /* Bypass retransmit FIFO Off */
+
GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */
GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */
GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */
@@ -1805,9 +1913,13 @@ enum {
OP_ADDR64VLAN = OP_ADDR64 | OP_VLAN,
OP_LRGLEN = 0x24,
OP_LRGLENVLAN = OP_LRGLEN | OP_VLAN,
+ OP_MSS = 0x28,
+ OP_MSSVLAN = OP_MSS | OP_VLAN,
+
OP_BUFFER = 0x40,
OP_PACKET = 0x41,
OP_LARGESEND = 0x43,
+ OP_LSOV2 = 0x45,
/* YUKON-2 STATUS opcodes defines */
OP_RXSTAT = 0x60,
@@ -1818,6 +1930,19 @@ enum {
OP_RXTIMEVLAN = OP_RXTIMESTAMP | OP_RXVLAN,
OP_RSS_HASH = 0x65,
OP_TXINDEXLE = 0x68,
+ OP_MACSEC = 0x6c,
+ OP_PUTIDX = 0x70,
+};
+
+enum status_css {
+ CSS_TCPUDPCSOK = 1<<7, /* TCP / UDP checksum is ok */
+ CSS_ISUDP = 1<<6, /* packet is a UDP packet */
+ CSS_ISTCP = 1<<5, /* packet is a TCP packet */
+ CSS_ISIPFRAG = 1<<4, /* packet is a TCP/UDP frag, CS calc not done */
+ CSS_ISIPV6 = 1<<3, /* packet is a IPv6 packet */
+ CSS_IPV4CSUMOK = 1<<2, /* IP v4: TCP header checksum is ok */
+ CSS_ISIPV4 = 1<<1, /* packet is a IPv4 packet */
+ CSS_LINK_BIT = 1<<0, /* port number (legacy) */
};
/* Yukon 2 hardware interface */
@@ -1838,7 +1963,7 @@ struct sky2_rx_le {
struct sky2_status_le {
__le32 status; /* also checksum */
__le16 length; /* also vlan tag */
- u8 link;
+ u8 css;
u8 opcode;
} __attribute((packed));
@@ -1873,6 +1998,7 @@ struct sky2_port {
struct sky2_tx_le *tx_le;
u16 tx_cons; /* next le to check */
u16 tx_prod; /* next le to use */
+ u16 tx_next; /* debug only */
u32 tx_addr64;
u16 tx_pending;
u16 tx_last_mss;
@@ -1903,6 +2029,9 @@ struct sky2_port {
enum flow_control flow_mode;
enum flow_control flow_status;
+#ifdef CONFIG_SKY2_DEBUG
+ struct dentry *debugfs;
+#endif
struct net_device_stats net_stats;
};
diff --git a/drivers/net/sni_82596.c b/drivers/net/sni_82596.c
new file mode 100644
index 00000000000..2cf6794acb4
--- /dev/null
+++ b/drivers/net/sni_82596.c
@@ -0,0 +1,185 @@
+/*
+ * sni_82596.c -- driver for intel 82596 ethernet controller, as
+ * used in older SNI RM machines
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#define SNI_82596_DRIVER_VERSION "SNI RM 82596 driver - Revision: 0.01"
+
+static const char sni_82596_string[] = "snirm_82596";
+
+#define DMA_ALLOC dma_alloc_coherent
+#define DMA_FREE dma_free_coherent
+#define DMA_WBACK(priv, addr, len) do { } while (0)
+#define DMA_INV(priv, addr, len) do { } while (0)
+#define DMA_WBACK_INV(priv, addr, len) do { } while (0)
+
+#define SYSBUS 0x00004400
+
+/* big endian CPU, 82596 little endian */
+#define SWAP32(x) cpu_to_le32((u32)(x))
+#define SWAP16(x) cpu_to_le16((u16)(x))
+
+#define OPT_MPU_16BIT 0x01
+
+#include "lib82596.c"
+
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_DESCRIPTION("i82596 driver");
+MODULE_LICENSE("GPL");
+module_param(i596_debug, int, 0);
+MODULE_PARM_DESC(i596_debug, "82596 debug mask");
+
+static inline void ca(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ writel(0, lp->ca);
+}
+
+
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ u32 v = (u32) (c) | (u32) (x);
+
+ if (lp->options & OPT_MPU_16BIT) {
+ writew(v & 0xffff, lp->mpu_port);
+ wmb(); /* order writes to MPU port */
+ udelay(1);
+ writew(v >> 16, lp->mpu_port);
+ } else {
+ writel(v, lp->mpu_port);
+ wmb(); /* order writes to MPU port */
+ udelay(1);
+ writel(v, lp->mpu_port);
+ }
+}
+
+
+static int __devinit sni_82596_probe(struct platform_device *dev)
+{
+ struct net_device *netdevice;
+ struct i596_private *lp;
+ struct resource *res, *ca, *idprom, *options;
+ int retval = -ENOMEM;
+ void __iomem *mpu_addr;
+ void __iomem *ca_addr;
+ u8 __iomem *eth_addr;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ ca = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ options = platform_get_resource(dev, 0, 0);
+ idprom = platform_get_resource(dev, IORESOURCE_MEM, 2);
+ if (!res || !ca || !options || !idprom)
+ return -ENODEV;
+ mpu_addr = ioremap_nocache(res->start, 4);
+ if (!mpu_addr)
+ return -ENOMEM;
+ ca_addr = ioremap_nocache(ca->start, 4);
+ if (!ca_addr)
+ goto probe_failed_free_mpu;
+
+ printk(KERN_INFO "Found i82596 at 0x%x\n", res->start);
+
+ netdevice = alloc_etherdev(sizeof(struct i596_private));
+ if (!netdevice)
+ goto probe_failed_free_ca;
+
+ SET_NETDEV_DEV(netdevice, &dev->dev);
+ platform_set_drvdata (dev, netdevice);
+
+ netdevice->base_addr = res->start;
+ netdevice->irq = platform_get_irq(dev, 0);
+
+ eth_addr = ioremap_nocache(idprom->start, 0x10);
+ if (!eth_addr)
+ goto probe_failed;
+
+ /* someone seems to like messed up stuff */
+ netdevice->dev_addr[0] = readb(eth_addr + 0x0b);
+ netdevice->dev_addr[1] = readb(eth_addr + 0x0a);
+ netdevice->dev_addr[2] = readb(eth_addr + 0x09);
+ netdevice->dev_addr[3] = readb(eth_addr + 0x08);
+ netdevice->dev_addr[4] = readb(eth_addr + 0x07);
+ netdevice->dev_addr[5] = readb(eth_addr + 0x06);
+ iounmap(eth_addr);
+
+ if (!netdevice->irq) {
+ printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
+ __FILE__, netdevice->base_addr);
+ goto probe_failed;
+ }
+
+ lp = netdev_priv(netdevice);
+ lp->options = options->flags & IORESOURCE_BITS;
+ lp->ca = ca_addr;
+ lp->mpu_port = mpu_addr;
+
+ retval = i82596_probe(netdevice);
+ if (retval == 0)
+ return 0;
+
+probe_failed:
+ free_netdev(netdevice);
+probe_failed_free_ca:
+ iounmap(ca_addr);
+probe_failed_free_mpu:
+ iounmap(mpu_addr);
+ return retval;
+}
+
+static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct i596_private *lp = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ DMA_FREE(dev->dev.parent, sizeof(struct i596_private),
+ lp->dma, lp->dma_addr);
+ iounmap(lp->ca);
+ iounmap(lp->mpu_port);
+ free_netdev (dev);
+ return 0;
+}
+
+static struct platform_driver sni_82596_driver = {
+ .probe = sni_82596_probe,
+ .remove = __devexit_p(sni_82596_driver_remove),
+ .driver = {
+ .name = sni_82596_string,
+ },
+};
+
+static int __devinit sni_82596_init(void)
+{
+ printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n");
+ return platform_driver_register(&sni_82596_driver);
+}
+
+
+static void __exit sni_82596_exit(void)
+{
+ platform_driver_unregister(&sni_82596_driver);
+}
+
+module_init(sni_82596_init);
+module_exit(sni_82596_exit);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 7a4aa6a9f94..590b12c7246 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -434,7 +434,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
if (!descr->skb) {
if (netif_msg_rx_err(card) && net_ratelimit())
- pr_err("Not enough memory to allocate rx buffer\n");
+ dev_err(&card->netdev->dev,
+ "Not enough memory to allocate rx buffer\n");
card->spider_stats.alloc_rx_skb_error++;
return -ENOMEM;
}
@@ -455,7 +456,7 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
dev_kfree_skb_any(descr->skb);
descr->skb = NULL;
if (netif_msg_rx_err(card) && net_ratelimit())
- pr_err("Could not iommu-map rx buffer\n");
+ dev_err(&card->netdev->dev, "Could not iommu-map rx buffer\n");
card->spider_stats.rx_iommu_map_error++;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
} else {
@@ -500,6 +501,20 @@ spider_net_enable_rxdmac(struct spider_net_card *card)
}
/**
+ * spider_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * spider_net_disable_rxdmac terminates processing on the DMA controller
+ * by turing off the DMA controller, with the force-end flag set.
+ */
+static inline void
+spider_net_disable_rxdmac(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
+ SPIDER_NET_DMA_RX_FEND_VALUE);
+}
+
+/**
* spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
* @card: card structure
*
@@ -655,20 +670,6 @@ write_hash:
}
/**
- * spider_net_disable_rxdmac - disables the receive DMA controller
- * @card: card structure
- *
- * spider_net_disable_rxdmac terminates processing on the DMA controller by
- * turing off DMA and issueing a force end
- */
-static void
-spider_net_disable_rxdmac(struct spider_net_card *card)
-{
- spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
- SPIDER_NET_DMA_RX_FEND_VALUE);
-}
-
-/**
* spider_net_prepare_tx_descr - fill tx descriptor with skb data
* @card: card structure
* @descr: descriptor structure to fill out
@@ -692,7 +693,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(buf)) {
if (netif_msg_tx_err(card) && net_ratelimit())
- pr_err("could not iommu-map packet (%p, %i). "
+ dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). "
"Dropping packet\n", skb->data, skb->len);
card->spider_stats.tx_iommu_map_error++;
return -ENOMEM;
@@ -715,7 +716,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
hwdescr->data_status = 0;
hwdescr->dmac_cmd_status =
- SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+ SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_TXFRMTL;
spin_unlock_irqrestore(&chain->lock, flags);
if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -832,9 +833,8 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
case SPIDER_NET_DESCR_PROTECTION_ERROR:
case SPIDER_NET_DESCR_FORCE_END:
if (netif_msg_tx_err(card))
- pr_err("%s: forcing end of tx descriptor "
- "with status x%02x\n",
- card->netdev->name, status);
+ dev_err(&card->netdev->dev, "forcing end of tx descriptor "
+ "with status x%02x\n", status);
card->netdev_stats.tx_errors++;
break;
@@ -1022,34 +1022,94 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
netif_receive_skb(skb);
}
-#ifdef DEBUG
static void show_rx_chain(struct spider_net_card *card)
{
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *start= chain->tail;
struct spider_net_descr *descr= start;
+ struct spider_net_hw_descr *hwd = start->hwdescr;
+ struct device *dev = &card->netdev->dev;
+ u32 curr_desc, next_desc;
int status;
+ int tot = 0;
int cnt = 0;
- int cstat = spider_net_get_descr_status(descr);
- printk(KERN_INFO "RX chain tail at descr=%ld\n",
- (start - card->descr) - card->tx_chain.num_desc);
+ int off = start - chain->ring;
+ int cstat = hwd->dmac_cmd_status;
+
+ dev_info(dev, "Total number of descrs=%d\n",
+ chain->num_desc);
+ dev_info(dev, "Chain tail located at descr=%d, status=0x%x\n",
+ off, cstat);
+
+ curr_desc = spider_net_read_reg(card, SPIDER_NET_GDACTDPA);
+ next_desc = spider_net_read_reg(card, SPIDER_NET_GDACNEXTDA);
+
status = cstat;
do
{
- status = spider_net_get_descr_status(descr);
+ hwd = descr->hwdescr;
+ off = descr - chain->ring;
+ status = hwd->dmac_cmd_status;
+
+ if (descr == chain->head)
+ dev_info(dev, "Chain head is at %d, head status=0x%x\n",
+ off, status);
+
+ if (curr_desc == descr->bus_addr)
+ dev_info(dev, "HW curr desc (GDACTDPA) is at %d, status=0x%x\n",
+ off, status);
+
+ if (next_desc == descr->bus_addr)
+ dev_info(dev, "HW next desc (GDACNEXTDA) is at %d, status=0x%x\n",
+ off, status);
+
+ if (hwd->next_descr_addr == 0)
+ dev_info(dev, "chain is cut at %d\n", off);
+
if (cstat != status) {
- printk(KERN_INFO "Have %d descrs with stat=x%08x\n", cnt, cstat);
+ int from = (chain->num_desc + off - cnt) % chain->num_desc;
+ int to = (chain->num_desc + off - 1) % chain->num_desc;
+ dev_info(dev, "Have %d (from %d to %d) descrs "
+ "with stat=0x%08x\n", cnt, from, to, cstat);
cstat = status;
cnt = 0;
}
+
cnt ++;
+ tot ++;
+ descr = descr->next;
+ } while (descr != start);
+
+ dev_info(dev, "Last %d descrs with stat=0x%08x "
+ "for a total of %d descrs\n", cnt, cstat, tot);
+
+#ifdef DEBUG
+ /* Now dump the whole ring */
+ descr = start;
+ do
+ {
+ struct spider_net_hw_descr *hwd = descr->hwdescr;
+ status = spider_net_get_descr_status(hwd);
+ cnt = descr - chain->ring;
+ dev_info(dev, "Descr %d stat=0x%08x skb=%p\n",
+ cnt, status, descr->skb);
+ dev_info(dev, "bus addr=%08x buf addr=%08x sz=%d\n",
+ descr->bus_addr, hwd->buf_addr, hwd->buf_size);
+ dev_info(dev, "next=%08x result sz=%d valid sz=%d\n",
+ hwd->next_descr_addr, hwd->result_size,
+ hwd->valid_size);
+ dev_info(dev, "dmac=%08x data stat=%08x data err=%08x\n",
+ hwd->dmac_cmd_status, hwd->data_status,
+ hwd->data_error);
+ dev_info(dev, "\n");
+
descr = descr->next;
} while (descr != start);
- printk(KERN_INFO "Last %d descrs with stat=x%08x\n", cnt, cstat);
-}
#endif
+}
+
/**
* spider_net_resync_head_ptr - Advance head ptr past empty descrs
*
@@ -1127,6 +1187,7 @@ spider_net_decode_one_descr(struct spider_net_card *card)
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *descr = chain->tail;
struct spider_net_hw_descr *hwdescr = descr->hwdescr;
+ u32 hw_buf_addr;
int status;
status = spider_net_get_descr_status(hwdescr);
@@ -1140,15 +1201,17 @@ spider_net_decode_one_descr(struct spider_net_card *card)
chain->tail = descr->next;
/* unmap descriptor */
- pci_unmap_single(card->pdev, hwdescr->buf_addr,
+ hw_buf_addr = hwdescr->buf_addr;
+ hwdescr->buf_addr = 0xffffffff;
+ pci_unmap_single(card->pdev, hw_buf_addr,
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
(status == SPIDER_NET_DESCR_PROTECTION_ERROR) ||
(status == SPIDER_NET_DESCR_FORCE_END) ) {
if (netif_msg_rx_err(card))
- pr_err("%s: dropping RX descriptor with state %d\n",
- card->netdev->name, status);
+ dev_err(&card->netdev->dev,
+ "dropping RX descriptor with state %d\n", status);
card->netdev_stats.rx_dropped++;
goto bad_desc;
}
@@ -1156,8 +1219,8 @@ spider_net_decode_one_descr(struct spider_net_card *card)
if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
(status != SPIDER_NET_DESCR_FRAME_END) ) {
if (netif_msg_rx_err(card))
- pr_err("%s: RX descriptor with unknown state %d\n",
- card->netdev->name, status);
+ dev_err(&card->netdev->dev,
+ "RX descriptor with unknown state %d\n", status);
card->spider_stats.rx_desc_unk_state++;
goto bad_desc;
}
@@ -1165,18 +1228,17 @@ spider_net_decode_one_descr(struct spider_net_card *card)
/* The cases we'll throw away the packet immediately */
if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
if (netif_msg_rx_err(card))
- pr_err("%s: error in received descriptor found, "
+ dev_err(&card->netdev->dev,
+ "error in received descriptor found, "
"data_status=x%08x, data_error=x%08x\n",
- card->netdev->name,
hwdescr->data_status, hwdescr->data_error);
goto bad_desc;
}
- if (hwdescr->dmac_cmd_status & 0xfcf4) {
- pr_err("%s: bad status, cmd_status=x%08x\n",
- card->netdev->name,
+ if (hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_BAD_STATUS) {
+ dev_err(&card->netdev->dev, "bad status, cmd_status=x%08x\n",
hwdescr->dmac_cmd_status);
- pr_err("buf_addr=x%08x\n", hwdescr->buf_addr);
+ pr_err("buf_addr=x%08x\n", hw_buf_addr);
pr_err("buf_size=x%08x\n", hwdescr->buf_size);
pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr);
pr_err("result_size=x%08x\n", hwdescr->result_size);
@@ -1196,6 +1258,8 @@ spider_net_decode_one_descr(struct spider_net_card *card)
return 1;
bad_desc:
+ if (netif_msg_rx_err(card))
+ show_rx_chain(card);
dev_kfree_skb_irq(descr->skb);
descr->skb = NULL;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
@@ -1221,7 +1285,6 @@ spider_net_poll(struct net_device *netdev, int *budget)
int packets_to_do, packets_done = 0;
int no_more_packets = 0;
- spider_net_cleanup_tx_ring(card);
packets_to_do = min(*budget, netdev->quota);
while (packets_to_do) {
@@ -1246,6 +1309,8 @@ spider_net_poll(struct net_device *netdev, int *budget)
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
+ spider_net_cleanup_tx_ring(card);
+
/* if all packets are in the stack, enable interrupts and return 0 */
/* if not, return 1 */
if (no_more_packets) {
@@ -1376,11 +1441,17 @@ static void
spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
{
u32 error_reg1, error_reg2;
+ u32 mask_reg1, mask_reg2;
u32 i;
int show_error = 1;
error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+ mask_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1MSK);
+ mask_reg2 = spider_net_read_reg(card,SPIDER_NET_GHIINT2MSK);
+
+ error_reg1 &= mask_reg1;
+ error_reg2 &= mask_reg2;
/* check GHIINT0STS ************************************/
if (status_reg)
@@ -1415,7 +1486,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GPWFFINT:
/* PHY command queue full */
if (netif_msg_intr(card))
- pr_err("PHY write queue full\n");
+ dev_err(&card->netdev->dev, "PHY write queue full\n");
show_error = 0;
break;
@@ -1582,9 +1653,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
}
if ((show_error) && (netif_msg_intr(card)) && net_ratelimit())
- pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, "
+ dev_err(&card->netdev->dev, "Error interrupt, GHIINT0STS = 0x%08x, "
"GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
- card->netdev->name,
status_reg, error_reg1, error_reg2);
/* clear interrupt sources */
@@ -1609,9 +1679,11 @@ spider_net_interrupt(int irq, void *ptr)
{
struct net_device *netdev = ptr;
struct spider_net_card *card = netdev_priv(netdev);
- u32 status_reg;
+ u32 status_reg, mask_reg;
status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
+ mask_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ status_reg &= mask_reg;
if (!status_reg)
return IRQ_NONE;
@@ -1653,6 +1725,38 @@ spider_net_poll_controller(struct net_device *netdev)
#endif /* CONFIG_NET_POLL_CONTROLLER */
/**
+ * spider_net_enable_interrupts - enable interrupts
+ * @card: card structure
+ *
+ * spider_net_enable_interrupt enables several interrupts
+ */
+static void
+spider_net_enable_interrupts(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
+ SPIDER_NET_INT0_MASK_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
+ SPIDER_NET_INT1_MASK_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
+ SPIDER_NET_INT2_MASK_VALUE);
+}
+
+/**
+ * spider_net_disable_interrupts - disable interrupts
+ * @card: card structure
+ *
+ * spider_net_disable_interrupts disables all the interrupts
+ */
+static void
+spider_net_disable_interrupts(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+}
+
+/**
* spider_net_init_card - initializes the card
* @card: card structure
*
@@ -1672,6 +1776,7 @@ spider_net_init_card(struct spider_net_card *card)
spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4);
+ spider_net_disable_interrupts(card);
}
/**
@@ -1759,14 +1864,6 @@ spider_net_enable_card(struct spider_net_card *card)
spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
SPIDER_NET_OPMODE_VALUE);
- /* set interrupt mask registers */
- spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
- SPIDER_NET_INT0_MASK_VALUE);
- spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
- SPIDER_NET_INT1_MASK_VALUE);
- spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
- SPIDER_NET_INT2_MASK_VALUE);
-
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
SPIDER_NET_GDTBSTA);
}
@@ -1849,7 +1946,8 @@ spider_net_init_firmware(struct spider_net_card *card)
SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
- pr_err("Incorrect size of spidernet firmware in " \
+ dev_err(&card->netdev->dev,
+ "Incorrect size of spidernet firmware in " \
"filesystem. Looking in host firmware...\n");
goto try_host_fw;
}
@@ -1873,8 +1971,8 @@ try_host_fw:
if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
- pr_err("Incorrect size of spidernet firmware in " \
- "host firmware\n");
+ dev_err(&card->netdev->dev,
+ "Incorrect size of spidernet firmware in host firmware\n");
goto done;
}
@@ -1884,7 +1982,8 @@ done:
return err;
out_err:
if (netif_msg_probe(card))
- pr_err("Couldn't find spidernet firmware in filesystem " \
+ dev_err(&card->netdev->dev,
+ "Couldn't find spidernet firmware in filesystem " \
"or host firmware\n");
return err;
}
@@ -1941,6 +2040,8 @@ spider_net_open(struct net_device *netdev)
netif_carrier_on(netdev);
netif_poll_enable(netdev);
+ spider_net_enable_interrupts(card);
+
return 0;
register_int_failed:
@@ -2113,11 +2214,7 @@ spider_net_stop(struct net_device *netdev)
del_timer_sync(&card->tx_timer);
del_timer_sync(&card->aneg_timer);
- /* disable/mask all interrupts */
- spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
- spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
- spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
- spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+ spider_net_disable_interrupts(card);
free_irq(netdev->irq, netdev);
@@ -2279,13 +2376,14 @@ spider_net_setup_netdev(struct spider_net_card *card)
result = spider_net_set_mac(netdev, &addr);
if ((result) && (netif_msg_probe(card)))
- pr_err("Failed to set MAC address: %i\n", result);
+ dev_err(&card->netdev->dev,
+ "Failed to set MAC address: %i\n", result);
result = register_netdev(netdev);
if (result) {
if (netif_msg_probe(card))
- pr_err("Couldn't register net_device: %i\n",
- result);
+ dev_err(&card->netdev->dev,
+ "Couldn't register net_device: %i\n", result);
return result;
}
@@ -2363,17 +2461,19 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
unsigned long mmio_start, mmio_len;
if (pci_enable_device(pdev)) {
- pr_err("Couldn't enable PCI device\n");
+ dev_err(&pdev->dev, "Couldn't enable PCI device\n");
return NULL;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
- pr_err("Couldn't find proper PCI device base address.\n");
+ dev_err(&pdev->dev,
+ "Couldn't find proper PCI device base address.\n");
goto out_disable_dev;
}
if (pci_request_regions(pdev, spider_net_driver_name)) {
- pr_err("Couldn't obtain PCI resources, aborting.\n");
+ dev_err(&pdev->dev,
+ "Couldn't obtain PCI resources, aborting.\n");
goto out_disable_dev;
}
@@ -2381,8 +2481,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
card = spider_net_alloc_card();
if (!card) {
- pr_err("Couldn't allocate net_device structure, "
- "aborting.\n");
+ dev_err(&pdev->dev,
+ "Couldn't allocate net_device structure, aborting.\n");
goto out_release_regions;
}
card->pdev = pdev;
@@ -2396,7 +2496,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
card->regs = ioremap(mmio_start, mmio_len);
if (!card->regs) {
- pr_err("Couldn't obtain PCI resources, aborting.\n");
+ dev_err(&pdev->dev,
+ "Couldn't obtain PCI resources, aborting.\n");
goto out_release_regions;
}
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 1d054aa7150..dbbdb8cee3c 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -349,11 +349,23 @@ enum spider_net_int2_status {
#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
#define SPIDER_NET_DMAC_NOINTR_COMPLETE 0x00800000
-#define SPIDER_NET_DMAC_NOCS 0x00040000
+#define SPIDER_NET_DMAC_TXFRMTL 0x00040000
#define SPIDER_NET_DMAC_TCP 0x00020000
#define SPIDER_NET_DMAC_UDP 0x00030000
#define SPIDER_NET_TXDCEST 0x08000000
+#define SPIDER_NET_DESCR_RXFDIS 0x00000001
+#define SPIDER_NET_DESCR_RXDCEIS 0x00000002
+#define SPIDER_NET_DESCR_RXDEN0IS 0x00000004
+#define SPIDER_NET_DESCR_RXINVDIS 0x00000008
+#define SPIDER_NET_DESCR_RXRERRIS 0x00000010
+#define SPIDER_NET_DESCR_RXFDCIMS 0x00000100
+#define SPIDER_NET_DESCR_RXDCEIMS 0x00000200
+#define SPIDER_NET_DESCR_RXDEN0IMS 0x00000400
+#define SPIDER_NET_DESCR_RXINVDIMS 0x00000800
+#define SPIDER_NET_DESCR_RXRERRMIS 0x00001000
+#define SPIDER_NET_DESCR_UNUSED 0x077fe0e0
+
#define SPIDER_NET_DESCR_IND_PROC_MASK 0xF0000000
#define SPIDER_NET_DESCR_COMPLETE 0x00000000 /* used in rx and tx */
#define SPIDER_NET_DESCR_RESPONSE_ERROR 0x10000000 /* used in rx and tx */
@@ -364,6 +376,13 @@ enum spider_net_int2_status {
#define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000
#define SPIDER_NET_DESCR_TXDESFLG 0x00800000
+#define SPIDER_NET_DESCR_BAD_STATUS (SPIDER_NET_DESCR_RXDEN0IS | \
+ SPIDER_NET_DESCR_RXRERRIS | \
+ SPIDER_NET_DESCR_RXDEN0IMS | \
+ SPIDER_NET_DESCR_RXINVDIMS | \
+ SPIDER_NET_DESCR_RXRERRMIS | \
+ SPIDER_NET_DESCR_UNUSED)
+
/* Descriptor, as defined by the hardware */
struct spider_net_hw_descr {
u32 buf_addr;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 51c3fe2108a..15146a11923 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2625,7 +2625,7 @@ static void quattro_sbus_free_irqs(void)
#endif /* CONFIG_SBUS */
#ifdef CONFIG_PCI
-static struct quattro * __init quattro_pci_find(struct pci_dev *pdev)
+static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev)
{
struct pci_dev *bdev = pdev->bus->self;
struct quattro *qp;
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 463d600ed83..75655add3f3 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -23,9 +23,9 @@
*/
#ifdef TC35815_NAPI
-#define DRV_VERSION "1.35-NAPI"
+#define DRV_VERSION "1.36-NAPI"
#else
-#define DRV_VERSION "1.35"
+#define DRV_VERSION "1.36"
#endif
static const char *version = "tc35815.c:v" DRV_VERSION "\n";
#define MODNAME "tc35815"
@@ -49,6 +49,7 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
#include <linux/pci.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -597,13 +598,46 @@ static int tc_mdio_read(struct net_device *dev, int phy_id, int location);
static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
int val);
-static void __devinit tc35815_init_dev_addr (struct net_device *dev)
+#ifdef CONFIG_CPU_TX49XX
+/*
+ * Find a platform_device providing a MAC address. The platform code
+ * should provide a "tc35815-mac" device with a MAC address in its
+ * platform_data.
+ */
+static int __devinit tc35815_mac_match(struct device *dev, void *data)
+{
+ struct platform_device *plat_dev = to_platform_device(dev);
+ struct pci_dev *pci_dev = data;
+ unsigned int id = (pci_dev->bus->number << 8) | pci_dev->devfn;
+ return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
+}
+
+static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+{
+ struct tc35815_local *lp = dev->priv;
+ struct device *pd = bus_find_device(&platform_bus_type, NULL,
+ lp->pci_dev, tc35815_mac_match);
+ if (pd) {
+ if (pd->platform_data)
+ memcpy(dev->dev_addr, pd->platform_data, ETH_ALEN);
+ put_device(pd);
+ return is_valid_ether_addr(dev->dev_addr) ? 0 : -ENODEV;
+ }
+ return -ENODEV;
+}
+#else
+static int __devinit tc35815_read_plat_dev_addr(struct device *dev)
+{
+ return -ENODEV;
+}
+#endif
+
+static int __devinit tc35815_init_dev_addr (struct net_device *dev)
{
struct tc35815_regs __iomem *tr =
(struct tc35815_regs __iomem *)dev->base_addr;
int i;
- /* dev_addr will be overwritten on NETDEV_REGISTER event */
while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)
;
for (i = 0; i < 6; i += 2) {
@@ -615,6 +649,9 @@ static void __devinit tc35815_init_dev_addr (struct net_device *dev)
dev->dev_addr[i] = data & 0xff;
dev->dev_addr[i+1] = data >> 8;
}
+ if (!is_valid_ether_addr(dev->dev_addr))
+ return tc35815_read_plat_dev_addr(dev);
+ return 0;
}
static int __devinit tc35815_init_one (struct pci_dev *pdev,
@@ -724,7 +761,10 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
tc35815_chip_reset(dev);
/* Retrieve the ethernet address. */
- tc35815_init_dev_addr(dev);
+ if (tc35815_init_dev_addr(dev)) {
+ dev_warn(&pdev->dev, "not valid ether addr\n");
+ random_ether_addr(dev->dev_addr);
+ }
rc = register_netdev (dev);
if (rc)
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index e22a3f5333e..9f1b6ab9c22 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -363,7 +363,7 @@ static int __devinit xl_probe(struct pci_dev *pdev,
}
-static int __init xl_init(struct net_device *dev)
+static int __devinit xl_init(struct net_device *dev)
{
struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 8c9634a98c1..1c537d5a306 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -2,17 +2,17 @@
# Tulip family network device configuration
#
-menu "Tulip family network device support"
- depends on NET_ETHERNET && (PCI || EISA || CARDBUS)
-
-config NET_TULIP
+menuconfig NET_TULIP
bool "\"Tulip\" family network device support"
+ depends on PCI || EISA || CARDBUS
help
This selects the "Tulip" family of EISA/PCI network cards.
+if NET_TULIP
+
config DE2104X
tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)"
- depends on NET_TULIP && PCI && EXPERIMENTAL
+ depends on PCI && EXPERIMENTAL
select CRC32
---help---
This driver is developed for the SMC EtherPower series Ethernet
@@ -30,7 +30,7 @@ config DE2104X
config TULIP
tristate "DECchip Tulip (dc2114x) PCI support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
---help---
This driver is developed for the SMC EtherPower series Ethernet
@@ -95,7 +95,7 @@ config TULIP_NAPI_HW_MITIGATION
config DE4X5
tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
- depends on NET_TULIP && (PCI || EISA)
+ depends on PCI || EISA
select CRC32
---help---
This is support for the DIGITAL series of PCI/EISA Ethernet cards.
@@ -112,7 +112,7 @@ config DE4X5
config WINBOND_840
tristate "Winbond W89c840 Ethernet support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
select MII
help
@@ -123,7 +123,7 @@ config WINBOND_840
config DM9102
tristate "Davicom DM910x/DM980x support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
---help---
This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
@@ -137,7 +137,7 @@ config DM9102
config ULI526X
tristate "ULi M526x controller support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
---help---
This driver is for ULi M5261/M5263 10/100M Ethernet Controller
@@ -149,7 +149,7 @@ config ULI526X
config PCMCIA_XIRCOM
tristate "Xircom CardBus support (new driver)"
- depends on NET_TULIP && CARDBUS
+ depends on CARDBUS
---help---
This driver is for the Digital "Tulip" Ethernet CardBus adapters.
It should work with most DEC 21*4*-based chips/ethercards, as well
@@ -162,7 +162,7 @@ config PCMCIA_XIRCOM
config PCMCIA_XIRTULIP
tristate "Xircom Tulip-like CardBus support (old driver)"
- depends on NET_TULIP && CARDBUS && BROKEN_ON_SMP
+ depends on CARDBUS && BROKEN_ON_SMP
select CRC32
---help---
This driver is for the Digital "Tulip" Ethernet CardBus adapters.
@@ -174,5 +174,4 @@ config PCMCIA_XIRTULIP
<file:Documentation/networking/net-modules.txt>. The module will
be called xircom_tulip_cb. If unsure, say N.
-endmenu
-
+endif # NET_TULIP
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 861729806dc..d380e0b3f05 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -785,7 +785,6 @@ static void __de_set_rx_mode (struct net_device *dev)
de->tx_head = NEXT_TX(entry);
- BUG_ON(TX_BUFFS_AVAIL(de) < 0);
if (TX_BUFFS_AVAIL(de) == 0)
netif_stop_queue(dev);
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 62143f92c23..42fca26afc5 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -597,7 +597,7 @@ static char *args;
#endif
struct parameters {
- int fdx;
+ bool fdx;
int autosense;
};
@@ -809,10 +809,10 @@ struct de4x5_private {
s32 irq_en; /* Summary interrupt bits */
int media; /* Media (eg TP), mode (eg 100B)*/
int c_media; /* Remember the last media conn */
- int fdx; /* media full duplex flag */
+ bool fdx; /* media full duplex flag */
int linkOK; /* Link is OK */
int autosense; /* Allow/disallow autosensing */
- int tx_enable; /* Enable descriptor polling */
+ bool tx_enable; /* Enable descriptor polling */
int setup_f; /* Setup frame filtering type */
int local_state; /* State within a 'media' state */
struct mii_phy phy[DE4X5_MAX_PHY]; /* List of attached PHY devices */
@@ -838,8 +838,8 @@ struct de4x5_private {
struct de4x5_srom srom; /* A copy of the SROM */
int cfrv; /* Card CFRV copy */
int rx_ovf; /* Check for 'RX overflow' tag */
- int useSROM; /* For non-DEC card use SROM */
- int useMII; /* Infoblock using the MII */
+ bool useSROM; /* For non-DEC card use SROM */
+ bool useMII; /* Infoblock using the MII */
int asBitValid; /* Autosense bits in GEP? */
int asPolarity; /* 0 => asserted high */
int asBit; /* Autosense bit number in GEP */
@@ -928,7 +928,7 @@ static int dc21040_state(struct net_device *dev, int csr13, int csr14, int c
static int test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec);
static int test_for_100Mb(struct net_device *dev, int msec);
static int wait_for_link(struct net_device *dev);
-static int test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec);
+static int test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec);
static int is_spd_100(struct net_device *dev);
static int is_100_up(struct net_device *dev);
static int is_10_up(struct net_device *dev);
@@ -1109,7 +1109,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
/*
** Now find out what kind of DC21040/DC21041/DC21140 board we have.
*/
- lp->useSROM = FALSE;
+ lp->useSROM = false;
if (lp->bus == PCI) {
PCI_signature(name, lp);
} else {
@@ -1137,7 +1137,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
lp->cache.gepc = GEP_INIT;
lp->asBit = GEP_SLNK;
lp->asPolarity = GEP_SLNK;
- lp->asBitValid = TRUE;
+ lp->asBitValid = ~0;
lp->timeout = -1;
lp->gendev = gendev;
spin_lock_init(&lp->lock);
@@ -1463,7 +1463,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
u_long flags = 0;
netif_stop_queue(dev);
- if (lp->tx_enable == NO) { /* Cannot send for now */
+ if (!lp->tx_enable) { /* Cannot send for now */
return -1;
}
@@ -2424,7 +2424,7 @@ dc21040_autoconf(struct net_device *dev)
switch (lp->media) {
case INIT:
DISABLE_IRQs;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
lp->timeout = -1;
de4x5_save_skbs(dev);
if ((lp->autosense == AUTO) || (lp->autosense == TP)) {
@@ -2477,7 +2477,7 @@ dc21040_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
break;
}
@@ -2578,7 +2578,7 @@ dc21041_autoconf(struct net_device *dev)
switch (lp->media) {
case INIT:
DISABLE_IRQs;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
lp->timeout = -1;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
if ((lp->autosense == AUTO) || (lp->autosense == TP_NW)) {
@@ -2757,7 +2757,7 @@ dc21041_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
break;
}
@@ -2781,7 +2781,7 @@ dc21140m_autoconf(struct net_device *dev)
case INIT:
if (lp->timeout < 0) {
DISABLE_IRQs;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
lp->linkOK = 0;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
}
@@ -2830,7 +2830,7 @@ dc21140m_autoconf(struct net_device *dev)
if (lp->timeout < 0) {
mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
}
- cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+ cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
if (cr < 0) {
next_tick = cr & ~TIMER_CB;
} else {
@@ -2845,7 +2845,7 @@ dc21140m_autoconf(struct net_device *dev)
break;
case 1:
- if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+ if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000)) < 0) {
next_tick = sr & ~TIMER_CB;
} else {
lp->media = SPD_DET;
@@ -2857,10 +2857,10 @@ dc21140m_autoconf(struct net_device *dev)
if (!(anlpa & MII_ANLPA_RF) &&
(cap = anlpa & MII_ANLPA_TAF & ana)) {
if (cap & MII_ANA_100M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
lp->media = _100Mb;
} else if (cap & MII_ANA_10M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
lp->media = _10Mb;
}
@@ -2932,7 +2932,7 @@ dc21140m_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
break;
}
@@ -2965,7 +2965,7 @@ dc2114x_autoconf(struct net_device *dev)
case INIT:
if (lp->timeout < 0) {
DISABLE_IRQs;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
lp->linkOK = 0;
lp->timeout = -1;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
@@ -3013,7 +3013,7 @@ dc2114x_autoconf(struct net_device *dev)
if (lp->timeout < 0) {
mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
}
- cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+ cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
if (cr < 0) {
next_tick = cr & ~TIMER_CB;
} else {
@@ -3028,7 +3028,8 @@ dc2114x_autoconf(struct net_device *dev)
break;
case 1:
- if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+ sr = test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000);
+ if (sr < 0) {
next_tick = sr & ~TIMER_CB;
} else {
lp->media = SPD_DET;
@@ -3040,10 +3041,10 @@ dc2114x_autoconf(struct net_device *dev)
if (!(anlpa & MII_ANLPA_RF) &&
(cap = anlpa & MII_ANLPA_TAF & ana)) {
if (cap & MII_ANA_100M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
lp->media = _100Mb;
} else if (cap & MII_ANA_10M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
lp->media = _10Mb;
}
}
@@ -3222,14 +3223,14 @@ srom_map_media(struct net_device *dev)
{
struct de4x5_private *lp = netdev_priv(dev);
- lp->fdx = 0;
+ lp->fdx = false;
if (lp->infoblock_media == lp->media)
return 0;
switch(lp->infoblock_media) {
case SROM_10BASETF:
if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
+ lp->fdx = true;
case SROM_10BASET:
if (lp->params.fdx && !lp->fdx) return -1;
if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) {
@@ -3249,7 +3250,7 @@ srom_map_media(struct net_device *dev)
case SROM_100BASETF:
if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
+ lp->fdx = true;
case SROM_100BASET:
if (lp->params.fdx && !lp->fdx) return -1;
lp->media = _100Mb;
@@ -3261,7 +3262,7 @@ srom_map_media(struct net_device *dev)
case SROM_100BASEFF:
if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
+ lp->fdx = true;
case SROM_100BASEF:
if (lp->params.fdx && !lp->fdx) return -1;
lp->media = _100Mb;
@@ -3297,7 +3298,7 @@ de4x5_init_connection(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
de4x5_rst_desc_ring(dev);
de4x5_setup_intr(dev);
- lp->tx_enable = YES;
+ lp->tx_enable = true;
spin_unlock_irqrestore(&lp->lock, flags);
outl(POLL_DEMAND, DE4X5_TPD);
@@ -3336,7 +3337,7 @@ de4x5_reset_phy(struct net_device *dev)
}
}
if (lp->useMII) {
- next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, FALSE, 500);
+ next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, false, 500);
}
} else if (lp->chipset == DC21140) {
PHY_HARD_RESET;
@@ -3466,7 +3467,7 @@ wait_for_link(struct net_device *dev)
**
*/
static int
-test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
+test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec)
{
struct de4x5_private *lp = netdev_priv(dev);
int test;
@@ -3476,9 +3477,8 @@ test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
lp->timeout = msec/100;
}
- if (pol) pol = ~0;
reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
- test = (reg ^ pol) & mask;
+ test = (reg ^ (pol ? ~0 : 0)) & mask;
if (test && --lp->timeout) {
reg = 100 | TIMER_CB;
@@ -3992,10 +3992,10 @@ PCI_signature(char *name, struct de4x5_private *lp)
)))))));
}
if (lp->chipset != DC21041) {
- lp->useSROM = TRUE; /* card is not recognisably DEC */
+ lp->useSROM = true; /* card is not recognisably DEC */
}
} else if ((lp->chipset & ~0x00ff) == DC2114x) {
- lp->useSROM = TRUE;
+ lp->useSROM = true;
}
return status;
@@ -4216,7 +4216,7 @@ srom_repair(struct net_device *dev, int card)
memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom));
memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN);
memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100);
- lp->useSROM = TRUE;
+ lp->useSROM = true;
break;
}
@@ -4392,7 +4392,7 @@ srom_infoleaf_info(struct net_device *dev)
if (lp->chipset == infoleaf_array[i].chipset) break;
}
if (i == INFOLEAF_SIZE) {
- lp->useSROM = FALSE;
+ lp->useSROM = false;
printk("%s: Cannot find correct chipset for SROM decoding!\n",
dev->name);
return -ENXIO;
@@ -4409,7 +4409,7 @@ srom_infoleaf_info(struct net_device *dev)
if (lp->device == *p) break;
}
if (i == 0) {
- lp->useSROM = FALSE;
+ lp->useSROM = false;
printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n",
dev->name, lp->device);
return -ENXIO;
@@ -4542,7 +4542,7 @@ dc21140_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@@ -4577,7 +4577,7 @@ dc21142_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@@ -4611,7 +4611,7 @@ dc21143_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@@ -4650,7 +4650,7 @@ compact_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -4691,7 +4691,7 @@ type0_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -4731,7 +4731,7 @@ type1_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->ibn = 1;
lp->active = *p;
lp->infoblock_csr6 = OMR_MII_100;
- lp->useMII = TRUE;
+ lp->useMII = true;
lp->infoblock_media = ANS;
de4x5_switch_mac_port(dev);
@@ -4773,7 +4773,7 @@ type2_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
lp->cache.gep = ((s32)(TWIDDLE(p)) << 16);
lp->infoblock_csr6 = OMR_SIA;
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -4814,7 +4814,7 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->active = *p;
if (MOTO_SROM_BUG) lp->active = 0;
lp->infoblock_csr6 = OMR_MII_100;
- lp->useMII = TRUE;
+ lp->useMII = true;
lp->infoblock_media = ANS;
de4x5_switch_mac_port(dev);
@@ -4856,7 +4856,7 @@ type4_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -5077,7 +5077,7 @@ mii_get_phy(struct net_device *dev)
int id;
lp->active = 0;
- lp->useMII = TRUE;
+ lp->useMII = true;
/* Search the MII address space for possible PHY devices */
for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
@@ -5127,7 +5127,7 @@ mii_get_phy(struct net_device *dev)
de4x5_dbg_mii(dev, k);
}
}
- if (!lp->mii_cnt) lp->useMII = FALSE;
+ if (!lp->mii_cnt) lp->useMII = false;
return lp->mii_cnt;
}
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
index 57226e5eb8a..12af0cc037f 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/tulip/de4x5.h
@@ -893,15 +893,6 @@
#define PHYS_ADDR_ONLY 1 /* Update the physical address only */
/*
-** Booleans
-*/
-#define NO 0
-#define FALSE 0
-
-#define YES ~0
-#define TRUE ~0
-
-/*
** Adapter state
*/
#define INITIALISED 0 /* After h/w initialised and mem alloc'd */
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 18b731bb4da..e4736a3b1b7 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -2276,7 +2276,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
phy_stop(phydev);
/* Mask all interrupts */
- out_be32(ugeth->uccf->p_ucce, 0x00000000);
+ out_be32(ugeth->uccf->p_uccm, 0x00000000);
/* Clear all interrupts */
out_be32(ugeth->uccf->p_ucce, 0xffffffff);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index a12f576391c..37bf4f2c0a4 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -192,7 +192,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
usb_pipeendpoint(pipe), maxp, period);
}
}
- return 0;
+ return 0;
}
/* Passes this packet up the stack, updating its accounting.
@@ -326,7 +326,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
if (netif_running (dev->net)
&& netif_device_present (dev->net)
&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
- switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
+ switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
case -EPIPE:
usbnet_defer_kevent (dev, EVENT_RX_HALT);
break;
@@ -393,8 +393,8 @@ static void rx_complete (struct urb *urb)
entry->urb = NULL;
switch (urb_status) {
- // success
- case 0:
+ /* success */
+ case 0:
if (skb->len < dev->net->hard_header_len) {
entry->state = rx_cleanup;
dev->stats.rx_errors++;
@@ -404,28 +404,30 @@ static void rx_complete (struct urb *urb)
}
break;
- // stalls need manual reset. this is rare ... except that
- // when going through USB 2.0 TTs, unplug appears this way.
- // we avoid the highspeed version of the ETIMEOUT/EILSEQ
- // storm, recovering as needed.
- case -EPIPE:
+ /* stalls need manual reset. this is rare ... except that
+ * when going through USB 2.0 TTs, unplug appears this way.
+ * we avoid the highspeed version of the ETIMEOUT/EILSEQ
+ * storm, recovering as needed.
+ */
+ case -EPIPE:
dev->stats.rx_errors++;
usbnet_defer_kevent (dev, EVENT_RX_HALT);
// FALLTHROUGH
- // software-driven interface shutdown
- case -ECONNRESET: // async unlink
- case -ESHUTDOWN: // hardware gone
+ /* software-driven interface shutdown */
+ case -ECONNRESET: /* async unlink */
+ case -ESHUTDOWN: /* hardware gone */
if (netif_msg_ifdown (dev))
devdbg (dev, "rx shutdown, code %d", urb_status);
goto block;
- // we get controller i/o faults during khubd disconnect() delays.
- // throttle down resubmits, to avoid log floods; just temporarily,
- // so we still recover when the fault isn't a khubd delay.
- case -EPROTO:
- case -ETIME:
- case -EILSEQ:
+ /* we get controller i/o faults during khubd disconnect() delays.
+ * throttle down resubmits, to avoid log floods; just temporarily,
+ * so we still recover when the fault isn't a khubd delay.
+ */
+ case -EPROTO:
+ case -ETIME:
+ case -EILSEQ:
dev->stats.rx_errors++;
if (!timer_pending (&dev->delay)) {
mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
@@ -438,12 +440,12 @@ block:
urb = NULL;
break;
- // data overrun ... flush fifo?
- case -EOVERFLOW:
+ /* data overrun ... flush fifo? */
+ case -EOVERFLOW:
dev->stats.rx_over_errors++;
// FALLTHROUGH
- default:
+ default:
entry->state = rx_cleanup;
dev->stats.rx_errors++;
if (netif_msg_rx_err (dev))
@@ -471,22 +473,22 @@ static void intr_complete (struct urb *urb)
int status = urb->status;
switch (status) {
- /* success */
- case 0:
+ /* success */
+ case 0:
dev->driver_info->status(dev, urb);
break;
- /* software-driven interface shutdown */
- case -ENOENT: // urb killed
- case -ESHUTDOWN: // hardware gone
+ /* software-driven interface shutdown */
+ case -ENOENT: /* urb killed */
+ case -ESHUTDOWN: /* hardware gone */
if (netif_msg_ifdown (dev))
devdbg (dev, "intr shutdown, code %d", status);
return;
- /* NOTE: not throttling like RX/TX, since this endpoint
- * already polls infrequently
- */
- default:
+ /* NOTE: not throttling like RX/TX, since this endpoint
+ * already polls infrequently
+ */
+ default:
devdbg (dev, "intr status %d", status);
break;
}
@@ -569,9 +571,9 @@ static int usbnet_stop (struct net_device *net)
temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);
// maybe wait for deletions to finish.
- while (!skb_queue_empty(&dev->rxq) &&
- !skb_queue_empty(&dev->txq) &&
- !skb_queue_empty(&dev->done)) {
+ while (!skb_queue_empty(&dev->rxq)
+ && !skb_queue_empty(&dev->txq)
+ && !skb_queue_empty(&dev->done)) {
msleep(UNLINK_TIMEOUT_MS);
if (netif_msg_ifdown (dev))
devdbg (dev, "waited for %d urb completions", temp);
@@ -1011,16 +1013,16 @@ static void usbnet_bh (unsigned long param)
while ((skb = skb_dequeue (&dev->done))) {
entry = (struct skb_data *) skb->cb;
switch (entry->state) {
- case rx_done:
+ case rx_done:
entry->state = rx_cleanup;
rx_process (dev, skb);
continue;
- case tx_done:
- case rx_cleanup:
+ case tx_done:
+ case rx_cleanup:
usb_free_urb (entry->urb);
dev_kfree_skb (skb);
continue;
- default:
+ default:
devdbg (dev, "bogus skb state %d", entry->state);
}
}
@@ -1211,7 +1213,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
status = 0;
}
- if (status == 0 && dev->status)
+ if (status >= 0 && dev->status)
status = init_status (dev, udev);
if (status < 0)
goto out3;
diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h
index a3f8b9e7bc0..a6c5820767d 100644
--- a/drivers/net/usb/usbnet.h
+++ b/drivers/net/usb/usbnet.h
@@ -47,7 +47,7 @@ struct usbnet {
unsigned long data [5];
u32 xid;
u32 hard_mtu; /* count any extra framing */
- size_t rx_urb_size; /* size for rx urbs */
+ size_t rx_urb_size; /* size for rx urbs */
struct mii_if_info mii;
/* various kinds of pending driver work */
@@ -85,7 +85,7 @@ struct driver_info {
#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
-#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
+#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
/* init device ... can sleep, or cause probe() failure */
int (*bind)(struct usbnet *, struct usb_interface *);
@@ -146,9 +146,9 @@ extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *);
/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
- |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
- |USB_CDC_PACKET_TYPE_PROMISCUOUS \
- |USB_CDC_PACKET_TYPE_DIRECTED)
+ |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+ |USB_CDC_PACKET_TYPE_PROMISCUOUS \
+ |USB_CDC_PACKET_TYPE_DIRECTED)
/* we record the state for each of our queued skbs */
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fa2399cbd5c..ae27af0141c 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -546,6 +546,18 @@ config USB_ZD1201
To compile this driver as a module, choose M here: the
module will be called zd1201.
+config RTL8187
+ tristate "Realtek 8187 USB support"
+ depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
+ select EEPROM_93CX6
+ ---help---
+ This is a driver for RTL8187 based cards.
+ These are USB based chips found in cards such as:
+
+ Netgear WG111v2
+
+ Thanks to Realtek for their support!
+
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index d2124602263..ef35bc6c4a2 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -44,3 +44,6 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
obj-$(CONFIG_LIBERTAS_USB) += libertas/
+
+rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o
+obj-$(CONFIG_RTL8187) += rtl8187.o
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index b37f1e34870..d779199c30d 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -1638,7 +1638,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
return;
}
- if (phy->analog > 1) {
+ if (phy->analog == 1) {
value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
value |= (baseband_attenuation << 2) & 0x003C;
} else {
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 5b3abd54d0e..90900525379 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -326,7 +326,6 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
char *p = page;
struct ap_data *ap = (struct ap_data *) data;
char *policy_txt;
- struct list_head *ptr;
struct mac_entry *entry;
if (off != 0) {
@@ -352,14 +351,12 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
p += sprintf(p, "MAC list:\n");
spin_lock_bh(&ap->mac_restrictions.lock);
- for (ptr = ap->mac_restrictions.mac_list.next;
- ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
+ list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) {
if (p - page > PAGE_SIZE - 80) {
p += sprintf(p, "All entries did not fit one page.\n");
break;
}
- entry = list_entry(ptr, struct mac_entry, list);
p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
}
spin_unlock_bh(&ap->mac_restrictions.lock);
@@ -413,7 +410,6 @@ int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
u8 *mac)
{
- struct list_head *ptr;
struct mac_entry *entry;
int found = 0;
@@ -421,10 +417,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
return 0;
spin_lock_bh(&mac_restrictions->lock);
- for (ptr = mac_restrictions->mac_list.next;
- ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
- entry = list_entry(ptr, struct mac_entry, list);
-
+ list_for_each_entry(entry, &mac_restrictions->mac_list, list) {
if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
found = 1;
break;
@@ -519,7 +512,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
{
char *p = page;
struct ap_data *ap = (struct ap_data *) data;
- struct list_head *ptr;
+ struct sta_info *sta;
int i;
if (off > PROC_LIMIT) {
@@ -529,9 +522,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
spin_lock_bh(&ap->sta_table_lock);
- for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
- struct sta_info *sta = (struct sta_info *) ptr;
-
+ list_for_each_entry(sta, &ap->sta_list, list) {
if (!sta->ap)
continue;
@@ -861,7 +852,7 @@ void hostap_init_ap_proc(local_info_t *local)
void hostap_free_data(struct ap_data *ap)
{
- struct list_head *n, *ptr;
+ struct sta_info *n, *sta;
if (ap == NULL || !ap->initialized) {
printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
@@ -875,8 +866,7 @@ void hostap_free_data(struct ap_data *ap)
ap->crypt = ap->crypt_priv = NULL;
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
- list_for_each_safe(ptr, n, &ap->sta_list) {
- struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ list_for_each_entry_safe(sta, n, &ap->sta_list, list) {
ap_sta_hash_del(ap, sta);
list_del(&sta->list);
if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
@@ -2704,6 +2694,8 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
if (hdr->addr1[0] & 0x01) {
/* broadcast/multicast frame - no AP related processing */
+ if (local->ap->num_sta <= 0)
+ ret = AP_TX_DROP;
goto out;
}
@@ -3198,15 +3190,14 @@ int hostap_update_rx_stats(struct ap_data *ap,
void hostap_update_rates(local_info_t *local)
{
- struct list_head *ptr;
+ struct sta_info *sta;
struct ap_data *ap = local->ap;
if (!ap)
return;
spin_lock_bh(&ap->sta_table_lock);
- for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
- struct sta_info *sta = (struct sta_info *) ptr;
+ list_for_each_entry(sta, &ap->sta_list, list) {
prism2_check_tx_rates(sta);
}
spin_unlock_bh(&ap->sta_table_lock);
@@ -3242,11 +3233,10 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
void hostap_add_wds_links(local_info_t *local)
{
struct ap_data *ap = local->ap;
- struct list_head *ptr;
+ struct sta_info *sta;
spin_lock_bh(&ap->sta_table_lock);
- list_for_each(ptr, &ap->sta_list) {
- struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ list_for_each_entry(sta, &ap->sta_list, list) {
if (sta->ap)
hostap_wds_link_oper(local, sta->addr, WDS_ADD);
}
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index c090a5aebb5..30acd39d76a 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -1,8 +1,6 @@
#ifndef HOSTAP_CONFIG_H
#define HOSTAP_CONFIG_H
-#define PRISM2_VERSION "0.4.4-kernel"
-
/* In the previous versions of Host AP driver, support for user space version
* of IEEE 802.11 management (hostapd) used to be disabled in the default
* configuration. From now on, support for hostapd is always included and it is
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ee1532b62e4..30e723f6597 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -22,7 +22,6 @@
#include "hostap_wlan.h"
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
static dev_info_t dev_info = "hostap_cs";
MODULE_AUTHOR("Jouni Malinen");
@@ -30,7 +29,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PC Card).");
MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
static int ignore_cis_vcc;
@@ -910,14 +908,12 @@ static struct pcmcia_driver hostap_driver = {
static int __init init_prism2_pccard(void)
{
- printk(KERN_INFO "%s: %s\n", dev_info, version);
return pcmcia_register_driver(&hostap_driver);
}
static void __exit exit_prism2_pccard(void)
{
pcmcia_unregister_driver(&hostap_driver);
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index cdea7f71b9e..8c71077d653 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3893,8 +3893,6 @@ static void prism2_get_drvinfo(struct net_device *dev,
local = iface->local;
strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
- strncpy(info->version, PRISM2_VERSION,
- sizeof(info->version) - 1);
snprintf(info->fw_version, sizeof(info->fw_version) - 1,
"%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
(local->sta_fw_ver >> 8) & 0xff,
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 4743426cf6a..446de51bab7 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -37,7 +37,6 @@
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP common routines");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
#define TX_TIMEOUT (2 * HZ)
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index db4899ed4bb..0cd48d151f5 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -20,7 +20,6 @@
#include "hostap_wlan.h"
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
static char *dev_info = "hostap_pci";
@@ -29,7 +28,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
"PCI cards.");
MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
/* struct local_info::hw_priv */
@@ -462,8 +460,6 @@ static struct pci_driver prism2_pci_drv_id = {
static int __init init_prism2_pci(void)
{
- printk(KERN_INFO "%s: %s\n", dev_info, version);
-
return pci_register_driver(&prism2_pci_drv_id);
}
@@ -471,7 +467,6 @@ static int __init init_prism2_pci(void)
static void __exit exit_prism2_pci(void)
{
pci_unregister_driver(&prism2_pci_drv_id);
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index f0fd5ecdb24..0183df757b3 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -23,7 +23,6 @@
#include "hostap_wlan.h"
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
static char *dev_info = "hostap_plx";
@@ -32,7 +31,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PLX).");
MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
static int ignore_cis;
@@ -623,8 +621,6 @@ static struct pci_driver prism2_plx_drv_id = {
static int __init init_prism2_plx(void)
{
- printk(KERN_INFO "%s: %s\n", dev_info, version);
-
return pci_register_driver(&prism2_plx_drv_id);
}
@@ -632,7 +628,6 @@ static int __init init_prism2_plx(void)
static void __exit exit_prism2_plx(void)
{
pci_unregister_driver(&prism2_plx_drv_id);
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
new file mode 100644
index 00000000000..6124e467b15
--- /dev/null
+++ b/drivers/net/wireless/rtl8187.h
@@ -0,0 +1,145 @@
+/*
+ * Definitions for RTL8187 hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * 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.
+ */
+
+#ifndef RTL8187_H
+#define RTL8187_H
+
+#include "rtl818x.h"
+
+#define RTL8187_EEPROM_TXPWR_BASE 0x05
+#define RTL8187_EEPROM_MAC_ADDR 0x07
+#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */
+
+#define RTL8187_REQT_READ 0xC0
+#define RTL8187_REQT_WRITE 0x40
+#define RTL8187_REQ_GET_REG 0x05
+#define RTL8187_REQ_SET_REG 0x05
+
+#define RTL8187_MAX_RX 0x9C4
+
+struct rtl8187_rx_info {
+ struct urb *urb;
+ struct ieee80211_hw *dev;
+};
+
+struct rtl8187_rx_hdr {
+ __le16 len;
+ __le16 rate;
+ u8 noise;
+ u8 signal;
+ u8 agc;
+ u8 reserved;
+ __le64 mac_time;
+} __attribute__((packed));
+
+struct rtl8187_tx_info {
+ struct ieee80211_tx_control *control;
+ struct urb *urb;
+ struct ieee80211_hw *dev;
+};
+
+struct rtl8187_tx_hdr {
+ __le32 flags;
+#define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15)
+#define RTL8187_TX_FLAG_MORE_FRAG (1 << 17)
+#define RTL8187_TX_FLAG_CTS (1 << 18)
+#define RTL8187_TX_FLAG_RTS (1 << 23)
+ __le16 rts_duration;
+ __le16 len;
+ __le32 retry;
+} __attribute__((packed));
+
+struct rtl8187_priv {
+ /* common between rtl818x drivers */
+ struct rtl818x_csr *map;
+ void (*rf_init)(struct ieee80211_hw *);
+ int mode;
+
+ /* rtl8187 specific */
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+ struct ieee80211_hw_mode modes[2];
+ struct usb_device *udev;
+ u8 *hwaddr;
+ u16 txpwr_base;
+ u8 asic_rev;
+ struct sk_buff_head rx_queue;
+};
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
+
+static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
+{
+ u8 val;
+
+ usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+ RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+ return val;
+}
+
+static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
+{
+ __le16 val;
+
+ usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+ RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+ return le16_to_cpu(val);
+}
+
+static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
+{
+ __le32 val;
+
+ usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+ RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+ return le32_to_cpu(val);
+}
+
+static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
+ u8 *addr, u8 val)
+{
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+}
+
+static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
+ __le16 *addr, u16 val)
+{
+ __le16 buf = cpu_to_le16(val);
+
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
+ __le32 *addr, u32 val)
+{
+ __le32 buf = cpu_to_le32(val);
+
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+#endif /* RTL8187_H */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
new file mode 100644
index 00000000000..cea85894b7f
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -0,0 +1,731 @@
+/*
+ * Linux device driver for RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays and register offsets below are taken from the original
+ * r8187 driver sources. Thanks to Realtek for their support!
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/eeprom_93cx6.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
+MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
+MODULE_DESCRIPTION("RTL8187 USB wireless driver");
+MODULE_LICENSE("GPL");
+
+static struct usb_device_id rtl8187_table[] __devinitdata = {
+ /* Realtek */
+ {USB_DEVICE(0x0bda, 0x8187)},
+ /* Netgear */
+ {USB_DEVICE(0x0846, 0x6100)},
+ {USB_DEVICE(0x0846, 0x6a00)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, rtl8187_table);
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ data <<= 8;
+ data |= addr | 0x80;
+
+ rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF);
+ rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
+ rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
+ rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
+
+ msleep(1);
+}
+
+static void rtl8187_tx_cb(struct urb *urb)
+{
+ struct ieee80211_tx_status status = { {0} };
+ struct sk_buff *skb = (struct sk_buff *)urb->context;
+ struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
+
+ usb_free_urb(info->urb);
+ if (info->control)
+ memcpy(&status.control, info->control, sizeof(status.control));
+ kfree(info->control);
+ skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
+ status.flags |= IEEE80211_TX_STATUS_ACK;
+ ieee80211_tx_status_irqsafe(info->dev, skb, &status);
+}
+
+static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_tx_hdr *hdr;
+ struct rtl8187_tx_info *info;
+ struct urb *urb;
+ u32 tmp;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ tmp = skb->len - sizeof(*hdr);
+ tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
+ tmp |= control->rts_cts_rate << 19;
+ tmp |= control->tx_rate << 24;
+ if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
+ tmp |= RTL8187_TX_FLAG_MORE_FRAG;
+ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+ tmp |= RTL8187_TX_FLAG_RTS;
+ hdr->rts_duration =
+ ieee80211_rts_duration(dev, skb->len, control);
+ }
+ if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+ tmp |= RTL8187_TX_FLAG_CTS;
+ hdr->flags = cpu_to_le32(tmp);
+ hdr->len = 0;
+ tmp = control->retry_limit << 8;
+ hdr->retry = cpu_to_le32(tmp);
+
+ info = (struct rtl8187_tx_info *)skb->cb;
+ info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
+ info->urb = urb;
+ info->dev = dev;
+ usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
+ hdr, skb->len, rtl8187_tx_cb, skb);
+ usb_submit_urb(urb, GFP_ATOMIC);
+
+ return 0;
+}
+
+static void rtl8187_rx_cb(struct urb *urb)
+{
+ struct sk_buff *skb = (struct sk_buff *)urb->context;
+ struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
+ struct ieee80211_hw *dev = info->dev;
+ struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_rx_hdr *hdr;
+ struct ieee80211_rx_status rx_status = { 0 };
+ int rate, signal;
+
+ spin_lock(&priv->rx_queue.lock);
+ if (skb->next)
+ __skb_unlink(skb, &priv->rx_queue);
+ else {
+ spin_unlock(&priv->rx_queue.lock);
+ return;
+ }
+ spin_unlock(&priv->rx_queue.lock);
+
+ if (unlikely(urb->status)) {
+ usb_free_urb(urb);
+ dev_kfree_skb_irq(skb);
+ return;
+ }
+
+ skb_put(skb, urb->actual_length);
+ hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
+ skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF);
+
+ signal = hdr->agc >> 1;
+ rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF;
+ if (rate > 3) { /* OFDM rate */
+ if (signal > 90)
+ signal = 90;
+ else if (signal < 25)
+ signal = 25;
+ signal = 90 - signal;
+ } else { /* CCK rate */
+ if (signal > 95)
+ signal = 95;
+ else if (signal < 30)
+ signal = 30;
+ signal = 95 - signal;
+ }
+
+ rx_status.antenna = (hdr->signal >> 7) & 1;
+ rx_status.signal = 64 - min(hdr->noise, (u8)64);
+ rx_status.ssi = signal;
+ rx_status.rate = rate;
+ rx_status.freq = dev->conf.freq;
+ rx_status.channel = dev->conf.channel;
+ rx_status.phymode = dev->conf.phymode;
+ rx_status.mactime = le64_to_cpu(hdr->mac_time);
+ ieee80211_rx_irqsafe(dev, skb, &rx_status);
+
+ skb = dev_alloc_skb(RTL8187_MAX_RX);
+ if (unlikely(!skb)) {
+ usb_free_urb(urb);
+ /* TODO check rx queue length and refill *somewhere* */
+ return;
+ }
+
+ info = (struct rtl8187_rx_info *)skb->cb;
+ info->urb = urb;
+ info->dev = dev;
+ urb->transfer_buffer = skb_tail_pointer(skb);
+ urb->context = skb;
+ skb_queue_tail(&priv->rx_queue, skb);
+
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int rtl8187_init_urbs(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct urb *entry;
+ struct sk_buff *skb;
+ struct rtl8187_rx_info *info;
+
+ while (skb_queue_len(&priv->rx_queue) < 8) {
+ skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
+ if (!skb)
+ break;
+ entry = usb_alloc_urb(0, GFP_KERNEL);
+ if (!entry) {
+ kfree_skb(skb);
+ break;
+ }
+ usb_fill_bulk_urb(entry, priv->udev,
+ usb_rcvbulkpipe(priv->udev, 1),
+ skb_tail_pointer(skb),
+ RTL8187_MAX_RX, rtl8187_rx_cb, skb);
+ info = (struct rtl8187_rx_info *)skb->cb;
+ info->urb = entry;
+ info->dev = dev;
+ skb_queue_tail(&priv->rx_queue, skb);
+ usb_submit_urb(entry, GFP_KERNEL);
+ }
+
+ return 0;
+}
+
+static int rtl8187_init_hw(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 reg;
+ int i;
+
+ /* reset */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+ msleep(200);
+ rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10);
+ rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11);
+ rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00);
+ msleep(200);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= (1 << 1);
+ reg |= RTL818X_CMD_RESET;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ i = 10;
+ do {
+ msleep(2);
+ if (!(rtl818x_ioread8(priv, &priv->map->CMD) &
+ RTL818X_CMD_RESET))
+ break;
+ } while (--i);
+
+ if (!i) {
+ printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
+ return -ETIMEDOUT;
+ }
+
+ /* reload registers from eeprom */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
+
+ i = 10;
+ do {
+ msleep(4);
+ if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) &
+ RTL818X_EEPROM_CMD_CONFIG))
+ break;
+ } while (--i);
+
+ if (!i) {
+ printk(KERN_ERR "%s: eeprom reset timeout!\n",
+ wiphy_name(dev->wiphy));
+ return -ETIMEDOUT;
+ }
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ /* setup card */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
+
+ rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
+ reg &= 0x3F;
+ reg |= 0x80;
+ rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
+ rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
+ rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+
+ // TODO: set RESP_RATE and BRSR properly
+ rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+
+ /* host_usb_init */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+ reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
+ rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80);
+ msleep(100);
+
+ rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+ rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
+ msleep(100);
+
+ priv->rf_init(dev);
+
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+ reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
+ rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
+ rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
+ rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+
+ return 0;
+}
+
+static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
+{
+ u32 reg;
+ struct rtl8187_priv *priv = dev->priv;
+
+ reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ /* Enable TX loopback on MAC level to avoid TX during channel
+ * changes, as this has be seen to causes problems and the
+ * card will stop work until next reset
+ */
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+ reg | RTL818X_TX_CONF_LOOPBACK_MAC);
+ msleep(10);
+ rtl8225_rf_set_channel(dev, channel);
+ msleep(10);
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+}
+
+static int rtl8187_open(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u32 reg;
+ int ret;
+
+ ret = rtl8187_init_hw(dev);
+ if (ret)
+ return ret;
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+
+ rtl8187_init_urbs(dev);
+
+ reg = RTL818X_RX_CONF_ONLYERLPKT |
+ RTL818X_RX_CONF_RX_AUTORESETPHY |
+ RTL818X_RX_CONF_BSSID |
+ RTL818X_RX_CONF_MGMT |
+ RTL818X_RX_CONF_CTRL |
+ RTL818X_RX_CONF_DATA |
+ (7 << 13 /* RX FIFO threshold NONE */) |
+ (7 << 10 /* MAX RX DMA */) |
+ RTL818X_RX_CONF_BROADCAST |
+ RTL818X_RX_CONF_MULTICAST |
+ RTL818X_RX_CONF_NICMAC;
+ if (priv->mode == IEEE80211_IF_TYPE_MNTR)
+ reg |= RTL818X_RX_CONF_MONITOR;
+
+ rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
+ reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
+ reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+ rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+ reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
+ rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
+
+ reg = RTL818X_TX_CONF_CW_MIN |
+ (7 << 21 /* MAX TX DMA */) |
+ RTL818X_TX_CONF_NO_ICV;
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg |= RTL818X_CMD_TX_ENABLE;
+ reg |= RTL818X_CMD_RX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ return 0;
+}
+
+static int rtl8187_stop(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_rx_info *info;
+ struct sk_buff *skb;
+ u32 reg;
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= ~RTL818X_CMD_TX_ENABLE;
+ reg &= ~RTL818X_CMD_RX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ rtl8225_rf_stop(dev);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ while ((skb = skb_dequeue(&priv->rx_queue))) {
+ info = (struct rtl8187_rx_info *)skb->cb;
+ usb_kill_urb(info->urb);
+ kfree_skb(skb);
+ }
+ return 0;
+}
+
+static int rtl8187_add_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */
+ if (priv->mode != IEEE80211_IF_TYPE_MGMT)
+ return -1;
+
+ switch (conf->type) {
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_MNTR:
+ priv->mode = conf->type;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ priv->hwaddr = conf->mac_addr;
+
+ return 0;
+}
+
+static void rtl8187_remove_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ priv->mode = IEEE80211_IF_TYPE_MGMT;
+}
+
+static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ rtl8187_set_channel(dev, conf->channel);
+
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+
+ if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+ } else {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
+ rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
+ rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
+ rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
+ return 0;
+}
+
+static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
+ struct ieee80211_if_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
+
+ if (is_valid_ether_addr(conf->bssid))
+ rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
+ else
+ rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
+
+ return 0;
+}
+
+static const struct ieee80211_ops rtl8187_ops = {
+ .tx = rtl8187_tx,
+ .open = rtl8187_open,
+ .stop = rtl8187_stop,
+ .add_interface = rtl8187_add_interface,
+ .remove_interface = rtl8187_remove_interface,
+ .config = rtl8187_config,
+ .config_interface = rtl8187_config_interface,
+};
+
+static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+ struct ieee80211_hw *dev = eeprom->data;
+ struct rtl8187_priv *priv = dev->priv;
+ u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+
+ eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
+ eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
+ eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
+ eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+}
+
+static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+ struct ieee80211_hw *dev = eeprom->data;
+ struct rtl8187_priv *priv = dev->priv;
+ u8 reg = RTL818X_EEPROM_CMD_PROGRAM;
+
+ if (eeprom->reg_data_in)
+ reg |= RTL818X_EEPROM_CMD_WRITE;
+ if (eeprom->reg_data_out)
+ reg |= RTL818X_EEPROM_CMD_READ;
+ if (eeprom->reg_data_clock)
+ reg |= RTL818X_EEPROM_CMD_CK;
+ if (eeprom->reg_chip_select)
+ reg |= RTL818X_EEPROM_CMD_CS;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
+ udelay(10);
+}
+
+static int __devinit rtl8187_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct ieee80211_hw *dev;
+ struct rtl8187_priv *priv;
+ struct eeprom_93cx6 eeprom;
+ struct ieee80211_channel *channel;
+ u16 txpwr, reg;
+ int err, i;
+
+ dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
+ if (!dev) {
+ printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n");
+ return -ENOMEM;
+ }
+
+ priv = dev->priv;
+
+ SET_IEEE80211_DEV(dev, &intf->dev);
+ usb_set_intfdata(intf, dev);
+ priv->udev = udev;
+
+ usb_get_dev(udev);
+
+ skb_queue_head_init(&priv->rx_queue);
+ memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+ memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+ priv->map = (struct rtl818x_csr *)0xFF00;
+ priv->modes[0].mode = MODE_IEEE80211G;
+ priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+ priv->modes[0].rates = priv->rates;
+ priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+ priv->modes[0].channels = priv->channels;
+ priv->modes[1].mode = MODE_IEEE80211B;
+ priv->modes[1].num_rates = 4;
+ priv->modes[1].rates = priv->rates;
+ priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+ priv->modes[1].channels = priv->channels;
+ priv->mode = IEEE80211_IF_TYPE_MGMT;
+ dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_WEP_INCLUDE_IV |
+ IEEE80211_HW_DATA_NULLFUNC_ACK;
+ dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
+ dev->queues = 1;
+ dev->max_rssi = 65;
+ dev->max_signal = 64;
+
+ for (i = 0; i < 2; i++)
+ if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
+ goto err_free_dev;
+
+ eeprom.data = dev;
+ eeprom.register_read = rtl8187_eeprom_register_read;
+ eeprom.register_write = rtl8187_eeprom_register_write;
+ if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
+ eeprom.width = PCI_EEPROM_WIDTH_93C66;
+ else
+ eeprom.width = PCI_EEPROM_WIDTH_93C46;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ udelay(10);
+
+ eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR,
+ (__le16 __force *)dev->wiphy->perm_addr, 3);
+ if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+ printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly "
+ "generated MAC address\n");
+ random_ether_addr(dev->wiphy->perm_addr);
+ }
+
+ channel = priv->channels;
+ for (i = 0; i < 3; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
+ &txpwr);
+ (*channel++).val = txpwr & 0xFF;
+ (*channel++).val = txpwr >> 8;
+ }
+ for (i = 0; i < 2; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
+ &txpwr);
+ (*channel++).val = txpwr & 0xFF;
+ (*channel++).val = txpwr >> 8;
+ }
+ for (i = 0; i < 2; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
+ &txpwr);
+ (*channel++).val = txpwr & 0xFF;
+ (*channel++).val = txpwr >> 8;
+ }
+
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
+ &priv->txpwr_base);
+
+ reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
+ /* 0 means asic B-cut, we should use SW 3 wire
+ * bit-by-bit banging for radio. 1 means we can use
+ * USB specific request to write radio registers */
+ priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write(dev, 0, 0x1B7);
+
+ if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
+ priv->rf_init = rtl8225_rf_init;
+ else
+ priv->rf_init = rtl8225z2_rf_init;
+
+ rtl8225_write(dev, 0, 0x0B7);
+
+ err = ieee80211_register_hw(dev);
+ if (err) {
+ printk(KERN_ERR "rtl8187: Cannot register device\n");
+ goto err_free_dev;
+ }
+
+ printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n",
+ wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr),
+ priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
+ "rtl8225" : "rtl8225z2");
+
+ return 0;
+
+ err_free_dev:
+ ieee80211_free_hw(dev);
+ usb_set_intfdata(intf, NULL);
+ usb_put_dev(udev);
+ return err;
+}
+
+static void __devexit rtl8187_disconnect(struct usb_interface *intf)
+{
+ struct ieee80211_hw *dev = usb_get_intfdata(intf);
+ struct rtl8187_priv *priv;
+
+ if (!dev)
+ return;
+
+ ieee80211_unregister_hw(dev);
+
+ priv = dev->priv;
+ usb_put_dev(interface_to_usbdev(intf));
+ ieee80211_free_hw(dev);
+}
+
+static struct usb_driver rtl8187_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = rtl8187_table,
+ .probe = rtl8187_probe,
+ .disconnect = rtl8187_disconnect,
+};
+
+static int __init rtl8187_init(void)
+{
+ return usb_register(&rtl8187_driver);
+}
+
+static void __exit rtl8187_exit(void)
+{
+ usb_deregister(&rtl8187_driver);
+}
+
+module_init(rtl8187_init);
+module_exit(rtl8187_exit);
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
new file mode 100644
index 00000000000..e25a09f1b06
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -0,0 +1,745 @@
+/*
+ * Radio tuning for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays, register offsets, and phy value tables below are
+ * taken from the original r8187 driver sources. Thanks to Realtek
+ * for their support!
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u16 reg80, reg84, reg82;
+ u32 bangdata;
+ int i;
+
+ bangdata = (data << 4) | (addr & 0xf);
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
+
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ udelay(10);
+
+ for (i = 15; i >= 0; i--) {
+ u16 reg = reg80 | (bangdata & (1 << i)) >> i;
+
+ if (i & 1)
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+
+ if (!(i & 1))
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ msleep(2);
+}
+
+static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u16 reg80, reg82, reg84;
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+ reg80 &= ~(0x3 << 2);
+ reg84 &= ~0xF;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ udelay(10);
+
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ addr, 0x8225, &data, sizeof(data), HZ / 2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ msleep(2);
+}
+
+void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ if (priv->asic_rev)
+ rtl8225_write_8051(dev, addr, data);
+ else
+ rtl8225_write_bitbang(dev, addr, data);
+}
+
+u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u16 reg80, reg82, reg84, out;
+ int i;
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+ reg80 &= ~0xF;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(4);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ udelay(5);
+
+ for (i = 4; i >= 0; i--) {
+ u16 reg = reg80 | ((addr >> i) & 1);
+
+ if (!(i & 1)) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ udelay(1);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ udelay(2);
+
+ if (i & 1) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ udelay(1);
+ }
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(2);
+
+ out = 0;
+ for (i = 11; i >= 0; i--) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(1);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+
+ if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
+ out |= 1 << i;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(2);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 2));
+ udelay(2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
+
+ return out;
+}
+
+static const u16 rtl8225bcd_rxgain[] = {
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+ 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
+ 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
+};
+
+static const u8 rtl8225_agc[] = {
+ 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
+ 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
+ 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
+ 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
+ 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
+ 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
+ 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
+ 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
+ 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
+ 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
+ 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
+ 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
+ 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const u8 rtl8225_gain[] = {
+ 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
+ 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
+ 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
+ 0x33, 0x80, 0x79, 0xc5, /* -78dBm */
+ 0x43, 0x78, 0x76, 0xc5, /* -74dBm */
+ 0x53, 0x60, 0x73, 0xc5, /* -70dBm */
+ 0x63, 0x58, 0x70, 0xc5, /* -66dBm */
+};
+
+static const u8 rtl8225_threshold[] = {
+ 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
+};
+
+static const u8 rtl8225_tx_gain_cck_ofdm[] = {
+ 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
+};
+
+static const u8 rtl8225_tx_power_cck[] = {
+ 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
+ 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
+ 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
+ 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
+ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
+ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
+};
+
+static const u8 rtl8225_tx_power_cck_ch14[] = {
+ 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
+ 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225_tx_power_ofdm[] = {
+ 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
+};
+
+static const u32 rtl8225_chan[] = {
+ 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
+ 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
+};
+
+static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ u32 reg;
+ int i;
+
+ cck_power = priv->channels[channel - 1].val & 0xF;
+ ofdm_power = priv->channels[channel - 1].val >> 4;
+
+ cck_power = min(cck_power, (u8)11);
+ ofdm_power = min(ofdm_power, (u8)35);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+ rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
+
+ if (channel == 14)
+ tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
+ else
+ tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ msleep(1); // FIXME: optional?
+
+ /* anaparam2 on */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write_phy_ofdm(dev, 2, 0x42);
+ rtl8225_write_phy_ofdm(dev, 6, 0x00);
+ rtl8225_write_phy_ofdm(dev, 8, 0x00);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+ rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
+
+ tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
+
+ rtl8225_write_phy_ofdm(dev, 5, *tmp);
+ rtl8225_write_phy_ofdm(dev, 7, *tmp);
+
+ msleep(1);
+}
+
+void rtl8225_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ int i;
+
+ rtl8225_write(dev, 0x0, 0x067); msleep(1);
+ rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+ rtl8225_write(dev, 0x3, 0x441); msleep(1);
+ rtl8225_write(dev, 0x4, 0x486); msleep(1);
+ rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
+ rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
+ rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+ rtl8225_write(dev, 0x8, 0x01F); msleep(1);
+ rtl8225_write(dev, 0x9, 0x334); msleep(1);
+ rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
+ rtl8225_write(dev, 0xB, 0x391); msleep(1);
+ rtl8225_write(dev, 0xC, 0x050); msleep(1);
+ rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
+ rtl8225_write(dev, 0xE, 0x029); msleep(1);
+ rtl8225_write(dev, 0xF, 0x914); msleep(100);
+
+ rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(200);
+
+ if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+ rtl8225_write(dev, 0x02, 0x0c4d);
+ msleep(200);
+ rtl8225_write(dev, 0x02, 0x044d);
+ msleep(100);
+ if (!(rtl8225_read(dev, 6) & (1 << 7)))
+ printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+ wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+ }
+
+ rtl8225_write(dev, 0x0, 0x127);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x0, 0x027);
+ rtl8225_write(dev, 0x0, 0x22F);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ msleep(1);
+ }
+
+ msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+ rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+ rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
+
+ rtl8225_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ msleep(1);
+ rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+
+ /* set sensitivity */
+ rtl8225_write(dev, 0x0c, 0x50);
+ rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+ rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+ rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
+}
+
+static const u8 rtl8225z2_tx_power_cck_ch14[] = {
+ 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225z2_tx_power_cck[] = {
+ 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_ofdm[] = {
+ 0x42, 0x00, 0x40, 0x00, 0x40
+};
+
+static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
+};
+
+static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ u32 reg;
+ int i;
+
+ cck_power = priv->channels[channel - 1].val & 0xF;
+ ofdm_power = priv->channels[channel - 1].val >> 4;
+
+ cck_power = min(cck_power, (u8)15);
+ cck_power += priv->txpwr_base & 0xF;
+ cck_power = min(cck_power, (u8)35);
+
+ ofdm_power = min(ofdm_power, (u8)15);
+ ofdm_power += priv->txpwr_base >> 4;
+ ofdm_power = min(ofdm_power, (u8)35);
+
+ if (channel == 14)
+ tmp = rtl8225z2_tx_power_cck_ch14;
+ else
+ tmp = rtl8225z2_tx_power_cck;
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+ rtl8225z2_tx_gain_cck_ofdm[cck_power]);
+ msleep(1);
+
+ /* anaparam2 on */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write_phy_ofdm(dev, 2, 0x42);
+ rtl8225_write_phy_ofdm(dev, 5, 0x00);
+ rtl8225_write_phy_ofdm(dev, 6, 0x40);
+ rtl8225_write_phy_ofdm(dev, 7, 0x00);
+ rtl8225_write_phy_ofdm(dev, 8, 0x40);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+ rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
+ msleep(1);
+}
+
+static const u16 rtl8225z2_rxgain[] = {
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+ 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+ 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static const u8 rtl8225z2_gain_bg[] = {
+ 0x23, 0x15, 0xa5, /* -82-1dBm */
+ 0x23, 0x15, 0xb5, /* -82-2dBm */
+ 0x23, 0x15, 0xc5, /* -82-3dBm */
+ 0x33, 0x15, 0xc5, /* -78dBm */
+ 0x43, 0x15, 0xc5, /* -74dBm */
+ 0x53, 0x15, 0xc5, /* -70dBm */
+ 0x63, 0x15, 0xc5 /* -66dBm */
+};
+
+void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ int i;
+
+ rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
+ rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+ rtl8225_write(dev, 0x3, 0x441); msleep(1);
+ rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
+ rtl8225_write(dev, 0x5, 0xC72); msleep(1);
+ rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
+ rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+ rtl8225_write(dev, 0x8, 0x03F); msleep(1);
+ rtl8225_write(dev, 0x9, 0x335); msleep(1);
+ rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
+ rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
+ rtl8225_write(dev, 0xc, 0x850); msleep(1);
+ rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
+ rtl8225_write(dev, 0xe, 0x02B); msleep(1);
+ rtl8225_write(dev, 0xf, 0x114); msleep(100);
+
+ rtl8225_write(dev, 0x0, 0x1B7);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x3, 0x080);
+ rtl8225_write(dev, 0x5, 0x004);
+ rtl8225_write(dev, 0x0, 0x0B7);
+ rtl8225_write(dev, 0x2, 0xc4D);
+
+ msleep(200);
+ rtl8225_write(dev, 0x2, 0x44D);
+ msleep(100);
+
+ if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+ rtl8225_write(dev, 0x02, 0x0C4D);
+ msleep(200);
+ rtl8225_write(dev, 0x02, 0x044D);
+ msleep(100);
+ if (!(rtl8225_read(dev, 6) & (1 << 7)))
+ printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+ wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+ }
+
+ msleep(200);
+
+ rtl8225_write(dev, 0x0, 0x2BF);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ msleep(1);
+ }
+
+ msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+ rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
+
+ rtl8225z2_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ msleep(1);
+ rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+}
+
+void rtl8225_rf_stop(struct ieee80211_hw *dev)
+{
+ u8 reg;
+ struct rtl8187_priv *priv = dev->priv;
+
+ rtl8225_write(dev, 0x4, 0x1f); msleep(1);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ if (priv->rf_init == rtl8225_rf_init)
+ rtl8225_rf_set_tx_power(dev, channel);
+ else
+ rtl8225z2_rf_set_tx_power(dev, channel);
+
+ rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
+ msleep(10);
+}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h
new file mode 100644
index 00000000000..798ba4a9737
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.h
@@ -0,0 +1,44 @@
+/*
+ * Radio tuning definitions for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * 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.
+ */
+
+#ifndef RTL8187_RTL8225_H
+#define RTL8187_RTL8225_H
+
+#define RTL8225_ANAPARAM_ON 0xa0000a59
+#define RTL8225_ANAPARAM2_ON 0x860c7312
+#define RTL8225_ANAPARAM_OFF 0xa00beb59
+#define RTL8225_ANAPARAM2_OFF 0x840dec11
+
+void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
+u16 rtl8225_read(struct ieee80211_hw *, u8 addr);
+
+void rtl8225_rf_init(struct ieee80211_hw *);
+void rtl8225z2_rf_init(struct ieee80211_hw *);
+void rtl8225_rf_stop(struct ieee80211_hw *);
+void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
+
+
+static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
+ u8 addr, u32 data)
+{
+ rtl8187_write_phy(dev, addr, data);
+}
+
+static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
+ u8 addr, u32 data)
+{
+ rtl8187_write_phy(dev, addr, data | 0x10000);
+}
+
+#endif /* RTL8187_RTL8225_H */
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
new file mode 100644
index 00000000000..283de30628e
--- /dev/null
+++ b/drivers/net/wireless/rtl818x.h
@@ -0,0 +1,226 @@
+/*
+ * Definitions for RTL818x hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * 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.
+ */
+
+#ifndef RTL818X_H
+#define RTL818X_H
+
+struct rtl818x_csr {
+ u8 MAC[6];
+ u8 reserved_0[2];
+ __le32 MAR[2];
+ u8 RX_FIFO_COUNT;
+ u8 reserved_1;
+ u8 TX_FIFO_COUNT;
+ u8 BQREQ;
+ u8 reserved_2[4];
+ __le32 TSFT[2];
+ __le32 TLPDA;
+ __le32 TNPDA;
+ __le32 THPDA;
+ __le16 BRSR;
+ u8 BSSID[6];
+ u8 RESP_RATE;
+ u8 EIFS;
+ u8 reserved_3[1];
+ u8 CMD;
+#define RTL818X_CMD_TX_ENABLE (1 << 2)
+#define RTL818X_CMD_RX_ENABLE (1 << 3)
+#define RTL818X_CMD_RESET (1 << 4)
+ u8 reserved_4[4];
+ __le16 INT_MASK;
+ __le16 INT_STATUS;
+#define RTL818X_INT_RX_OK (1 << 0)
+#define RTL818X_INT_RX_ERR (1 << 1)
+#define RTL818X_INT_TXL_OK (1 << 2)
+#define RTL818X_INT_TXL_ERR (1 << 3)
+#define RTL818X_INT_RX_DU (1 << 4)
+#define RTL818X_INT_RX_FO (1 << 5)
+#define RTL818X_INT_TXN_OK (1 << 6)
+#define RTL818X_INT_TXN_ERR (1 << 7)
+#define RTL818X_INT_TXH_OK (1 << 8)
+#define RTL818X_INT_TXH_ERR (1 << 9)
+#define RTL818X_INT_TXB_OK (1 << 10)
+#define RTL818X_INT_TXB_ERR (1 << 11)
+#define RTL818X_INT_ATIM (1 << 12)
+#define RTL818X_INT_BEACON (1 << 13)
+#define RTL818X_INT_TIME_OUT (1 << 14)
+#define RTL818X_INT_TX_FO (1 << 15)
+ __le32 TX_CONF;
+#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17)
+#define RTL818X_TX_CONF_NO_ICV (1 << 19)
+#define RTL818X_TX_CONF_DISCW (1 << 20)
+#define RTL818X_TX_CONF_R8180_ABCD (2 << 25)
+#define RTL818X_TX_CONF_R8180_F (3 << 25)
+#define RTL818X_TX_CONF_R8185_ABC (4 << 25)
+#define RTL818X_TX_CONF_R8185_D (5 << 25)
+#define RTL818X_TX_CONF_HWVER_MASK (7 << 25)
+#define RTL818X_TX_CONF_CW_MIN (1 << 31)
+ __le32 RX_CONF;
+#define RTL818X_RX_CONF_MONITOR (1 << 0)
+#define RTL818X_RX_CONF_NICMAC (1 << 1)
+#define RTL818X_RX_CONF_MULTICAST (1 << 2)
+#define RTL818X_RX_CONF_BROADCAST (1 << 3)
+#define RTL818X_RX_CONF_DATA (1 << 18)
+#define RTL818X_RX_CONF_CTRL (1 << 19)
+#define RTL818X_RX_CONF_MGMT (1 << 20)
+#define RTL818X_RX_CONF_BSSID (1 << 23)
+#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28)
+#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31)
+ __le32 INT_TIMEOUT;
+ __le32 TBDA;
+ u8 EEPROM_CMD;
+#define RTL818X_EEPROM_CMD_READ (1 << 0)
+#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
+#define RTL818X_EEPROM_CMD_CK (1 << 2)
+#define RTL818X_EEPROM_CMD_CS (1 << 3)
+#define RTL818X_EEPROM_CMD_NORMAL (0 << 6)
+#define RTL818X_EEPROM_CMD_LOAD (1 << 6)
+#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6)
+#define RTL818X_EEPROM_CMD_CONFIG (3 << 6)
+ u8 CONFIG0;
+ u8 CONFIG1;
+ u8 CONFIG2;
+ __le32 ANAPARAM;
+ u8 MSR;
+#define RTL818X_MSR_NO_LINK (0 << 2)
+#define RTL818X_MSR_ADHOC (1 << 2)
+#define RTL818X_MSR_INFRA (2 << 2)
+ u8 CONFIG3;
+#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6)
+ u8 CONFIG4;
+#define RTL818X_CONFIG4_POWEROFF (1 << 6)
+#define RTL818X_CONFIG4_VCOOFF (1 << 7)
+ u8 TESTR;
+ u8 reserved_9[2];
+ __le16 PGSELECT;
+ __le32 ANAPARAM2;
+ u8 reserved_10[12];
+ __le16 BEACON_INTERVAL;
+ __le16 ATIM_WND;
+ __le16 BEACON_INTERVAL_TIME;
+ __le16 ATIMTR_INTERVAL;
+ u8 reserved_11[4];
+ u8 PHY[4];
+ __le16 RFPinsOutput;
+ __le16 RFPinsEnable;
+ __le16 RFPinsSelect;
+ __le16 RFPinsInput;
+ __le32 RF_PARA;
+ __le32 RF_TIMING;
+ u8 GP_ENABLE;
+ u8 GPIO;
+ u8 reserved_12[10];
+ u8 TX_AGC_CTL;
+#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0)
+#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1)
+#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2)
+ u8 TX_GAIN_CCK;
+ u8 TX_GAIN_OFDM;
+ u8 TX_ANTENNA;
+ u8 reserved_13[16];
+ u8 WPA_CONF;
+ u8 reserved_14[3];
+ u8 SIFS;
+ u8 DIFS;
+ u8 SLOT;
+ u8 reserved_15[5];
+ u8 CW_CONF;
+#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0)
+#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1)
+ u8 CW_VAL;
+ u8 RATE_FALLBACK;
+ u8 reserved_16[25];
+ u8 CONFIG5;
+ u8 TX_DMA_POLLING;
+ u8 reserved_17[2];
+ __le16 CWR;
+ u8 RETRY_CTR;
+ u8 reserved_18[5];
+ __le32 RDSAR;
+ u8 reserved_19[18];
+ u16 TALLY_CNT;
+ u8 TALLY_SEL;
+} __attribute__((packed));
+
+static const struct ieee80211_rate rtl818x_rates[] = {
+ { .rate = 10,
+ .val = 0,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 20,
+ .val = 1,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 55,
+ .val = 2,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 110,
+ .val = 3,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 60,
+ .val = 4,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 90,
+ .val = 5,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 120,
+ .val = 6,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 180,
+ .val = 7,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 240,
+ .val = 8,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 360,
+ .val = 9,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 480,
+ .val = 10,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 540,
+ .val = 11,
+ .flags = IEEE80211_RATE_OFDM },
+};
+
+static const struct ieee80211_channel rtl818x_channels[] = {
+ { .chan = 1,
+ .freq = 2412},
+ { .chan = 2,
+ .freq = 2417},
+ { .chan = 3,
+ .freq = 2422},
+ { .chan = 4,
+ .freq = 2427},
+ { .chan = 5,
+ .freq = 2432},
+ { .chan = 6,
+ .freq = 2437},
+ { .chan = 7,
+ .freq = 2442},
+ { .chan = 8,
+ .freq = 2447},
+ { .chan = 9,
+ .freq = 2452},
+ { .chan = 10,
+ .freq = 2457},
+ { .chan = 11,
+ .freq = 2462},
+ { .chan = 12,
+ .freq = 2467},
+ { .chan = 13,
+ .freq = 2472},
+ { .chan = 14,
+ .freq = 2484}
+};
+
+#endif /* RTL818X_H */
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 6603ad5be63..4d505903352 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o
zd1211rw-objs := zd_chip.o zd_ieee80211.o \
zd_mac.o zd_netdev.o \
zd_rf_al2230.o zd_rf_rf2959.o \
- zd_rf_al7230b.o \
+ zd_rf_al7230b.o zd_rf_uw2453.o \
zd_rf.o zd_usb.o zd_util.o
ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 95b4a2a2670..5b624bfc01a 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1253,6 +1253,9 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
{
int r;
+ if (!zd_rf_should_update_pwr_int(&chip->rf))
+ return 0;
+
r = update_pwr_int(chip, channel);
if (r)
return r;
@@ -1283,7 +1286,7 @@ static int patch_cck_gain(struct zd_chip *chip)
int r;
u32 value;
- if (!chip->patch_cck_gain)
+ if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
return 0;
ZD_ASSERT(mutex_is_locked(&chip->mutex));
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ce0a5f6da0d..79d0288c193 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -608,6 +608,9 @@ enum {
#define CR_ZD1211B_TXOP CTL_REG(0x0b20)
#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28)
+/* Used to detect PLL lock */
+#define UW2453_INTR_REG ((zd_addr_t)0x85c1)
+
#define CWIN_SIZE 0x007f043f
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index 549c23bcd6c..7407409b60b 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -52,34 +52,38 @@ const char *zd_rf_name(u8 type)
void zd_rf_init(struct zd_rf *rf)
{
memset(rf, 0, sizeof(*rf));
+
+ /* default to update channel integration, as almost all RF's do want
+ * this */
+ rf->update_channel_int = 1;
}
void zd_rf_clear(struct zd_rf *rf)
{
+ if (rf->clear)
+ rf->clear(rf);
ZD_MEMCLEAR(rf, sizeof(*rf));
}
int zd_rf_init_hw(struct zd_rf *rf, u8 type)
{
- int r, t;
+ int r = 0;
+ int t;
struct zd_chip *chip = zd_rf_to_chip(rf);
ZD_ASSERT(mutex_is_locked(&chip->mutex));
switch (type) {
case RF2959_RF:
r = zd_rf_init_rf2959(rf);
- if (r)
- return r;
break;
case AL2230_RF:
r = zd_rf_init_al2230(rf);
- if (r)
- return r;
break;
case AL7230B_RF:
r = zd_rf_init_al7230b(rf);
- if (r)
- return r;
+ break;
+ case UW2453_RF:
+ r = zd_rf_init_uw2453(rf);
break;
default:
dev_err(zd_chip_dev(chip),
@@ -88,6 +92,9 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
return -ENODEV;
}
+ if (r)
+ return r;
+
rf->type = type;
r = zd_chip_lock_phy_regs(chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index aa9cc105ce6..c6dfd8227f6 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -48,12 +48,26 @@ struct zd_rf {
u8 channel;
+ /* whether channel integration and calibration should be updated
+ * defaults to 1 (yes) */
+ u8 update_channel_int:1;
+
+ /* whether CR47 should be patched from the EEPROM, if the appropriate
+ * flag is set in the POD. The vendor driver suggests that this should
+ * be done for all RF's, but a bug in their code prevents but their
+ * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
+ u8 patch_cck_gain:1;
+
+ /* private RF driver data */
+ void *priv;
+
/* RF-specific functions */
int (*init_hw)(struct zd_rf *rf);
int (*set_channel)(struct zd_rf *rf, u8 channel);
int (*switch_radio_on)(struct zd_rf *rf);
int (*switch_radio_off)(struct zd_rf *rf);
int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
+ void (*clear)(struct zd_rf *rf);
};
const char *zd_rf_name(u8 type);
@@ -71,10 +85,24 @@ int zd_switch_radio_off(struct zd_rf *rf);
int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
+{
+ return rf->update_channel_int;
+}
+
+static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
+{
+ return rf->patch_cck_gain;
+}
+
+int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
+int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+
/* Functions for individual RF chips */
int zd_rf_init_rf2959(struct zd_rf *rf);
int zd_rf_init_al2230(struct zd_rf *rf);
int zd_rf_init_al7230b(struct zd_rf *rf);
+int zd_rf_init_uw2453(struct zd_rf *rf);
#endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 511392acfed..e7a4ecf7b6e 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -432,5 +432,6 @@ int zd_rf_init_al2230(struct zd_rf *rf)
rf->switch_radio_on = zd1211_al2230_switch_radio_on;
}
rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+ rf->patch_cck_gain = 1;
return 0;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index 5e5e9ddc6a7..f4e8b6ada85 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -483,6 +483,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf)
rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
rf->set_channel = zd1211_al7230b_set_channel;
rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+ rf->patch_cck_gain = 1;
}
rf->switch_radio_off = al7230b_switch_radio_off;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
new file mode 100644
index 00000000000..414e40d571a
--- /dev/null
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -0,0 +1,534 @@
+/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+/* This RF programming code is based upon the code found in v2.16.0.0 of the
+ * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
+ * for this RF on their website, so we're able to understand more than
+ * usual as to what is going on. Thumbs up for Ubec for doing that. */
+
+/* The 3-wire serial interface provides access to 8 write-only registers.
+ * The data format is a 4 bit register address followed by a 20 bit value. */
+#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
+
+/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
+ * fractional divide ratio) and 3 (VCO config).
+ *
+ * We configure the RF to produce an interrupt when the PLL is locked onto
+ * the configured frequency. During initialization, we run through a variety
+ * of different VCO configurations on channel 1 until we detect a PLL lock.
+ * When this happens, we remember which VCO configuration produced the lock
+ * and use it later. Actually, we use the configuration *after* the one that
+ * produced the lock, which seems odd, but it works.
+ *
+ * If we do not see a PLL lock on any standard VCO config, we fall back on an
+ * autocal configuration, which has a fixed (as opposed to per-channel) VCO
+ * config and different synth values from the standard set (divide ratio
+ * is still shared with the standard set). */
+
+/* The per-channel synth values for all standard VCO configurations. These get
+ * written to register 1. */
+static const u8 uw2453_std_synth[] = {
+ RF_CHANNEL( 1) = 0x47,
+ RF_CHANNEL( 2) = 0x47,
+ RF_CHANNEL( 3) = 0x67,
+ RF_CHANNEL( 4) = 0x67,
+ RF_CHANNEL( 5) = 0x67,
+ RF_CHANNEL( 6) = 0x67,
+ RF_CHANNEL( 7) = 0x57,
+ RF_CHANNEL( 8) = 0x57,
+ RF_CHANNEL( 9) = 0x57,
+ RF_CHANNEL(10) = 0x57,
+ RF_CHANNEL(11) = 0x77,
+ RF_CHANNEL(12) = 0x77,
+ RF_CHANNEL(13) = 0x77,
+ RF_CHANNEL(14) = 0x4f,
+};
+
+/* This table stores the synthesizer fractional divide ratio for *all* VCO
+ * configurations (both standard and autocal). These get written to register 2.
+ */
+static const u16 uw2453_synth_divide[] = {
+ RF_CHANNEL( 1) = 0x999,
+ RF_CHANNEL( 2) = 0x99b,
+ RF_CHANNEL( 3) = 0x998,
+ RF_CHANNEL( 4) = 0x99a,
+ RF_CHANNEL( 5) = 0x999,
+ RF_CHANNEL( 6) = 0x99b,
+ RF_CHANNEL( 7) = 0x998,
+ RF_CHANNEL( 8) = 0x99a,
+ RF_CHANNEL( 9) = 0x999,
+ RF_CHANNEL(10) = 0x99b,
+ RF_CHANNEL(11) = 0x998,
+ RF_CHANNEL(12) = 0x99a,
+ RF_CHANNEL(13) = 0x999,
+ RF_CHANNEL(14) = 0xccc,
+};
+
+/* Here is the data for all the standard VCO configurations. We shrink our
+ * table a little by observing that both channels in a consecutive pair share
+ * the same value. We also observe that the high 4 bits ([0:3] in the specs)
+ * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
+ * below. */
+#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
+#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
+static const u16 uw2453_std_vco_cfg[][7] = {
+ { /* table 1 */
+ RF_CHANPAIR( 1, 2) = 0x664d,
+ RF_CHANPAIR( 3, 4) = 0x604d,
+ RF_CHANPAIR( 5, 6) = 0x6675,
+ RF_CHANPAIR( 7, 8) = 0x6475,
+ RF_CHANPAIR( 9, 10) = 0x6655,
+ RF_CHANPAIR(11, 12) = 0x6455,
+ RF_CHANPAIR(13, 14) = 0x6665,
+ },
+ { /* table 2 */
+ RF_CHANPAIR( 1, 2) = 0x666d,
+ RF_CHANPAIR( 3, 4) = 0x606d,
+ RF_CHANPAIR( 5, 6) = 0x664d,
+ RF_CHANPAIR( 7, 8) = 0x644d,
+ RF_CHANPAIR( 9, 10) = 0x6675,
+ RF_CHANPAIR(11, 12) = 0x6475,
+ RF_CHANPAIR(13, 14) = 0x6655,
+ },
+ { /* table 3 */
+ RF_CHANPAIR( 1, 2) = 0x665d,
+ RF_CHANPAIR( 3, 4) = 0x605d,
+ RF_CHANPAIR( 5, 6) = 0x666d,
+ RF_CHANPAIR( 7, 8) = 0x646d,
+ RF_CHANPAIR( 9, 10) = 0x664d,
+ RF_CHANPAIR(11, 12) = 0x644d,
+ RF_CHANPAIR(13, 14) = 0x6675,
+ },
+ { /* table 4 */
+ RF_CHANPAIR( 1, 2) = 0x667d,
+ RF_CHANPAIR( 3, 4) = 0x607d,
+ RF_CHANPAIR( 5, 6) = 0x665d,
+ RF_CHANPAIR( 7, 8) = 0x645d,
+ RF_CHANPAIR( 9, 10) = 0x666d,
+ RF_CHANPAIR(11, 12) = 0x646d,
+ RF_CHANPAIR(13, 14) = 0x664d,
+ },
+ { /* table 5 */
+ RF_CHANPAIR( 1, 2) = 0x6643,
+ RF_CHANPAIR( 3, 4) = 0x6043,
+ RF_CHANPAIR( 5, 6) = 0x667d,
+ RF_CHANPAIR( 7, 8) = 0x647d,
+ RF_CHANPAIR( 9, 10) = 0x665d,
+ RF_CHANPAIR(11, 12) = 0x645d,
+ RF_CHANPAIR(13, 14) = 0x666d,
+ },
+ { /* table 6 */
+ RF_CHANPAIR( 1, 2) = 0x6663,
+ RF_CHANPAIR( 3, 4) = 0x6063,
+ RF_CHANPAIR( 5, 6) = 0x6643,
+ RF_CHANPAIR( 7, 8) = 0x6443,
+ RF_CHANPAIR( 9, 10) = 0x667d,
+ RF_CHANPAIR(11, 12) = 0x647d,
+ RF_CHANPAIR(13, 14) = 0x665d,
+ },
+ { /* table 7 */
+ RF_CHANPAIR( 1, 2) = 0x6653,
+ RF_CHANPAIR( 3, 4) = 0x6053,
+ RF_CHANPAIR( 5, 6) = 0x6663,
+ RF_CHANPAIR( 7, 8) = 0x6463,
+ RF_CHANPAIR( 9, 10) = 0x6643,
+ RF_CHANPAIR(11, 12) = 0x6443,
+ RF_CHANPAIR(13, 14) = 0x667d,
+ },
+ { /* table 8 */
+ RF_CHANPAIR( 1, 2) = 0x6673,
+ RF_CHANPAIR( 3, 4) = 0x6073,
+ RF_CHANPAIR( 5, 6) = 0x6653,
+ RF_CHANPAIR( 7, 8) = 0x6453,
+ RF_CHANPAIR( 9, 10) = 0x6663,
+ RF_CHANPAIR(11, 12) = 0x6463,
+ RF_CHANPAIR(13, 14) = 0x6643,
+ },
+ { /* table 9 */
+ RF_CHANPAIR( 1, 2) = 0x664b,
+ RF_CHANPAIR( 3, 4) = 0x604b,
+ RF_CHANPAIR( 5, 6) = 0x6673,
+ RF_CHANPAIR( 7, 8) = 0x6473,
+ RF_CHANPAIR( 9, 10) = 0x6653,
+ RF_CHANPAIR(11, 12) = 0x6453,
+ RF_CHANPAIR(13, 14) = 0x6663,
+ },
+ { /* table 10 */
+ RF_CHANPAIR( 1, 2) = 0x666b,
+ RF_CHANPAIR( 3, 4) = 0x606b,
+ RF_CHANPAIR( 5, 6) = 0x664b,
+ RF_CHANPAIR( 7, 8) = 0x644b,
+ RF_CHANPAIR( 9, 10) = 0x6673,
+ RF_CHANPAIR(11, 12) = 0x6473,
+ RF_CHANPAIR(13, 14) = 0x6653,
+ },
+ { /* table 11 */
+ RF_CHANPAIR( 1, 2) = 0x665b,
+ RF_CHANPAIR( 3, 4) = 0x605b,
+ RF_CHANPAIR( 5, 6) = 0x666b,
+ RF_CHANPAIR( 7, 8) = 0x646b,
+ RF_CHANPAIR( 9, 10) = 0x664b,
+ RF_CHANPAIR(11, 12) = 0x644b,
+ RF_CHANPAIR(13, 14) = 0x6673,
+ },
+
+};
+
+/* The per-channel synth values for autocal. These get written to register 1. */
+static const u16 uw2453_autocal_synth[] = {
+ RF_CHANNEL( 1) = 0x6847,
+ RF_CHANNEL( 2) = 0x6847,
+ RF_CHANNEL( 3) = 0x6867,
+ RF_CHANNEL( 4) = 0x6867,
+ RF_CHANNEL( 5) = 0x6867,
+ RF_CHANNEL( 6) = 0x6867,
+ RF_CHANNEL( 7) = 0x6857,
+ RF_CHANNEL( 8) = 0x6857,
+ RF_CHANNEL( 9) = 0x6857,
+ RF_CHANNEL(10) = 0x6857,
+ RF_CHANNEL(11) = 0x6877,
+ RF_CHANNEL(12) = 0x6877,
+ RF_CHANNEL(13) = 0x6877,
+ RF_CHANNEL(14) = 0x684f,
+};
+
+/* The VCO configuration for autocal (all channels) */
+static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
+
+/* TX gain settings. The array index corresponds to the TX power integration
+ * values found in the EEPROM. The values get written to register 7. */
+static u32 uw2453_txgain[] = {
+ [0x00] = 0x0e313,
+ [0x01] = 0x0fb13,
+ [0x02] = 0x0e093,
+ [0x03] = 0x0f893,
+ [0x04] = 0x0ea93,
+ [0x05] = 0x1f093,
+ [0x06] = 0x1f493,
+ [0x07] = 0x1f693,
+ [0x08] = 0x1f393,
+ [0x09] = 0x1f35b,
+ [0x0a] = 0x1e6db,
+ [0x0b] = 0x1ff3f,
+ [0x0c] = 0x1ffff,
+ [0x0d] = 0x361d7,
+ [0x0e] = 0x37fbf,
+ [0x0f] = 0x3ff8b,
+ [0x10] = 0x3ff33,
+ [0x11] = 0x3fb3f,
+ [0x12] = 0x3ffff,
+};
+
+/* RF-specific structure */
+struct uw2453_priv {
+ /* index into synth/VCO config tables where PLL lock was found
+ * -1 means autocal */
+ int config;
+};
+
+#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
+
+static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
+ bool autocal)
+{
+ int r;
+ int idx = channel - 1;
+ u32 val;
+
+ if (autocal)
+ val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
+ else
+ val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
+
+ r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
+ if (r)
+ return r;
+
+ return zd_rfwrite_locked(chip,
+ UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
+}
+
+static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
+{
+ /* vendor driver always sets these upper bits even though the specs say
+ * they are reserved */
+ u32 val = 0x40000 | value;
+ return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
+}
+
+static int uw2453_init_mode(struct zd_chip *chip)
+{
+ static const u32 rv[] = {
+ UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
+ UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
+ UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
+ UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
+ };
+
+ return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+}
+
+static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
+{
+ u8 int_value = chip->pwr_int_values[channel - 1];
+
+ if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
+ dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
+ "int value %x on channel %d\n", int_value, channel);
+ return 0;
+ }
+
+ return zd_rfwrite_locked(chip,
+ UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
+}
+
+static int uw2453_init_hw(struct zd_rf *rf)
+{
+ int i, r;
+ int found_config = -1;
+ u16 intr_status;
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+
+ static const struct zd_ioreq16 ioreqs[] = {
+ { CR10, 0x89 }, { CR15, 0x20 },
+ { CR17, 0x28 }, /* 6112 no change */
+ { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 },
+ { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 },
+ { CR33, 0x28 }, { CR34, 0x30 },
+ { CR35, 0x43 }, /* 6112 3e->43 */
+ { CR41, 0x24 }, { CR44, 0x32 },
+ { CR46, 0x92 }, /* 6112 96->92 */
+ { CR47, 0x1e },
+ { CR48, 0x04 }, /* 5602 Roger */
+ { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 },
+ { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 },
+ { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d },
+ { CR99, 0x28 }, { CR100, 0x02 },
+ { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
+ { CR102, 0x27 },
+ { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */
+ { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
+ { CR109, 0x13 },
+ { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
+ { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 },
+ { CR114, 0x23 }, /* 6221 27->23 */
+ { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
+ { CR116, 0x24 }, /* 6220 1c->24 */
+ { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
+ { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
+ { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
+ { CR120, 0x4f },
+ { CR121, 0x1f }, /* 6220 4f->1f */
+ { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad },
+ { CR126, 0x6c }, { CR127, 0x03 },
+ { CR128, 0x14 }, /* 6302 12->11 */
+ { CR129, 0x12 }, /* 6301 10->0f */
+ { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 },
+ { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff },
+ { CR253, 0xff },
+ };
+
+ static const u32 rv[] = {
+ UW2453_REGWRITE(4, 0x2b), /* configure reciever gain */
+ UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
+ UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
+ UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
+
+ /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
+ * RSSI circuit powered down, reduced RSSI range */
+ UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
+
+ /* synthesizer configuration for channel 1 */
+ UW2453_REGWRITE(1, 0x47),
+ UW2453_REGWRITE(2, 0x999),
+
+ /* disable manual VCO band selection */
+ UW2453_REGWRITE(3, 0x7602),
+
+ /* enable manual VCO band selection, configure current level */
+ UW2453_REGWRITE(3, 0x46063),
+ };
+
+ r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+ if (r)
+ return r;
+
+ r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+ if (r)
+ return r;
+
+ r = uw2453_init_mode(chip);
+ if (r)
+ return r;
+
+ /* Try all standard VCO configuration settings on channel 1 */
+ for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
+ /* Configure synthesizer for channel 1 */
+ r = uw2453_synth_set_channel(chip, 1, false);
+ if (r)
+ return r;
+
+ /* Write VCO config */
+ r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
+ if (r)
+ return r;
+
+ /* ack interrupt event */
+ r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
+ if (r)
+ return r;
+
+ /* check interrupt status */
+ r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
+ if (r)
+ return r;
+
+ if (!intr_status & 0xf) {
+ dev_dbg_f(zd_chip_dev(chip),
+ "PLL locked on configuration %d\n", i);
+ found_config = i;
+ break;
+ }
+ }
+
+ if (found_config == -1) {
+ /* autocal */
+ dev_dbg_f(zd_chip_dev(chip),
+ "PLL did not lock, using autocal\n");
+
+ r = uw2453_synth_set_channel(chip, 1, true);
+ if (r)
+ return r;
+
+ r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
+ if (r)
+ return r;
+ }
+
+ /* To match the vendor driver behaviour, we use the configuration after
+ * the one that produced a lock. */
+ UW2453_PRIV(rf)->config = found_config + 1;
+
+ return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
+{
+ int r;
+ u16 vco_cfg;
+ int config = UW2453_PRIV(rf)->config;
+ bool autocal = (config == -1);
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+
+ static const struct zd_ioreq16 ioreqs[] = {
+ { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 },
+ { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 },
+ };
+
+ r = uw2453_synth_set_channel(chip, channel, autocal);
+ if (r)
+ return r;
+
+ if (autocal)
+ vco_cfg = UW2453_AUTOCAL_VCO_CFG;
+ else
+ vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
+
+ r = uw2453_write_vco_cfg(chip, vco_cfg);
+ if (r)
+ return r;
+
+ r = uw2453_init_mode(chip);
+ if (r)
+ return r;
+
+ r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+ if (r)
+ return r;
+
+ r = uw2453_set_tx_gain_level(chip, channel);
+ if (r)
+ return r;
+
+ return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_switch_radio_on(struct zd_rf *rf)
+{
+ int r;
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+ struct zd_ioreq16 ioreqs[] = {
+ { CR11, 0x00 }, { CR251, 0x3f },
+ };
+
+ /* enter RXTX mode */
+ r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
+ if (r)
+ return r;
+
+ if (chip->is_zd1211b)
+ ioreqs[1].value = 0x7f;
+
+ return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int uw2453_switch_radio_off(struct zd_rf *rf)
+{
+ int r;
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+ static const struct zd_ioreq16 ioreqs[] = {
+ { CR11, 0x04 }, { CR251, 0x2f },
+ };
+
+ /* enter IDLE mode */
+ /* FIXME: shouldn't we go to SLEEP? sent email to zydas */
+ r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
+ if (r)
+ return r;
+
+ return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static void uw2453_clear(struct zd_rf *rf)
+{
+ kfree(rf->priv);
+}
+
+int zd_rf_init_uw2453(struct zd_rf *rf)
+{
+ rf->init_hw = uw2453_init_hw;
+ rf->set_channel = uw2453_set_channel;
+ rf->switch_radio_on = uw2453_switch_radio_on;
+ rf->switch_radio_off = uw2453_switch_radio_off;
+ rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+ rf->clear = uw2453_clear;
+ /* we have our own TX integration code */
+ rf->update_channel_int = 0;
+
+ rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
+ if (rf->priv == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 8459549d0ce..740a2194fdd 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -54,6 +54,7 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
/* ZD1211B */
{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 967a8e22b2d..7c3236690cc 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -136,11 +136,10 @@ static int quirk_smc_fir_enabled(struct pnp_dev *dev)
static void quirk_smc_enable(struct pnp_dev *dev)
{
- /*
- * If the BIOS left the device disabled, or it is enabled and
- * responding correctly, we're in good shape.
- */
- if (!dev->active || quirk_smc_fir_enabled(dev))
+ struct resource fir, sir, irq;
+
+ pnp_activate_dev(dev);
+ if (quirk_smc_fir_enabled(dev))
return;
/*
@@ -152,16 +151,62 @@ static void quirk_smc_enable(struct pnp_dev *dev)
* this. Fortunately, they do fix things up if we auto-configure
* the device using its _PRS and _SRS methods.
*/
- dev_err(&dev->dev, "%s device not responding, auto-configuring "
- "resources\n", dev->id->id);
+ dev_err(&dev->dev, "%s not responding at SIR 0x%lx, FIR 0x%lx; "
+ "auto-configuring\n", dev->id->id,
+ (unsigned long) pnp_port_start(dev, 0),
+ (unsigned long) pnp_port_start(dev, 1));
pnp_disable_dev(dev);
pnp_init_resource_table(&dev->res);
pnp_auto_config_dev(dev);
pnp_activate_dev(dev);
+ if (quirk_smc_fir_enabled(dev)) {
+ dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n",
+ (unsigned long) pnp_port_start(dev, 0),
+ (unsigned long) pnp_port_start(dev, 1));
+ return;
+ }
+
+ /*
+ * The Toshiba Portege 4000 _CRS reports the FIR region first,
+ * followed by the SIR region. The BIOS will configure the bridge,
+ * but only if we call _SRS with SIR first, then FIR. It also
+ * reports the IRQ as active high, when it is really active low.
+ */
+ dev_err(&dev->dev, "not responding at SIR 0x%lx, FIR 0x%lx; "
+ "swapping SIR/FIR and reconfiguring\n",
+ (unsigned long) pnp_port_start(dev, 0),
+ (unsigned long) pnp_port_start(dev, 1));
+
+ /*
+ * Clear IORESOURCE_AUTO so pnp_activate_dev() doesn't reassign
+ * these resources any more.
+ */
+ fir = dev->res.port_resource[0];
+ sir = dev->res.port_resource[1];
+ fir.flags &= ~IORESOURCE_AUTO;
+ sir.flags &= ~IORESOURCE_AUTO;
+
+ irq = dev->res.irq_resource[0];
+ irq.flags &= ~IORESOURCE_AUTO;
+ irq.flags &= ~IORESOURCE_BITS;
+ irq.flags |= IORESOURCE_IRQ_LOWEDGE;
+
+ pnp_disable_dev(dev);
+ dev->res.port_resource[0] = sir;
+ dev->res.port_resource[1] = fir;
+ dev->res.irq_resource[0] = irq;
+ pnp_activate_dev(dev);
+
+ if (quirk_smc_fir_enabled(dev)) {
+ dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n",
+ (unsigned long) pnp_port_start(dev, 0),
+ (unsigned long) pnp_port_start(dev, 1));
+ return;
+ }
- if (!quirk_smc_fir_enabled(dev))
- dev_err(&dev->dev, "giving up; try \"smsc-ircc2.nopnp\"\n");
+ dev_err(&dev->dev, "giving up; try \"smsc-ircc2.nopnp\" and "
+ "email bjorn.helgaas@hp.com\n");
}
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
new file mode 100644
index 00000000000..ab9c3e5a7c1
--- /dev/null
+++ b/drivers/power/Kconfig
@@ -0,0 +1,51 @@
+menuconfig POWER_SUPPLY
+ tristate "Power supply class support"
+ help
+ Say Y here to enable power supply class support. This allows
+ power supply (batteries, AC, USB) monitoring by userspace
+ via sysfs and uevent (if available) and/or APM kernel interface
+ (if selected below).
+
+if POWER_SUPPLY
+
+config POWER_SUPPLY_DEBUG
+ bool "Power supply debug"
+ help
+ Say Y here to enable debugging messages for power supply class
+ and drivers.
+
+config PDA_POWER
+ tristate "Generic PDA/phone power driver"
+ help
+ Say Y here to enable generic power driver for PDAs and phones with
+ one or two external power supplies (AC/USB) connected to main and
+ backup batteries, and optional builtin charger.
+
+config APM_POWER
+ tristate "APM emulation for class batteries"
+ depends on APM_EMULATION
+ help
+ Say Y here to enable support APM status emulation using
+ battery class devices.
+
+config BATTERY_DS2760
+ tristate "DS2760 battery driver (HP iPAQ & others)"
+ select W1
+ select W1_SLAVE_DS2760
+ help
+ Say Y here to enable support for batteries with ds2760 chip.
+
+config BATTERY_PMU
+ tristate "Apple PMU battery"
+ depends on ADB_PMU
+ help
+ Say Y here to expose battery information on Apple machines
+ through the generic battery class.
+
+config BATTERY_OLPC
+ tristate "One Laptop Per Child battery"
+ depends on X86_32 && OLPC
+ help
+ Say Y to enable support for the battery on the OLPC laptop.
+
+endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
new file mode 100644
index 00000000000..6413ded5fe5
--- /dev/null
+++ b/drivers/power/Makefile
@@ -0,0 +1,22 @@
+power_supply-objs := power_supply_core.o
+
+ifeq ($(CONFIG_SYSFS),y)
+power_supply-objs += power_supply_sysfs.o
+endif
+
+ifeq ($(CONFIG_LEDS_TRIGGERS),y)
+power_supply-objs += power_supply_leds.o
+endif
+
+ifeq ($(CONFIG_POWER_SUPPLY_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
+
+obj-$(CONFIG_PDA_POWER) += pda_power.o
+obj-$(CONFIG_APM_POWER) += apm_power.o
+
+obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
+obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
+obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
new file mode 100644
index 00000000000..042bd950d03
--- /dev/null
+++ b/drivers/power/apm_power.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2007 Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Author: Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ */
+
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/apm-emulation.h>
+
+#define PSY_PROP(psy, prop, val) psy->get_property(psy, \
+ POWER_SUPPLY_PROP_##prop, val)
+
+#define _MPSY_PROP(prop, val) main_battery->get_property(main_battery, \
+ prop, val)
+
+#define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
+
+static struct power_supply *main_battery;
+
+static void find_main_battery(void)
+{
+ struct device *dev;
+ struct power_supply *bat, *batm;
+ union power_supply_propval full;
+ int max_charge = 0;
+
+ main_battery = NULL;
+ batm = NULL;
+ list_for_each_entry(dev, &power_supply_class->devices, node) {
+ bat = dev_get_drvdata(dev);
+ /* If none of battery devices cantains 'use_for_apm' flag,
+ choice one with maximum design charge */
+ if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full)) {
+ if (full.intval > max_charge) {
+ batm = bat;
+ max_charge = full.intval;
+ }
+ }
+
+ if (bat->use_for_apm)
+ main_battery = bat;
+ }
+ if (!main_battery)
+ main_battery = batm;
+
+ return;
+}
+
+static int calculate_time(int status)
+{
+ union power_supply_propval charge_full, charge_empty;
+ union power_supply_propval charge, I;
+
+ if (MPSY_PROP(CHARGE_FULL, &charge_full)) {
+ /* if battery can't report this property, use design value */
+ if (MPSY_PROP(CHARGE_FULL_DESIGN, &charge_full))
+ return -1;
+ }
+
+ if (MPSY_PROP(CHARGE_EMPTY, &charge_empty)) {
+ /* if battery can't report this property, use design value */
+ if (MPSY_PROP(CHARGE_EMPTY_DESIGN, &charge_empty))
+ charge_empty.intval = 0;
+ }
+
+ if (MPSY_PROP(CHARGE_AVG, &charge)) {
+ /* if battery can't report average value, use momentary */
+ if (MPSY_PROP(CHARGE_NOW, &charge))
+ return -1;
+ }
+
+ if (MPSY_PROP(CURRENT_AVG, &I)) {
+ /* if battery can't report average value, use momentary */
+ if (MPSY_PROP(CURRENT_NOW, &I))
+ return -1;
+ }
+
+ if (status == POWER_SUPPLY_STATUS_CHARGING)
+ return ((charge.intval - charge_full.intval) * 60L) /
+ I.intval;
+ else
+ return -((charge.intval - charge_empty.intval) * 60L) /
+ I.intval;
+}
+
+static int calculate_capacity(int using_charge)
+{
+ enum power_supply_property full_prop, empty_prop;
+ enum power_supply_property full_design_prop, empty_design_prop;
+ enum power_supply_property now_prop, avg_prop;
+ union power_supply_propval empty, full, cur;
+ int ret;
+
+ if (using_charge) {
+ full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
+ empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
+ full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
+ empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
+ now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
+ avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
+ } else {
+ full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
+ empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
+ full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
+ empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
+ now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
+ avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
+ }
+
+ if (_MPSY_PROP(full_prop, &full)) {
+ /* if battery can't report this property, use design value */
+ if (_MPSY_PROP(full_design_prop, &full))
+ return -1;
+ }
+
+ if (_MPSY_PROP(avg_prop, &cur)) {
+ /* if battery can't report average value, use momentary */
+ if (_MPSY_PROP(now_prop, &cur))
+ return -1;
+ }
+
+ if (_MPSY_PROP(empty_prop, &empty)) {
+ /* if battery can't report this property, use design value */
+ if (_MPSY_PROP(empty_design_prop, &empty))
+ empty.intval = 0;
+ }
+
+ if (full.intval - empty.intval)
+ ret = ((cur.intval - empty.intval) * 100L) /
+ (full.intval - empty.intval);
+ else
+ return -1;
+
+ if (ret > 100)
+ return 100;
+ else if (ret < 0)
+ return 0;
+
+ return ret;
+}
+
+static void apm_battery_apm_get_power_status(struct apm_power_info *info)
+{
+ union power_supply_propval status;
+ union power_supply_propval capacity, time_to_full, time_to_empty;
+
+ down(&power_supply_class->sem);
+ find_main_battery();
+ if (!main_battery) {
+ up(&power_supply_class->sem);
+ return;
+ }
+
+ /* status */
+
+ if (MPSY_PROP(STATUS, &status))
+ status.intval = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ /* ac line status */
+
+ if ((status.intval == POWER_SUPPLY_STATUS_CHARGING) ||
+ (status.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) ||
+ (status.intval == POWER_SUPPLY_STATUS_FULL))
+ info->ac_line_status = APM_AC_ONLINE;
+ else
+ info->ac_line_status = APM_AC_OFFLINE;
+
+ /* battery life (i.e. capacity, in percents) */
+
+ if (MPSY_PROP(CAPACITY, &capacity) == 0) {
+ info->battery_life = capacity.intval;
+ } else {
+ /* try calculate using energy */
+ info->battery_life = calculate_capacity(0);
+ /* if failed try calculate using charge instead */
+ if (info->battery_life == -1)
+ info->battery_life = calculate_capacity(1);
+ }
+
+ /* charging status */
+
+ if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+ info->battery_status = APM_BATTERY_STATUS_CHARGING;
+ } else {
+ if (info->battery_life > 50)
+ info->battery_status = APM_BATTERY_STATUS_HIGH;
+ else if (info->battery_life > 5)
+ info->battery_status = APM_BATTERY_STATUS_LOW;
+ else
+ info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+ }
+ info->battery_flag = info->battery_status;
+
+ /* time */
+
+ info->units = APM_UNITS_MINS;
+
+ if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+ if (MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full)) {
+ if (MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full))
+ info->time = calculate_time(status.intval);
+ else
+ info->time = time_to_full.intval / 60;
+ }
+ } else {
+ if (MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty)) {
+ if (MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty))
+ info->time = calculate_time(status.intval);
+ else
+ info->time = time_to_empty.intval / 60;
+ }
+ }
+
+ up(&power_supply_class->sem);
+ return;
+}
+
+static int __init apm_battery_init(void)
+{
+ printk(KERN_INFO "APM Battery Driver\n");
+
+ apm_get_power_status = apm_battery_apm_get_power_status;
+ return 0;
+}
+
+static void __exit apm_battery_exit(void)
+{
+ apm_get_power_status = NULL;
+ return;
+}
+
+module_init(apm_battery_init);
+module_exit(apm_battery_exit);
+
+MODULE_AUTHOR("Eugeny Boger <eugenyboger@dgap.mipt.ru>");
+MODULE_DESCRIPTION("APM emulation driver for battery monitoring class");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
new file mode 100644
index 00000000000..00e1ea6f1de
--- /dev/null
+++ b/drivers/power/ds2760_battery.c
@@ -0,0 +1,470 @@
+/*
+ * Driver for batteries with DS2760 chips inside.
+ *
+ * Copyright © 2007 Anton Vorontsov
+ * 2004-2007 Matt Reimer
+ * 2004 Szabolcs Gyurko
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * Author: Anton Vorontsov <cbou@mail.ru>
+ * February 2007
+ *
+ * Matt Reimer <mreimer@vpop.net>
+ * April 2004, 2005, 2007
+ *
+ * Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ * September 2004
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#include "../w1/w1.h"
+#include "../w1/slaves/w1_ds2760.h"
+
+struct ds2760_device_info {
+ struct device *dev;
+
+ /* DS2760 data, valid after calling ds2760_battery_read_status() */
+ unsigned long update_time; /* jiffies when data read */
+ char raw[DS2760_DATA_SIZE]; /* raw DS2760 data */
+ int voltage_raw; /* units of 4.88 mV */
+ int voltage_uV; /* units of µV */
+ int current_raw; /* units of 0.625 mA */
+ int current_uA; /* units of µA */
+ int accum_current_raw; /* units of 0.25 mAh */
+ int accum_current_uAh; /* units of µAh */
+ int temp_raw; /* units of 0.125 °C */
+ int temp_C; /* units of 0.1 °C */
+ int rated_capacity; /* units of µAh */
+ int rem_capacity; /* percentage */
+ int full_active_uAh; /* units of µAh */
+ int empty_uAh; /* units of µAh */
+ int life_sec; /* units of seconds */
+ int charge_status; /* POWER_SUPPLY_STATUS_* */
+
+ int full_counter;
+ struct power_supply bat;
+ struct device *w1_dev;
+ struct workqueue_struct *monitor_wqueue;
+ struct delayed_work monitor_work;
+};
+
+static unsigned int cache_time = 1000;
+module_param(cache_time, uint, 0644);
+MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+
+/* Some batteries have their rated capacity stored a N * 10 mAh, while
+ * others use an index into this table. */
+static int rated_capacities[] = {
+ 0,
+ 920, /* Samsung */
+ 920, /* BYD */
+ 920, /* Lishen */
+ 920, /* NEC */
+ 1440, /* Samsung */
+ 1440, /* BYD */
+ 1440, /* Lishen */
+ 1440, /* NEC */
+ 2880, /* Samsung */
+ 2880, /* BYD */
+ 2880, /* Lishen */
+ 2880 /* NEC */
+};
+
+/* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C
+ * temp is in Celsius */
+static int battery_interpolate(int array[], int temp)
+{
+ int index, dt;
+
+ if (temp <= 0)
+ return array[0];
+ if (temp >= 40)
+ return array[4];
+
+ index = temp / 10;
+ dt = temp % 10;
+
+ return array[index] + (((array[index + 1] - array[index]) * dt) / 10);
+}
+
+static int ds2760_battery_read_status(struct ds2760_device_info *di)
+{
+ int ret, i, start, count, scale[5];
+
+ if (di->update_time && time_before(jiffies, di->update_time +
+ msecs_to_jiffies(cache_time)))
+ return 0;
+
+ /* The first time we read the entire contents of SRAM/EEPROM,
+ * but after that we just read the interesting bits that change. */
+ if (di->update_time == 0) {
+ start = 0;
+ count = DS2760_DATA_SIZE;
+ } else {
+ start = DS2760_VOLTAGE_MSB;
+ count = DS2760_TEMP_LSB - start + 1;
+ }
+
+ ret = w1_ds2760_read(di->w1_dev, di->raw + start, start, count);
+ if (ret != count) {
+ dev_warn(di->dev, "call to w1_ds2760_read failed (0x%p)\n",
+ di->w1_dev);
+ return 1;
+ }
+
+ di->update_time = jiffies;
+
+ /* DS2760 reports voltage in units of 4.88mV, but the battery class
+ * reports in units of uV, so convert by multiplying by 4880. */
+ di->voltage_raw = (di->raw[DS2760_VOLTAGE_MSB] << 3) |
+ (di->raw[DS2760_VOLTAGE_LSB] >> 5);
+ di->voltage_uV = di->voltage_raw * 4880;
+
+ /* DS2760 reports current in signed units of 0.625mA, but the battery
+ * class reports in units of µA, so convert by multiplying by 625. */
+ di->current_raw =
+ (((signed char)di->raw[DS2760_CURRENT_MSB]) << 5) |
+ (di->raw[DS2760_CURRENT_LSB] >> 3);
+ di->current_uA = di->current_raw * 625;
+
+ /* DS2760 reports accumulated current in signed units of 0.25mAh. */
+ di->accum_current_raw =
+ (((signed char)di->raw[DS2760_CURRENT_ACCUM_MSB]) << 8) |
+ di->raw[DS2760_CURRENT_ACCUM_LSB];
+ di->accum_current_uAh = di->accum_current_raw * 250;
+
+ /* DS2760 reports temperature in signed units of 0.125°C, but the
+ * battery class reports in units of 1/10 °C, so we convert by
+ * multiplying by .125 * 10 = 1.25. */
+ di->temp_raw = (((signed char)di->raw[DS2760_TEMP_MSB]) << 3) |
+ (di->raw[DS2760_TEMP_LSB] >> 5);
+ di->temp_C = di->temp_raw + (di->temp_raw / 4);
+
+ /* At least some battery monitors (e.g. HP iPAQ) store the battery's
+ * maximum rated capacity. */
+ if (di->raw[DS2760_RATED_CAPACITY] < ARRAY_SIZE(rated_capacities))
+ di->rated_capacity = rated_capacities[
+ (unsigned int)di->raw[DS2760_RATED_CAPACITY]];
+ else
+ di->rated_capacity = di->raw[DS2760_RATED_CAPACITY] * 10;
+
+ di->rated_capacity *= 1000; /* convert to µAh */
+
+ /* Calculate the full level at the present temperature. */
+ di->full_active_uAh = di->raw[DS2760_ACTIVE_FULL] << 8 |
+ di->raw[DS2760_ACTIVE_FULL + 1];
+
+ scale[0] = di->raw[DS2760_ACTIVE_FULL] << 8 |
+ di->raw[DS2760_ACTIVE_FULL + 1];
+ for (i = 1; i < 5; i++)
+ scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i];
+
+ di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10);
+ di->full_active_uAh *= 1000; /* convert to µAh */
+
+ /* Calculate the empty level at the present temperature. */
+ scale[4] = di->raw[DS2760_ACTIVE_EMPTY + 4];
+ for (i = 3; i >= 0; i--)
+ scale[i] = scale[i + 1] + di->raw[DS2760_ACTIVE_EMPTY + i];
+
+ di->empty_uAh = battery_interpolate(scale, di->temp_C / 10);
+ di->empty_uAh *= 1000; /* convert to µAh */
+
+ /* From Maxim Application Note 131: remaining capacity =
+ * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */
+ di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) /
+ (di->full_active_uAh - di->empty_uAh);
+
+ if (di->rem_capacity < 0)
+ di->rem_capacity = 0;
+ if (di->rem_capacity > 100)
+ di->rem_capacity = 100;
+
+ if (di->current_uA)
+ di->life_sec = -((di->accum_current_uAh - di->empty_uAh) *
+ 3600L) / di->current_uA;
+ else
+ di->life_sec = 0;
+
+ return 0;
+}
+
+static void ds2760_battery_update_status(struct ds2760_device_info *di)
+{
+ int old_charge_status = di->charge_status;
+
+ ds2760_battery_read_status(di);
+
+ if (di->charge_status == POWER_SUPPLY_STATUS_UNKNOWN)
+ di->full_counter = 0;
+
+ if (power_supply_am_i_supplied(&di->bat)) {
+ if (di->current_uA > 10000) {
+ di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+ di->full_counter = 0;
+ } else if (di->current_uA < -5000) {
+ if (di->charge_status != POWER_SUPPLY_STATUS_NOT_CHARGING)
+ dev_notice(di->dev, "not enough power to "
+ "charge\n");
+ di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ di->full_counter = 0;
+ } else if (di->current_uA < 10000 &&
+ di->charge_status != POWER_SUPPLY_STATUS_FULL) {
+
+ /* Don't consider the battery to be full unless
+ * we've seen the current < 10 mA at least two
+ * consecutive times. */
+
+ di->full_counter++;
+
+ if (di->full_counter < 2) {
+ di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+ } else {
+ unsigned char acr[2];
+ int acr_val;
+
+ /* acr is in units of 0.25 mAh */
+ acr_val = di->full_active_uAh * 4L / 1000;
+
+ acr[0] = acr_val >> 8;
+ acr[1] = acr_val & 0xff;
+
+ if (w1_ds2760_write(di->w1_dev, acr,
+ DS2760_CURRENT_ACCUM_MSB, 2) < 2)
+ dev_warn(di->dev,
+ "ACR reset failed\n");
+
+ di->charge_status = POWER_SUPPLY_STATUS_FULL;
+ }
+ }
+ } else {
+ di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
+ di->full_counter = 0;
+ }
+
+ if (di->charge_status != old_charge_status)
+ power_supply_changed(&di->bat);
+
+ return;
+}
+
+static void ds2760_battery_work(struct work_struct *work)
+{
+ struct ds2760_device_info *di = container_of(work,
+ struct ds2760_device_info, monitor_work.work);
+ const int interval = HZ * 60;
+
+ dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+ ds2760_battery_update_status(di);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);
+
+ return;
+}
+
+#define to_ds2760_device_info(x) container_of((x), struct ds2760_device_info, \
+ bat);
+
+static void ds2760_battery_external_power_changed(struct power_supply *psy)
+{
+ struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+ dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+ cancel_delayed_work(&di->monitor_work);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
+
+ return;
+}
+
+static int ds2760_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = di->charge_status;
+ return 0;
+ default:
+ break;
+ }
+
+ ds2760_battery_read_status(di);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = di->voltage_uV;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = di->current_uA;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = di->rated_capacity;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ val->intval = di->full_active_uAh;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_EMPTY:
+ val->intval = di->empty_uAh;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = di->accum_current_uAh;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = di->temp_C;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property ds2760_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_TEMP,
+};
+
+static int ds2760_battery_probe(struct platform_device *pdev)
+{
+ int retval = 0;
+ struct ds2760_device_info *di;
+ struct ds2760_platform_data *pdata;
+
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di) {
+ retval = -ENOMEM;
+ goto di_alloc_failed;
+ }
+
+ platform_set_drvdata(pdev, di);
+
+ pdata = pdev->dev.platform_data;
+ di->dev = &pdev->dev;
+ di->w1_dev = pdev->dev.parent;
+ di->bat.name = pdev->dev.bus_id;
+ di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat.properties = ds2760_battery_props;
+ di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props);
+ di->bat.get_property = ds2760_battery_get_property;
+ di->bat.external_power_changed =
+ ds2760_battery_external_power_changed;
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ retval = power_supply_register(&pdev->dev, &di->bat);
+ if (retval) {
+ dev_err(di->dev, "failed to register battery");
+ goto batt_failed;
+ }
+
+ INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
+ di->monitor_wqueue = create_singlethread_workqueue(pdev->dev.bus_id);
+ if (!di->monitor_wqueue) {
+ retval = -ESRCH;
+ goto workqueue_failed;
+ }
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);
+
+ goto success;
+
+workqueue_failed:
+ power_supply_unregister(&di->bat);
+batt_failed:
+ kfree(di);
+di_alloc_failed:
+success:
+ return retval;
+}
+
+static int ds2760_battery_remove(struct platform_device *pdev)
+{
+ struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+ cancel_rearming_delayed_workqueue(di->monitor_wqueue,
+ &di->monitor_work);
+ destroy_workqueue(di->monitor_wqueue);
+ power_supply_unregister(&di->bat);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ds2760_battery_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ return 0;
+}
+
+static int ds2760_battery_resume(struct platform_device *pdev)
+{
+ struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ power_supply_changed(&di->bat);
+
+ cancel_delayed_work(&di->monitor_work);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
+
+ return 0;
+}
+
+#else
+
+#define ds2760_battery_suspend NULL
+#define ds2760_battery_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct platform_driver ds2760_battery_driver = {
+ .driver = {
+ .name = "ds2760-battery",
+ },
+ .probe = ds2760_battery_probe,
+ .remove = ds2760_battery_remove,
+ .suspend = ds2760_battery_suspend,
+ .resume = ds2760_battery_resume,
+};
+
+static int __init ds2760_battery_init(void)
+{
+ return platform_driver_register(&ds2760_battery_driver);
+}
+
+static void __exit ds2760_battery_exit(void)
+{
+ platform_driver_unregister(&ds2760_battery_driver);
+ return;
+}
+
+module_init(ds2760_battery_init);
+module_exit(ds2760_battery_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
+ "Matt Reimer <mreimer@vpop.net>, "
+ "Anton Vorontsov <cbou@mail.ru>");
+MODULE_DESCRIPTION("ds2760 battery driver");
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
new file mode 100644
index 00000000000..878684df766
--- /dev/null
+++ b/drivers/power/olpc_battery.c
@@ -0,0 +1,352 @@
+/*
+ * Battery driver for One Laptop Per Child board.
+ *
+ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <asm/olpc.h>
+
+
+#define EC_BAT_VOLTAGE 0x10 /* uint16_t, *9.76/32, mV */
+#define EC_BAT_CURRENT 0x11 /* int16_t, *15.625/120, mA */
+#define EC_BAT_ACR 0x12
+#define EC_BAT_TEMP 0x13 /* uint16_t, *100/256, °C */
+#define EC_AMB_TEMP 0x14 /* uint16_t, *100/256, °C */
+#define EC_BAT_STATUS 0x15 /* uint8_t, bitmask */
+#define EC_BAT_SOC 0x16 /* uint8_t, percentage */
+#define EC_BAT_SERIAL 0x17 /* uint8_t[6] */
+#define EC_BAT_EEPROM 0x18 /* uint8_t adr as input, uint8_t output */
+#define EC_BAT_ERRCODE 0x1f /* uint8_t, bitmask */
+
+#define BAT_STAT_PRESENT 0x01
+#define BAT_STAT_FULL 0x02
+#define BAT_STAT_LOW 0x04
+#define BAT_STAT_DESTROY 0x08
+#define BAT_STAT_AC 0x10
+#define BAT_STAT_CHARGING 0x20
+#define BAT_STAT_DISCHARGING 0x40
+
+#define BAT_ERR_INFOFAIL 0x02
+#define BAT_ERR_OVERVOLTAGE 0x04
+#define BAT_ERR_OVERTEMP 0x05
+#define BAT_ERR_GAUGESTOP 0x06
+#define BAT_ERR_OUT_OF_CONTROL 0x07
+#define BAT_ERR_ID_FAIL 0x09
+#define BAT_ERR_ACR_FAIL 0x10
+
+#define BAT_ADDR_MFR_TYPE 0x5F
+
+/*********************************************************************
+ * Power
+ *********************************************************************/
+
+static int olpc_ac_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int ret = 0;
+ uint8_t status;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+ if (ret)
+ return ret;
+
+ val->intval = !!(status & BAT_STAT_AC);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property olpc_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply olpc_ac = {
+ .name = "olpc-ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = olpc_ac_props,
+ .num_properties = ARRAY_SIZE(olpc_ac_props),
+ .get_property = olpc_ac_get_prop,
+};
+
+/*********************************************************************
+ * Battery properties
+ *********************************************************************/
+static int olpc_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int ret = 0;
+ int16_t ec_word;
+ uint8_t ec_byte;
+
+ ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ /* Theoretically there's a race here -- the battery could be
+ removed immediately after we check whether it's present, and
+ then we query for some other property of the now-absent battery.
+ It doesn't matter though -- the EC will return the last-known
+ information, and it's as if we just ran that _little_ bit faster
+ and managed to read it out before the battery went away. */
+ if (!(ec_byte & BAT_STAT_PRESENT) && psp != POWER_SUPPLY_PROP_PRESENT)
+ return -ENODEV;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (olpc_platform_info.ecver > 0x44) {
+ if (ec_byte & BAT_STAT_CHARGING)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (ec_byte & BAT_STAT_DISCHARGING)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (ec_byte & BAT_STAT_FULL)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else /* er,... */
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ /* Older EC didn't report charge/discharge bits */
+ if (!(ec_byte & BAT_STAT_AC)) /* No AC means discharging */
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (ec_byte & BAT_STAT_FULL)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else /* Not _necessarily_ true but EC doesn't tell all yet */
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ }
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = !!(ec_byte & BAT_STAT_PRESENT);
+ break;
+
+ case POWER_SUPPLY_PROP_HEALTH:
+ if (ec_byte & BAT_STAT_DESTROY)
+ val->intval = POWER_SUPPLY_HEALTH_DEAD;
+ else {
+ ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ switch (ec_byte) {
+ case 0:
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+
+ case BAT_ERR_OVERTEMP:
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ break;
+
+ case BAT_ERR_OVERVOLTAGE:
+ val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ break;
+
+ case BAT_ERR_INFOFAIL:
+ case BAT_ERR_OUT_OF_CONTROL:
+ case BAT_ERR_ID_FAIL:
+ case BAT_ERR_ACR_FAIL:
+ val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ break;
+
+ default:
+ /* Eep. We don't know this failure code */
+ return -EIO;
+ }
+ }
+ break;
+
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ ec_byte = BAT_ADDR_MFR_TYPE;
+ ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ switch (ec_byte >> 4) {
+ case 1:
+ val->strval = "Gold Peak";
+ break;
+ case 2:
+ val->strval = "BYD";
+ break;
+ default:
+ val->strval = "Unknown";
+ break;
+ }
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ ec_byte = BAT_ADDR_MFR_TYPE;
+ ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ switch (ec_byte & 0xf) {
+ case 1:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
+ break;
+ case 2:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+ break;
+ }
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 9760L / 32;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 15625L / 120;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
+ if (ret)
+ return ret;
+ val->intval = ec_byte;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ if (ec_byte & BAT_STAT_FULL)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (ec_byte & BAT_STAT_LOW)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 100 / 256;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_AMBIENT:
+ ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 100 / 256;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static enum power_supply_property olpc_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_AMBIENT,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+/*********************************************************************
+ * Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static struct power_supply olpc_bat = {
+ .properties = olpc_bat_props,
+ .num_properties = ARRAY_SIZE(olpc_bat_props),
+ .get_property = olpc_bat_get_property,
+ .use_for_apm = 1,
+};
+
+void olpc_battery_trigger_uevent(unsigned long cause)
+{
+ if (cause & EC_SCI_SRC_ACPWR)
+ kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE);
+ if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY))
+ kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE);
+}
+
+static int __init olpc_bat_init(void)
+{
+ int ret = 0;
+ uint8_t status;
+
+ if (!olpc_platform_info.ecver)
+ return -ENXIO;
+ if (olpc_platform_info.ecver < 0x43) {
+ printk(KERN_NOTICE "OLPC EC version 0x%02x too old for battery driver.\n", olpc_platform_info.ecver);
+ return -ENXIO;
+ }
+
+ ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+ if (ret)
+ return ret;
+
+ /* Ignore the status. It doesn't actually matter */
+
+ bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0);
+ if (IS_ERR(bat_pdev))
+ return PTR_ERR(bat_pdev);
+
+ ret = power_supply_register(&bat_pdev->dev, &olpc_ac);
+ if (ret)
+ goto ac_failed;
+
+ olpc_bat.name = bat_pdev->name;
+
+ ret = power_supply_register(&bat_pdev->dev, &olpc_bat);
+ if (ret)
+ goto battery_failed;
+
+ olpc_register_battery_callback(&olpc_battery_trigger_uevent);
+ goto success;
+
+battery_failed:
+ power_supply_unregister(&olpc_ac);
+ac_failed:
+ platform_device_unregister(bat_pdev);
+success:
+ return ret;
+}
+
+static void __exit olpc_bat_exit(void)
+{
+ olpc_deregister_battery_callback();
+ power_supply_unregister(&olpc_bat);
+ power_supply_unregister(&olpc_ac);
+ platform_device_unregister(bat_pdev);
+ return;
+}
+
+module_init(olpc_bat_init);
+module_exit(olpc_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Battery driver for One Laptop Per Child 'XO' machine");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
new file mode 100644
index 00000000000..4e1eb040e14
--- /dev/null
+++ b/drivers/power/pda_power.c
@@ -0,0 +1,261 @@
+/*
+ * Common power driver for PDAs and phones with one or two external
+ * power supplies (AC/USB) connected to main and backup batteries,
+ * and optional builtin charger.
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/power_supply.h>
+#include <linux/pda_power.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+
+static inline unsigned int get_irq_flags(struct resource *res)
+{
+ unsigned int flags = IRQF_DISABLED | IRQF_SHARED;
+
+ flags |= res->flags & IRQF_TRIGGER_MASK;
+
+ return flags;
+}
+
+static struct device *dev;
+static struct pda_power_pdata *pdata;
+static struct resource *ac_irq, *usb_irq;
+static struct timer_list charger_timer;
+static struct timer_list supply_timer;
+
+static int pda_power_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ if (psy->type == POWER_SUPPLY_TYPE_MAINS)
+ val->intval = pdata->is_ac_online ?
+ pdata->is_ac_online() : 0;
+ else
+ val->intval = pdata->is_usb_online ?
+ pdata->is_usb_online() : 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static enum power_supply_property pda_power_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static char *pda_power_supplied_to[] = {
+ "main-battery",
+ "backup-battery",
+};
+
+static struct power_supply pda_power_supplies[] = {
+ {
+ .name = "ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .supplied_to = pda_power_supplied_to,
+ .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+ .properties = pda_power_props,
+ .num_properties = ARRAY_SIZE(pda_power_props),
+ .get_property = pda_power_get_property,
+ },
+ {
+ .name = "usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .supplied_to = pda_power_supplied_to,
+ .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+ .properties = pda_power_props,
+ .num_properties = ARRAY_SIZE(pda_power_props),
+ .get_property = pda_power_get_property,
+ },
+};
+
+static void update_charger(void)
+{
+ if (!pdata->set_charge)
+ return;
+
+ if (pdata->is_ac_online && pdata->is_ac_online()) {
+ dev_dbg(dev, "charger on (AC)\n");
+ pdata->set_charge(PDA_POWER_CHARGE_AC);
+ } else if (pdata->is_usb_online && pdata->is_usb_online()) {
+ dev_dbg(dev, "charger on (USB)\n");
+ pdata->set_charge(PDA_POWER_CHARGE_USB);
+ } else {
+ dev_dbg(dev, "charger off\n");
+ pdata->set_charge(0);
+ }
+
+ return;
+}
+
+static void supply_timer_func(unsigned long irq)
+{
+ if (ac_irq && irq == ac_irq->start)
+ power_supply_changed(&pda_power_supplies[0]);
+ else if (usb_irq && irq == usb_irq->start)
+ power_supply_changed(&pda_power_supplies[1]);
+ return;
+}
+
+static void charger_timer_func(unsigned long irq)
+{
+ update_charger();
+
+ /* Okay, charger set. Now wait a bit before notifying supplicants,
+ * charge power should stabilize. */
+ supply_timer.data = irq;
+ mod_timer(&supply_timer,
+ jiffies + msecs_to_jiffies(pdata->wait_for_charger));
+ return;
+}
+
+static irqreturn_t power_changed_isr(int irq, void *unused)
+{
+ /* Wait a bit before reading ac/usb line status and setting charger,
+ * because ac/usb status readings may lag from irq. */
+ charger_timer.data = irq;
+ mod_timer(&charger_timer,
+ jiffies + msecs_to_jiffies(pdata->wait_for_status));
+ return IRQ_HANDLED;
+}
+
+static int pda_power_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ dev = &pdev->dev;
+
+ if (pdev->id != -1) {
+ dev_err(dev, "it's meaningless to register several "
+ "pda_powers; use id = -1\n");
+ ret = -EINVAL;
+ goto wrongid;
+ }
+
+ pdata = pdev->dev.platform_data;
+
+ update_charger();
+
+ if (!pdata->wait_for_status)
+ pdata->wait_for_status = 500;
+
+ if (!pdata->wait_for_charger)
+ pdata->wait_for_charger = 500;
+
+ setup_timer(&charger_timer, charger_timer_func, 0);
+ setup_timer(&supply_timer, supply_timer_func, 0);
+
+ ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
+ usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
+ if (!ac_irq && !usb_irq) {
+ dev_err(dev, "no ac/usb irq specified\n");
+ ret = -ENODEV;
+ goto noirqs;
+ }
+
+ if (pdata->supplied_to) {
+ pda_power_supplies[0].supplied_to = pdata->supplied_to;
+ pda_power_supplies[1].supplied_to = pdata->supplied_to;
+ pda_power_supplies[0].num_supplicants = pdata->num_supplicants;
+ pda_power_supplies[1].num_supplicants = pdata->num_supplicants;
+ }
+
+ ret = power_supply_register(&pdev->dev, &pda_power_supplies[0]);
+ if (ret) {
+ dev_err(dev, "failed to register %s power supply\n",
+ pda_power_supplies[0].name);
+ goto supply0_failed;
+ }
+
+ ret = power_supply_register(&pdev->dev, &pda_power_supplies[1]);
+ if (ret) {
+ dev_err(dev, "failed to register %s power supply\n",
+ pda_power_supplies[1].name);
+ goto supply1_failed;
+ }
+
+ if (ac_irq) {
+ ret = request_irq(ac_irq->start, power_changed_isr,
+ get_irq_flags(ac_irq), ac_irq->name,
+ &pda_power_supplies[0]);
+ if (ret) {
+ dev_err(dev, "request ac irq failed\n");
+ goto ac_irq_failed;
+ }
+ }
+
+ if (usb_irq) {
+ ret = request_irq(usb_irq->start, power_changed_isr,
+ get_irq_flags(usb_irq), usb_irq->name,
+ &pda_power_supplies[1]);
+ if (ret) {
+ dev_err(dev, "request usb irq failed\n");
+ goto usb_irq_failed;
+ }
+ }
+
+ goto success;
+
+usb_irq_failed:
+ if (ac_irq)
+ free_irq(ac_irq->start, &pda_power_supplies[0]);
+ac_irq_failed:
+ power_supply_unregister(&pda_power_supplies[1]);
+supply1_failed:
+ power_supply_unregister(&pda_power_supplies[0]);
+supply0_failed:
+noirqs:
+wrongid:
+success:
+ return ret;
+}
+
+static int pda_power_remove(struct platform_device *pdev)
+{
+ if (usb_irq)
+ free_irq(usb_irq->start, &pda_power_supplies[1]);
+ if (ac_irq)
+ free_irq(ac_irq->start, &pda_power_supplies[0]);
+ del_timer_sync(&charger_timer);
+ del_timer_sync(&supply_timer);
+ power_supply_unregister(&pda_power_supplies[1]);
+ power_supply_unregister(&pda_power_supplies[0]);
+ return 0;
+}
+
+static struct platform_driver pda_power_pdrv = {
+ .driver = {
+ .name = "pda-power",
+ },
+ .probe = pda_power_probe,
+ .remove = pda_power_remove,
+};
+
+static int __init pda_power_init(void)
+{
+ return platform_driver_register(&pda_power_pdrv);
+}
+
+static void __exit pda_power_exit(void)
+{
+ platform_driver_unregister(&pda_power_pdrv);
+ return;
+}
+
+module_init(pda_power_init);
+module_exit(pda_power_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
diff --git a/drivers/power/pmu_battery.c b/drivers/power/pmu_battery.c
new file mode 100644
index 00000000000..2fea4af0e40
--- /dev/null
+++ b/drivers/power/pmu_battery.c
@@ -0,0 +1,215 @@
+/*
+ * Battery class driver for Apple PMU
+ *
+ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+static struct pmu_battery_dev {
+ struct power_supply bat;
+ struct pmu_battery_info *pbi;
+ char name[16];
+ int propval;
+} *pbats[PMU_MAX_BATTERIES];
+
+#define to_pmu_battery_dev(x) container_of(x, struct pmu_battery_dev, bat)
+
+/*********************************************************************
+ * Power
+ *********************************************************************/
+
+static int pmu_get_ac_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = (!!(pmu_power_flags & PMU_PWR_AC_PRESENT)) ||
+ (pmu_battery_count == 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property pmu_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply pmu_ac = {
+ .name = "pmu-ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = pmu_ac_props,
+ .num_properties = ARRAY_SIZE(pmu_ac_props),
+ .get_property = pmu_get_ac_prop,
+};
+
+/*********************************************************************
+ * Battery properties
+ *********************************************************************/
+
+static char *pmu_batt_types[] = {
+ "Smart", "Comet", "Hooper", "Unknown"
+};
+
+static char *pmu_bat_get_model_name(struct pmu_battery_info *pbi)
+{
+ switch (pbi->flags & PMU_BATT_TYPE_MASK) {
+ case PMU_BATT_TYPE_SMART:
+ return pmu_batt_types[0];
+ case PMU_BATT_TYPE_COMET:
+ return pmu_batt_types[1];
+ case PMU_BATT_TYPE_HOOPER:
+ return pmu_batt_types[2];
+ default: break;
+ }
+ return pmu_batt_types[3];
+}
+
+static int pmu_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct pmu_battery_dev *pbat = to_pmu_battery_dev(psy);
+ struct pmu_battery_info *pbi = pbat->pbi;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (pbi->flags & PMU_BATT_CHARGING)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = !!(pbi->flags & PMU_BATT_PRESENT);
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = pmu_bat_get_model_name(pbi);
+ break;
+ case POWER_SUPPLY_PROP_ENERGY_AVG:
+ val->intval = pbi->charge * 1000; /* mWh -> µWh */
+ break;
+ case POWER_SUPPLY_PROP_ENERGY_FULL:
+ val->intval = pbi->max_charge * 1000; /* mWh -> µWh */
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ val->intval = pbi->amperage * 1000; /* mA -> µA */
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ val->intval = pbi->voltage * 1000; /* mV -> µV */
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+ val->intval = pbi->time_remaining;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property pmu_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_ENERGY_AVG,
+ POWER_SUPPLY_PROP_ENERGY_FULL,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+};
+
+/*********************************************************************
+ * Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static int __init pmu_bat_init(void)
+{
+ int ret;
+ int i;
+
+ bat_pdev = platform_device_register_simple("pmu-battery",
+ 0, NULL, 0);
+ if (IS_ERR(bat_pdev)) {
+ ret = PTR_ERR(bat_pdev);
+ goto pdev_register_failed;
+ }
+
+ ret = power_supply_register(&bat_pdev->dev, &pmu_ac);
+ if (ret)
+ goto ac_register_failed;
+
+ for (i = 0; i < pmu_battery_count; i++) {
+ struct pmu_battery_dev *pbat = kzalloc(sizeof(*pbat),
+ GFP_KERNEL);
+ if (!pbat)
+ break;
+
+ sprintf(pbat->name, "PMU battery %d", i);
+ pbat->bat.name = pbat->name;
+ pbat->bat.properties = pmu_bat_props;
+ pbat->bat.num_properties = ARRAY_SIZE(pmu_bat_props);
+ pbat->bat.get_property = pmu_bat_get_property;
+ pbat->pbi = &pmu_batteries[i];
+
+ ret = power_supply_register(&bat_pdev->dev, &pbat->bat);
+ if (ret) {
+ kfree(pbat);
+ goto battery_register_failed;
+ }
+ pbats[i] = pbat;
+ }
+
+ goto success;
+
+battery_register_failed:
+ while (i--) {
+ if (!pbats[i])
+ continue;
+ power_supply_unregister(&pbats[i]->bat);
+ kfree(pbats[i]);
+ }
+ power_supply_unregister(&pmu_ac);
+ac_register_failed:
+ platform_device_unregister(bat_pdev);
+pdev_register_failed:
+success:
+ return ret;
+}
+
+static void __exit pmu_bat_exit(void)
+{
+ int i;
+
+ for (i = 0; i < PMU_MAX_BATTERIES; i++) {
+ if (!pbats[i])
+ continue;
+ power_supply_unregister(&pbats[i]->bat);
+ kfree(pbats[i]);
+ }
+ power_supply_unregister(&pmu_ac);
+ platform_device_unregister(bat_pdev);
+
+ return;
+}
+
+module_init(pmu_bat_init);
+module_exit(pmu_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PMU battery driver");
diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h
new file mode 100644
index 00000000000..a9880d468ee
--- /dev/null
+++ b/drivers/power/power_supply.h
@@ -0,0 +1,42 @@
+/*
+ * Functions private to power supply class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#ifdef CONFIG_SYSFS
+
+extern int power_supply_create_attrs(struct power_supply *psy);
+extern void power_supply_remove_attrs(struct power_supply *psy);
+extern int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size);
+
+#else
+
+static inline int power_supply_create_attrs(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_attrs(struct power_supply *psy) {}
+#define power_supply_uevent NULL
+
+#endif /* CONFIG_SYSFS */
+
+#ifdef CONFIG_LEDS_TRIGGERS
+
+extern void power_supply_update_leds(struct power_supply *psy);
+extern int power_supply_create_triggers(struct power_supply *psy);
+extern void power_supply_remove_triggers(struct power_supply *psy);
+
+#else
+
+static inline void power_supply_update_leds(struct power_supply *psy) {}
+static inline int power_supply_create_triggers(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_triggers(struct power_supply *psy) {}
+
+#endif /* CONFIG_LEDS_TRIGGERS */
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
new file mode 100644
index 00000000000..e87ea515675
--- /dev/null
+++ b/drivers/power/power_supply_core.c
@@ -0,0 +1,168 @@
+/*
+ * Universal power supply monitor class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include "power_supply.h"
+
+struct class *power_supply_class;
+
+static void power_supply_changed_work(struct work_struct *work)
+{
+ struct power_supply *psy = container_of(work, struct power_supply,
+ changed_work);
+ int i;
+
+ dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+ for (i = 0; i < psy->num_supplicants; i++) {
+ struct device *dev;
+
+ down(&power_supply_class->sem);
+ list_for_each_entry(dev, &power_supply_class->devices, node) {
+ struct power_supply *pst = dev_get_drvdata(dev);
+
+ if (!strcmp(psy->supplied_to[i], pst->name)) {
+ if (pst->external_power_changed)
+ pst->external_power_changed(pst);
+ }
+ }
+ up(&power_supply_class->sem);
+ }
+
+ power_supply_update_leds(psy);
+
+ kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
+
+ return;
+}
+
+void power_supply_changed(struct power_supply *psy)
+{
+ dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+ schedule_work(&psy->changed_work);
+
+ return;
+}
+
+int power_supply_am_i_supplied(struct power_supply *psy)
+{
+ union power_supply_propval ret = {0,};
+ struct device *dev;
+
+ down(&power_supply_class->sem);
+ list_for_each_entry(dev, &power_supply_class->devices, node) {
+ struct power_supply *epsy = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < epsy->num_supplicants; i++) {
+ if (!strcmp(epsy->supplied_to[i], psy->name)) {
+ if (epsy->get_property(epsy,
+ POWER_SUPPLY_PROP_ONLINE, &ret))
+ continue;
+ if (ret.intval)
+ goto out;
+ }
+ }
+ }
+out:
+ up(&power_supply_class->sem);
+
+ dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, ret.intval);
+
+ return ret.intval;
+}
+
+int power_supply_register(struct device *parent, struct power_supply *psy)
+{
+ int rc = 0;
+
+ psy->dev = device_create(power_supply_class, parent, 0,
+ "%s", psy->name);
+ if (IS_ERR(psy->dev)) {
+ rc = PTR_ERR(psy->dev);
+ goto dev_create_failed;
+ }
+
+ dev_set_drvdata(psy->dev, psy);
+
+ INIT_WORK(&psy->changed_work, power_supply_changed_work);
+
+ rc = power_supply_create_attrs(psy);
+ if (rc)
+ goto create_attrs_failed;
+
+ rc = power_supply_create_triggers(psy);
+ if (rc)
+ goto create_triggers_failed;
+
+ power_supply_changed(psy);
+
+ goto success;
+
+create_triggers_failed:
+ power_supply_remove_attrs(psy);
+create_attrs_failed:
+ device_unregister(psy->dev);
+dev_create_failed:
+success:
+ return rc;
+}
+
+void power_supply_unregister(struct power_supply *psy)
+{
+ flush_scheduled_work();
+ power_supply_remove_triggers(psy);
+ power_supply_remove_attrs(psy);
+ device_unregister(psy->dev);
+ return;
+}
+
+static int __init power_supply_class_init(void)
+{
+ power_supply_class = class_create(THIS_MODULE, "power_supply");
+
+ if (IS_ERR(power_supply_class))
+ return PTR_ERR(power_supply_class);
+
+ power_supply_class->dev_uevent = power_supply_uevent;
+
+ return 0;
+}
+
+static void __exit power_supply_class_exit(void)
+{
+ class_destroy(power_supply_class);
+ return;
+}
+
+EXPORT_SYMBOL_GPL(power_supply_changed);
+EXPORT_SYMBOL_GPL(power_supply_am_i_supplied);
+EXPORT_SYMBOL_GPL(power_supply_register);
+EXPORT_SYMBOL_GPL(power_supply_unregister);
+
+/* exported for the APM Power driver, APM emulation */
+EXPORT_SYMBOL_GPL(power_supply_class);
+
+subsys_initcall(power_supply_class_init);
+module_exit(power_supply_class_exit);
+
+MODULE_DESCRIPTION("Universal power supply monitor class");
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, "
+ "Szabolcs Gyurko, "
+ "Anton Vorontsov <cbou@mail.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c
new file mode 100644
index 00000000000..7232490bb59
--- /dev/null
+++ b/drivers/power/power_supply_leds.c
@@ -0,0 +1,176 @@
+/*
+ * LEDs triggers for power supply class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#include <linux/power_supply.h>
+
+/* Battery specific LEDs triggers. */
+
+static void power_supply_update_bat_leds(struct power_supply *psy)
+{
+ union power_supply_propval status;
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
+ return;
+
+ dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, status.intval);
+
+ switch (status.intval) {
+ case POWER_SUPPLY_STATUS_FULL:
+ led_trigger_event(psy->charging_full_trig, LED_FULL);
+ led_trigger_event(psy->charging_trig, LED_OFF);
+ led_trigger_event(psy->full_trig, LED_FULL);
+ break;
+ case POWER_SUPPLY_STATUS_CHARGING:
+ led_trigger_event(psy->charging_full_trig, LED_FULL);
+ led_trigger_event(psy->charging_trig, LED_FULL);
+ led_trigger_event(psy->full_trig, LED_OFF);
+ break;
+ default:
+ led_trigger_event(psy->charging_full_trig, LED_OFF);
+ led_trigger_event(psy->charging_trig, LED_OFF);
+ led_trigger_event(psy->full_trig, LED_OFF);
+ break;
+ }
+
+ return;
+}
+
+static int power_supply_create_bat_triggers(struct power_supply *psy)
+{
+ int rc = 0;
+
+ psy->charging_full_trig_name = kmalloc(strlen(psy->name) +
+ sizeof("-charging-or-full"), GFP_KERNEL);
+ if (!psy->charging_full_trig_name)
+ goto charging_full_failed;
+
+ psy->charging_trig_name = kmalloc(strlen(psy->name) +
+ sizeof("-charging"), GFP_KERNEL);
+ if (!psy->charging_trig_name)
+ goto charging_failed;
+
+ psy->full_trig_name = kmalloc(strlen(psy->name) +
+ sizeof("-full"), GFP_KERNEL);
+ if (!psy->full_trig_name)
+ goto full_failed;
+
+ strcpy(psy->charging_full_trig_name, psy->name);
+ strcat(psy->charging_full_trig_name, "-charging-or-full");
+ strcpy(psy->charging_trig_name, psy->name);
+ strcat(psy->charging_trig_name, "-charging");
+ strcpy(psy->full_trig_name, psy->name);
+ strcat(psy->full_trig_name, "-full");
+
+ led_trigger_register_simple(psy->charging_full_trig_name,
+ &psy->charging_full_trig);
+ led_trigger_register_simple(psy->charging_trig_name,
+ &psy->charging_trig);
+ led_trigger_register_simple(psy->full_trig_name,
+ &psy->full_trig);
+
+ goto success;
+
+full_failed:
+ kfree(psy->charging_trig_name);
+charging_failed:
+ kfree(psy->charging_full_trig_name);
+charging_full_failed:
+ rc = -ENOMEM;
+success:
+ return rc;
+}
+
+static void power_supply_remove_bat_triggers(struct power_supply *psy)
+{
+ led_trigger_unregister_simple(psy->charging_full_trig);
+ led_trigger_unregister_simple(psy->charging_trig);
+ led_trigger_unregister_simple(psy->full_trig);
+ kfree(psy->full_trig_name);
+ kfree(psy->charging_trig_name);
+ kfree(psy->charging_full_trig_name);
+ return;
+}
+
+/* Generated power specific LEDs triggers. */
+
+static void power_supply_update_gen_leds(struct power_supply *psy)
+{
+ union power_supply_propval online;
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
+ return;
+
+ dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, online.intval);
+
+ if (online.intval)
+ led_trigger_event(psy->online_trig, LED_FULL);
+ else
+ led_trigger_event(psy->online_trig, LED_OFF);
+
+ return;
+}
+
+static int power_supply_create_gen_triggers(struct power_supply *psy)
+{
+ int rc = 0;
+
+ psy->online_trig_name = kmalloc(strlen(psy->name) + sizeof("-online"),
+ GFP_KERNEL);
+ if (!psy->online_trig_name)
+ goto online_failed;
+
+ strcpy(psy->online_trig_name, psy->name);
+ strcat(psy->online_trig_name, "-online");
+
+ led_trigger_register_simple(psy->online_trig_name, &psy->online_trig);
+
+ goto success;
+
+online_failed:
+ rc = -ENOMEM;
+success:
+ return rc;
+}
+
+static void power_supply_remove_gen_triggers(struct power_supply *psy)
+{
+ led_trigger_unregister_simple(psy->online_trig);
+ kfree(psy->online_trig_name);
+ return;
+}
+
+/* Choice what triggers to create&update. */
+
+void power_supply_update_leds(struct power_supply *psy)
+{
+ if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ power_supply_update_bat_leds(psy);
+ else
+ power_supply_update_gen_leds(psy);
+ return;
+}
+
+int power_supply_create_triggers(struct power_supply *psy)
+{
+ if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ return power_supply_create_bat_triggers(psy);
+ return power_supply_create_gen_triggers(psy);
+}
+
+void power_supply_remove_triggers(struct power_supply *psy)
+{
+ if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ power_supply_remove_bat_triggers(psy);
+ else
+ power_supply_remove_gen_triggers(psy);
+ return;
+}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
new file mode 100644
index 00000000000..c07d4258d34
--- /dev/null
+++ b/drivers/power/power_supply_sysfs.c
@@ -0,0 +1,299 @@
+/*
+ * Sysfs interface for the universal power supply monitor class
+ *
+ * Copyright © 2007 David Woodhouse <dwmw2@infradead.org>
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#include <linux/ctype.h>
+#include <linux/power_supply.h>
+
+/*
+ * This is because the name "current" breaks the device attr macro.
+ * The "current" word resolves to "(get_current())" so instead of
+ * "current" "(get_current())" appears in the sysfs.
+ *
+ * The source of this definition is the device.h which calls __ATTR
+ * macro in sysfs.h which calls the __stringify macro.
+ *
+ * Only modification that the name is not tried to be resolved
+ * (as a macro let's say).
+ */
+
+#define POWER_SUPPLY_ATTR(_name) \
+{ \
+ .attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE }, \
+ .show = power_supply_show_property, \
+ .store = NULL, \
+}
+
+static struct device_attribute power_supply_attrs[];
+
+static ssize_t power_supply_show_property(struct device *dev,
+ struct device_attribute *attr,
+ char *buf) {
+ static char *status_text[] = {
+ "Unknown", "Charging", "Discharging", "Not charging", "Full"
+ };
+ static char *health_text[] = {
+ "Unknown", "Good", "Overheat", "Dead", "Over voltage",
+ "Unspecified failure"
+ };
+ static char *technology_text[] = {
+ "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd"
+ };
+ static char *capacity_level_text[] = {
+ "Unknown", "Critical", "Low", "Normal", "High", "Full"
+ };
+ ssize_t ret;
+ struct power_supply *psy = dev_get_drvdata(dev);
+ const ptrdiff_t off = attr - power_supply_attrs;
+ union power_supply_propval value;
+
+ ret = psy->get_property(psy, off, &value);
+
+ if (ret < 0) {
+ if (ret != -ENODEV)
+ dev_err(dev, "driver failed to report `%s' property\n",
+ attr->attr.name);
+ return ret;
+ }
+
+ if (off == POWER_SUPPLY_PROP_STATUS)
+ return sprintf(buf, "%s\n", status_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_HEALTH)
+ return sprintf(buf, "%s\n", health_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_TECHNOLOGY)
+ return sprintf(buf, "%s\n", technology_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL)
+ return sprintf(buf, "%s\n",
+ capacity_level_text[value.intval]);
+ else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
+ return sprintf(buf, "%s\n", value.strval);
+
+ return sprintf(buf, "%d\n", value.intval);
+}
+
+/* Must be in the same order as POWER_SUPPLY_PROP_* */
+static struct device_attribute power_supply_attrs[] = {
+ /* Properties of type `int' */
+ POWER_SUPPLY_ATTR(status),
+ POWER_SUPPLY_ATTR(health),
+ POWER_SUPPLY_ATTR(present),
+ POWER_SUPPLY_ATTR(online),
+ POWER_SUPPLY_ATTR(technology),
+ POWER_SUPPLY_ATTR(voltage_max_design),
+ POWER_SUPPLY_ATTR(voltage_min_design),
+ POWER_SUPPLY_ATTR(voltage_now),
+ POWER_SUPPLY_ATTR(voltage_avg),
+ POWER_SUPPLY_ATTR(current_now),
+ POWER_SUPPLY_ATTR(current_avg),
+ POWER_SUPPLY_ATTR(charge_full_design),
+ POWER_SUPPLY_ATTR(charge_empty_design),
+ POWER_SUPPLY_ATTR(charge_full),
+ POWER_SUPPLY_ATTR(charge_empty),
+ POWER_SUPPLY_ATTR(charge_now),
+ POWER_SUPPLY_ATTR(charge_avg),
+ POWER_SUPPLY_ATTR(energy_full_design),
+ POWER_SUPPLY_ATTR(energy_empty_design),
+ POWER_SUPPLY_ATTR(energy_full),
+ POWER_SUPPLY_ATTR(energy_empty),
+ POWER_SUPPLY_ATTR(energy_now),
+ POWER_SUPPLY_ATTR(energy_avg),
+ POWER_SUPPLY_ATTR(capacity),
+ POWER_SUPPLY_ATTR(capacity_level),
+ POWER_SUPPLY_ATTR(temp),
+ POWER_SUPPLY_ATTR(temp_ambient),
+ POWER_SUPPLY_ATTR(time_to_empty_now),
+ POWER_SUPPLY_ATTR(time_to_empty_avg),
+ POWER_SUPPLY_ATTR(time_to_full_now),
+ POWER_SUPPLY_ATTR(time_to_full_avg),
+ /* Properties of type `const char *' */
+ POWER_SUPPLY_ATTR(model_name),
+ POWER_SUPPLY_ATTR(manufacturer),
+};
+
+static ssize_t power_supply_show_static_attrs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf) {
+ static char *type_text[] = { "Battery", "UPS", "Mains", "USB" };
+ struct power_supply *psy = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", type_text[psy->type]);
+}
+
+static struct device_attribute power_supply_static_attrs[] = {
+ __ATTR(type, 0444, power_supply_show_static_attrs, NULL),
+};
+
+int power_supply_create_attrs(struct power_supply *psy)
+{
+ int rc = 0;
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++) {
+ rc = device_create_file(psy->dev,
+ &power_supply_static_attrs[i]);
+ if (rc)
+ goto statics_failed;
+ }
+
+ for (j = 0; j < psy->num_properties; j++) {
+ rc = device_create_file(psy->dev,
+ &power_supply_attrs[psy->properties[j]]);
+ if (rc)
+ goto dynamics_failed;
+ }
+
+ goto succeed;
+
+dynamics_failed:
+ while (j--)
+ device_remove_file(psy->dev,
+ &power_supply_attrs[psy->properties[j]]);
+statics_failed:
+ while (i--)
+ device_remove_file(psy->dev,
+ &power_supply_static_attrs[psy->properties[i]]);
+succeed:
+ return rc;
+}
+
+void power_supply_remove_attrs(struct power_supply *psy)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++)
+ device_remove_file(psy->dev,
+ &power_supply_static_attrs[i]);
+
+ for (i = 0; i < psy->num_properties; i++)
+ device_remove_file(psy->dev,
+ &power_supply_attrs[psy->properties[i]]);
+
+ return;
+}
+
+static char *kstruprdup(const char *str, gfp_t gfp)
+{
+ char *ret, *ustr;
+
+ ustr = ret = kmalloc(strlen(str) + 1, gfp);
+
+ if (!ret)
+ return NULL;
+
+ while (*str)
+ *ustr++ = toupper(*str++);
+
+ *ustr = 0;
+
+ return ret;
+}
+
+int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ struct power_supply *psy = dev_get_drvdata(dev);
+ int i = 0, length = 0, ret = 0, j;
+ char *prop_buf;
+ char *attrname;
+
+ dev_dbg(dev, "uevent\n");
+
+ if (!psy) {
+ dev_dbg(dev, "No power supply yet\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
+
+ ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "POWER_SUPPLY_NAME=%s", psy->name);
+ if (ret)
+ return ret;
+
+ prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!prop_buf)
+ return -ENOMEM;
+
+ for (j = 0; j < ARRAY_SIZE(power_supply_static_attrs); j++) {
+ struct device_attribute *attr;
+ char *line;
+
+ attr = &power_supply_static_attrs[j];
+
+ ret = power_supply_show_static_attrs(dev, attr, prop_buf);
+ if (ret < 0)
+ goto out;
+
+ line = strchr(prop_buf, '\n');
+ if (line)
+ *line = 0;
+
+ attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+ if (!attrname) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
+
+ ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "POWER_SUPPLY_%s=%s",
+ attrname, prop_buf);
+ kfree(attrname);
+ if (ret)
+ goto out;
+ }
+
+ dev_dbg(dev, "%zd dynamic props\n", psy->num_properties);
+
+ for (j = 0; j < psy->num_properties; j++) {
+ struct device_attribute *attr;
+ char *line;
+
+ attr = &power_supply_attrs[psy->properties[j]];
+
+ ret = power_supply_show_property(dev, attr, prop_buf);
+ if (ret == -ENODEV) {
+ /* When a battery is absent, we expect -ENODEV. Don't abort;
+ send the uevent with at least the the PRESENT=0 property */
+ ret = 0;
+ continue;
+ }
+
+ if (ret < 0)
+ goto out;
+
+ line = strchr(prop_buf, '\n');
+ if (line)
+ *line = 0;
+
+ attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+ if (!attrname) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
+
+ ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "POWER_SUPPLY_%s=%s",
+ attrname, prop_buf);
+ kfree(attrname);
+ if (ret)
+ goto out;
+ }
+
+out:
+ free_page((unsigned long)prop_buf);
+
+ return ret;
+}
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 8b3b0f4a157..ac7e8ef504c 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -28,6 +28,7 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL;
static struct proc_dir_entry *dasd_devices_entry = NULL;
static struct proc_dir_entry *dasd_statistics_entry = NULL;
+#ifdef CONFIG_DASD_PROFILE
static char *
dasd_get_user_string(const char __user *user_buf, size_t user_len)
{
@@ -47,6 +48,7 @@ dasd_get_user_string(const char __user *user_buf, size_t user_len)
buffer[user_len] = 0;
return buffer;
}
+#endif /* CONFIG_DASD_PROFILE */
static int
dasd_devices_show(struct seq_file *m, void *v)
@@ -167,6 +169,7 @@ dasd_calc_metrics(char *page, char **start, off_t off,
return len;
}
+#ifdef CONFIG_DASD_PROFILE
static char *
dasd_statistics_array(char *str, unsigned int *array, int shift)
{
@@ -180,6 +183,7 @@ dasd_statistics_array(char *str, unsigned int *array, int shift)
str += sprintf(str,"\n");
return str;
}
+#endif /* CONFIG_DASD_PROFILE */
static int
dasd_statistics_read(char *page, char **start, off_t off,
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index dbb99d1b6f5..c7318a12585 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -72,6 +72,18 @@ typedef unsigned int sclp_cmdw_t;
typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
+struct sccb_header {
+ u16 length;
+ u8 function_code;
+ u8 control_mask[3];
+ u16 response_code;
+} __attribute__((packed));
+
+extern u64 sclp_facilities;
+
+#define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL)
+#define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL)
+
struct gds_subvector {
u8 length;
u8 key;
diff --git a/drivers/s390/char/sclp_chp.c b/drivers/s390/char/sclp_chp.c
index a66b914519b..c68f5e7e63a 100644
--- a/drivers/s390/char/sclp_chp.c
+++ b/drivers/s390/char/sclp_chp.c
@@ -55,6 +55,8 @@ static int do_configure(sclp_cmdw_t cmd)
struct chp_cfg_data *data;
int rc;
+ if (!SCLP_HAS_CHP_RECONFIG)
+ return -EOPNOTSUPP;
/* Prepare sccb. */
data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!data)
@@ -152,6 +154,8 @@ int sclp_chp_read_info(struct sclp_chp_info *info)
struct chp_info_data *data;
int rc;
+ if (!SCLP_HAS_CHP_INFO)
+ return -EOPNOTSUPP;
/* Prepare sccb. */
data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!data)
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
index 7bcbe643b08..a1136e05275 100644
--- a/drivers/s390/char/sclp_info.c
+++ b/drivers/s390/char/sclp_info.c
@@ -11,47 +11,106 @@
#include <asm/sclp.h>
#include "sclp.h"
-struct sclp_readinfo_sccb s390_readinfo_sccb;
+struct sclp_readinfo_sccb {
+ struct sccb_header header; /* 0-7 */
+ u16 rnmax; /* 8-9 */
+ u8 rnsize; /* 10 */
+ u8 _reserved0[24 - 11]; /* 11-23 */
+ u8 loadparm[8]; /* 24-31 */
+ u8 _reserved1[48 - 32]; /* 32-47 */
+ u64 facilities; /* 48-55 */
+ u8 _reserved2[91 - 56]; /* 56-90 */
+ u8 flags; /* 91 */
+ u8 _reserved3[100 - 92]; /* 92-99 */
+ u32 rnsize2; /* 100-103 */
+ u64 rnmax2; /* 104-111 */
+ u8 _reserved4[4096 - 112]; /* 112-4095 */
+} __attribute__((packed, aligned(4096)));
+
+static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
+static int __initdata early_readinfo_sccb_valid;
+
+u64 sclp_facilities;
void __init sclp_readinfo_early(void)
{
- sclp_cmdw_t command;
- struct sccb_header *sccb;
int ret;
+ int i;
+ struct sclp_readinfo_sccb *sccb;
+ sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
+ SCLP_CMDW_READ_SCP_INFO};
- __ctl_set_bit(0, 9); /* enable service signal subclass mask */
-
- sccb = &s390_readinfo_sccb.header;
- command = SCLP_CMDW_READ_SCP_INFO_FORCED;
- while (1) {
- u16 response;
-
- memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
- sccb->length = sizeof(s390_readinfo_sccb);
- sccb->control_mask[2] = 0x80;
-
- ret = sclp_service_call(command, &s390_readinfo_sccb);
-
- if (ret == -EIO)
- goto out;
- if (ret == -EBUSY)
- continue;
+ /* Enable service signal subclass mask. */
+ __ctl_set_bit(0, 9);
+ sccb = &early_readinfo_sccb;
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ do {
+ memset(sccb, 0, sizeof(*sccb));
+ sccb->header.length = sizeof(*sccb);
+ sccb->header.control_mask[2] = 0x80;
+ ret = sclp_service_call(commands[i], sccb);
+ } while (ret == -EBUSY);
+ if (ret)
+ break;
__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
PSW_MASK_WAIT | PSW_DEFAULT_KEY);
local_irq_disable();
+ /*
+ * Contents of the sccb might have changed
+ * therefore a barrier is needed.
+ */
barrier();
+ if (sccb->header.response_code == 0x10) {
+ early_readinfo_sccb_valid = 1;
+ break;
+ }
+ if (sccb->header.response_code != 0x1f0)
+ break;
+ }
+ /* Disable service signal subclass mask again. */
+ __ctl_clear_bit(0, 9);
+}
- response = sccb->response_code;
+void __init sclp_facilities_detect(void)
+{
+ if (!early_readinfo_sccb_valid)
+ return;
+ sclp_facilities = early_readinfo_sccb.facilities;
+}
- if (response == 0x10)
- break;
+unsigned long long __init sclp_memory_detect(void)
+{
+ unsigned long long memsize;
+ struct sclp_readinfo_sccb *sccb;
- if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
- break;
+ if (!early_readinfo_sccb_valid)
+ return 0;
+ sccb = &early_readinfo_sccb;
+ if (sccb->rnsize)
+ memsize = sccb->rnsize << 20;
+ else
+ memsize = sccb->rnsize2 << 20;
+ if (sccb->rnmax)
+ memsize *= sccb->rnmax;
+ else
+ memsize *= sccb->rnmax2;
+ return memsize;
+}
- command = SCLP_CMDW_READ_SCP_INFO;
- }
-out:
- __ctl_clear_bit(0, 9); /* disable service signal subclass mask */
+/*
+ * This function will be called after sclp_memory_detect(), which gets called
+ * early from early.c code. Therefore the sccb should have valid contents.
+ */
+void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
+{
+ struct sclp_readinfo_sccb *sccb;
+
+ if (!early_readinfo_sccb_valid)
+ return;
+ sccb = &early_readinfo_sccb;
+ info->is_valid = 1;
+ if (sccb->flags & 0x2)
+ info->has_dump = 1;
+ memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
}
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index fce3dac5cb3..82e6a6b253e 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -175,13 +175,12 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static const struct file_operations vmcp_fops = {
.owner = THIS_MODULE,
- .open = &vmcp_open,
- .release = &vmcp_release,
- .read = &vmcp_read,
- .llseek = &no_llseek,
- .write = &vmcp_write,
- .unlocked_ioctl = &vmcp_ioctl,
- .compat_ioctl = &vmcp_ioctl
+ .open = vmcp_open,
+ .release = vmcp_release,
+ .read = vmcp_read,
+ .write = vmcp_write,
+ .unlocked_ioctl = vmcp_ioctl,
+ .compat_ioctl = vmcp_ioctl
};
static struct miscdevice vmcp_dev = {
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index a5a00e9ae4d..12f7a4ce82c 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -835,7 +835,7 @@ static void vmlogrdr_cleanup(void)
}
-static int vmlogrdr_init(void)
+static int __init vmlogrdr_init(void)
{
int rc;
int i;
@@ -885,7 +885,7 @@ cleanup:
}
-static void vmlogrdr_exit(void)
+static void __exit vmlogrdr_exit(void)
{
vmlogrdr_cleanup();
printk (KERN_INFO "vmlogrdr: driver unloaded\n");
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 4e711a985d5..3712ede1672 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -156,7 +156,7 @@ static int memcpy_real(void *dest, unsigned long src, size_t count)
return rc;
}
-static int memcpy_real_user(__user void *dest, unsigned long src, size_t count)
+static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
{
static char buf[4096];
int offs = 0, size;
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 997f4687453..60b9347f7c9 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -27,7 +27,6 @@
/*
* diag210 is used under VM to get information about a virtual device
*/
-#ifdef CONFIG_64BIT
int
diag210(struct diag210 * addr)
{
@@ -43,6 +42,7 @@ diag210(struct diag210 * addr)
spin_lock_irqsave(&diag210_lock, flags);
diag210_tmp = *addr;
+#ifdef CONFIG_64BIT
asm volatile(
" lhi %0,-1\n"
" sam31\n"
@@ -51,19 +51,8 @@ diag210(struct diag210 * addr)
" srl %0,28\n"
"1: sam64\n"
EX_TABLE(0b,1b)
- : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory");
-
- *addr = diag210_tmp;
- spin_unlock_irqrestore(&diag210_lock, flags);
-
- return ccode;
-}
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
#else
-int
-diag210(struct diag210 * addr)
-{
- int ccode;
-
asm volatile(
" lhi %0,-1\n"
" diag %1,0,0x210\n"
@@ -71,11 +60,14 @@ diag210(struct diag210 * addr)
" srl %0,28\n"
"1:\n"
EX_TABLE(0b,1b)
- : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory");
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
+#endif
+
+ *addr = diag210_tmp;
+ spin_unlock_irqrestore(&diag210_lock, flags);
return ccode;
}
-#endif
/*
* Input :
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 5aac0ec3636..90bd2201451 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -43,6 +43,7 @@ static void ap_poll_all(unsigned long);
static void ap_poll_timeout(unsigned long);
static int ap_poll_thread_start(void);
static void ap_poll_thread_stop(void);
+static void ap_request_timeout(unsigned long);
/**
* Module description.
@@ -189,6 +190,7 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
case AP_RESPONSE_NORMAL:
return 0;
case AP_RESPONSE_Q_FULL:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
return -EBUSY;
default: /* Device is gone. */
return -ENODEV;
@@ -252,6 +254,8 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
if (status.queue_empty)
return -ENOENT;
return -EBUSY;
+ case AP_RESPONSE_RESET_IN_PROGRESS:
+ return -EBUSY;
default:
return -ENODEV;
}
@@ -326,11 +330,12 @@ static int ap_init_queue(ap_qid_t qid)
i = AP_MAX_RESET; /* return with -ENODEV */
break;
case AP_RESPONSE_RESET_IN_PROGRESS:
+ rc = -EBUSY;
case AP_RESPONSE_BUSY:
default:
break;
}
- if (rc != -ENODEV)
+ if (rc != -ENODEV && rc != -EBUSY)
break;
if (i < AP_MAX_RESET - 1) {
udelay(5);
@@ -341,6 +346,40 @@ static int ap_init_queue(ap_qid_t qid)
}
/**
+ * Arm request timeout if a AP device was idle and a new request is submitted.
+ */
+static void ap_increase_queue_count(struct ap_device *ap_dev)
+{
+ int timeout = ap_dev->drv->request_timeout;
+
+ ap_dev->queue_count++;
+ if (ap_dev->queue_count == 1) {
+ mod_timer(&ap_dev->timeout, jiffies + timeout);
+ ap_dev->reset = AP_RESET_ARMED;
+ }
+}
+
+/**
+ * AP device is still alive, re-schedule request timeout if there are still
+ * pending requests.
+ */
+static void ap_decrease_queue_count(struct ap_device *ap_dev)
+{
+ int timeout = ap_dev->drv->request_timeout;
+
+ ap_dev->queue_count--;
+ if (ap_dev->queue_count > 0)
+ mod_timer(&ap_dev->timeout, jiffies + timeout);
+ else
+ /**
+ * The timeout timer should to be disabled now - since
+ * del_timer_sync() is very expensive, we just tell via the
+ * reset flag to ignore the pending timeout timer.
+ */
+ ap_dev->reset = AP_RESET_IGNORE;
+}
+
+/**
* AP device related attributes.
*/
static ssize_t ap_hwtype_show(struct device *dev,
@@ -498,6 +537,7 @@ static int ap_device_remove(struct device *dev)
struct ap_driver *ap_drv = ap_dev->drv;
ap_flush_queue(ap_dev);
+ del_timer_sync(&ap_dev->timeout);
if (ap_drv->remove)
ap_drv->remove(ap_dev);
spin_lock_bh(&ap_device_lock);
@@ -759,17 +799,21 @@ static void ap_scan_bus(struct work_struct *unused)
__ap_scan_bus);
rc = ap_query_queue(qid, &queue_depth, &device_type);
if (dev) {
+ if (rc == -EBUSY) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(AP_RESET_TIMEOUT);
+ rc = ap_query_queue(qid, &queue_depth,
+ &device_type);
+ }
ap_dev = to_ap_dev(dev);
spin_lock_bh(&ap_dev->lock);
if (rc || ap_dev->unregistered) {
spin_unlock_bh(&ap_dev->lock);
- put_device(dev);
device_unregister(dev);
+ put_device(dev);
continue;
- } else
- spin_unlock_bh(&ap_dev->lock);
- }
- if (dev) {
+ }
+ spin_unlock_bh(&ap_dev->lock);
put_device(dev);
continue;
}
@@ -788,6 +832,8 @@ static void ap_scan_bus(struct work_struct *unused)
INIT_LIST_HEAD(&ap_dev->pendingq);
INIT_LIST_HEAD(&ap_dev->requestq);
INIT_LIST_HEAD(&ap_dev->list);
+ setup_timer(&ap_dev->timeout, ap_request_timeout,
+ (unsigned long) ap_dev);
if (device_type == 0)
ap_probe_device_type(ap_dev);
else
@@ -853,7 +899,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
atomic_dec(&ap_poll_requests);
- ap_dev->queue_count--;
+ ap_decrease_queue_count(ap_dev);
list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
if (ap_msg->psmid != ap_dev->reply->psmid)
continue;
@@ -904,7 +950,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
atomic_inc(&ap_poll_requests);
- ap_dev->queue_count++;
+ ap_increase_queue_count(ap_dev);
list_move_tail(&ap_msg->list, &ap_dev->pendingq);
ap_dev->requestq_count--;
ap_dev->pendingq_count++;
@@ -914,6 +960,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
*flags |= 2;
break;
case AP_RESPONSE_Q_FULL:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
*flags |= 2;
break;
case AP_RESPONSE_MESSAGE_TOO_BIG:
@@ -960,10 +1007,11 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms
list_add_tail(&ap_msg->list, &ap_dev->pendingq);
atomic_inc(&ap_poll_requests);
ap_dev->pendingq_count++;
- ap_dev->queue_count++;
+ ap_increase_queue_count(ap_dev);
ap_dev->total_request_count++;
break;
case AP_RESPONSE_Q_FULL:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
list_add_tail(&ap_msg->list, &ap_dev->requestq);
ap_dev->requestq_count++;
ap_dev->total_request_count++;
@@ -1046,6 +1094,25 @@ static void ap_poll_timeout(unsigned long unused)
}
/**
+ * Reset a not responding AP device and move all requests from the
+ * pending queue to the request queue.
+ */
+static void ap_reset(struct ap_device *ap_dev)
+{
+ int rc;
+
+ ap_dev->reset = AP_RESET_IGNORE;
+ atomic_sub(ap_dev->queue_count, &ap_poll_requests);
+ ap_dev->queue_count = 0;
+ list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
+ ap_dev->requestq_count += ap_dev->pendingq_count;
+ ap_dev->pendingq_count = 0;
+ rc = ap_init_queue(ap_dev->qid);
+ if (rc == -ENODEV)
+ ap_dev->unregistered = 1;
+}
+
+/**
* Poll all AP devices on the bus in a round robin fashion. Continue
* polling until bit 2^0 of the control flags is not set. If bit 2^1
* of the control flags has been set arm the poll timer.
@@ -1056,6 +1123,8 @@ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
if (!ap_dev->unregistered) {
if (ap_poll_queue(ap_dev, flags))
ap_dev->unregistered = 1;
+ if (ap_dev->reset == AP_RESET_DO)
+ ap_reset(ap_dev);
}
spin_unlock(&ap_dev->lock);
return 0;
@@ -1147,6 +1216,17 @@ static void ap_poll_thread_stop(void)
mutex_unlock(&ap_poll_thread_mutex);
}
+/**
+ * Handling of request timeouts
+ */
+static void ap_request_timeout(unsigned long data)
+{
+ struct ap_device *ap_dev = (struct ap_device *) data;
+
+ if (ap_dev->reset == AP_RESET_ARMED)
+ ap_dev->reset = AP_RESET_DO;
+}
+
static void ap_reset_domain(void)
{
int i;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 008559ea742..87c2d644287 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -33,6 +33,7 @@
#define AP_DEVICES 64 /* Number of AP devices. */
#define AP_DOMAINS 16 /* Number of AP domains. */
#define AP_MAX_RESET 90 /* Maximum number of resets. */
+#define AP_RESET_TIMEOUT (HZ/2) /* Time in ticks for reset timeouts. */
#define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */
#define AP_POLL_TIME 1 /* Time in ticks between receive polls. */
@@ -83,6 +84,13 @@ struct ap_queue_status {
#define AP_DEVICE_TYPE_CEX2A 6
#define AP_DEVICE_TYPE_CEX2C 7
+/**
+ * AP reset flag states
+ */
+#define AP_RESET_IGNORE 0 /* request timeout will be ignored */
+#define AP_RESET_ARMED 1 /* request timeout timer is active */
+#define AP_RESET_DO 2 /* AP reset required */
+
struct ap_device;
struct ap_message;
@@ -95,6 +103,7 @@ struct ap_driver {
/* receive is called from tasklet context */
void (*receive)(struct ap_device *, struct ap_message *,
struct ap_message *);
+ int request_timeout; /* request timeout in jiffies */
};
#define to_ap_drv(x) container_of((x), struct ap_driver, driver)
@@ -112,6 +121,8 @@ struct ap_device {
int queue_depth; /* AP queue depth.*/
int device_type; /* AP device type. */
int unregistered; /* marks AP device as unregistered */
+ struct timer_list timeout; /* Timer for request timeouts. */
+ int reset; /* Reset required after req. timeout. */
int queue_count; /* # messages currently on AP queue. */
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 5bb13a9d089..08657f604b8 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_cex2a_driver = {
.remove = zcrypt_cex2a_remove,
.receive = zcrypt_cex2a_receive,
.ids = zcrypt_cex2a_ids,
+ .request_timeout = CEX2A_CLEANUP_TIME,
};
/**
@@ -306,18 +307,13 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, CEX2A_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
@@ -348,18 +344,13 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, CEX2A_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 818ffe05ac0..6e93b475178 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_pcica_driver = {
.remove = zcrypt_pcica_remove,
.receive = zcrypt_pcica_receive,
.ids = zcrypt_pcica_ids,
+ .request_timeout = PCICA_CLEANUP_TIME,
};
/**
@@ -290,18 +291,13 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICA_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
@@ -332,18 +328,13 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICA_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index f295a403b29..d6d59bf9ac3 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -82,6 +82,7 @@ static struct ap_driver zcrypt_pcicc_driver = {
.remove = zcrypt_pcicc_remove,
.receive = zcrypt_pcicc_receive,
.ids = zcrypt_pcicc_ids,
+ .request_timeout = PCICC_CLEANUP_TIME,
};
/**
@@ -501,18 +502,13 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
@@ -544,18 +540,13 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 252443b6bd1..64948788d30 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -93,6 +93,7 @@ static struct ap_driver zcrypt_pcixcc_driver = {
.remove = zcrypt_pcixcc_remove,
.receive = zcrypt_pcixcc_receive,
.ids = zcrypt_pcixcc_ids,
+ .request_timeout = PCIXCC_CLEANUP_TIME,
};
/**
@@ -641,18 +642,13 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &resp_type.work, PCIXCC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
@@ -685,18 +681,13 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &resp_type.work, PCIXCC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
@@ -729,17 +720,12 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
goto out_free;
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &resp_type.work, PCIXCC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
memset(ap_msg.message, 0x0, ap_msg.length);
kfree(ap_msg.message);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 6b76babc7fb..a0ea4359851 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -842,12 +842,16 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 61de78a9f6e..4fff61b32dc 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -143,7 +143,7 @@ static struct console sercons;
static unsigned long break_pressed; /* break, really ... */
#endif
-static unsigned char zs_init_regs[16] __initdata = {
+static unsigned char zs_init_regs[16] = {
0, /* write 0 */
0, /* write 1 */
0, /* write 2 */
@@ -1581,7 +1581,7 @@ static void __init show_serial_version(void)
/* Initialize Z8530s zs_channels
*/
-static void __init probe_sccs(void)
+static void probe_sccs(void)
{
struct dec_serial **pp;
int i, n, n_chips = 0, n_channels, chip, channel;
@@ -1923,7 +1923,7 @@ static struct tty_driver *serial_console_device(struct console *c, int *index)
* - initialize the serial port
* Return non-zero if we didn't find a serial port.
*/
-static int __init serial_console_setup(struct console *co, char *options)
+static int serial_console_setup(struct console *co, char *options)
{
struct dec_serial *info;
int baud = 9600;
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 70250252ae2..1a60f9c473a 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -336,7 +336,7 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
memcpy(priv->reg, buffer, 4);
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
if (priv->reg[2] & priv->reg[1] & 0x10)
- parport_generic_irq(0, pp, NULL);
+ parport_generic_irq(0, pp);
return 1;
}
#endif
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 904e5aeb696..df95d6c2cef 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -35,4 +35,17 @@ config W1_SLAVE_DS2433_CRC
Each block has 30 bytes of data and a two byte CRC16.
Full block writes are only allowed if the CRC is valid.
+config W1_SLAVE_DS2760
+ tristate "Dallas 2760 battery monitor chip (HP iPAQ & others)"
+ depends on W1
+ help
+ If you enable this you will have the DS2760 battery monitor
+ chip support.
+
+ The battery monitor chip is used in many batteries/devices
+ as the one who is responsible for charging/discharging/monitoring
+ Li+ batteries.
+
+ If you are unsure, say N.
+
endmenu
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index 725dcfdfddb..a8eb7524df1 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -5,4 +5,5 @@
obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o
obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o
obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o
+obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
new file mode 100644
index 00000000000..88a37fbccc3
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.c
@@ -0,0 +1,213 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/idr.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+#include "w1_ds2760.h"
+
+static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
+ int io)
+{
+ struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+ if (!dev)
+ return 0;
+
+ mutex_lock(&sl->master->mutex);
+
+ if (addr > DS2760_DATA_SIZE || addr < 0) {
+ count = 0;
+ goto out;
+ }
+ if (addr + count > DS2760_DATA_SIZE)
+ count = DS2760_DATA_SIZE - addr;
+
+ if (!w1_reset_select_slave(sl)) {
+ if (!io) {
+ w1_write_8(sl->master, W1_DS2760_READ_DATA);
+ w1_write_8(sl->master, addr);
+ count = w1_read_block(sl->master, buf, count);
+ } else {
+ w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
+ w1_write_8(sl->master, addr);
+ w1_write_block(sl->master, buf, count);
+ /* XXX w1_write_block returns void, not n_written */
+ }
+ }
+
+out:
+ mutex_unlock(&sl->master->mutex);
+
+ return count;
+}
+
+int w1_ds2760_read(struct device *dev, char *buf, int addr, size_t count)
+{
+ return w1_ds2760_io(dev, buf, addr, count, 0);
+}
+
+int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count)
+{
+ return w1_ds2760_io(dev, buf, addr, count, 1);
+}
+
+static ssize_t w1_ds2760_read_bin(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ return w1_ds2760_read(dev, buf, off, count);
+}
+
+static struct bin_attribute w1_ds2760_bin_attr = {
+ .attr = {
+ .name = "w1_slave",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = DS2760_DATA_SIZE,
+ .read = w1_ds2760_read_bin,
+};
+
+static DEFINE_IDR(bat_idr);
+static DEFINE_MUTEX(bat_idr_lock);
+
+static int new_bat_id(void)
+{
+ int ret;
+
+ while (1) {
+ int id;
+
+ ret = idr_pre_get(&bat_idr, GFP_KERNEL);
+ if (ret == 0)
+ return -ENOMEM;
+
+ mutex_lock(&bat_idr_lock);
+ ret = idr_get_new(&bat_idr, NULL, &id);
+ mutex_unlock(&bat_idr_lock);
+
+ if (ret == 0) {
+ ret = id & MAX_ID_MASK;
+ break;
+ } else if (ret == -EAGAIN) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static void release_bat_id(int id)
+{
+ mutex_lock(&bat_idr_lock);
+ idr_remove(&bat_idr, id);
+ mutex_unlock(&bat_idr_lock);
+
+ return;
+}
+
+static int w1_ds2760_add_slave(struct w1_slave *sl)
+{
+ int ret;
+ int id;
+ struct platform_device *pdev;
+
+ id = new_bat_id();
+ if (id < 0) {
+ ret = id;
+ goto noid;
+ }
+
+ pdev = platform_device_alloc("ds2760-battery", id);
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto pdev_alloc_failed;
+ }
+ pdev->dev.parent = &sl->dev;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto pdev_add_failed;
+
+ ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+ if (ret)
+ goto bin_attr_failed;
+
+ dev_set_drvdata(&sl->dev, pdev);
+
+ goto success;
+
+bin_attr_failed:
+pdev_add_failed:
+ platform_device_unregister(pdev);
+pdev_alloc_failed:
+ release_bat_id(id);
+noid:
+success:
+ return ret;
+}
+
+static void w1_ds2760_remove_slave(struct w1_slave *sl)
+{
+ struct platform_device *pdev = dev_get_drvdata(&sl->dev);
+ int id = pdev->id;
+
+ platform_device_unregister(pdev);
+ release_bat_id(id);
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+
+ return;
+}
+
+static struct w1_family_ops w1_ds2760_fops = {
+ .add_slave = w1_ds2760_add_slave,
+ .remove_slave = w1_ds2760_remove_slave,
+};
+
+static struct w1_family w1_ds2760_family = {
+ .fid = W1_FAMILY_DS2760,
+ .fops = &w1_ds2760_fops,
+};
+
+static int __init w1_ds2760_init(void)
+{
+ printk(KERN_INFO "1-Wire driver for the DS2760 battery monitor "
+ " chip - (c) 2004-2005, Szabolcs Gyurko\n");
+ idr_init(&bat_idr);
+ return w1_register_family(&w1_ds2760_family);
+}
+
+static void __exit w1_ds2760_exit(void)
+{
+ w1_unregister_family(&w1_ds2760_family);
+ idr_destroy(&bat_idr);
+}
+
+EXPORT_SYMBOL(w1_ds2760_read);
+EXPORT_SYMBOL(w1_ds2760_write);
+
+module_init(w1_ds2760_init);
+module_exit(w1_ds2760_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>");
+MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
diff --git a/drivers/w1/slaves/w1_ds2760.h b/drivers/w1/slaves/w1_ds2760.h
new file mode 100644
index 00000000000..f1302429cb0
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.h
@@ -0,0 +1,50 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#ifndef __w1_ds2760_h__
+#define __w1_ds2760_h__
+
+/* Known commands to the DS2760 chip */
+#define W1_DS2760_SWAP 0xAA
+#define W1_DS2760_READ_DATA 0x69
+#define W1_DS2760_WRITE_DATA 0x6C
+#define W1_DS2760_COPY_DATA 0x48
+#define W1_DS2760_RECALL_DATA 0xB8
+#define W1_DS2760_LOCK 0x6A
+
+/* Number of valid register addresses */
+#define DS2760_DATA_SIZE 0x40
+
+#define DS2760_PROTECTION_REG 0x00
+#define DS2760_STATUS_REG 0x01
+#define DS2760_EEPROM_REG 0x07
+#define DS2760_SPECIAL_FEATURE_REG 0x08
+#define DS2760_VOLTAGE_MSB 0x0c
+#define DS2760_VOLTAGE_LSB 0x0d
+#define DS2760_CURRENT_MSB 0x0e
+#define DS2760_CURRENT_LSB 0x0f
+#define DS2760_CURRENT_ACCUM_MSB 0x10
+#define DS2760_CURRENT_ACCUM_LSB 0x11
+#define DS2760_TEMP_MSB 0x18
+#define DS2760_TEMP_LSB 0x19
+#define DS2760_EEPROM_BLOCK0 0x20
+#define DS2760_ACTIVE_FULL 0x20
+#define DS2760_EEPROM_BLOCK1 0x30
+#define DS2760_RATED_CAPACITY 0x32
+#define DS2760_CURRENT_OFFSET_BIAS 0x33
+#define DS2760_ACTIVE_EMPTY 0x3b
+
+extern int w1_ds2760_read(struct device *dev, char *buf, int addr,
+ size_t count);
+extern int w1_ds2760_write(struct device *dev, char *buf, int addr,
+ size_t count);
+
+#endif /* !__w1_ds2760_h__ */
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 1e2ac40c2c1..ef1e1dafa19 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -33,6 +33,7 @@
#define W1_THERM_DS1822 0x22
#define W1_EEPROM_DS2433 0x23
#define W1_THERM_DS18B20 0x28
+#define W1_FAMILY_DS2760 0x30
#define MAXNAMELEN 32